From c9621eff19a7aea18907b1b889e870d0947be84c Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 28 Feb 2020 20:46:33 -0500 Subject: [PATCH] GBHawk: CPU optimizations --- .../CPUs/LR35902/Execute.cs | 124 +++++-- .../CPUs/LR35902/Interrupts.cs | 27 +- .../CPUs/LR35902/LR35902.cs | 252 +++++++++----- .../CPUs/LR35902/Operations.cs | 91 ++--- .../CPUs/LR35902/Registers.cs | 2 +- .../CPUs/LR35902/Tables_Direct.cs | 325 ++++++------------ .../Consoles/Nintendo/GBHawk/Audio.cs | 4 - .../GBHawkLink4x/GBHawkLink4x.IEmulator.cs | 2 +- 8 files changed, 431 insertions(+), 396 deletions(-) diff --git a/BizHawk.Emulation.Cores/CPUs/LR35902/Execute.cs b/BizHawk.Emulation.Cores/CPUs/LR35902/Execute.cs index 0dd55e28cd..ddfaf3ec8e 100644 --- a/BizHawk.Emulation.Cores/CPUs/LR35902/Execute.cs +++ b/BizHawk.Emulation.Cores/CPUs/LR35902/Execute.cs @@ -9,7 +9,8 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 // variables for executing instructions public int instr_pntr = 0; - public ushort[] cur_instr; + public ushort[] cur_instr = new ushort [60]; + public ushort[] instr_table = new ushort[256 * 2 * 60 + 60 * 8]; public int opcode; public bool CB_prefix; public bool halted; @@ -17,11 +18,14 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public bool jammed; public int LY; - public void FetchInstruction(byte opcode) + // unsaved variables + public bool checker; + + public void BuildInstructionTable() { - if (!CB_prefix) + for (int i = 0; i < 256; i++) { - switch (opcode) + switch (i) { case 0x00: NOP_(); break; // NOP case 0x01: LD_IND_16(C, B, PCl, PCh); break; // LD BC, nn @@ -47,7 +51,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 case 0x15: INT_OP(DEC8, D); break; // DEC D case 0x16: LD_IND_8_INC(D, PCl, PCh); break; // LD D, n case 0x17: INT_OP(RL, Aim); break; // RLA - case 0x18: JR_COND(true); break; // JR, r8 + case 0x18: JR_COND(ALWAYS_T); break; // JR, r8 case 0x19: ADD_16(L, H, E, D); break; // ADD HL, DE case 0x1A: REG_OP_IND(TR, A, E, D); break; // LD A, (DE) case 0x1B: DEC_16(E, D); break; // DEC DE @@ -55,7 +59,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 case 0x1D: INT_OP(DEC8, E); break; // DEC E case 0x1E: LD_IND_8_INC(E, PCl, PCh); break; // LD E, n case 0x1F: INT_OP(RR, Aim); break; // RRA - case 0x20: JR_COND(!FlagZ); break; // JR NZ, r8 + case 0x20: JR_COND(FLAG_NZ); break; // JR NZ, r8 case 0x21: LD_IND_16(L, H, PCl, PCh); break; // LD HL, nn case 0x22: LD_8_IND_INC(L, H, A); break; // LD (HL+), A case 0x23: INC_16(L, H); break; // INC HL @@ -63,7 +67,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 case 0x25: INT_OP(DEC8, H); break; // DEC H case 0x26: LD_IND_8_INC(H, PCl, PCh); break; // LD H, n case 0x27: INT_OP(DA, A); break; // DAA - case 0x28: JR_COND(FlagZ); break; // JR Z, r8 + case 0x28: JR_COND(FLAG_Z); break; // JR Z, r8 case 0x29: ADD_16(L, H, L, H); break; // ADD HL, HL case 0x2A: LD_IND_8_INC_HL(A, L, H); break; // LD A, (HL+) case 0x2B: DEC_16(L, H); break; // DEC HL @@ -71,7 +75,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 case 0x2D: INT_OP(DEC8, L); break; // DEC L case 0x2E: LD_IND_8_INC(L, PCl, PCh); break; // LD L, n case 0x2F: INT_OP(CPL, A); break; // CPL - case 0x30: JR_COND(!FlagC); break; // JR NC, r8 + case 0x30: JR_COND(FLAG_NC); break; // JR NC, r8 case 0x31: LD_IND_16(SPl, SPh, PCl, PCh); break; // LD SP, nn case 0x32: LD_8_IND_DEC(L, H, A); break; // LD (HL-), A case 0x33: INC_16(SPl, SPh); break; // INC SP @@ -79,7 +83,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 case 0x35: DEC_8_IND(L, H); break; // DEC (HL) case 0x36: LD_8_IND_IND(L, H, PCl, PCh); break; // LD (HL), n case 0x37: INT_OP(SCF, A); break; // SCF - case 0x38: JR_COND(FlagC); break; // JR C, r8 + case 0x38: JR_COND(FLAG_C); break; // JR C, r8 case 0x39: ADD_16(L, H, SPl, SPh); break; // ADD HL, SP case 0x3A: LD_IND_8_DEC_HL(A, L, H); break; // LD A, (HL-) case 0x3B: DEC_16(SPl, SPh); break; // DEC SP @@ -215,35 +219,35 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 case 0xBD: REG_OP(CP8, A, L); break; // CP A, L case 0xBE: REG_OP_IND(CP8, A, L, H); break; // CP A, (HL) case 0xBF: REG_OP(CP8, A, A); break; // CP A, A - case 0xC0: RET_COND(!FlagZ); break; // Ret NZ + case 0xC0: RET_COND(FLAG_NZ); break; // Ret NZ case 0xC1: POP_(C, B); break; // POP BC - case 0xC2: JP_COND(!FlagZ); break; // JP NZ - case 0xC3: JP_COND(true); break; // JP - case 0xC4: CALL_COND(!FlagZ); break; // CALL NZ + case 0xC2: JP_COND(FLAG_NZ); break; // JP NZ + case 0xC3: JP_COND(ALWAYS_T); break; // JP + case 0xC4: CALL_COND(FLAG_NZ); break; // CALL NZ case 0xC5: PUSH_(C, B); break; // PUSH BC case 0xC6: REG_OP_IND_INC(ADD8, A, PCl, PCh); break; // ADD A, n case 0xC7: RST_(0); break; // RST 0 - case 0xC8: RET_COND(FlagZ); break; // RET Z + case 0xC8: RET_COND(FLAG_Z); break; // RET Z case 0xC9: RET_(); break; // RET - case 0xCA: JP_COND(FlagZ); break; // JP Z + case 0xCA: JP_COND(FLAG_Z); break; // JP Z case 0xCB: PREFIX_(); break; // PREFIX - case 0xCC: CALL_COND(FlagZ); break; // CALL Z - case 0xCD: CALL_COND(true); break; // CALL + case 0xCC: CALL_COND(FLAG_Z); break; // CALL Z + case 0xCD: CALL_COND(ALWAYS_T); break; // CALL case 0xCE: REG_OP_IND_INC(ADC8, A, PCl, PCh); break; // ADC A, n case 0xCF: RST_(0x08); break; // RST 0x08 - case 0xD0: RET_COND(!FlagC); break; // Ret NC + case 0xD0: RET_COND(FLAG_NC); break; // Ret NC case 0xD1: POP_(E, D); break; // POP DE - case 0xD2: JP_COND(!FlagC); break; // JP NC + case 0xD2: JP_COND(FLAG_NC); break; // JP NC case 0xD3: JAM_(); break; // JAM - case 0xD4: CALL_COND(!FlagC); break; // CALL NC + case 0xD4: CALL_COND(FLAG_NC); break; // CALL NC case 0xD5: PUSH_(E, D); break; // PUSH DE case 0xD6: REG_OP_IND_INC(SUB8, A, PCl, PCh); break; // SUB A, n case 0xD7: RST_(0x10); break; // RST 0x10 - case 0xD8: RET_COND(FlagC); break; // RET C + case 0xD8: RET_COND(FLAG_C); break; // RET C case 0xD9: RETI_(); break; // RETI - case 0xDA: JP_COND(FlagC); break; // JP C + case 0xDA: JP_COND(FLAG_C); break; // JP C case 0xDB: JAM_(); break; // JAM - case 0xDC: CALL_COND(FlagC); break; // CALL C + case 0xDC: CALL_COND(FLAG_C); break; // CALL C case 0xDD: JAM_(); break; // JAM case 0xDE: REG_OP_IND_INC(SBC8, A, PCl, PCh); break; // SBC A, n case 0xDF: RST_(0x18); break; // RST 0x18 @@ -280,11 +284,13 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 case 0xFE: REG_OP_IND_INC(CP8, A, PCl, PCh); break; // XOR A, n case 0xFF: RST_(0x38); break; // RST 0x38 } - } - else - { - CB_prefix = false; - switch (opcode) + + for (int j = 0; j < cur_instr.Length; j++) + { + instr_table[i * 60 + j] = cur_instr[j]; + } + + switch (i) { case 0x00: INT_OP(RLC, B); break; // RLC B case 0x01: INT_OP(RLC, C); break; // RLC C @@ -543,7 +549,69 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 case 0xFE: BIT_OP_IND(SET, 7, L, H); break; // SET 7, (HL) case 0xFF: BIT_OP(SET, 7, A); break; // SET 7, A } + + for (int j = 0; j < cur_instr.Length; j++) + { + instr_table[256 * 60 + i * 60 + j] = cur_instr[j]; + } } + + // other miscellaneous vectors + + // reset + instr_table[256 * 60 * 2] = IDLE; + instr_table[256 * 60 * 2 + 1] = IDLE; + instr_table[256 * 60 * 2 + 2] = HALT_CHK; + instr_table[256 * 60 * 2 + 3] = OP; + + // halt loop + instr_table[256 * 60 * 2 + 60] = IDLE; + instr_table[256 * 60 * 2 + 60 + 1] = IDLE; + instr_table[256 * 60 * 2 + 60 + 2] = IDLE; + instr_table[256 * 60 * 2 + 60 + 3] = OP; + + // skipped loop + instr_table[256 * 60 * 2 + 60 * 2] = IDLE; + instr_table[256 * 60 * 2 + 60 * 2 + 1] = IDLE; + instr_table[256 * 60 * 2 + 60 * 2 + 2] = IDLE; + instr_table[256 * 60 * 2 + 60 * 2 + 3] = HALT; + instr_table[256 * 60 * 2 + 60 * 2 + 4] = (ushort)0; + + // GBC Halt loop + instr_table[256 * 60 * 2 + 60 * 3] = IDLE; + instr_table[256 * 60 * 2 + 60 * 3 + 1] = IDLE; + instr_table[256 * 60 * 2 + 60 * 3 + 2] = HALT_CHK; + instr_table[256 * 60 * 2 + 60 * 3 + 3] = HALT; + instr_table[256 * 60 * 2 + 60 * 3 + 4] = (ushort)0; + + // spec Halt loop + instr_table[256 * 60 * 2 + 60 * 4] = HALT_CHK; + instr_table[256 * 60 * 2 + 60 * 4 + 1] = IDLE; + instr_table[256 * 60 * 2 + 60 * 4 + 2] = IDLE; + instr_table[256 * 60 * 2 + 60 * 4 + 3] = HALT; + instr_table[256 * 60 * 2 + 60 * 4 + 4] = (ushort)0; + + // Stop loop + instr_table[256 * 60 * 2 + 60 * 5] = IDLE; + instr_table[256 * 60 * 2 + 60 * 5 + 1] = IDLE; + instr_table[256 * 60 * 2 + 60 * 5 + 2] = IDLE; + instr_table[256 * 60 * 2 + 60 * 5 + 3] = STOP; + + // interrupt vectors + INTERRUPT_(); + + for (int i = 0; i < cur_instr.Length; i++) + { + instr_table[256 * 60 * 2 + 60 * 6 + i] = cur_instr[i]; + } + + INTERRUPT_GBC_NOP(); + + for (int i = 0; i < cur_instr.Length; i++) + { + instr_table[256 * 60 * 2 + 60 * 7 + i] = cur_instr[i]; + } + } } } \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/CPUs/LR35902/Interrupts.cs b/BizHawk.Emulation.Cores/CPUs/LR35902/Interrupts.cs index c6041522d9..e3ee32dcbe 100644 --- a/BizHawk.Emulation.Cores/CPUs/LR35902/Interrupts.cs +++ b/BizHawk.Emulation.Cores/CPUs/LR35902/Interrupts.cs @@ -9,18 +9,18 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 DEC16, SPl, SPh, IDLE, WR, SPl, SPh, PCh, - IDLE, + INT_GET, 4, W, DEC16, SPl, SPh, - IDLE, + INT_GET, 3, W, WR, SPl, SPh, PCl, + INT_GET, 2, W, IDLE, + INT_GET, 1, W, IDLE, - IDLE, - IDLE, - IDLE, + INT_GET, 0, W, ASGN, PCh, 0, IDLE, - INT_GET, W,// NOTE: here is where we check for a cancelled IRQ + IDLE, TR, PCl, W, IRQ_CLEAR, IDLE, @@ -41,13 +41,13 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 IDLE, IDLE, IDLE, + IDLE, IDLE, - IDLE, - IDLE, - IDLE, - IDLE, - INT_GET, W,// NOTE: here is where we check for a cancelled IRQ - IDLE, + INT_GET, 4, W, + INT_GET, 3, W, + INT_GET, 2, W, + INT_GET, 1, W, + INT_GET, 0, W, TR, PCl, W, IDLE, ASGN, PCh, 0, @@ -75,6 +75,9 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 Halt_bug_2 = false; Halt_bug_3 = false; interrupts_enabled = false; + + int_src = 5; + int_clear = 0; } } } \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs b/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs index e808c71394..bc8ba885b8 100644 --- a/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs +++ b/BizHawk.Emulation.Cores/CPUs/LR35902/LR35902.cs @@ -56,6 +56,16 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public const ushort INT_GET = 44; public const ushort HALT_CHK = 45; // when in halt mode, actually check I Flag here public const ushort IRQ_CLEAR = 46; + public const ushort COND_CHECK = 47; + public const ushort HALT_FUNC = 48; + + // test conditions + public const ushort ALWAYS_T = 0; + public const ushort ALWAYS_F = 1; + public const ushort FLAG_Z = 2; + public const ushort FLAG_NZ = 3; + public const ushort FLAG_C = 4; + public const ushort FLAG_NC = 5; public LR35902() { @@ -66,11 +76,11 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 { ResetRegisters(); ResetInterrupts(); + BuildInstructionTable(); TotalExecutedCycles = 8; stop_check = false; - cur_instr = new ushort[] { IDLE, IDLE, HALT_CHK, OP }; + instr_pntr = 256 * 60 * 2; // point to reset stopped = jammed = halted = FlagI = false; - instr_pntr = 0; EI_pending = 0; CB_prefix = false; } @@ -126,7 +136,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 // Execute instructions public void ExecuteOne(ref byte interrupt_src, byte interrupt_enable) { - switch (cur_instr[instr_pntr++]) + switch (instr_table[instr_pntr++]) { case IDLE: // do nothing @@ -154,7 +164,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 // call interrupt processor // lowest bit set is highest priority - INTERRUPT_(); + instr_pntr = 256 * 60 * 2 + 60 * 6; // point to Interrupt } else { @@ -163,101 +173,100 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 CDLCallback?.Invoke(RegPC, eCDLogMemFlags.FetchFirst); FetchInstruction(ReadMemory(RegPC++)); } - instr_pntr = 0; I_use = false; break; case RD: - Read_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + Read_Func(instr_table[instr_pntr++], instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case WR: - Write_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + Write_Func(instr_table[instr_pntr++], instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case TR: - TR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + TR_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case ADD16: - ADD16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + ADD16_Func(instr_table[instr_pntr++], instr_table[instr_pntr++], instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case ADD8: - ADD8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + ADD8_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case SUB8: - SUB8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + SUB8_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case ADC8: - ADC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + ADC8_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case SBC8: - SBC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + SBC8_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case INC16: - INC16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + INC16_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case INC8: - INC8_Func(cur_instr[instr_pntr++]); + INC8_Func(instr_table[instr_pntr++]); break; case DEC16: - DEC16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + DEC16_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case DEC8: - DEC8_Func(cur_instr[instr_pntr++]); + DEC8_Func(instr_table[instr_pntr++]); break; case RLC: - RLC_Func(cur_instr[instr_pntr++]); + RLC_Func(instr_table[instr_pntr++]); break; case RL: - RL_Func(cur_instr[instr_pntr++]); + RL_Func(instr_table[instr_pntr++]); break; case RRC: - RRC_Func(cur_instr[instr_pntr++]); + RRC_Func(instr_table[instr_pntr++]); break; case RR: - RR_Func(cur_instr[instr_pntr++]); + RR_Func(instr_table[instr_pntr++]); break; case CPL: - CPL_Func(cur_instr[instr_pntr++]); + CPL_Func(instr_table[instr_pntr++]); break; case DA: - DA_Func(cur_instr[instr_pntr++]); + DA_Func(instr_table[instr_pntr++]); break; case SCF: - SCF_Func(cur_instr[instr_pntr++]); + SCF_Func(instr_table[instr_pntr++]); break; case CCF: - CCF_Func(cur_instr[instr_pntr++]); + CCF_Func(instr_table[instr_pntr++]); break; case AND8: - AND8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + AND8_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case XOR8: - XOR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + XOR8_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case OR8: - OR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + OR8_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case CP8: - CP8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + CP8_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case SLA: - SLA_Func(cur_instr[instr_pntr++]); + SLA_Func(instr_table[instr_pntr++]); break; case SRA: - SRA_Func(cur_instr[instr_pntr++]); + SRA_Func(instr_table[instr_pntr++]); break; case SRL: - SRL_Func(cur_instr[instr_pntr++]); + SRL_Func(instr_table[instr_pntr++]); break; case SWAP: - SWAP_Func(cur_instr[instr_pntr++]); + SWAP_Func(instr_table[instr_pntr++]); break; case BIT: - BIT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + BIT_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case RES: - RES_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + RES_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case SET: - SET_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + SET_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case EI: if (EI_pending == 0) { EI_pending = 2; } @@ -271,7 +280,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 bool temp = false; - if (cur_instr[instr_pntr++] == 1) + if (instr_table[instr_pntr++] == 1) { temp = FlagI; } @@ -306,11 +315,11 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 // call the interrupt processor after 4 extra cycles if (!Halt_bug_3) { - INTERRUPT_GBC_NOP(); + instr_pntr = 256 * 60 * 2 + 60 * 7; // point to Interrupt for GBC } else { - INTERRUPT_(); + instr_pntr = 256 * 60 * 2 + 60 * 6; // point to Interrupt Halt_bug_3 = false; //Console.WriteLine("Hit INT"); } @@ -318,7 +327,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 else { // call interrupt processor - INTERRUPT_(); + instr_pntr = 256 * 60 * 2 + 60 * 6; // point to Interrupt Halt_bug_3 = false; } } @@ -348,13 +357,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 } else { - cur_instr = new[] - { - IDLE, - IDLE, - IDLE, - OP - }; + instr_pntr = 256 * 60 * 2 + 60; // point to halt loop } } else @@ -380,37 +383,22 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 { if (skip_once) { - cur_instr = new ushort[] - {IDLE, - IDLE, - IDLE, - HALT, 0 }; - + instr_pntr = 256 * 60 * 2 + 60 * 2; // point to skipped loop skip_once = false; } else { if (is_GBC) { - cur_instr = new ushort[] - {IDLE, - IDLE, - HALT_CHK, - HALT, 0 }; + instr_pntr = 256 * 60 * 2 + 60 * 3; // point to GBC Halt loop } else { - cur_instr = new ushort[] - {HALT_CHK, - IDLE, - IDLE, - HALT, 0 }; + instr_pntr = 256 * 60 * 2 + 60 * 4; // point to spec Halt loop } - } - + } } I_use = false; - instr_pntr = 0; break; case STOP: stopped = true; @@ -436,18 +424,12 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 if (TraceCallback != null && !CB_prefix) TraceCallback(State()); CDLCallback?.Invoke(RegPC, eCDLogMemFlags.FetchFirst); FetchInstruction(ReadMemory(RegPC++)); - instr_pntr = 0; stop_check = false; } else { - instr_pntr = 0; - cur_instr = new ushort[] - {IDLE, - IDLE, - IDLE, - STOP }; + instr_pntr = 256 * 60 * 2 + 60 * 5; // point to stop loop } } else if (interrupt_src.Bit(4)) // button pressed, not actually an interrupt though @@ -463,30 +445,22 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 if (TraceCallback != null && !CB_prefix) TraceCallback(State()); CDLCallback?.Invoke(RegPC, eCDLogMemFlags.FetchFirst); FetchInstruction(ReadMemory(RegPC++)); - instr_pntr = 0; stop_check = false; } else { - instr_pntr = 0; - cur_instr = new[] - { - IDLE, - IDLE, - IDLE, - STOP - }; + instr_pntr = 256 * 60 * 2 + 60 * 5; // point to stop loop } break; case PREFIX: CB_prefix = true; break; case ASGN: - ASGN_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + ASGN_Func(instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case ADDS: - ADDS_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + ADDS_Func(instr_table[instr_pntr++], instr_table[instr_pntr++], instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case OP_G: OnExecFetch?.Invoke(RegPC); @@ -494,15 +468,13 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 CDLCallback?.Invoke(RegPC, eCDLogMemFlags.FetchFirst); FetchInstruction(ReadMemory(RegPC)); // note no increment - - instr_pntr = 0; break; case JAM: jammed = true; instr_pntr--; break; case RD_F: - Read_Func_F(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + Read_Func_F(instr_table[instr_pntr++], instr_table[instr_pntr++], instr_table[instr_pntr++]); break; case EI_RETI: EI_pending = 1; @@ -510,16 +482,20 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 case INT_GET: // check if any interrupts got cancelled along the way // interrupt src = 5 sets the PC to zero as observed - // also the triggering interrupt seems like it is held low (i.e. annot trigger I flag) until the interrupt is serviced + // also the triggering interrupt seems like it is held low (i.e. cannot trigger I flag) until the interrupt is serviced + ushort bit_check = instr_table[instr_pntr++]; + //Console.WriteLine(interrupt_src + " " + interrupt_enable + " " + TotalExecutedCycles); + if (interrupt_src.Bit(bit_check) && interrupt_enable.Bit(bit_check)) { int_src = bit_check; int_clear = (byte)(1 << bit_check); } + /* if (interrupt_src.Bit(0) && interrupt_enable.Bit(0)) { int_src = 0; int_clear = 1; } else if (interrupt_src.Bit(1) && interrupt_enable.Bit(1)) { int_src = 1; int_clear = 2; } else if (interrupt_src.Bit(2) && interrupt_enable.Bit(2)) { int_src = 2; int_clear = 4; } else if (interrupt_src.Bit(3) && interrupt_enable.Bit(3)) { int_src = 3; int_clear = 8; } else if (interrupt_src.Bit(4) && interrupt_enable.Bit(4)) { int_src = 4; int_clear = 16; } else { int_src = 5; int_clear = 0; } - - Regs[cur_instr[instr_pntr++]] = INT_vectors[int_src]; + */ + Regs[instr_table[instr_pntr++]] = INT_vectors[int_src]; break; case HALT_CHK: I_use = FlagI; @@ -538,6 +514,83 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 if ((interrupt_src & interrupt_enable) == 0) { FlagI = false; } + // reset back to default state + int_src = 5; + int_clear = 0; + break; + case COND_CHECK: + checker = false; + switch (instr_table[instr_pntr++]) + { + case ALWAYS_T: + checker = true; + break; + case ALWAYS_F: + checker = false; + break; + case FLAG_Z: + checker = FlagZ; + break; + case FLAG_NZ: + checker = !FlagZ; + break; + case FLAG_C: + checker = FlagC; + break; + case FLAG_NC: + checker = !FlagC; + break; + } + + // true condition is what is represented in the instruction vectors + // jump ahead if false + if (checker) + { + instr_pntr++; + } + else + { + // 0 = JR COND, 1 = JP COND, 2 = RET COND, 3 = CALL + switch (instr_table[instr_pntr++]) + { + case 0: + instr_pntr += 10; + break; + case 1: + instr_pntr += 8; + break; + case 2: + instr_pntr += 22; + break; + case 3: + instr_pntr += 26; + break; + } + } + break; + case HALT_FUNC: + if (was_FlagI && (EI_pending == 0) && !interrupts_enabled) + { + // in GBC mode, the HALT bug is worked around by simply adding a NOP + // so it just takes 4 cycles longer to reach the next instruction + + // otherwise, if interrupts are disabled, + // a glitchy decrement to the program counter happens + + // either way, nothing needs to be done here + } + else + { + instr_pntr += 3; + + if (!is_GBC) { skip_once = true; } + // If the interrupt flag is not currently set, but it does get set in the first check + // then a bug is triggered + // With interrupts enabled, this runs the halt command twice + // when they are disabled, it reads the next byte twice + if (!was_FlagI || (was_FlagI && !interrupts_enabled)) { Halt_bug_2 = true; } + + } break; } TotalExecutedCycles++; @@ -577,8 +630,23 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 interrupts_enabled ? "E" : "e")) }; } - // State Save/Load + void FetchInstruction(int op) + { + opcode = op; + + instr_pntr = 0; + + if (CB_prefix) { instr_pntr += 256 * 60; } + + instr_pntr += op * 60; + + CB_prefix = false; + + was_FlagI = FlagI; + } + + // State Save/Load public void SyncState(Serializer ser) { ser.BeginSection(nameof(LR35902)); @@ -598,13 +666,13 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 ser.Sync(nameof(is_GBC), ref is_GBC); ser.Sync(nameof(instr_pntr), ref instr_pntr); - ser.Sync(nameof(cur_instr), ref cur_instr, false); ser.Sync(nameof(CB_prefix), ref CB_prefix); ser.Sync(nameof(stopped), ref stopped); ser.Sync(nameof(opcode), ref opcode); ser.Sync(nameof(jammed), ref jammed); ser.Sync(nameof(LY), ref LY); ser.Sync(nameof(FlagI), ref FlagI); + ser.Sync(nameof(was_FlagI), ref was_FlagI); ser.EndSection(); } diff --git a/BizHawk.Emulation.Cores/CPUs/LR35902/Operations.cs b/BizHawk.Emulation.Cores/CPUs/LR35902/Operations.cs index aeb84545d0..df1fc3b556 100644 --- a/BizHawk.Emulation.Cores/CPUs/LR35902/Operations.cs +++ b/BizHawk.Emulation.Cores/CPUs/LR35902/Operations.cs @@ -4,6 +4,13 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 { public partial class LR35902 { + // local variables for operations, not stated + int Reg16_d, Reg16_s, c; + ushort ans, ans_l, ans_h, temp; + byte a_d; + bool imm; + + public void Read_Func(ushort dest, ushort src_l, ushort src_h) { ushort addr = (ushort)(Regs[src_l] | (Regs[src_h]) << 8); @@ -35,15 +42,15 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void ADD16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) { - int Reg16_d = Regs[dest_l] | (Regs[dest_h] << 8); - int Reg16_s = Regs[src_l] | (Regs[src_h] << 8); + Reg16_d = Regs[dest_l] | (Regs[dest_h] << 8); + Reg16_s = Regs[src_l] | (Regs[src_h] << 8); Reg16_d += Reg16_s; FlagC = Reg16_d.Bit(16); - ushort ans_l = (ushort)(Reg16_d & 0xFF); - ushort ans_h = (ushort)((Reg16_d & 0xFF00) >> 8); + ans_l = (ushort)(Reg16_d & 0xFF); + ans_h = (ushort)((Reg16_d & 0xFF00) >> 8); // redo for half carry flag Reg16_d = Regs[dest_l] | ((Regs[dest_h] & 0x0F) << 8); @@ -60,13 +67,13 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void ADD8_Func(ushort dest, ushort src) { - int Reg16_d = Regs[dest]; + Reg16_d = Regs[dest]; Reg16_d += Regs[src]; FlagC = Reg16_d.Bit(8); FlagZ = (Reg16_d & 0xFF) == 0; - ushort ans = (ushort)(Reg16_d & 0xFF); + ans = (ushort)(Reg16_d & 0xFF); // redo for half carry flag Reg16_d = Regs[dest] & 0xF; @@ -81,13 +88,13 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void SUB8_Func(ushort dest, ushort src) { - int Reg16_d = Regs[dest]; + Reg16_d = Regs[dest]; Reg16_d -= Regs[src]; FlagC = Reg16_d.Bit(8); FlagZ = (Reg16_d & 0xFF) == 0; - ushort ans = (ushort)(Reg16_d & 0xFF); + ans = (ushort)(Reg16_d & 0xFF); // redo for half carry flag Reg16_d = Regs[dest] & 0xF; @@ -123,7 +130,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void SWAP_Func(ushort src) { - ushort temp = (ushort)((Regs[src] << 4) & 0xF0); + temp = (ushort)((Regs[src] << 4) & 0xF0); Regs[src] = (ushort)(temp | (Regs[src] >> 4)); FlagZ = Regs[src] == 0; @@ -147,7 +154,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 { FlagC = Regs[src].Bit(0); - ushort temp = (ushort)(Regs[src] & 0x80); // MSB doesn't change in this operation + temp = (ushort)(Regs[src] & 0x80); // MSB doesn't change in this operation Regs[src] = (ushort)((Regs[src] >> 1) | temp); @@ -221,7 +228,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void CP8_Func(ushort dest, ushort src) { - int Reg16_d = Regs[dest]; + Reg16_d = Regs[dest]; Reg16_d -= Regs[src]; FlagC = Reg16_d.Bit(8); @@ -238,7 +245,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void RRC_Func(ushort src) { - bool imm = src == Aim; + imm = src == Aim; if (imm) { src = A; } FlagC = Regs[src].Bit(0); @@ -252,10 +259,10 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void RR_Func(ushort src) { - bool imm = src == Aim; + imm = src == Aim; if (imm) { src = A; } - ushort c = (ushort)(FlagC ? 0x80 : 0); + c = FlagC ? 0x80 : 0; FlagC = Regs[src].Bit(0); @@ -268,10 +275,10 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void RLC_Func(ushort src) { - bool imm = src == Aim; + imm = src == Aim; if (imm) { src = A; } - ushort c = (ushort)(Regs[src].Bit(7) ? 1 : 0); + c = Regs[src].Bit(7) ? 1 : 0; FlagC = Regs[src].Bit(7); Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | c); @@ -283,10 +290,10 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void RL_Func(ushort src) { - bool imm = src == Aim; + imm = src == Aim; if (imm) { src = A; } - ushort c = (ushort)(FlagC ? 1 : 0); + c = FlagC ? 1 : 0; FlagC = Regs[src].Bit(7); Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | c); @@ -298,12 +305,12 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void INC8_Func(ushort src) { - int Reg16_d = Regs[src]; + Reg16_d = Regs[src]; Reg16_d += 1; FlagZ = (Reg16_d & 0xFF) == 0; - ushort ans = (ushort)(Reg16_d & 0xFF); + ans = (ushort)(Reg16_d & 0xFF); // redo for half carry flag Reg16_d = Regs[src] & 0xF; @@ -317,12 +324,12 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void DEC8_Func(ushort src) { - int Reg16_d = Regs[src]; + Reg16_d = Regs[src]; Reg16_d -= 1; FlagZ = (Reg16_d & 0xFF) == 0; - ushort ans = (ushort)(Reg16_d & 0xFF); + ans = (ushort)(Reg16_d & 0xFF); // redo for half carry flag Reg16_d = Regs[src] & 0xF; @@ -336,7 +343,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void INC16_Func(ushort src_l, ushort src_h) { - int Reg16_d = Regs[src_l] | (Regs[src_h] << 8); + Reg16_d = Regs[src_l] | (Regs[src_h] << 8); Reg16_d += 1; @@ -346,7 +353,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void DEC16_Func(ushort src_l, ushort src_h) { - int Reg16_d = Regs[src_l] | (Regs[src_h] << 8); + Reg16_d = Regs[src_l] | (Regs[src_h] << 8); Reg16_d -= 1; @@ -356,15 +363,15 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void ADC8_Func(ushort dest, ushort src) { - int Reg16_d = Regs[dest]; - int c = FlagC ? 1 : 0; + Reg16_d = Regs[dest]; + c = FlagC ? 1 : 0; Reg16_d += (Regs[src] + c); FlagC = Reg16_d.Bit(8); FlagZ = (Reg16_d & 0xFF) == 0; - ushort ans = (ushort)(Reg16_d & 0xFF); + ans = (ushort)(Reg16_d & 0xFF); // redo for half carry flag Reg16_d = Regs[dest] & 0xF; @@ -378,15 +385,15 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public void SBC8_Func(ushort dest, ushort src) { - int Reg16_d = Regs[dest]; - int c = FlagC ? 1 : 0; + Reg16_d = Regs[dest]; + c = FlagC ? 1 : 0; Reg16_d -= (Regs[src] + c); FlagC = Reg16_d.Bit(8); FlagZ = (Reg16_d & 0xFF) == 0; - ushort ans = (ushort)(Reg16_d & 0xFF); + ans = (ushort)(Reg16_d & 0xFF); // redo for half carry flag Reg16_d = Regs[dest] & 0xF; @@ -401,36 +408,36 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 // DA code courtesy of AWJ: http://forums.nesdev.com/viewtopic.php?f=20&t=15944 public void DA_Func(ushort src) { - byte a = (byte)Regs[src]; + a_d = (byte)Regs[src]; if (!FlagN) { // after an addition, adjust if (half-)carry occurred or if result is out of bounds - if (FlagC || a > 0x99) { a += 0x60; FlagC = true; } - if (FlagH || (a & 0x0f) > 0x09) { a += 0x6; } + if (FlagC || a_d > 0x99) { a_d += 0x60; FlagC = true; } + if (FlagH || (a_d & 0x0f) > 0x09) { a_d += 0x6; } } else { // after a subtraction, only adjust if (half-)carry occurred - if (FlagC) { a -= 0x60; } - if (FlagH) { a -= 0x6; } + if (FlagC) { a_d -= 0x60; } + if (FlagH) { a_d -= 0x6; } } - a &= 0xFF; + a_d &= 0xFF; - Regs[src] = a; + Regs[src] = a_d; - FlagZ = a == 0; + FlagZ = a_d == 0; FlagH = false; } // used for signed operations public void ADDS_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) { - int Reg16_d = Regs[dest_l]; - int Reg16_s = Regs[src_l]; + Reg16_d = Regs[dest_l]; + Reg16_s = Regs[src_l]; Reg16_d += Reg16_s; - ushort temp = 0; + temp = 0; // since this is signed addition, calculate the high byte carry appropriately if (Reg16_s.Bit(7)) @@ -449,7 +456,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 temp = (ushort)(Reg16_d.Bit(8) ? 1 : 0); } - ushort ans_l = (ushort)(Reg16_d & 0xFF); + ans_l = (ushort)(Reg16_d & 0xFF); // JR operations do not effect flags if (dest_l != PCl) diff --git a/BizHawk.Emulation.Cores/CPUs/LR35902/Registers.cs b/BizHawk.Emulation.Cores/CPUs/LR35902/Registers.cs index 1b7b15ce24..5c7b66e181 100644 --- a/BizHawk.Emulation.Cores/CPUs/LR35902/Registers.cs +++ b/BizHawk.Emulation.Cores/CPUs/LR35902/Registers.cs @@ -26,7 +26,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 public ushort[] Regs = new ushort[14]; - public bool FlagI; + public bool was_FlagI, FlagI; public bool FlagC { diff --git a/BizHawk.Emulation.Cores/CPUs/LR35902/Tables_Direct.cs b/BizHawk.Emulation.Cores/CPUs/LR35902/Tables_Direct.cs index 07a1bd8ee7..9240a505b9 100644 --- a/BizHawk.Emulation.Cores/CPUs/LR35902/Tables_Direct.cs +++ b/BizHawk.Emulation.Cores/CPUs/LR35902/Tables_Direct.cs @@ -8,46 +8,40 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 private void NOP_() { cur_instr = new[] - { - IDLE, - IDLE, - HALT_CHK, - OP - }; + {IDLE, + IDLE, + HALT_CHK, + OP }; } private void INC_16(ushort srcL, ushort srcH) { cur_instr = new[] - { - IDLE, - IDLE, - IDLE, - INC16, - srcL, - srcH, - IDLE, - IDLE, - HALT_CHK, - OP - }; + {IDLE, + IDLE, + IDLE, + INC16, + srcL, + srcH, + IDLE, + IDLE, + HALT_CHK, + OP }; } private void DEC_16(ushort src_l, ushort src_h) { cur_instr = new[] - { - IDLE, - IDLE, - IDLE, - DEC16, - src_l, - src_h, - IDLE, - IDLE, - HALT_CHK, - OP - }; + {IDLE, + IDLE, + IDLE, + DEC16, + src_l, + src_h, + IDLE, + IDLE, + HALT_CHK, + OP }; } private void ADD_16(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) @@ -83,119 +77,52 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 private void HALT_() { - if (FlagI && (EI_pending == 0) && !interrupts_enabled) - { - if (is_GBC) - { - // in GBC mode, the HALT bug is worked around by simply adding a NOP - // so it just takes 4 cycles longer to reach the next instruction - cur_instr = new[] - {IDLE, - IDLE, - IDLE, - OP_G}; - } - else - { // if interrupts are disabled, - // a glitchy decrement to the program counter happens - { - cur_instr = new[] - {IDLE, - IDLE, - IDLE, - OP_G}; - } - } - } - else - { - cur_instr = new ushort[] - { + cur_instr = new ushort[] + {HALT_FUNC, IDLE, + IDLE, + OP_G, HALT_CHK, IDLE, - HALT, 0 }; - - if (!is_GBC) { skip_once = true; } - // If the interrupt flag is not currently set, but it does get set in the first check - // then a bug is triggered - // With interrupts enabled, this runs the halt command twice - // when they are disabled, it reads the next byte twice - if (!FlagI ||(FlagI && !interrupts_enabled)) { Halt_bug_2 = true; } - - } + HALT, 0}; } - private void JR_COND(bool cond) + private void JR_COND(ushort cond) { - if (cond) - { - cur_instr = new ushort[] - {IDLE, - IDLE, - IDLE, - RD, W, PCl, PCh, - IDLE, - INC16, PCl, PCh, - IDLE, - ASGN, Z, 0, - IDLE, - ADDS, PCl, PCh, W, Z, - HALT_CHK, - OP }; - } - else - { - cur_instr = new[] - {IDLE, - IDLE, - IDLE, - RD, Z, PCl, PCh, - IDLE, - INC16, PCl, PCh, - HALT_CHK, - OP }; - } + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + RD, W, PCl, PCh, + INC16, PCl, PCh, + COND_CHECK, cond, (ushort)0, + IDLE, + ASGN, Z, 0, + IDLE, + ADDS, PCl, PCh, W, Z, + HALT_CHK, + OP }; } - private void JP_COND(bool cond) + private void JP_COND(ushort cond) { - if (cond) - { - cur_instr = new[] - {IDLE, - IDLE, - IDLE, - RD, W, PCl, PCh, - IDLE, - INC16, PCl, PCh, - IDLE, - RD, Z, PCl, PCh, - IDLE, - INC16, PCl, PCh, - IDLE, - TR, PCl, W, - IDLE, - TR, PCh, Z, - HALT_CHK, - OP }; - } - else - { - cur_instr = new[] - {IDLE, - IDLE, - IDLE, - RD, W, PCl, PCh, - IDLE, - INC16, PCl, PCh, - IDLE, - RD, Z, PCl, PCh, - IDLE, - INC16, PCl, PCh, - HALT_CHK, - OP }; - } + cur_instr = new[] + {IDLE, + IDLE, + IDLE, + RD, W, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + RD, Z, PCl, PCh, + INC16, PCl, PCh, + COND_CHECK, cond, (ushort)1, + IDLE, + TR, PCl, W, + IDLE, + TR, PCh, Z, + HALT_CHK, + OP }; } private void RET_() @@ -241,92 +168,58 @@ namespace BizHawk.Emulation.Cores.Components.LR35902 } - private void RET_COND(bool cond) + private void RET_COND(ushort cond) { - if (cond) - { - cur_instr = new[] - {IDLE, - IDLE, - IDLE, - IDLE, - IDLE, - IDLE, - IDLE, - RD, PCl, SPl, SPh, - IDLE, - INC16, SPl, SPh, - IDLE, - RD, PCh, SPl, SPh, - IDLE, - INC16, SPl, SPh, - IDLE, - IDLE, - IDLE, - IDLE, - HALT_CHK, - OP }; - } - else - { - cur_instr = new[] - {IDLE, - IDLE, - IDLE, - IDLE, - IDLE, - IDLE, - HALT_CHK, - OP }; - } + cur_instr = new[] + {IDLE, + IDLE, + IDLE, + IDLE, + IDLE, + COND_CHECK, cond, (ushort)2, + IDLE, + RD, PCl, SPl, SPh, + IDLE, + INC16, SPl, SPh, + IDLE, + RD, PCh, SPl, SPh, + IDLE, + INC16, SPl, SPh, + IDLE, + IDLE, + IDLE, + IDLE, + HALT_CHK, + OP }; } - private void CALL_COND(bool cond) + private void CALL_COND(ushort cond) { - if (cond) - { - cur_instr = new[] - {IDLE, - IDLE, - IDLE, - RD, W, PCl, PCh, - INC16, PCl, PCh, - IDLE, - IDLE, - RD, Z, PCl, PCh, - INC16, PCl, PCh, - IDLE, - DEC16, SPl, SPh, - IDLE, - IDLE, - IDLE, - IDLE, - WR, SPl, SPh, PCh, - IDLE, - IDLE, - DEC16, SPl, SPh, - WR, SPl, SPh, PCl, - TR, PCl, W, - TR, PCh, Z, - HALT_CHK, - OP }; - } - else - { - cur_instr = new[] - {IDLE, - IDLE, - IDLE, - RD, W, PCl, PCh, - IDLE, - INC16, PCl, PCh, - IDLE, - RD, Z, PCl, PCh, - IDLE, - INC16, PCl, PCh, - HALT_CHK, - OP }; - } + cur_instr = new[] + {IDLE, + IDLE, + IDLE, + RD, W, PCl, PCh, + INC16, PCl, PCh, + IDLE, + IDLE, + RD, Z, PCl, PCh, + INC16, PCl, PCh, + COND_CHECK, cond, (ushort)3, + DEC16, SPl, SPh, + IDLE, + IDLE, + IDLE, + IDLE, + WR, SPl, SPh, PCh, + IDLE, + IDLE, + DEC16, SPl, SPh, + WR, SPl, SPh, PCl, + TR, PCl, W, + TR, PCh, Z, + HALT_CHK, + OP }; } private void INT_OP(ushort operation, ushort src) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Audio.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Audio.cs index d62869a6cc..c2ab2ec95f 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Audio.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Audio.cs @@ -966,7 +966,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk ser.Sync(nameof(SQ1_vol_done), ref SQ1_vol_done); ser.Sync(nameof(SQ1_calc_done), ref SQ1_calc_done); ser.Sync(nameof(SQ1_swp_enable), ref SQ1_swp_enable); - //ser.Sync("Duplicate_SQ1_len_center", ref SQ1_len_cntr); // Deleting this breaks backwards compatibility with binary states ser.Sync(nameof(SQ1_enable), ref SQ1_enable); ser.Sync(nameof(SQ1_vol_state), ref SQ1_vol_state); ser.Sync(nameof(SQ1_duty_cntr), ref SQ1_duty_cntr); @@ -989,7 +988,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk ser.Sync(nameof(SQ1_output), ref SQ1_output); ser.Sync(nameof(SQ2_vol_done), ref SQ2_vol_done); - ser.Sync("Duplicate_SQ2_len_counter", ref SQ2_len_cntr); // Deleting this breaks backwards compatibility with binary states ser.Sync(nameof(SQ2_enable), ref SQ2_enable); ser.Sync(nameof(SQ2_vol_state), ref SQ2_vol_state); ser.Sync(nameof(SQ2_duty_cntr), ref SQ2_duty_cntr); @@ -1007,7 +1005,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk ser.Sync(nameof(SQ2_output), ref SQ2_output); ser.Sync(nameof(WAVE_can_get), ref WAVE_can_get); - ser.Sync("duplicate_WAVE_len_counter", ref WAVE_len_cntr); // Deleting this breaks backwards compatibility with binary states ser.Sync(nameof(WAVE_enable), ref WAVE_enable); ser.Sync(nameof(WAVE_wave_cntr), ref WAVE_wave_cntr); ser.Sync(nameof(WAVE_intl_cntr), ref WAVE_intl_cntr); @@ -1021,7 +1018,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk ser.Sync(nameof(WAVE_output), ref WAVE_output); ser.Sync(nameof(NOISE_vol_done), ref NOISE_vol_done); - ser.Sync("NOISE_len_counter", ref NOISE_len_cntr); // Deleting this breaks backwards compatibility with binary states ser.Sync(nameof(NOISE_enable), ref NOISE_enable); ser.Sync(nameof(NOISE_vol_state), ref NOISE_vol_state); ser.Sync(nameof(NOISE_intl_cntr), ref NOISE_intl_cntr); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IEmulator.cs index 7000fc9741..28670a965e 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawkLink4x/GBHawkLink4x.IEmulator.cs @@ -922,7 +922,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink4x public void GetSamplesSync(out short[] samples, out int nsamp) { A.audio.GetSamplesSync(out var temp_samp_A, out var nsamp_A); - B.audio.GetSamplesSync(out short[] temp_samp_B, out var nsamp_B); + B.audio.GetSamplesSync(out var temp_samp_B, out var nsamp_B); C.audio.GetSamplesSync(out var temp_samp_C, out var nsamp_C); D.audio.GetSamplesSync(out var temp_samp_D, out var nsamp_D);