GBHawk: CPU optimizations
This commit is contained in:
parent
2e645d0563
commit
c9621eff19
|
@ -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];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue