123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485 |
- /******************************************************************************
- *
- * CZ80 (Z80 CPU emulator) version 0.9
- * Compiled with Dev-C++
- * Copyright 2004-2005 St駱hane Dallongeville
- *
- * (Modified by NJ)
- *
- *****************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "cz80.h"
- #if PICODRIVE_HACKS
- #include <pico/pico_int.h>
- #include <pico/memory.h>
- #endif
- #ifndef ALIGN_DATA
- #ifdef _MSC_VER
- #define ALIGN_DATA
- #define inline
- #undef CZ80_USE_JUMPTABLE
- #define CZ80_USE_JUMPTABLE 0
- #else
- #define ALIGN_DATA __attribute__((aligned(4)))
- #endif
- #endif
- #define CF 0x01
- #define NF 0x02
- #define PF 0x04
- #define VF PF
- #define XF 0x08
- #define HF 0x10
- #define YF 0x20
- #define ZF 0x40
- #define SF 0x80
- /******************************************************************************
- マクロ
- ******************************************************************************/
- #include "cz80macro.h"
- /******************************************************************************
- グローバル構造体
- ******************************************************************************/
- cz80_struc ALIGN_DATA CZ80;
- /******************************************************************************
- ローカル変数
- ******************************************************************************/
- static UINT8 ALIGN_DATA cz80_bad_address[1 << CZ80_FETCH_SFT];
- static UINT8 ALIGN_DATA SZ[256];
- static UINT8 ALIGN_DATA SZP[256];
- static UINT8 ALIGN_DATA SZ_BIT[256];
- static UINT8 ALIGN_DATA SZHV_inc[256];
- static UINT8 ALIGN_DATA SZHV_dec[256];
- #if CZ80_BIG_FLAGS_ARRAY
- static UINT8 ALIGN_DATA SZHVC_add[2*256*256];
- static UINT8 ALIGN_DATA SZHVC_sub[2*256*256];
- #endif
- /******************************************************************************
- ローカル関数
- ******************************************************************************/
- /*--------------------------------------------------------
- 割り込みコールバック
- --------------------------------------------------------*/
- static INT32 Cz80_Interrupt_Callback(INT32 line)
- {
- return 0xff;
- }
- /******************************************************************************
- CZ80インタフェース関数
- ******************************************************************************/
- /*--------------------------------------------------------
- CPU初期化
- --------------------------------------------------------*/
- void Cz80_Init(cz80_struc *CPU)
- {
- UINT32 i, j, p;
- #if CZ80_BIG_FLAGS_ARRAY
- int oldval, newval, val;
- UINT8 *padd, *padc, *psub, *psbc;
- #endif
- memset(CPU, 0, sizeof(cz80_struc));
- memset(cz80_bad_address, 0xff, sizeof(cz80_bad_address));
- for (i = 0; i < CZ80_FETCH_BANK; i++)
- {
- CPU->Fetch[i] = (FPTR)cz80_bad_address - (i << CZ80_FETCH_SFT);
- #if CZ80_ENCRYPTED_ROM
- CPU->OPFetch[i] = 0;
- #endif
- }
- // flags tables initialisation
- for (i = 0; i < 256; i++)
- {
- SZ[i] = i & (SF | YF | XF);
- if (!i) SZ[i] |= ZF;
- SZ_BIT[i] = i & (SF | YF | XF);
- if (!i) SZ_BIT[i] |= ZF | PF;
- for (j = 0, p = 0; j < 8; j++) if (i & (1 << j)) p++;
- SZP[i] = SZ[i];
- if (!(p & 1)) SZP[i] |= PF;
- SZHV_inc[i] = SZ[i];
- if(i == 0x80) SZHV_inc[i] |= VF;
- if((i & 0x0f) == 0x00) SZHV_inc[i] |= HF;
- SZHV_dec[i] = SZ[i] | NF;
- if (i == 0x7f) SZHV_dec[i] |= VF;
- if ((i & 0x0f) == 0x0f) SZHV_dec[i] |= HF;
- }
- #if CZ80_BIG_FLAGS_ARRAY
- padd = &SZHVC_add[ 0*256];
- padc = &SZHVC_add[256*256];
- psub = &SZHVC_sub[ 0*256];
- psbc = &SZHVC_sub[256*256];
- for (oldval = 0; oldval < 256; oldval++)
- {
- for (newval = 0; newval < 256; newval++)
- {
- /* add or adc w/o carry set */
- val = newval - oldval;
- *padd = (newval) ? ((newval & 0x80) ? SF : 0) : ZF;
- *padd |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
- if ((newval & 0x0f) < (oldval & 0x0f)) *padd |= HF;
- if (newval < oldval ) *padd |= CF;
- if ((val ^ oldval ^ 0x80) & (val ^ newval) & 0x80) *padd |= VF;
- padd++;
- /* adc with carry set */
- val = newval - oldval - 1;
- *padc = (newval) ? ((newval & 0x80) ? SF : 0) : ZF;
- *padc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
- if ((newval & 0x0f) <= (oldval & 0x0f)) *padc |= HF;
- if (newval <= oldval) *padc |= CF;
- if ((val ^ oldval ^ 0x80) & (val ^ newval) & 0x80) *padc |= VF;
- padc++;
- /* cp, sub or sbc w/o carry set */
- val = oldval - newval;
- *psub = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF);
- *psub |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
- if ((newval & 0x0f) > (oldval & 0x0f)) *psub |= HF;
- if (newval > oldval) *psub |= CF;
- if ((val^oldval) & (oldval^newval) & 0x80) *psub |= VF;
- psub++;
- /* sbc with carry set */
- val = oldval - newval - 1;
- *psbc = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF);
- *psbc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */
- if ((newval & 0x0f) >= (oldval & 0x0f)) *psbc |= HF;
- if (newval >= oldval) *psbc |= CF;
- if ((val ^ oldval) & (oldval^newval) & 0x80) *psbc |= VF;
- psbc++;
- }
- }
- #endif
- CPU->pzR8[0] = &zB;
- CPU->pzR8[1] = &zC;
- CPU->pzR8[2] = &zD;
- CPU->pzR8[3] = &zE;
- CPU->pzR8[4] = &zH;
- CPU->pzR8[5] = &zL;
- CPU->pzR8[6] = &zF; // 処理の都合上、Aと入れ替え
- CPU->pzR8[7] = &zA; // 処理の都合上、Fと入れ替え
- CPU->pzR16[0] = pzBC;
- CPU->pzR16[1] = pzDE;
- CPU->pzR16[2] = pzHL;
- CPU->pzR16[3] = pzAF;
- zIX = zIY = 0xffff;
- CPU->Interrupt_Callback = Cz80_Interrupt_Callback;
- }
- /*--------------------------------------------------------
- CPUリセット
- --------------------------------------------------------*/
- void Cz80_Reset(cz80_struc *CPU)
- {
- // I, R, CPU and interrupts logic is reset, registers are untouched
- memset(&CPU->R, 0, (FPTR)&CPU->BasePC - (FPTR)&CPU->R);
- Cz80_Set_Reg(CPU, CZ80_PC, 0);
- }
- /* */
- #if PICODRIVE_HACKS
- static inline unsigned char picodrive_read(unsigned short a)
- {
- uptr v = z80_read_map[a >> Z80_MEM_SHIFT];
- if (map_flag_set(v))
- return ((z80_read_f *)(v << 1))(a);
- return *(unsigned char *)((v << 1) + a);
- }
- #endif
- /*--------------------------------------------------------
- CPU実行
- --------------------------------------------------------*/
- INT32 Cz80_Exec(cz80_struc *CPU, INT32 cycles)
- {
- #if CZ80_USE_JUMPTABLE
- #include "cz80jmp.c"
- #endif
- FPTR PC;
- #if CZ80_ENCRYPTED_ROM
- FPTR OPBase;
- #endif
- UINT32 Opcode;
- UINT32 adr = 0;
- UINT32 res;
- UINT32 val;
- union16 *data;
- PC = CPU->PC;
- #if CZ80_ENCRYPTED_ROM
- OPBase = CPU->OPBase;
- #endif
- CPU->ICount = cycles - CPU->ExtraCycles;
- CPU->ExtraCycles = 0;
- Cz80_Exec:
- if (CPU->Status)
- {
- if (CPU->Status & CZ80_HAS_NMI)
- {
- zIFF1 = 0;
- CPU->Status &= ~(CZ80_HALTED | CZ80_HAS_NMI);
- CPU->ExtraCycles += 11;
- PUSH_16(zRealPC);
- SET_PC(0x66);
- } else if (CPU->Status & CZ80_HAS_INT)
- {
- CHECK_INT
- } else if (CPU->Status & CZ80_HALTED)
- {
- goto Cz80_Exec_End;
- }
- CPU->ICount -= CPU->ExtraCycles;
- CPU->ExtraCycles = 0;
- }
- if (CPU->ICount > 0)
- {
- Cz80_Exec_nocheck:
- data = pzHL;
- Opcode = READ_OP();
- #if CZ80_EMULATE_R_EXACTLY
- zR++;
- #endif
- #include "cz80_op.c"
- }
- Cz80_Exec_End:
- CPU->PC = PC;
- #if CZ80_ENCRYPTED_ROM
- CPU->OPBase = OPBase;
- #endif
- if (!((CPU->Status & CZ80_HALTED) && CPU->ICount > 0))
- cycles -= CPU->ICount;
- CPU->ICount = 0;
- #if !CZ80_EMULATE_R_EXACTLY
- zR = (zR + (cycles >> 2)) & 0x7f;
- #endif
- return cycles;
- }
- /*--------------------------------------------------------
- 割り込み処理
- --------------------------------------------------------*/
- void Cz80_Set_IRQ(cz80_struc *CPU, INT32 line, INT32 state)
- {
- if (line == IRQ_LINE_NMI)
- {
- if (state)
- CPU->Status |= CZ80_HAS_NMI;
- else
- CPU->Status &= ~CZ80_HAS_NMI;
- } else
- {
- CPU->IRQLine = line;
- CPU->IRQState = state;
- if (state)
- {
- if (zIFF1)
- CPU->Status |= CZ80_HAS_INT;
- } else
- {
- CPU->Status &= ~CZ80_HAS_INT;
- }
- }
- }
- /*--------------------------------------------------------
- レジスタ取得
- --------------------------------------------------------*/
- UINT32 Cz80_Get_Reg(cz80_struc *CPU, INT32 regnum)
- {
- switch (regnum)
- {
- case CZ80_PC: return (CPU->PC - CPU->BasePC);
- case CZ80_SP: return zSP;
- case CZ80_AF: return zAF;
- case CZ80_BC: return zBC;
- case CZ80_DE: return zDE;
- case CZ80_HL: return zHL;
- case CZ80_IX: return zIX;
- case CZ80_IY: return zIY;
- case CZ80_AF2: return zAF2;
- case CZ80_BC2: return zBC2;
- case CZ80_DE2: return zDE2;
- case CZ80_HL2: return zHL2;
- case CZ80_R: return zR;
- case CZ80_I: return zI;
- case CZ80_IM: return zIM;
- case CZ80_IFF1: return zIFF1;
- case CZ80_IFF2: return zIFF2;
- case CZ80_HALT: return CPU->Status & CZ80_HALTED;
- case CZ80_IRQ: return CPU->IRQState;
- default: return 0;
- }
- }
- /*--------------------------------------------------------
- レジスタ設定
- --------------------------------------------------------*/
- void Cz80_Set_Reg(cz80_struc *CPU, INT32 regnum, UINT32 val)
- {
- switch (regnum)
- {
- case CZ80_PC:
- CPU->BasePC = CPU->Fetch[val >> CZ80_FETCH_SFT];
- #if CZ80_ENCRYPTED_ROM
- CPU->OPBase = CPU->OPFetch[val >> CZ80_FETCH_SFT];
- #endif
- CPU->PC = val + CPU->BasePC;
- break;
- case CZ80_SP: zSP = val; break;
- case CZ80_AF: zAF = val; break;
- case CZ80_BC: zBC = val; break;
- case CZ80_DE: zDE = val; break;
- case CZ80_HL: zHL = val; break;
- case CZ80_IX: zIX = val; break;
- case CZ80_IY: zIY = val; break;
- case CZ80_AF2: zAF2 = val; break;
- case CZ80_BC2: zBC2 = val; break;
- case CZ80_DE2: zDE2 = val; break;
- case CZ80_HL2: zHL2 = val; break;
- case CZ80_R: zR = val; break;
- case CZ80_I: zI = val; break;
- case CZ80_IM: zIM = val; break;
- case CZ80_IFF1: zIFF1 = val ? (1 << 2) : 0; break;
- case CZ80_IFF2: zIFF2 = val ? (1 << 2) : 0; break;
- case CZ80_HALT: CPU->Status = !!val * CZ80_HALTED; break;
- case CZ80_IRQ: CPU->IRQState = val; break;
- default: break;
- }
- }
- /*--------------------------------------------------------
- フェッチアドレス設定
- --------------------------------------------------------*/
- void Cz80_Set_Fetch(cz80_struc *CPU, UINT32 low_adr, UINT32 high_adr, FPTR fetch_adr)
- {
- int i, j;
- i = low_adr >> CZ80_FETCH_SFT;
- j = high_adr >> CZ80_FETCH_SFT;
- fetch_adr -= i << CZ80_FETCH_SFT;
- while (i <= j)
- {
- CPU->Fetch[i] = fetch_adr;
- #if CZ80_ENCRYPTED_ROM
- CPU->OPFetch[i] = 0;
- #endif
- i++;
- }
- }
- /*--------------------------------------------------------
- フェッチアドレス設定 (暗号化ROM対応)
- --------------------------------------------------------*/
- #if CZ80_ENCRYPTED_ROM
- void Cz80_Set_Encrypt_Range(cz80_struc *CPU, UINT32 low_adr, UINT32 high_adr, UINT32 decrypted_rom)
- {
- int i, j;
- i = low_adr >> CZ80_FETCH_SFT;
- j = high_adr >> CZ80_FETCH_SFT;
- decrypted_rom -= i << CZ80_FETCH_SFT;
- while (i <= j)
- {
- CPU->OPFetch[i] = (INT32)decrypted_rom - (INT32)CPU->Fetch[i];
- i++;
- }
- }
- #endif
- /*--------------------------------------------------------
- メモリリード/ライト関数設定
- --------------------------------------------------------*/
- void Cz80_Set_ReadB(cz80_struc *CPU, UINT8 (*Func)(UINT32 address))
- {
- CPU->Read_Byte = Func;
- }
- void Cz80_Set_WriteB(cz80_struc *CPU, void (*Func)(UINT32 address, UINT8 data))
- {
- CPU->Write_Byte = Func;
- }
- /*--------------------------------------------------------
- ポートリード/ライト関数設定
- --------------------------------------------------------*/
- void Cz80_Set_INPort(cz80_struc *CPU, UINT8 (*Func)(UINT16 port))
- {
- CPU->IN_Port = Func;
- }
- void Cz80_Set_OUTPort(cz80_struc *CPU, void (*Func)(UINT16 port, UINT8 value))
- {
- CPU->OUT_Port = Func;
- }
- /*--------------------------------------------------------
- コールバック関数設定
- --------------------------------------------------------*/
- void Cz80_Set_IRQ_Callback(cz80_struc *CPU, INT32 (*Func)(INT32 irqline))
- {
- CPU->Interrupt_Callback = Func;
- }
|