basic psp snd + cz80
[picodrive.git] / cpu / cz80 / cz80.c
diff --git a/cpu/cz80/cz80.c b/cpu/cz80/cz80.c
new file mode 100644 (file)
index 0000000..bcff740
--- /dev/null
@@ -0,0 +1,460 @@
+/******************************************************************************\r
+ *\r
+ * CZ80 (Z80 CPU emulator) version 0.9\r
+ * Compiled with Dev-C++\r
+ * Copyright 2004-2005 Stéphane Dallongeville\r
+ *\r
+ * (Modified by NJ)\r
+ *\r
+ *****************************************************************************/\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include "cz80.h"\r
+\r
+#ifndef ALIGN_DATA\r
+#define ALIGN_DATA      __attribute__((aligned(4)))\r
+#endif\r
+\r
+#define CF                                     0x01\r
+#define NF                                     0x02\r
+#define PF                                     0x04\r
+#define VF                                     PF\r
+#define XF                                     0x08\r
+#define HF                                     0x10\r
+#define YF                                     0x20\r
+#define ZF                                     0x40\r
+#define SF                                     0x80\r
+\r
+\r
+/******************************************************************************\r
+       \83}\83N\83\8d\r
+******************************************************************************/\r
+\r
+#include "cz80macro.h"\r
+\r
+\r
+/******************************************************************************\r
+       \83O\83\8d\81[\83o\83\8b\8d\\91¢\91Ì\r
+******************************************************************************/\r
+\r
+cz80_struc ALIGN_DATA CZ80;\r
+\r
+\r
+/******************************************************************************\r
+       \83\8d\81[\83J\83\8b\95Ï\90\94\r
+******************************************************************************/\r
+\r
+static UINT8 ALIGN_DATA cz80_bad_address[1 << CZ80_FETCH_SFT];\r
+\r
+static UINT8 ALIGN_DATA SZ[256];\r
+static UINT8 ALIGN_DATA SZP[256];\r
+static UINT8 ALIGN_DATA SZ_BIT[256];\r
+static UINT8 ALIGN_DATA SZHV_inc[256];\r
+static UINT8 ALIGN_DATA SZHV_dec[256];\r
+#if CZ80_BIG_FLAGS_ARRAY\r
+static UINT8 ALIGN_DATA SZHVC_add[2*256*256];\r
+static UINT8 ALIGN_DATA SZHVC_sub[2*256*256];\r
+#endif\r
+\r
+\r
+/******************************************************************************\r
+       \83\8d\81[\83J\83\8b\8aÖ\90\94\r
+******************************************************************************/\r
+\r
+/*--------------------------------------------------------\r
+       \8a\84\82è\8d\9e\82Ý\83R\81[\83\8b\83o\83b\83N\r
+--------------------------------------------------------*/\r
+\r
+static INT32 Cz80_Interrupt_Callback(INT32 line)\r
+{\r
+       return 0xff;\r
+}\r
+\r
+\r
+/******************************************************************************\r
+       CZ80\83C\83\93\83^\83t\83F\81[\83X\8aÖ\90\94\r
+******************************************************************************/\r
+\r
+/*--------------------------------------------------------\r
+       CPU\8f\89\8aú\89»\r
+--------------------------------------------------------*/\r
+\r
+void Cz80_Init(cz80_struc *CPU)\r
+{\r
+       UINT32 i, j, p;\r
+#if CZ80_BIG_FLAGS_ARRAY\r
+       int oldval, newval, val;\r
+       UINT8 *padd, *padc, *psub, *psbc;\r
+#endif\r
+\r
+       memset(CPU, 0, sizeof(cz80_struc));\r
+\r
+       memset(cz80_bad_address, 0xff, sizeof(cz80_bad_address));\r
+\r
+       for (i = 0; i < CZ80_FETCH_BANK; i++)\r
+       {\r
+               CPU->Fetch[i] = (UINT32)cz80_bad_address;\r
+#if CZ80_ENCRYPTED_ROM\r
+               CPU->OPFetch[i] = 0;\r
+#endif\r
+       }\r
+\r
+       // flags tables initialisation\r
+       for (i = 0; i < 256; i++)\r
+       {\r
+               SZ[i] = i & (SF | YF | XF);\r
+               if (!i) SZ[i] |= ZF;\r
+\r
+               SZ_BIT[i] = i & (SF | YF | XF);\r
+               if (!i) SZ_BIT[i] |= ZF | PF;\r
+\r
+               for (j = 0, p = 0; j < 8; j++) if (i & (1 << j)) p++;\r
+               SZP[i] = SZ[i];\r
+               if (!(p & 1)) SZP[i] |= PF;\r
+\r
+               SZHV_inc[i] = SZ[i];\r
+               if(i == 0x80) SZHV_inc[i] |= VF;\r
+               if((i & 0x0f) == 0x00) SZHV_inc[i] |= HF;\r
+\r
+               SZHV_dec[i] = SZ[i] | NF;\r
+               if (i == 0x7f) SZHV_dec[i] |= VF;\r
+               if ((i & 0x0f) == 0x0f) SZHV_dec[i] |= HF;\r
+       }\r
+\r
+#if CZ80_BIG_FLAGS_ARRAY\r
+       padd = &SZHVC_add[  0*256];\r
+       padc = &SZHVC_add[256*256];\r
+       psub = &SZHVC_sub[  0*256];\r
+       psbc = &SZHVC_sub[256*256];\r
+\r
+       for (oldval = 0; oldval < 256; oldval++)\r
+       {\r
+               for (newval = 0; newval < 256; newval++)\r
+               {\r
+                       /* add or adc w/o carry set */\r
+                       val = newval - oldval;\r
+                       *padd = (newval) ? ((newval & 0x80) ? SF : 0) : ZF;\r
+                       *padd |= (newval & (YF | XF));  /* undocumented flag bits 5+3 */\r
+                       if ((newval & 0x0f) < (oldval & 0x0f)) *padd |= HF;\r
+                       if (newval < oldval ) *padd |= CF;\r
+                       if ((val ^ oldval ^ 0x80) & (val ^ newval) & 0x80) *padd |= VF;\r
+                       padd++;\r
+\r
+                       /* adc with carry set */\r
+                       val = newval - oldval - 1;\r
+                       *padc = (newval) ? ((newval & 0x80) ? SF : 0) : ZF;\r
+                       *padc |= (newval & (YF | XF));  /* undocumented flag bits 5+3 */\r
+                       if ((newval & 0x0f) <= (oldval & 0x0f)) *padc |= HF;\r
+                       if (newval <= oldval) *padc |= CF;\r
+                       if ((val ^ oldval ^ 0x80) & (val ^ newval) & 0x80) *padc |= VF;\r
+                       padc++;\r
+\r
+                       /* cp, sub or sbc w/o carry set */\r
+                       val = oldval - newval;\r
+                       *psub = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF);\r
+                       *psub |= (newval & (YF | XF));  /* undocumented flag bits 5+3 */\r
+                       if ((newval & 0x0f) > (oldval & 0x0f)) *psub |= HF;\r
+                       if (newval > oldval) *psub |= CF;\r
+                       if ((val^oldval) & (oldval^newval) & 0x80) *psub |= VF;\r
+                       psub++;\r
+\r
+                       /* sbc with carry set */\r
+                       val = oldval - newval - 1;\r
+                       *psbc = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF);\r
+                       *psbc |= (newval & (YF | XF));  /* undocumented flag bits 5+3 */\r
+                       if ((newval & 0x0f) >= (oldval & 0x0f)) *psbc |= HF;\r
+                       if (newval >= oldval) *psbc |= CF;\r
+                       if ((val ^ oldval) & (oldval^newval) & 0x80) *psbc |= VF;\r
+                       psbc++;\r
+               }\r
+       }\r
+#endif\r
+\r
+       CPU->pzR8[0] = &zB;\r
+       CPU->pzR8[1] = &zC;\r
+       CPU->pzR8[2] = &zD;\r
+       CPU->pzR8[3] = &zE;\r
+       CPU->pzR8[4] = &zH;\r
+       CPU->pzR8[5] = &zL;\r
+       CPU->pzR8[6] = &zF;     // \8f\88\97\9d\82Ì\93s\8d\87\8fã\81AA\82Æ\93ü\82ê\91Ö\82¦\r
+       CPU->pzR8[7] = &zA;     // \8f\88\97\9d\82Ì\93s\8d\87\8fã\81AF\82Æ\93ü\82ê\91Ö\82¦\r
+\r
+       CPU->pzR16[0] = pzBC;\r
+       CPU->pzR16[1] = pzDE;\r
+       CPU->pzR16[2] = pzHL;\r
+       CPU->pzR16[3] = pzAF;\r
+\r
+       zIX = zIY = 0xffff;\r
+       zF = ZF;\r
+\r
+       CPU->Interrupt_Callback = Cz80_Interrupt_Callback;\r
+}\r
+\r
+\r
+/*--------------------------------------------------------\r
+       CPU\83\8a\83Z\83b\83g\r
+--------------------------------------------------------*/\r
+\r
+void Cz80_Reset(cz80_struc *CPU)\r
+{\r
+       memset(CPU, 0, (INT32)&CPU->BasePC - (INT32)CPU);\r
+       Cz80_Set_Reg(CPU, CZ80_PC, 0);\r
+}\r
+\r
+\r
+/*--------------------------------------------------------\r
+       CPU\8eÀ\8ds\r
+--------------------------------------------------------*/\r
+\r
+INT32 Cz80_Exec(cz80_struc *CPU, INT32 cycles)\r
+{\r
+#if CZ80_USE_JUMPTABLE\r
+#include "cz80jmp.c"\r
+#endif\r
+\r
+       UINT32 PC;\r
+#if CZ80_ENCRYPTED_ROM\r
+       INT32 OPBase;\r
+#endif\r
+       UINT32 Opcode;\r
+       UINT32 adr = 0;\r
+       UINT32 res;\r
+       UINT32 val;\r
+       int afterEI = 0;\r
+\r
+       PC = CPU->PC;\r
+#if CZ80_ENCRYPTED_ROM\r
+       OPBase = CPU->OPBase;\r
+#endif\r
+       CPU->ICount = cycles - CPU->ExtraCycles;\r
+       CPU->ExtraCycles = 0;\r
+\r
+       if (!CPU->HaltState)\r
+       {\r
+Cz80_Exec:\r
+               if (CPU->ICount > 0)\r
+               {\r
+                       union16 *data = pzHL;\r
+                       Opcode = READ_OP();\r
+#if CZ80_EMULATE_R_EXACTLY\r
+                       zR++;\r
+#endif\r
+                       #include "cz80_op.c"\r
+               }\r
+\r
+               if (afterEI)\r
+               {\r
+                       afterEI = 0;\r
+Cz80_Check_Interrupt:\r
+                       CHECK_INT\r
+                       goto Cz80_Exec;\r
+               }\r
+       }\r
+       else CPU->ICount = 0;\r
+\r
+Cz80_Exec_End:\r
+       CPU->PC = PC;\r
+#if CZ80_ENCRYPTED_ROM\r
+       CPU->OPBase = OPBase;\r
+#endif\r
+       cycles -= CPU->ICount;\r
+#if !CZ80_EMULATE_R_EXACTLY\r
+       zR = (zR + (cycles >> 2)) & 0x7f;\r
+#endif\r
+\r
+       return cycles;\r
+}\r
+\r
+\r
+/*--------------------------------------------------------\r
+       \8a\84\82è\8d\9e\82Ý\8f\88\97\9d\r
+--------------------------------------------------------*/\r
+\r
+void Cz80_Set_IRQ(cz80_struc *CPU, INT32 line, INT32 state)\r
+{\r
+       if (line == IRQ_LINE_NMI)\r
+       {\r
+               zIFF1 = 0;\r
+               CPU->ExtraCycles += 11;\r
+               CPU->HaltState = 0;\r
+               PUSH_16(CPU->PC - CPU->BasePC)\r
+               Cz80_Set_Reg(CPU, CZ80_PC, 0x66);\r
+       }\r
+       else\r
+       {\r
+               CPU->IRQState = state;\r
+\r
+               if (state != CLEAR_LINE)\r
+               {\r
+                       UINT32 PC = CPU->PC;\r
+#if CZ80_ENCRYPTED_ROM\r
+                       INT32 OPBase = CPU->OPBase;\r
+#endif\r
+\r
+                       CPU->IRQLine = line;\r
+                       CHECK_INT\r
+                       CPU->PC = PC;\r
+#if CZ80_ENCRYPTED_ROM\r
+                       CPU->OPBase = OPBase;\r
+#endif\r
+               }\r
+       }\r
+}\r
+\r
+\r
+/*--------------------------------------------------------\r
+       \83\8c\83W\83X\83^\8eæ\93¾\r
+--------------------------------------------------------*/\r
+\r
+UINT32 Cz80_Get_Reg(cz80_struc *CPU, INT32 regnum)\r
+{\r
+       switch (regnum)\r
+       {\r
+       case CZ80_PC:   return (CPU->PC - CPU->BasePC);\r
+       case CZ80_SP:   return zSP;\r
+       case CZ80_AF:   return zAF;\r
+       case CZ80_BC:   return zBC;\r
+       case CZ80_DE:   return zDE;\r
+       case CZ80_HL:   return zHL;\r
+       case CZ80_IX:   return zIX;\r
+       case CZ80_IY:   return zIY;\r
+       case CZ80_AF2:  return zAF2;\r
+       case CZ80_BC2:  return zBC2;\r
+       case CZ80_DE2:  return zDE2;\r
+       case CZ80_HL2:  return zHL2;\r
+       case CZ80_R:    return zR;\r
+       case CZ80_I:    return zI;\r
+       case CZ80_IM:   return zIM;\r
+       case CZ80_IFF1: return zIFF1;\r
+       case CZ80_IFF2: return zIFF2;\r
+       case CZ80_HALT: return CPU->HaltState;\r
+       case CZ80_IRQ:  return CPU->IRQState;\r
+       default: return 0;\r
+       }\r
+}\r
+\r
+\r
+/*--------------------------------------------------------\r
+       \83\8c\83W\83X\83^\90Ý\92è\r
+--------------------------------------------------------*/\r
+\r
+void Cz80_Set_Reg(cz80_struc *CPU, INT32 regnum, UINT32 val)\r
+{\r
+       switch (regnum)\r
+       {\r
+       case CZ80_PC:\r
+               CPU->BasePC = CPU->Fetch[val >> CZ80_FETCH_SFT];\r
+#if CZ80_ENCRYPTED_ROM\r
+               CPU->OPBase = CPU->OPFetch[val >> CZ80_FETCH_SFT];\r
+#endif\r
+               CPU->PC = val + CPU->BasePC;\r
+               break;\r
+\r
+       case CZ80_SP:   zSP = val; break;\r
+       case CZ80_AF:   zAF = val; break;\r
+       case CZ80_BC:   zBC = val; break;\r
+       case CZ80_DE:   zDE = val; break;\r
+       case CZ80_HL:   zHL = val; break;\r
+       case CZ80_IX:   zIX = val; break;\r
+       case CZ80_IY:   zIY = val; break;\r
+       case CZ80_AF2:  zAF2 = val; break;\r
+       case CZ80_BC2:  zBC2 = val; break;\r
+       case CZ80_DE2:  zDE2 = val; break;\r
+       case CZ80_HL2:  zHL2 = val; break;\r
+       case CZ80_R:    zR = val; break;\r
+       case CZ80_I:    zI = val; break;\r
+       case CZ80_IM:   zIM = val; break;\r
+       case CZ80_IFF1: zIFF1 = val; break;\r
+       case CZ80_IFF2: zIFF2 = val; break;\r
+       case CZ80_HALT: CPU->HaltState = val; break;\r
+       case CZ80_IRQ:  CPU->IRQState = val; break;\r
+       default: break;\r
+       }\r
+}\r
+\r
+\r
+/*--------------------------------------------------------\r
+       \83t\83F\83b\83`\83A\83h\83\8c\83X\90Ý\92è\r
+--------------------------------------------------------*/\r
+\r
+void Cz80_Set_Fetch(cz80_struc *CPU, UINT32 low_adr, UINT32 high_adr, UINT32 fetch_adr)\r
+{\r
+       int i, j;\r
+\r
+       i = low_adr >> CZ80_FETCH_SFT;\r
+       j = high_adr >> CZ80_FETCH_SFT;\r
+       fetch_adr -= i << CZ80_FETCH_SFT;\r
+\r
+       while (i <= j)\r
+       {\r
+               CPU->Fetch[i] = fetch_adr;\r
+#if CZ80_ENCRYPTED_ROM\r
+               CPU->OPFetch[i] = 0;\r
+#endif\r
+               i++;\r
+       }\r
+}\r
+\r
+\r
+/*--------------------------------------------------------\r
+       \83t\83F\83b\83`\83A\83h\83\8c\83X\90Ý\92è (\88Ã\8d\86\89»ROM\91Î\89\9e)\r
+--------------------------------------------------------*/\r
+\r
+#if CZ80_ENCRYPTED_ROM\r
+void Cz80_Set_Encrypt_Range(cz80_struc *CPU, UINT32 low_adr, UINT32 high_adr, UINT32 decrypted_rom)\r
+{\r
+       int i, j;\r
+\r
+       i = low_adr >> CZ80_FETCH_SFT;\r
+       j = high_adr >> CZ80_FETCH_SFT;\r
+       decrypted_rom -= i << CZ80_FETCH_SFT;\r
+\r
+       while (i <= j)\r
+       {\r
+               CPU->OPFetch[i] = (INT32)decrypted_rom - (INT32)CPU->Fetch[i];\r
+               i++;\r
+       }\r
+}\r
+#endif\r
+\r
+\r
+/*--------------------------------------------------------\r
+       \83\81\83\82\83\8a\83\8a\81[\83h/\83\89\83C\83g\8aÖ\90\94\90Ý\92è\r
+--------------------------------------------------------*/\r
+\r
+void Cz80_Set_ReadB(cz80_struc *CPU, UINT8 (*Func)(UINT32 address))\r
+{\r
+       CPU->Read_Byte = Func;\r
+}\r
+\r
+void Cz80_Set_WriteB(cz80_struc *CPU, void (*Func)(UINT32 address, UINT8 data))\r
+{\r
+       CPU->Write_Byte = Func;\r
+}\r
+\r
+\r
+/*--------------------------------------------------------\r
+       \83|\81[\83g\83\8a\81[\83h/\83\89\83C\83g\8aÖ\90\94\90Ý\92è\r
+--------------------------------------------------------*/\r
+\r
+void Cz80_Set_INPort(cz80_struc *CPU, UINT8 (*Func)(UINT16 port))\r
+{\r
+       CPU->IN_Port = Func;\r
+}\r
+\r
+void Cz80_Set_OUTPort(cz80_struc *CPU, void (*Func)(UINT16 port, UINT8 value))\r
+{\r
+       CPU->OUT_Port = Func;\r
+}\r
+\r
+\r
+/*--------------------------------------------------------\r
+       \83R\81[\83\8b\83o\83b\83N\8aÖ\90\94\90Ý\92è\r
+--------------------------------------------------------*/\r
+\r
+void Cz80_Set_IRQ_Callback(cz80_struc *CPU, INT32 (*Func)(INT32 irqline))\r
+{\r
+       CPU->Interrupt_Callback = Func;\r
+}\r