/* * Copyright (C) 2017 FIX94 * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ #include #include #include #include "cpu.h" #include "apu.h" #include "ppu.h" #include "mem.h" #include "input.h" #define P_FLAG_C (1<<4) #define P_FLAG_H (1<<5) #define P_FLAG_N (1<<6) #define P_FLAG_Z (1<<7) //from main.c extern bool gbEmuGBSPlayback; extern uint16_t gbsLoadAddr; extern uint16_t gbsInitAddr; extern uint16_t gbsPlayAddr; extern uint16_t gbsSP; extern uint8_t cpuTimer; extern bool gbCgbMode; extern bool gbCgbBootrom; //initalized elsewhere uint8_t cpuAddSpeed = 1; bool cpuCgbSpeed = false; //used externally bool cpuDoStopSwitch; bool cpu_oam_dma; bool cpu_oam_dma_running; uint16_t cpu_oam_dma_addr; static uint16_t sp, pc, cpuTmp16; static uint8_t a,b,c,d,e,f,h,l,cpuTmp; //gbs stuff static bool gbsInitRet, gbsPlayRet; static uint8_t sub_in_val; static bool irqEnable; static bool cpuHaltLoop,cpuStopLoop,cpuHaltBug,cpuPrevInAny; static uint8_t curInstr; static bool cpu_oam_dma_started; static uint8_t cpu_oam_dma_pos; bool cpuDmaHalt; static void cpuSetupActionArr(); static const uint8_t *cpu_action_arr; static uint8_t cpu_arr_pos; static inline void cpuSetNopArr(); void cpuInit() { sub_in_val=0,cpuTmp=0,cpuTmp16=0; if(gbCgbBootrom) { //will get set up in Bootrom a=0,b=0,c=0,d=0,e=0,f=0,h=0,l=0; sp=0; pc=0; } else { if(gbCgbMode) //From GBC Bootrom a=0x11,b=0,c=0,d=0,e=0x08,f=0x80,h=0,l=0x7C; else //From GB Bootrom a=0x01,b=0,c=0x13,d=0,e=0xD8,f=0xB0,h=1,l=0x4D; sp = 0xFFFE; //Boot Stack Pointer pc = 0x0100; //hardcoded ROM entrypoint } irqEnable = false; cpuHaltLoop = false; cpuStopLoop = false; cpuHaltBug = false; cpuPrevInAny = false; cpuDoStopSwitch = false; cpu_oam_dma = false; cpu_oam_dma_running = false; cpu_oam_dma_addr = 0; cpuSetupActionArr(); //gbs stuff gbsInitRet = false; //for first init gbsPlayRet = true; //for first play call curInstr = 0; cpu_oam_dma_started = false; cpu_oam_dma_pos = 0; cpuDmaHalt = false; cpuSetNopArr(); } static inline void setAImmRegStats() { f &= ~(P_FLAG_C|P_FLAG_H|P_FLAG_N|P_FLAG_Z); if(a == 0) f |= P_FLAG_Z; } static inline void cpuAdd16(uint16_t x) { uint32_t r1,r2; r1=((h<<8)|l)+(x); r2=(((h<<8)|l)&0xFFF)+((x)&0xFFF); uint8_t tf = (uint8_t)(f&P_FLAG_Z); if(r1 > 0xFFFF) tf |= P_FLAG_C; if(r2 > 0x0FFF) tf |= P_FLAG_H; l = r1; h = r1 >> 8; f = tf; } static inline int16_t cpuAddSp16(uint8_t add) { int32_t n = (int8_t)add; uint32_t r1,r2,r3; r1=sp+n; r2=(sp&0xFF)+(n&0xFF); r3=(sp&0xF)+(n&0xF); uint8_t tf = 0; if(r2 > 0xFF) tf |= P_FLAG_C; if(r3 > 0x0F) tf |= P_FLAG_H; f = tf; return (uint16_t)r1; } static inline void setAddSubCmpFlags(uint16_t r1, uint16_t r2) { if(((uint8_t)r2)==0) f |= P_FLAG_Z; else f &= ~P_FLAG_Z; if(r2>0xFF) f |= P_FLAG_C; else f &= ~P_FLAG_C; if(r1>0xF) f |= P_FLAG_H; else f &= ~P_FLAG_H; } static inline uint8_t cpuDoAdd8(uint8_t x, uint8_t y) { uint16_t r1,r2; r1=(uint16_t)((x&0xF)+(y&0xF)); r2=(uint16_t)(x+y); setAddSubCmpFlags(r1, r2); f &= ~P_FLAG_N; return (uint8_t)r2; } static void cpuAdd8(uint8_t *reg) { a = cpuDoAdd8(a,*reg); } static inline uint8_t cpuDoSub8(uint8_t x, uint8_t y) { uint16_t r1,r2; r1=(uint16_t)((x&0xF)-(y&0xF)); r2=(uint16_t)(x-y); setAddSubCmpFlags(r1, r2); f |= P_FLAG_N; return (uint8_t)r2; } static void cpuSub8(uint8_t *reg) { a = cpuDoSub8(a,*reg); } static void cpuCmp8(uint8_t *reg) { cpuDoSub8(a,*reg); } static void cpuSbc8(uint8_t *reg) { uint16_t r1,r2; uint8_t x = *reg; r1=(uint16_t)((a&0xF)-((x)&0xF)-((f&P_FLAG_C)?1:0)); r2=(uint16_t)(a-(x)-((f&P_FLAG_C)?1:0)); a=(uint8_t)r2; setAddSubCmpFlags(r1, r2); f |= P_FLAG_N; } static void cpuAdc8(uint8_t *reg) { uint16_t r1,r2; uint8_t x = *reg; r1=(uint16_t)((a&0xF)+((x)&0xF)+((f&P_FLAG_C)?1:0)); r2=(uint16_t)(a+(x)+((f&P_FLAG_C)?1:0)); a=(uint8_t)r2; setAddSubCmpFlags(r1, r2); f &= ~P_FLAG_N; } static void cpuXOR(uint8_t *reg) { a ^= (*reg); setAImmRegStats(); } static void cpuOR(uint8_t *reg) { a |= (*reg); setAImmRegStats(); } static void cpuAND(uint8_t *reg) { a &= (*reg); setAImmRegStats(); f |= P_FLAG_H; } static void cpuCPL(uint8_t *reg) { uint8_t val = (*reg); f |= (P_FLAG_H|P_FLAG_N); *reg = ~val; } //rotate WITHOUT old carry used static void cpuRLC(uint8_t *reg) { uint8_t val = (*reg); f &= ~(P_FLAG_H|P_FLAG_N); if(val&0x80) f |= P_FLAG_C; else f &= ~P_FLAG_C; val <<= 1; if(f & P_FLAG_C) val |= 1; if(val == 0) f |= P_FLAG_Z; else f &= ~P_FLAG_Z; *reg = val; } //rotate WITHOUT old carry used static void cpuRRC(uint8_t *reg) { uint8_t val = (*reg); f &= ~(P_FLAG_H|P_FLAG_N); if(val&1) f |= P_FLAG_C; else f &= ~P_FLAG_C; val >>= 1; if(f & P_FLAG_C) val |= 0x80; if(val == 0) f |= P_FLAG_Z; else f &= ~P_FLAG_Z; *reg = val; } //rotate WITH old carry used static void cpuRL(uint8_t *reg) { uint8_t val = (*reg); uint8_t oldF = f; f &= ~(P_FLAG_H|P_FLAG_N); if(val&0x80) f |= P_FLAG_C; else f &= ~P_FLAG_C; val <<= 1; if(oldF & P_FLAG_C) val |= 1; if(val == 0) f |= P_FLAG_Z; else f &= ~P_FLAG_Z; *reg = val; } //rotate WITH old carry used static void cpuRR(uint8_t *reg) { uint8_t val = (*reg); uint8_t oldF = f; f &= ~(P_FLAG_H|P_FLAG_N); if(val&1) f |= P_FLAG_C; else f &= ~P_FLAG_C; val >>= 1; if(oldF & P_FLAG_C) val |= 0x80; if(val == 0) f |= P_FLAG_Z; else f &= ~P_FLAG_Z; *reg = val; } //Direct calls for a static void cpuRLCA() { cpuRLC(&a); f &= ~P_FLAG_Z; } static void cpuRRCA() { cpuRRC(&a); f &= ~P_FLAG_Z; } static void cpuRLA() { cpuRL(&a); f &= ~P_FLAG_Z; } static void cpuRRA() { cpuRR(&a); f &= ~P_FLAG_Z; } //shift left static void cpuSLA(uint8_t *reg) { uint8_t val = (*reg); f &= ~(P_FLAG_H|P_FLAG_N); if(val&0x80) f |= P_FLAG_C; else f &= ~P_FLAG_C; val <<= 1; if(val == 0) f |= P_FLAG_Z; else f &= ~P_FLAG_Z; *reg = val; } //shift right arithmetic static void cpuSRA(uint8_t *reg) { uint8_t val = (*reg); uint8_t oldSign = (val&0x80); f &= ~(P_FLAG_H|P_FLAG_N); if(val&1) f |= P_FLAG_C; else f &= ~P_FLAG_C; val >>= 1; val |= oldSign; if(val == 0) f |= P_FLAG_Z; else f &= ~P_FLAG_Z; *reg = val; } //shift right logical static void cpuSRL(uint8_t *reg) { uint8_t val = (*reg); f &= ~(P_FLAG_H|P_FLAG_N); if(val&1) f |= P_FLAG_C; else f &= ~P_FLAG_C; val >>= 1; if(val == 0) f |= P_FLAG_Z; else f &= ~P_FLAG_Z; *reg = val; } static void cpuSWAP(uint8_t *reg) { uint8_t val = (*reg); f &= ~(P_FLAG_H|P_FLAG_N|P_FLAG_C); uint8_t vL = val&0xF; val>>=4; val|=vL<<4; if(val == 0) f |= P_FLAG_Z; else f &= ~P_FLAG_Z; *reg = val; } static void cpuBIT(uint8_t *reg) { uint8_t val = (*reg); f &= ~P_FLAG_N; f |= P_FLAG_H; if((val&(1<>8; } static void cpuDeInc() { uint16_t tmp = e | d<<8; tmp++; e = tmp&0xFF; d = tmp>>8; } static void cpuHlInc() { uint16_t tmp = l | h<<8; tmp++; l = tmp&0xFF; h = tmp>>8; } static void cpuSpInc() { sp++; } static void cpuBcDec() { uint16_t tmp = c | b<<8; tmp--; c = tmp&0xFF; b = tmp>>8; } static void cpuDeDec() { uint16_t tmp = e | d<<8; tmp--; e = tmp&0xFF; d = tmp>>8; } static void cpuHlDec() { uint16_t tmp = l | h<<8; tmp--; l = tmp&0xFF; h = tmp>>8; } static void cpuSpDec() { sp--; } static void cpuNoAction(uint8_t *reg) { (void)reg; }; static void cpuLDa(uint8_t *reg) { a = (*reg); } static void cpuLDb(uint8_t *reg) { b = (*reg); } static void cpuLDc(uint8_t *reg) { c = (*reg); } static void cpuLDd(uint8_t *reg) { d = (*reg); } static void cpuLDe(uint8_t *reg) { e = (*reg); } static void cpuLDl(uint8_t *reg) { l = (*reg); } static void cpuLDh(uint8_t *reg) { h = (*reg); } static void cpuSTbc(uint8_t *reg) { memSet8(c | b<<8, (*reg)); } static void cpuSTde(uint8_t *reg) { memSet8(e | d<<8, (*reg)); } static void cpuSThl(uint8_t *reg) { memSet8(l | h<<8, (*reg)); } static void cpuSTt16(uint8_t *reg) { memSet8(cpuTmp16, (*reg)); } static void cpuSThlInc(uint8_t *reg) { cpuSThl(reg); cpuHlInc(); } static void cpuSThlDec(uint8_t *reg) { cpuSThl(reg); cpuHlDec(); } static void cpuInc(uint8_t *reg) { uint8_t tf = f&P_FLAG_C; *reg = cpuDoAdd8(*reg,1); f&=~P_FLAG_C; f|=tf; } static void cpuDec(uint8_t *reg) { uint8_t tf = f&P_FLAG_C; *reg = cpuDoSub8(*reg,1); f&=~P_FLAG_C; f|=tf; } static void cpuDAA(uint8_t *reg) { int16_t in = *reg; if (!(f & P_FLAG_N)) { if ((f & P_FLAG_H) || (in & 0xF) > 9) in += 0x06; if ((f & P_FLAG_C) || in > 0x9F) in += 0x60; } else { if (f & P_FLAG_H) in = (in - 6) & 0xFF; if (f & P_FLAG_C) in -= 0x60; } f &= ~(P_FLAG_H | P_FLAG_Z); if ((in & 0x100) == 0x100) f |= P_FLAG_C; in &= 0xFF; if (in == 0) f |= P_FLAG_Z; *reg = (uint8_t)in; } static void cpuSetStopLoop() { printf("CPU: Frozen until Button is pressed\n"); cpuStopLoop = true; } static void cpuSTOP(uint8_t *none) { (void)none; //printf("CPU called STOP instruction\n"); if(cpuDoStopSwitch) { cpuSetSpeed(!cpuCgbSpeed); cpuDoStopSwitch = false; } else cpuSetStopLoop(); //takes up 2 instructions? pc++; } enum { CPU_GET_INSTRUCTION = 0, CPU_GET_SUBINSTRUCTION, CPU_DELAY_CYCLE, CPU_ACTION_GET_INSTRUCTION, CPU_A_ACTION_GET_INSTRUCTION, CPU_B_ACTION_GET_INSTRUCTION, CPU_C_ACTION_GET_INSTRUCTION, CPU_D_ACTION_GET_INSTRUCTION, CPU_E_ACTION_GET_INSTRUCTION, CPU_H_ACTION_GET_INSTRUCTION, CPU_L_ACTION_GET_INSTRUCTION, CPU_ACTION_WRITE, CPU_A_ACTION_WRITE, CPU_B_ACTION_WRITE, CPU_C_ACTION_WRITE, CPU_D_ACTION_WRITE, CPU_E_ACTION_WRITE, CPU_H_ACTION_WRITE, CPU_L_ACTION_WRITE, CPU_BC_ACTION_ADD, CPU_DE_ACTION_ADD, CPU_HL_ACTION_ADD, CPU_SP_ACTION_ADD, CPU_HL_ADD_SPECIAL, CPU_SP_ADD_SPECIAL, CPU_ACTION_WRITE8_HL, CPU_TMP_ADD_PC, CPU_TMP_READ8_BC, CPU_TMP_READ8_DE, CPU_TMP_READ8_HL, CPU_TMP_READ8_HL_INC, CPU_TMP_READ8_HL_DEC, CPU_TMP_READ8_PC_INC, CPU_TMP_READ8_PC_INC_JRNZ_CHK, CPU_TMP_READ8_PC_INC_JRZ_CHK, CPU_TMP_READ8_PC_INC_JRNC_CHK, CPU_TMP_READ8_PC_INC_JRC_CHK, CPU_TMP_READ8_SP_INC, CPU_PCL_FROM_TMP_PCH_READ8_SP_INC, CPU_C_FROM_TMP_B_READ8_SP_INC, CPU_E_FROM_TMP_D_READ8_SP_INC, CPU_L_FROM_TMP_H_READ8_SP_INC, CPU_F_FROM_TMP_A_READ8_SP_INC, CPU_TMP_READHIGH_A, CPU_TMP_WRITEHIGH_A, CPU_C_READHIGH_A, CPU_C_WRITEHIGH_A, CPU_SP_FROM_HL, CPU_SP_WRITE8_A_DEC, CPU_SP_WRITE8_B_DEC, CPU_SP_WRITE8_C_DEC, CPU_SP_WRITE8_D_DEC, CPU_SP_WRITE8_E_DEC, CPU_SP_WRITE8_F_DEC, CPU_SP_WRITE8_H_DEC, CPU_SP_WRITE8_L_DEC, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_T16, CPU_SP_WRITE8_PCL_DEC_PC_FROM_00, CPU_SP_WRITE8_PCL_DEC_PC_FROM_08, CPU_SP_WRITE8_PCL_DEC_PC_FROM_10, CPU_SP_WRITE8_PCL_DEC_PC_FROM_18, CPU_SP_WRITE8_PCL_DEC_PC_FROM_20, CPU_SP_WRITE8_PCL_DEC_PC_FROM_28, CPU_SP_WRITE8_PCL_DEC_PC_FROM_30, CPU_SP_WRITE8_PCL_DEC_PC_FROM_38, CPU_SP_WRITE8_PCL_DEC_PC_FROM_40, CPU_SP_WRITE8_PCL_DEC_PC_FROM_48, CPU_SP_WRITE8_PCL_DEC_PC_FROM_50, CPU_SP_WRITE8_PCL_DEC_PC_FROM_58, CPU_SP_WRITE8_PCL_DEC_PC_FROM_60, CPU_A_READ8_TMP16, CPU_A_READ8_PC_INC, CPU_B_READ8_PC_INC, CPU_C_READ8_PC_INC, CPU_D_READ8_PC_INC, CPU_E_READ8_PC_INC, CPU_L_READ8_PC_INC, CPU_H_READ8_PC_INC, CPU_PCL_FROM_TMP_PCH_READ8_PC, CPU_SPL_FROM_TMP_SPH_READ8_PC_INC, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_CNZ_CHK, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_CNC_CHK, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_CZ_CHK, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_CC_CHK, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_JPNZ_CHK, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_JPNC_CHK, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_JPZ_CHK, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_JPC_CHK, CPU_TMP16_WRITE8_SPL_INC, CPU_TMP16_WRITE8_SPH, CPU_DI_GET_INSTRUCTION, CPU_EI_GET_INSTRUCTION, CPU_GET_INSTRUCTION_EI, CPU_SCF_GET_INSTRUCTION, CPU_CCF_GET_INSTRUCTION, CPU_PC_FROM_HL_GET_INSTRUCTION, CPU_PC_FROM_T16, CPU_RET_NZ_CHK, CPU_RET_NC_CHK, CPU_RET_Z_CHK, CPU_RET_C_CHK, }; /* arrays for multiple similar instructions */ static const uint8_t cpu_imm_arr[1] = { CPU_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_a_arr[1] = { CPU_A_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_b_arr[1] = { CPU_B_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_c_arr[1] = { CPU_C_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_d_arr[1] = { CPU_D_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_e_arr[1] = { CPU_E_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_h_arr[1] = { CPU_H_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_l_arr[1] = { CPU_L_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_bc_arr[2] = { CPU_TMP_READ8_BC, CPU_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_de_arr[2] = { CPU_TMP_READ8_DE, CPU_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_hl_arr[2] = { CPU_TMP_READ8_HL, CPU_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_pc_arr[2] = { CPU_TMP_READ8_PC_INC, CPU_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_hl_inc_arr[2] = { CPU_TMP_READ8_HL_INC, CPU_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_hl_dec_arr[2] = { CPU_TMP_READ8_HL_DEC, CPU_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_delay_arr[2] = { CPU_DELAY_CYCLE, CPU_ACTION_GET_INSTRUCTION }; static const uint8_t cpu_imm_hl_st_arr[3] = { CPU_TMP_READ8_HL, CPU_ACTION_WRITE8_HL, CPU_GET_INSTRUCTION }; /* arrays for single special instructions */ static const uint8_t cpu_nop_arr[1] = { CPU_GET_INSTRUCTION }; static const uint8_t cpu_sub_arr[1] = { CPU_GET_SUBINSTRUCTION }; static const uint8_t cpu_hljmp_arr[1] = { CPU_PC_FROM_HL_GET_INSTRUCTION }; static const uint8_t cpu_sp_from_hl_arr[2] = { CPU_SP_FROM_HL, CPU_GET_INSTRUCTION }; static const uint8_t cpu_absjmp_arr[4] = { CPU_TMP_READ8_PC_INC, CPU_PCL_FROM_TMP_PCH_READ8_PC, CPU_DELAY_CYCLE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_absjmpnz_arr[4] = { CPU_TMP_READ8_PC_INC, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_JPNZ_CHK, CPU_PC_FROM_T16, CPU_GET_INSTRUCTION }; static const uint8_t cpu_absjmpnc_arr[4] = { CPU_TMP_READ8_PC_INC, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_JPNC_CHK, CPU_PC_FROM_T16, CPU_GET_INSTRUCTION }; static const uint8_t cpu_absjmpz_arr[4] = { CPU_TMP_READ8_PC_INC, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_JPZ_CHK, CPU_PC_FROM_T16, CPU_GET_INSTRUCTION }; static const uint8_t cpu_absjmpc_arr[4] = { CPU_TMP_READ8_PC_INC, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_JPC_CHK, CPU_PC_FROM_T16, CPU_GET_INSTRUCTION }; static const uint8_t cpu_abscall_arr[6] = { CPU_TMP_READ8_PC_INC, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC, CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_T16, CPU_GET_INSTRUCTION }; static const uint8_t cpu_abscallnz_arr[6] = { CPU_TMP_READ8_PC_INC, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_CNZ_CHK, CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_T16, CPU_GET_INSTRUCTION }; static const uint8_t cpu_abscallnc_arr[6] = { CPU_TMP_READ8_PC_INC, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_CNC_CHK, CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_T16, CPU_GET_INSTRUCTION }; static const uint8_t cpu_abscallz_arr[6] = { CPU_TMP_READ8_PC_INC, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_CZ_CHK, CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_T16, CPU_GET_INSTRUCTION }; static const uint8_t cpu_abscallc_arr[6] = { CPU_TMP_READ8_PC_INC, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_CC_CHK, CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_T16, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ret_arr[4] = { CPU_TMP_READ8_SP_INC, CPU_PCL_FROM_TMP_PCH_READ8_SP_INC, CPU_DELAY_CYCLE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_reti_arr[4] = { CPU_TMP_READ8_SP_INC, CPU_PCL_FROM_TMP_PCH_READ8_SP_INC, CPU_DELAY_CYCLE, CPU_EI_GET_INSTRUCTION }; static const uint8_t cpu_retnz_arr[5] = { CPU_RET_NZ_CHK, CPU_TMP_READ8_SP_INC, CPU_PCL_FROM_TMP_PCH_READ8_SP_INC, CPU_DELAY_CYCLE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_retnc_arr[5] = { CPU_RET_NC_CHK, CPU_TMP_READ8_SP_INC, CPU_PCL_FROM_TMP_PCH_READ8_SP_INC, CPU_DELAY_CYCLE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_retz_arr[5] = { CPU_RET_Z_CHK, CPU_TMP_READ8_SP_INC, CPU_PCL_FROM_TMP_PCH_READ8_SP_INC, CPU_DELAY_CYCLE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_retc_arr[5] = { CPU_RET_C_CHK, CPU_TMP_READ8_SP_INC, CPU_PCL_FROM_TMP_PCH_READ8_SP_INC, CPU_DELAY_CYCLE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_rst00_arr[4] = { CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_00, CPU_GET_INSTRUCTION }; static const uint8_t cpu_rst08_arr[4] = { CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_08, CPU_GET_INSTRUCTION }; static const uint8_t cpu_rst10_arr[4] = { CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_10, CPU_GET_INSTRUCTION }; static const uint8_t cpu_rst18_arr[4] = { CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_18, CPU_GET_INSTRUCTION }; static const uint8_t cpu_rst20_arr[4] = { CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_20, CPU_GET_INSTRUCTION }; static const uint8_t cpu_rst28_arr[4] = { CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_28, CPU_GET_INSTRUCTION }; static const uint8_t cpu_rst30_arr[4] = { CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_30, CPU_GET_INSTRUCTION }; static const uint8_t cpu_rst38_arr[4] = { CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_38, CPU_GET_INSTRUCTION }; static const uint8_t cpu_rst40_arr[5] = { CPU_DELAY_CYCLE, CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_40, CPU_GET_INSTRUCTION }; static const uint8_t cpu_rst48_arr[5] = { CPU_DELAY_CYCLE, CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_48, CPU_GET_INSTRUCTION }; static const uint8_t cpu_rst50_arr[5] = { CPU_DELAY_CYCLE, CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_50, CPU_GET_INSTRUCTION }; static const uint8_t cpu_rst58_arr[5] = { CPU_DELAY_CYCLE, CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_58, CPU_GET_INSTRUCTION }; static const uint8_t cpu_rst60_arr[5] = { CPU_DELAY_CYCLE, CPU_DELAY_CYCLE, CPU_SP_WRITE8_PCH_DEC, CPU_SP_WRITE8_PCL_DEC_PC_FROM_60, CPU_GET_INSTRUCTION }; static const uint8_t cpu_push_bc_arr[4] = { CPU_DELAY_CYCLE, CPU_SP_WRITE8_B_DEC, CPU_SP_WRITE8_C_DEC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_push_de_arr[4] = { CPU_DELAY_CYCLE, CPU_SP_WRITE8_D_DEC, CPU_SP_WRITE8_E_DEC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_push_hl_arr[4] = { CPU_DELAY_CYCLE, CPU_SP_WRITE8_H_DEC, CPU_SP_WRITE8_L_DEC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_push_af_arr[4] = { CPU_DELAY_CYCLE, CPU_SP_WRITE8_A_DEC, CPU_SP_WRITE8_F_DEC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_pop_bc_arr[3] = { CPU_TMP_READ8_SP_INC, CPU_C_FROM_TMP_B_READ8_SP_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_pop_de_arr[3] = { CPU_TMP_READ8_SP_INC, CPU_E_FROM_TMP_D_READ8_SP_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_pop_hl_arr[3] = { CPU_TMP_READ8_SP_INC, CPU_L_FROM_TMP_H_READ8_SP_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_pop_af_arr[3] = { CPU_TMP_READ8_SP_INC, CPU_F_FROM_TMP_A_READ8_SP_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ld_a_arr[2] = { CPU_A_READ8_PC_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ld_b_arr[2] = { CPU_B_READ8_PC_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ld_c_arr[2] = { CPU_C_READ8_PC_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ld_d_arr[2] = { CPU_D_READ8_PC_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ld_e_arr[2] = { CPU_E_READ8_PC_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ld_h_arr[2] = { CPU_H_READ8_PC_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ld_l_arr[2] = { CPU_L_READ8_PC_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ldhc_a_arr[2] = { CPU_C_READHIGH_A, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ldh_a_arr[3] = { CPU_TMP_READ8_PC_INC, CPU_TMP_READHIGH_A, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ld_bc_arr[3] = { CPU_C_READ8_PC_INC, CPU_B_READ8_PC_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ld_de_arr[3] = { CPU_E_READ8_PC_INC, CPU_D_READ8_PC_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ld_hl_arr[3] = { CPU_L_READ8_PC_INC, CPU_H_READ8_PC_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ld_sp_arr[3] = { CPU_TMP_READ8_PC_INC, CPU_SPL_FROM_TMP_SPH_READ8_PC_INC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ld16_a_arr[4] = { CPU_TMP_READ8_PC_INC, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC, CPU_A_READ8_TMP16, CPU_GET_INSTRUCTION }; static const uint8_t cpu_st_a_arr[2] = { CPU_A_ACTION_WRITE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_st_b_arr[2] = { CPU_B_ACTION_WRITE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_st_c_arr[2] = { CPU_C_ACTION_WRITE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_st_d_arr[2] = { CPU_D_ACTION_WRITE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_st_e_arr[2] = { CPU_E_ACTION_WRITE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_st_h_arr[2] = { CPU_H_ACTION_WRITE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_st_l_arr[2] = { CPU_L_ACTION_WRITE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_st_imm_arr[3] = { CPU_TMP_READ8_PC_INC, CPU_ACTION_WRITE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_sthc_a_arr[2] = { CPU_C_WRITEHIGH_A, CPU_GET_INSTRUCTION }; static const uint8_t cpu_sth_a_arr[3] = { CPU_TMP_READ8_PC_INC, CPU_TMP_WRITEHIGH_A, CPU_GET_INSTRUCTION }; static const uint8_t cpu_st16_a_arr[4] = { CPU_TMP_READ8_PC_INC, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC, CPU_A_ACTION_WRITE, CPU_GET_INSTRUCTION }; static const uint8_t cpu_st16_sp_arr[5] = { CPU_TMP_READ8_PC_INC, CPU_T16L_FROM_TMP_T16H_READ8_PC_INC, CPU_TMP16_WRITE8_SPL_INC, CPU_TMP16_WRITE8_SPH, CPU_GET_INSTRUCTION }; static const uint8_t cpu_jr_arr[3] = { CPU_TMP_READ8_PC_INC, CPU_TMP_ADD_PC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_jrnz_arr[3] = { CPU_TMP_READ8_PC_INC_JRNZ_CHK, CPU_TMP_ADD_PC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_jrz_arr[3] = { CPU_TMP_READ8_PC_INC_JRZ_CHK, CPU_TMP_ADD_PC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_jrnc_arr[3] = { CPU_TMP_READ8_PC_INC_JRNC_CHK, CPU_TMP_ADD_PC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_jrc_arr[3] = { CPU_TMP_READ8_PC_INC_JRC_CHK, CPU_TMP_ADD_PC, CPU_GET_INSTRUCTION }; static const uint8_t cpu_di_arr[1] = { CPU_DI_GET_INSTRUCTION }; static const uint8_t cpu_ei_arr[1] = { CPU_GET_INSTRUCTION_EI }; static const uint8_t cpu_scf_arr[1] = { CPU_SCF_GET_INSTRUCTION }; static const uint8_t cpu_ccf_arr[1] = { CPU_CCF_GET_INSTRUCTION }; static const uint8_t cpu_add_bc_arr[2] = { CPU_BC_ACTION_ADD, CPU_GET_INSTRUCTION }; static const uint8_t cpu_add_de_arr[2] = { CPU_DE_ACTION_ADD, CPU_GET_INSTRUCTION }; static const uint8_t cpu_add_hl_arr[2] = { CPU_HL_ACTION_ADD, CPU_GET_INSTRUCTION }; static const uint8_t cpu_add_sp_arr[2] = { CPU_SP_ACTION_ADD, CPU_GET_INSTRUCTION }; static const uint8_t cpu_ld_hl_add_sp_imm_arr[3] = { CPU_TMP_READ8_PC_INC, CPU_HL_ADD_SPECIAL, CPU_GET_INSTRUCTION }; static const uint8_t cpu_add_sp_imm_arr[4] = { CPU_TMP_READ8_PC_INC, CPU_SP_ADD_SPECIAL, CPU_DELAY_CYCLE, CPU_GET_INSTRUCTION }; static inline void cpuSetNopArr() { cpu_action_arr = cpu_nop_arr; cpu_arr_pos = 0; } static const uint8_t *cpu_instr_arr[256] = { cpu_nop_arr, cpu_ld_bc_arr, cpu_st_a_arr, cpu_imm_delay_arr, //0x00-0x03 cpu_imm_b_arr, cpu_imm_b_arr, cpu_ld_b_arr, cpu_imm_a_arr, //0x04-0x07 cpu_st16_sp_arr, cpu_add_bc_arr, cpu_imm_bc_arr, cpu_imm_delay_arr, //0x08-0x0B cpu_imm_c_arr, cpu_imm_c_arr, cpu_ld_c_arr, cpu_imm_a_arr, //0x0C-0x0F cpu_imm_arr, cpu_ld_de_arr, cpu_st_a_arr, cpu_imm_delay_arr, //0x10-0x13 cpu_imm_d_arr, cpu_imm_d_arr, cpu_ld_d_arr, cpu_imm_a_arr, //0x14-0x17 cpu_jr_arr, cpu_add_de_arr, cpu_imm_de_arr, cpu_imm_delay_arr, //0x18-0x1B cpu_imm_e_arr, cpu_imm_e_arr, cpu_ld_e_arr, cpu_imm_a_arr, //0x1C-0x1F cpu_jrnz_arr, cpu_ld_hl_arr, cpu_st_a_arr, cpu_imm_delay_arr, //0x20-0x23 cpu_imm_h_arr, cpu_imm_h_arr, cpu_ld_h_arr, cpu_imm_a_arr, //0x24-0x27 cpu_jrz_arr, cpu_add_hl_arr, cpu_imm_hl_inc_arr, cpu_imm_delay_arr, //0x28-0x2B cpu_imm_l_arr, cpu_imm_l_arr, cpu_ld_l_arr, cpu_imm_a_arr, //0x2C-0x2F cpu_jrnc_arr, cpu_ld_sp_arr, cpu_st_a_arr, cpu_imm_delay_arr, //0x30-0x33 cpu_imm_hl_st_arr, cpu_imm_hl_st_arr, cpu_st_imm_arr, cpu_scf_arr, //0x34-0x37 cpu_jrc_arr, cpu_add_sp_arr, cpu_imm_hl_dec_arr, cpu_imm_delay_arr, //0x38-0x3B cpu_imm_a_arr, cpu_imm_a_arr, cpu_ld_a_arr, cpu_ccf_arr, //0x3C-0x3F cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0x40-0x43 cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0x44-0x47 cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0x48-0x4B cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0x4C-0x4F cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0x50-0x53 cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0x54-0x57 cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0x58-0x5B cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0x5C-0x5F cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0x60-0x63 cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0x64-0x67 cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0x68-0x6B cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0x6C-0x6F cpu_st_b_arr, cpu_st_c_arr, cpu_st_d_arr, cpu_st_e_arr, //0x70-0x73 cpu_st_h_arr, cpu_st_l_arr, cpu_imm_arr, cpu_st_a_arr, //0x74-0x77 cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0x78-0x7B cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0x7C-0x7F cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0x80-0x83 cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0x84-0x87 cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0x88-0x8B cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0x8C-0x8F cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0x90-0x93 cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0x94-0x97 cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0x98-0x9B cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0x9C-0x9F cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0xA0-0xA3 cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0xA4-0xA7 cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0xA8-0xAB cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0xAC-0xAF cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0xB0-0xB3 cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0xB4-0xB7 cpu_imm_b_arr, cpu_imm_c_arr, cpu_imm_d_arr, cpu_imm_e_arr, //0xB8-0xBB cpu_imm_h_arr, cpu_imm_l_arr, cpu_imm_hl_arr, cpu_imm_a_arr, //0xBC-0xBF cpu_retnz_arr, cpu_pop_bc_arr, cpu_absjmpnz_arr, cpu_absjmp_arr, //0xC0-0xC3 cpu_abscallnz_arr, cpu_push_bc_arr, cpu_imm_pc_arr, cpu_rst00_arr, //0xC4-0xC7 cpu_retz_arr, cpu_ret_arr, cpu_absjmpz_arr, cpu_sub_arr, //0xC8-0xCB cpu_abscallz_arr, cpu_abscall_arr, cpu_imm_pc_arr, cpu_rst08_arr, //0xCC-0xCF cpu_retnc_arr, cpu_pop_de_arr, cpu_absjmpnc_arr, NULL, //0xD0-0xD3 (0xD3=Invalid) cpu_abscallnc_arr, cpu_push_de_arr, cpu_imm_pc_arr, cpu_rst10_arr, //0xD4-0xD7 cpu_retc_arr, cpu_reti_arr, cpu_absjmpc_arr, NULL, //0xD8-0xDB (0xDB=Invalid) cpu_abscallc_arr, NULL, cpu_imm_pc_arr, cpu_rst18_arr, //0xDC-0xDF (0xDD=Invalid) cpu_sth_a_arr, cpu_pop_hl_arr, cpu_sthc_a_arr, NULL, //0xE0-0xE3 (0xE3=Invalid) NULL, cpu_push_hl_arr, cpu_imm_pc_arr, cpu_rst20_arr, //0xE4-0xE7 (0xE4=Invalid) cpu_add_sp_imm_arr, cpu_hljmp_arr, cpu_st16_a_arr, NULL, //0xE8-0xEB (0xEB=Invalid) NULL, NULL, cpu_imm_pc_arr, cpu_rst28_arr, //0xEC-0xEF (0xEC=Invalid, 0xED=Invalid) cpu_ldh_a_arr, cpu_pop_af_arr, cpu_ldhc_a_arr, cpu_di_arr, //0xF0-0xF3 NULL, cpu_push_af_arr, cpu_imm_pc_arr, cpu_rst30_arr, //0xF4-0xF7 (0xF4=Invalid) cpu_ld_hl_add_sp_imm_arr, cpu_sp_from_hl_arr, cpu_ld16_a_arr, cpu_ei_arr, //0xF8-0xFB NULL, NULL, cpu_imm_pc_arr, cpu_rst38_arr, //0xFC-0xFF (0xFC=Invalid, 0xFD=Invalid) }; typedef void (*cpu_action_t)(uint8_t*); static cpu_action_t cpu_actions_arr[256]; static cpu_action_t cpu_action_func; static void cpuSetupActionArr() { cpu_actions_arr[0x00] = cpuNoAction; cpu_actions_arr[0x01] = cpuNoAction; cpu_actions_arr[0x02] = cpuSTbc; cpu_actions_arr[0x03] = cpuBcInc; cpu_actions_arr[0x04] = cpuInc; cpu_actions_arr[0x05] = cpuDec; cpu_actions_arr[0x06] = cpuNoAction; cpu_actions_arr[0x07] = cpuRLCA; cpu_actions_arr[0x08] = cpuNoAction; cpu_actions_arr[0x09] = cpuNoAction; cpu_actions_arr[0x0A] = cpuLDa; cpu_actions_arr[0x0B] = cpuBcDec; cpu_actions_arr[0x0C] = cpuInc; cpu_actions_arr[0x0D] = cpuDec; cpu_actions_arr[0x0E] = cpuNoAction; cpu_actions_arr[0x0F] = cpuRRCA; cpu_actions_arr[0x10] = cpuSTOP; cpu_actions_arr[0x11] = cpuNoAction; cpu_actions_arr[0x12] = cpuSTde; cpu_actions_arr[0x13] = cpuDeInc; cpu_actions_arr[0x14] = cpuInc; cpu_actions_arr[0x15] = cpuDec; cpu_actions_arr[0x16] = cpuNoAction; cpu_actions_arr[0x17] = cpuRLA; cpu_actions_arr[0x18] = cpuNoAction; cpu_actions_arr[0x19] = cpuNoAction; cpu_actions_arr[0x1A] = cpuLDa; cpu_actions_arr[0x1B] = cpuDeDec; cpu_actions_arr[0x1C] = cpuInc; cpu_actions_arr[0x1D] = cpuDec; cpu_actions_arr[0x1E] = cpuNoAction; cpu_actions_arr[0x1F] = cpuRRA; cpu_actions_arr[0x20] = cpuNoAction; cpu_actions_arr[0x21] = cpuNoAction; cpu_actions_arr[0x22] = cpuSThlInc; cpu_actions_arr[0x23] = cpuHlInc; cpu_actions_arr[0x24] = cpuInc; cpu_actions_arr[0x25] = cpuDec; cpu_actions_arr[0x26] = cpuNoAction; cpu_actions_arr[0x27] = cpuDAA; cpu_actions_arr[0x28] = cpuNoAction; cpu_actions_arr[0x29] = cpuNoAction; cpu_actions_arr[0x2A] = cpuLDa; cpu_actions_arr[0x2B] = cpuHlDec; cpu_actions_arr[0x2C] = cpuInc; cpu_actions_arr[0x2D] = cpuDec; cpu_actions_arr[0x2E] = cpuNoAction; cpu_actions_arr[0x2F] = cpuCPL; cpu_actions_arr[0x30] = cpuNoAction; cpu_actions_arr[0x31] = cpuNoAction; cpu_actions_arr[0x32] = cpuSThlDec; cpu_actions_arr[0x33] = cpuSpInc; cpu_actions_arr[0x34] = cpuInc; cpu_actions_arr[0x35] = cpuDec; cpu_actions_arr[0x36] = cpuSThl; cpu_actions_arr[0x37] = cpuNoAction; cpu_actions_arr[0x38] = cpuNoAction; cpu_actions_arr[0x39] = cpuNoAction; cpu_actions_arr[0x3A] = cpuLDa; cpu_actions_arr[0x3B] = cpuSpDec; cpu_actions_arr[0x3C] = cpuInc; cpu_actions_arr[0x3D] = cpuDec; cpu_actions_arr[0x3E] = cpuNoAction; cpu_actions_arr[0x3F] = cpuNoAction; cpu_actions_arr[0x40] = cpuLDb; cpu_actions_arr[0x41] = cpuLDb; cpu_actions_arr[0x42] = cpuLDb; cpu_actions_arr[0x43] = cpuLDb; cpu_actions_arr[0x44] = cpuLDb; cpu_actions_arr[0x45] = cpuLDb; cpu_actions_arr[0x46] = cpuLDb; cpu_actions_arr[0x47] = cpuLDb; cpu_actions_arr[0x48] = cpuLDc; cpu_actions_arr[0x49] = cpuLDc; cpu_actions_arr[0x4A] = cpuLDc; cpu_actions_arr[0x4B] = cpuLDc; cpu_actions_arr[0x4C] = cpuLDc; cpu_actions_arr[0x4D] = cpuLDc; cpu_actions_arr[0x4E] = cpuLDc; cpu_actions_arr[0x4F] = cpuLDc; cpu_actions_arr[0x50] = cpuLDd; cpu_actions_arr[0x51] = cpuLDd; cpu_actions_arr[0x52] = cpuLDd; cpu_actions_arr[0x53] = cpuLDd; cpu_actions_arr[0x54] = cpuLDd; cpu_actions_arr[0x55] = cpuLDd; cpu_actions_arr[0x56] = cpuLDd; cpu_actions_arr[0x57] = cpuLDd; cpu_actions_arr[0x58] = cpuLDe; cpu_actions_arr[0x59] = cpuLDe; cpu_actions_arr[0x5A] = cpuLDe; cpu_actions_arr[0x5B] = cpuLDe; cpu_actions_arr[0x5C] = cpuLDe; cpu_actions_arr[0x5D] = cpuLDe; cpu_actions_arr[0x5E] = cpuLDe; cpu_actions_arr[0x5F] = cpuLDe; cpu_actions_arr[0x60] = cpuLDh; cpu_actions_arr[0x61] = cpuLDh; cpu_actions_arr[0x62] = cpuLDh; cpu_actions_arr[0x63] = cpuLDh; cpu_actions_arr[0x64] = cpuLDh; cpu_actions_arr[0x65] = cpuLDh; cpu_actions_arr[0x66] = cpuLDh; cpu_actions_arr[0x67] = cpuLDh; cpu_actions_arr[0x68] = cpuLDl; cpu_actions_arr[0x69] = cpuLDl; cpu_actions_arr[0x6A] = cpuLDl; cpu_actions_arr[0x6B] = cpuLDl; cpu_actions_arr[0x6C] = cpuLDl; cpu_actions_arr[0x6D] = cpuLDl; cpu_actions_arr[0x6E] = cpuLDl; cpu_actions_arr[0x6F] = cpuLDl; cpu_actions_arr[0x70] = cpuSThl; cpu_actions_arr[0x71] = cpuSThl; cpu_actions_arr[0x72] = cpuSThl; cpu_actions_arr[0x73] = cpuSThl; cpu_actions_arr[0x74] = cpuSThl; cpu_actions_arr[0x75] = cpuSThl; cpu_actions_arr[0x76] = cpuHALT; cpu_actions_arr[0x77] = cpuSThl; cpu_actions_arr[0x78] = cpuLDa; cpu_actions_arr[0x79] = cpuLDa; cpu_actions_arr[0x7A] = cpuLDa; cpu_actions_arr[0x7B] = cpuLDa; cpu_actions_arr[0x7C] = cpuLDa; cpu_actions_arr[0x7D] = cpuLDa; cpu_actions_arr[0x7E] = cpuLDa; cpu_actions_arr[0x7F] = cpuLDa; cpu_actions_arr[0x80] = cpuAdd8; cpu_actions_arr[0x81] = cpuAdd8; cpu_actions_arr[0x82] = cpuAdd8; cpu_actions_arr[0x83] = cpuAdd8; cpu_actions_arr[0x84] = cpuAdd8; cpu_actions_arr[0x85] = cpuAdd8; cpu_actions_arr[0x86] = cpuAdd8; cpu_actions_arr[0x87] = cpuAdd8; cpu_actions_arr[0x88] = cpuAdc8; cpu_actions_arr[0x89] = cpuAdc8; cpu_actions_arr[0x8A] = cpuAdc8; cpu_actions_arr[0x8B] = cpuAdc8; cpu_actions_arr[0x8C] = cpuAdc8; cpu_actions_arr[0x8D] = cpuAdc8; cpu_actions_arr[0x8E] = cpuAdc8; cpu_actions_arr[0x8F] = cpuAdc8; cpu_actions_arr[0x90] = cpuSub8; cpu_actions_arr[0x91] = cpuSub8; cpu_actions_arr[0x92] = cpuSub8; cpu_actions_arr[0x93] = cpuSub8; cpu_actions_arr[0x94] = cpuSub8; cpu_actions_arr[0x95] = cpuSub8; cpu_actions_arr[0x96] = cpuSub8; cpu_actions_arr[0x97] = cpuSub8; cpu_actions_arr[0x98] = cpuSbc8; cpu_actions_arr[0x99] = cpuSbc8; cpu_actions_arr[0x9A] = cpuSbc8; cpu_actions_arr[0x9B] = cpuSbc8; cpu_actions_arr[0x9C] = cpuSbc8; cpu_actions_arr[0x9D] = cpuSbc8; cpu_actions_arr[0x9E] = cpuSbc8; cpu_actions_arr[0x9F] = cpuSbc8; cpu_actions_arr[0xA0] = cpuAND; cpu_actions_arr[0xA1] = cpuAND; cpu_actions_arr[0xA2] = cpuAND; cpu_actions_arr[0xA3] = cpuAND; cpu_actions_arr[0xA4] = cpuAND; cpu_actions_arr[0xA5] = cpuAND; cpu_actions_arr[0xA6] = cpuAND; cpu_actions_arr[0xA7] = cpuAND; cpu_actions_arr[0xA8] = cpuXOR; cpu_actions_arr[0xA9] = cpuXOR; cpu_actions_arr[0xAA] = cpuXOR; cpu_actions_arr[0xAB] = cpuXOR; cpu_actions_arr[0xAC] = cpuXOR; cpu_actions_arr[0xAD] = cpuXOR; cpu_actions_arr[0xAE] = cpuXOR; cpu_actions_arr[0xAF] = cpuXOR; cpu_actions_arr[0xB0] = cpuOR; cpu_actions_arr[0xB1] = cpuOR; cpu_actions_arr[0xB2] = cpuOR; cpu_actions_arr[0xB3] = cpuOR; cpu_actions_arr[0xB4] = cpuOR; cpu_actions_arr[0xB5] = cpuOR; cpu_actions_arr[0xB6] = cpuOR; cpu_actions_arr[0xB7] = cpuOR; cpu_actions_arr[0xB8] = cpuCmp8; cpu_actions_arr[0xB9] = cpuCmp8; cpu_actions_arr[0xBA] = cpuCmp8; cpu_actions_arr[0xBB] = cpuCmp8; cpu_actions_arr[0xBC] = cpuCmp8; cpu_actions_arr[0xBD] = cpuCmp8; cpu_actions_arr[0xBE] = cpuCmp8; cpu_actions_arr[0xBF] = cpuCmp8; cpu_actions_arr[0xC0] = cpuNoAction; cpu_actions_arr[0xC1] = cpuNoAction; cpu_actions_arr[0xC2] = cpuNoAction; cpu_actions_arr[0xC3] = cpuNoAction; cpu_actions_arr[0xC4] = cpuNoAction; cpu_actions_arr[0xC5] = cpuNoAction; cpu_actions_arr[0xC6] = cpuAdd8; cpu_actions_arr[0xC7] = cpuNoAction; cpu_actions_arr[0xC8] = cpuNoAction; cpu_actions_arr[0xC9] = cpuNoAction; cpu_actions_arr[0xCA] = cpuNoAction; cpu_actions_arr[0xCB] = cpuNoAction; cpu_actions_arr[0xCC] = cpuNoAction; cpu_actions_arr[0xCD] = cpuNoAction; cpu_actions_arr[0xCE] = cpuAdc8; cpu_actions_arr[0xCF] = cpuNoAction; cpu_actions_arr[0xD0] = cpuNoAction; cpu_actions_arr[0xD1] = cpuNoAction; cpu_actions_arr[0xD2] = cpuNoAction; cpu_actions_arr[0xD3] = cpuNoAction; cpu_actions_arr[0xD4] = cpuNoAction; cpu_actions_arr[0xD5] = cpuNoAction; cpu_actions_arr[0xD6] = cpuSub8; cpu_actions_arr[0xD7] = cpuNoAction; cpu_actions_arr[0xD8] = cpuNoAction; cpu_actions_arr[0xD9] = cpuNoAction; cpu_actions_arr[0xDA] = cpuNoAction; cpu_actions_arr[0xDB] = cpuNoAction; cpu_actions_arr[0xDC] = cpuNoAction; cpu_actions_arr[0xDD] = cpuNoAction; cpu_actions_arr[0xDE] = cpuSbc8; cpu_actions_arr[0xDF] = cpuNoAction; cpu_actions_arr[0xE0] = cpuNoAction; cpu_actions_arr[0xE1] = cpuNoAction; cpu_actions_arr[0xE2] = cpuNoAction; cpu_actions_arr[0xE3] = cpuNoAction; cpu_actions_arr[0xE4] = cpuNoAction; cpu_actions_arr[0xE5] = cpuNoAction; cpu_actions_arr[0xE6] = cpuAND; cpu_actions_arr[0xE7] = cpuNoAction; cpu_actions_arr[0xE8] = cpuNoAction; cpu_actions_arr[0xE9] = cpuNoAction; cpu_actions_arr[0xEA] = cpuSTt16; cpu_actions_arr[0xEB] = cpuNoAction; cpu_actions_arr[0xEC] = cpuNoAction; cpu_actions_arr[0xED] = cpuNoAction; cpu_actions_arr[0xEE] = cpuXOR; cpu_actions_arr[0xEF] = cpuNoAction; cpu_actions_arr[0xF0] = cpuNoAction; cpu_actions_arr[0xF1] = cpuNoAction; cpu_actions_arr[0xF2] = cpuNoAction; cpu_actions_arr[0xF3] = cpuNoAction; cpu_actions_arr[0xF4] = cpuNoAction; cpu_actions_arr[0xF5] = cpuNoAction; cpu_actions_arr[0xF6] = cpuOR; cpu_actions_arr[0xF7] = cpuNoAction; cpu_actions_arr[0xF8] = cpuNoAction; cpu_actions_arr[0xF9] = cpuNoAction; cpu_actions_arr[0xFA] = cpuNoAction; cpu_actions_arr[0xFB] = cpuNoAction; cpu_actions_arr[0xFC] = cpuNoAction; cpu_actions_arr[0xFD] = cpuNoAction; cpu_actions_arr[0xFE] = cpuCmp8; cpu_actions_arr[0xFF] = cpuNoAction; cpu_action_func = cpuNoAction; } bool cpuHandleIrqUpdates() { if(gbEmuGBSPlayback) return false; if(!irqEnable) return false; uint8_t irqList = (memGetCurIrqList()); if(irqList & 1) { memClearCurIrqList(1); //printf("Beep Bop Interrupt 40 and jmp from %04x\n", pc); cpu_action_arr = cpu_rst40_arr; irqEnable = false; return true; } else if(irqList & 2) { memClearCurIrqList(2); //printf("Beep Bop Interrupt 48 and jmp from %04x\n", pc); cpu_action_arr = cpu_rst48_arr; irqEnable = false; return true; } else if(irqList & 4) { memClearCurIrqList(4); //printf("Beep Bop Interrupt 50 and jmp from %04x\n", pc); cpu_action_arr = cpu_rst50_arr; irqEnable = false; return true; } else if(irqList & 8) { memClearCurIrqList(8); //printf("Beep Bop Interrupt 58 and jmp from %04x\n", pc); cpu_action_arr = cpu_rst58_arr; irqEnable = false; return true; } else if(irqList & 0x10) { memClearCurIrqList(0x10); //printf("Beep Bop Interrupt 60 and jmp from %04x\n", pc); cpu_action_arr = cpu_rst60_arr; irqEnable = false; return true; } return false; } void cpuGetInstruction() { if(cpuHandleIrqUpdates()) { cpuHaltLoop = false; cpu_arr_pos = 0; return; } if(gbEmuGBSPlayback) { //init return if(pc == 0x8764) { //if(!gbsInitRet) // printf("Init return\n"); gbsInitRet = true; //allow play call cpuSetNopArr(); return; } //play return else if(pc == 0x8765) { //if(!gbsPlayRet) // printf("Play return\n"); gbsPlayRet = true; //allow next play call cpuSetNopArr(); return; } } if(cpuHaltLoop) { cpuSetNopArr(); //happens when IME=0 if(!irqEnable && memGetCurIrqList()) cpuHaltLoop = false; else //keep waiting return; } if(cpuStopLoop) { bool cpuInAny = inputAny(); if(cpuInAny && !cpuPrevInAny) cpuStopLoop = false; cpuPrevInAny = cpuInAny; cpuSetNopArr(); return; } curInstr = memGet8(pc); cpu_action_arr = cpu_instr_arr[curInstr]; cpu_arr_pos = 0; if(cpu_action_arr == NULL) { printf("CPU Error: Unsupported Instruction at %04x:%02x!\n", pc-1,curInstr); cpuSetNopArr(); cpuSetStopLoop(); } cpu_action_func = cpu_actions_arr[curInstr]; //if(pc==0xABC || pc == 0xAC1 || pc == 0x5E0E || pc == 0x5E0F) // printf("%04x %02x a %02x b %02x hl %04x\n", pc, curInstr, a, b, (l|(h<<8))); //HALT bug: PC doesnt increase after instruction is parsed! if(!cpuHaltBug) pc++; cpuHaltBug = false; } static void cpuHandleOAMDMA() { if(cpu_oam_dma) { if(!cpu_oam_dma_started) cpu_oam_dma_started = true; else { cpu_oam_dma = false; cpu_oam_dma_started = false; cpu_oam_dma_running = true; cpu_oam_dma_pos = 0; } } if(cpu_oam_dma_running) { if(cpu_oam_dma_pos == 0xA0) cpu_oam_dma_running = false; else { //printf("OAM Copying %02x\n", cpu_oam_dma_pos); ppuSetOAMDMAVal(cpu_oam_dma_pos,memGet8(cpu_oam_dma_addr+cpu_oam_dma_pos)); cpu_oam_dma_pos++; } } } /* Main CPU Interpreter */ void cpuCycle() { if(cpuDmaHalt) return; cpuHandleOAMDMA(); uint8_t cpu_action, sub_instr; cpu_action = cpu_action_arr[cpu_arr_pos]; cpu_arr_pos++; switch(cpu_action) { case CPU_GET_INSTRUCTION: cpuGetInstruction(); break; case CPU_GET_SUBINSTRUCTION: sub_instr = memGet8(pc++); //set sub array switch(sub_instr&7) { case 0: cpu_action_arr = cpu_imm_b_arr; break; case 1: cpu_action_arr = cpu_imm_c_arr; break; case 2: cpu_action_arr = cpu_imm_d_arr; break; case 3: cpu_action_arr = cpu_imm_e_arr; break; case 4: cpu_action_arr = cpu_imm_h_arr; break; case 5: cpu_action_arr = cpu_imm_l_arr; break; case 6: if((sub_instr&0xC0) == 0x40) //BIT only reads cpu_action_arr = cpu_imm_hl_arr; else //all other CB instructions do I/O cpu_action_arr = cpu_imm_hl_st_arr; break; case 7: cpu_action_arr = cpu_imm_a_arr; break; default: //should never happen printf("CPU Error: Unknown sub %02x\n", sub_instr); cpuSetNopArr(); cpuSetStopLoop(); break; } //set sub func switch(sub_instr>>3) { case 0: cpu_action_func = cpuRLC; break; case 1: cpu_action_func = cpuRRC; break; case 2: cpu_action_func = cpuRL; break; case 3: cpu_action_func = cpuRR; break; case 4: cpu_action_func = cpuSLA; break; case 5: cpu_action_func = cpuSRA; break; case 6: cpu_action_func = cpuSWAP; break; case 7: cpu_action_func = cpuSRL; break; case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: sub_in_val = ((sub_instr&0x3F)>>3)&7; cpu_action_func = cpuBIT; break; case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: sub_in_val = ((sub_instr&0x3F)>>3)&7; cpu_action_func = cpuRES; break; default: sub_in_val = ((sub_instr&0x3F)>>3)&7; cpu_action_func = cpuSET; break; } cpu_arr_pos = 0; break; case CPU_DELAY_CYCLE: break; case CPU_ACTION_GET_INSTRUCTION: cpu_action_func(&cpuTmp); cpuGetInstruction(); break; case CPU_A_ACTION_GET_INSTRUCTION: cpu_action_func(&a); cpuGetInstruction(); break; case CPU_B_ACTION_GET_INSTRUCTION: cpu_action_func(&b); cpuGetInstruction(); break; case CPU_C_ACTION_GET_INSTRUCTION: cpu_action_func(&c); cpuGetInstruction(); break; case CPU_D_ACTION_GET_INSTRUCTION: cpu_action_func(&d); cpuGetInstruction(); break; case CPU_E_ACTION_GET_INSTRUCTION: cpu_action_func(&e); cpuGetInstruction(); break; case CPU_H_ACTION_GET_INSTRUCTION: cpu_action_func(&h); cpuGetInstruction(); break; case CPU_L_ACTION_GET_INSTRUCTION: cpu_action_func(&l); cpuGetInstruction(); break; case CPU_ACTION_WRITE: cpu_action_func(&cpuTmp); break; case CPU_A_ACTION_WRITE: cpu_action_func(&a); break; case CPU_B_ACTION_WRITE: cpu_action_func(&b); break; case CPU_C_ACTION_WRITE: cpu_action_func(&c); break; case CPU_D_ACTION_WRITE: cpu_action_func(&d); break; case CPU_E_ACTION_WRITE: cpu_action_func(&e); break; case CPU_H_ACTION_WRITE: cpu_action_func(&h); break; case CPU_L_ACTION_WRITE: cpu_action_func(&l); break; case CPU_BC_ACTION_ADD: cpuAdd16(c|b<<8); break; case CPU_DE_ACTION_ADD: cpuAdd16(e|d<<8); break; case CPU_HL_ACTION_ADD: cpuAdd16(l|h<<8); break; case CPU_SP_ACTION_ADD: cpuAdd16(sp); break; case CPU_HL_ADD_SPECIAL: cpuTmp16 = cpuAddSp16(cpuTmp); h = cpuTmp16>>8; l = cpuTmp16&0xFF; break; case CPU_SP_ADD_SPECIAL: sp = cpuAddSp16(cpuTmp); break; case CPU_ACTION_WRITE8_HL: cpu_action_func(&cpuTmp); memSet8(l | h<<8, cpuTmp); break; case CPU_TMP_ADD_PC: pc += (int8_t)cpuTmp; break; case CPU_TMP_READ8_BC: cpuTmp = memGet8(c | b<<8); break; case CPU_TMP_READ8_DE: cpuTmp = memGet8(e | d<<8); break; case CPU_TMP_READ8_HL: cpuTmp = memGet8(l | h<<8); break; case CPU_TMP_READ8_HL_INC: cpuTmp = memGet8(l | h<<8); cpuHlInc(); break; case CPU_TMP_READ8_HL_DEC: cpuTmp = memGet8(l | h<<8); cpuHlDec(); break; case CPU_TMP_READ8_PC_INC: cpuTmp = memGet8(pc++); break; case CPU_TMP_READ8_PC_INC_JRNZ_CHK: cpuTmp = memGet8(pc++); if(f & P_FLAG_Z) cpu_arr_pos++; break; case CPU_TMP_READ8_PC_INC_JRZ_CHK: cpuTmp = memGet8(pc++); if(!(f & P_FLAG_Z)) cpu_arr_pos++; break; case CPU_TMP_READ8_PC_INC_JRNC_CHK: cpuTmp = memGet8(pc++); if(f & P_FLAG_C) cpu_arr_pos++; break; case CPU_TMP_READ8_PC_INC_JRC_CHK: cpuTmp = memGet8(pc++); if(!(f & P_FLAG_C)) cpu_arr_pos++; break; case CPU_TMP_READ8_SP_INC: cpuTmp = memGet8(sp++); break; case CPU_PCL_FROM_TMP_PCH_READ8_SP_INC: pc = (cpuTmp | (memGet8(sp++)<<8)); break; case CPU_C_FROM_TMP_B_READ8_SP_INC: c = cpuTmp; b = memGet8(sp++); break; case CPU_E_FROM_TMP_D_READ8_SP_INC: e = cpuTmp; d = memGet8(sp++); break; case CPU_L_FROM_TMP_H_READ8_SP_INC: l = cpuTmp; h = memGet8(sp++); break; case CPU_F_FROM_TMP_A_READ8_SP_INC: f = cpuTmp&0xF0; a = memGet8(sp++); break; case CPU_TMP_READHIGH_A: a = memGet8(0xFF00 | cpuTmp); break; case CPU_TMP_WRITEHIGH_A: memSet8(0xFF00 | cpuTmp, a); break; case CPU_C_READHIGH_A: a = memGet8(0xFF00 | c); break; case CPU_C_WRITEHIGH_A: memSet8(0xFF00 | c, a); break; case CPU_SP_FROM_HL: sp = (l | h<<8); break; case CPU_SP_WRITE8_A_DEC: sp--; memSet8(sp, a); break; case CPU_SP_WRITE8_B_DEC: sp--; memSet8(sp, b); break; case CPU_SP_WRITE8_C_DEC: sp--; memSet8(sp, c); break; case CPU_SP_WRITE8_D_DEC: sp--; memSet8(sp, d); break; case CPU_SP_WRITE8_E_DEC: sp--; memSet8(sp, e); break; case CPU_SP_WRITE8_F_DEC: sp--; memSet8(sp, f); break; case CPU_SP_WRITE8_H_DEC: sp--; memSet8(sp, h); break; case CPU_SP_WRITE8_L_DEC: sp--; memSet8(sp, l); break; case CPU_SP_WRITE8_PCH_DEC: sp--; memSet8(sp, pc>>8); break; case CPU_SP_WRITE8_PCL_DEC_PC_FROM_T16: sp--; memSet8(sp, pc&0xFF); pc = cpuTmp16; break; case CPU_SP_WRITE8_PCL_DEC_PC_FROM_00: sp--; memSet8(sp, pc&0xFF); pc = 0x00+gbsLoadAddr; break; case CPU_SP_WRITE8_PCL_DEC_PC_FROM_08: sp--; memSet8(sp, pc&0xFF); pc = 0x08+gbsLoadAddr; break; case CPU_SP_WRITE8_PCL_DEC_PC_FROM_10: sp--; memSet8(sp, pc&0xFF); pc = 0x10+gbsLoadAddr; break; case CPU_SP_WRITE8_PCL_DEC_PC_FROM_18: sp--; memSet8(sp, pc&0xFF); pc = 0x18+gbsLoadAddr; break; case CPU_SP_WRITE8_PCL_DEC_PC_FROM_20: sp--; memSet8(sp, pc&0xFF); pc = 0x20+gbsLoadAddr; break; case CPU_SP_WRITE8_PCL_DEC_PC_FROM_28: sp--; memSet8(sp, pc&0xFF); pc = 0x28+gbsLoadAddr; break; case CPU_SP_WRITE8_PCL_DEC_PC_FROM_30: sp--; memSet8(sp, pc&0xFF); pc = 0x30+gbsLoadAddr; break; case CPU_SP_WRITE8_PCL_DEC_PC_FROM_38: sp--; memSet8(sp, pc&0xFF); pc = 0x38+gbsLoadAddr; break; case CPU_SP_WRITE8_PCL_DEC_PC_FROM_40: sp--; memSet8(sp, pc&0xFF); pc = 0x40; break; case CPU_SP_WRITE8_PCL_DEC_PC_FROM_48: sp--; memSet8(sp, pc&0xFF); pc = 0x48; break; case CPU_SP_WRITE8_PCL_DEC_PC_FROM_50: sp--; memSet8(sp, pc&0xFF); pc = 0x50; break; case CPU_SP_WRITE8_PCL_DEC_PC_FROM_58: sp--; memSet8(sp, pc&0xFF); pc = 0x58; break; case CPU_SP_WRITE8_PCL_DEC_PC_FROM_60: sp--; memSet8(sp, pc&0xFF); pc = 0x60; break; case CPU_A_READ8_TMP16: a = memGet8(cpuTmp16); break; case CPU_A_READ8_PC_INC: a = memGet8(pc++); break; case CPU_B_READ8_PC_INC: b = memGet8(pc++); break; case CPU_C_READ8_PC_INC: c = memGet8(pc++); break; case CPU_D_READ8_PC_INC: d = memGet8(pc++); break; case CPU_E_READ8_PC_INC: e = memGet8(pc++); break; case CPU_L_READ8_PC_INC: l = memGet8(pc++); break; case CPU_H_READ8_PC_INC: h = memGet8(pc++); break; case CPU_PCL_FROM_TMP_PCH_READ8_PC: pc = (cpuTmp | (memGet8(pc)<<8)); break; case CPU_SPL_FROM_TMP_SPH_READ8_PC_INC: sp = (cpuTmp | (memGet8(pc++)<<8)); break; case CPU_T16L_FROM_TMP_T16H_READ8_PC_INC: cpuTmp16 = (cpuTmp | (memGet8(pc++)<<8)); break; case CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_CNZ_CHK: cpuTmp16 = (cpuTmp | (memGet8(pc++)<<8)); if(f & P_FLAG_Z) cpu_arr_pos+=3; break; case CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_CNC_CHK: cpuTmp16 = (cpuTmp | (memGet8(pc++)<<8)); if(f & P_FLAG_C) cpu_arr_pos+=3; break; case CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_CZ_CHK: cpuTmp16 = (cpuTmp | (memGet8(pc++)<<8)); if(!(f & P_FLAG_Z)) cpu_arr_pos+=3; break; case CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_CC_CHK: cpuTmp16 = (cpuTmp | (memGet8(pc++)<<8)); if(!(f & P_FLAG_C)) cpu_arr_pos+=3; break; case CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_JPNZ_CHK: cpuTmp16 = (cpuTmp | (memGet8(pc++)<<8)); if(f & P_FLAG_Z) cpu_arr_pos++; break; case CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_JPNC_CHK: cpuTmp16 = (cpuTmp | (memGet8(pc++)<<8)); if(f & P_FLAG_C) cpu_arr_pos++; break; case CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_JPZ_CHK: cpuTmp16 = (cpuTmp | (memGet8(pc++)<<8)); if(!(f & P_FLAG_Z)) cpu_arr_pos++; break; case CPU_T16L_FROM_TMP_T16H_READ8_PC_INC_JPC_CHK: cpuTmp16 = (cpuTmp | (memGet8(pc++)<<8)); if(!(f & P_FLAG_C)) cpu_arr_pos++; break; case CPU_TMP16_WRITE8_SPL_INC: memSet8(cpuTmp16++, sp&0xFF); break; case CPU_TMP16_WRITE8_SPH: memSet8(cpuTmp16, sp>>8); break; case CPU_DI_GET_INSTRUCTION: //printf("Disabled IRQs at %04x\n", pc); irqEnable = false; cpuGetInstruction(); break; case CPU_EI_GET_INSTRUCTION: irqEnable = true; //printf("Enabled IRQs and jmp to %04x ",pc); cpuGetInstruction(); //printf("%04x\n",pc); break; case CPU_GET_INSTRUCTION_EI: //printf("Enabled IRQs and jmp to %04x ",pc); cpuGetInstruction(); //printf("%04x\n",pc); irqEnable = true; break; case CPU_SCF_GET_INSTRUCTION: f |= P_FLAG_C; f &= ~(P_FLAG_H|P_FLAG_N); cpuGetInstruction(); break; case CPU_CCF_GET_INSTRUCTION: f ^= P_FLAG_C; f &= ~(P_FLAG_H|P_FLAG_N); cpuGetInstruction(); break; case CPU_PC_FROM_HL_GET_INSTRUCTION: pc = (l|(h<<8)); cpuGetInstruction(); break; case CPU_PC_FROM_T16: pc = cpuTmp16; break; case CPU_RET_NZ_CHK: if(f & P_FLAG_Z) cpu_arr_pos+=3; break; case CPU_RET_NC_CHK: if(f & P_FLAG_C) cpu_arr_pos+=3; break; case CPU_RET_Z_CHK: if(!(f & P_FLAG_Z)) cpu_arr_pos+=3; break; case CPU_RET_C_CHK: if(!(f & P_FLAG_C)) cpu_arr_pos+=3; break; } } uint16_t cpuCurPC() { return pc; } void cpuSetSpeed(bool cgb) { if(cgb) { //printf("CPU: CGB Speed\n"); cpuCgbSpeed = true; cpuAddSpeed = 2; cpuTimer = 1; } else { //printf("CPU: DMG Speed\n"); cpuCgbSpeed = false; cpuAddSpeed = 1; cpuTimer = 3; } } void cpuPlayGBS() { if(!gbsInitRet || !gbsPlayRet) return; gbsPlayRet = false; //push back detect pc sp--; memSet8(sp, 0x87); sp--; memSet8(sp, 0x65); //IMPORTANT: some GBS files dont work without this //Keep HL though, some GBS files use them as global address a = 0, b = 0, c = 0, d = 0, e = 0;//, h = 0, l = 0; //jump to play pc = gbsPlayAddr; cpuSetNopArr(); //printf("Playback Start at %04x\n", pc); } extern uint8_t gbsTMA, gbsTAC; void cpuLoadGBS(uint8_t song) { //full reset cpuInit(); ppuInit(); apuInit(); inputInit(); memInit(false,true); memSet8(0xFF06,gbsTMA); memSet8(0xFF07,gbsTAC); //set requested sp sp = gbsSP; //push back detect pc sp--; memSet8(sp, 0x87); sp--; memSet8(sp, 0x64); //IMPORTANT: some GBS files dont work without this a = 0, b = 0, c = 0, d = 0, e = 0, h = 0, l = 0; //set song and init routine a = song; pc = gbsInitAddr; //start getting instructions cpuSetNopArr(); //printf("Init Start at %04x\n", pc); }