GBHawk: fix IRQ clear timing

This commit is contained in:
alyosha-tas 2019-10-08 08:54:50 -04:00
parent 8beb0a9ae5
commit 1c07d3d2ad
2 changed files with 22 additions and 14 deletions

View File

@ -25,7 +25,7 @@ namespace BizHawk.Emulation.Common.Components.LR35902
IDLE,
TR, PCl, W,
ASGN, PCh, 0,
IDLE,
IRQ_CLEAR,
OP };
}
@ -54,13 +54,14 @@ namespace BizHawk.Emulation.Common.Components.LR35902
IDLE,
IDLE,
IDLE,
IDLE,
IRQ_CLEAR,
OP };
}
private static ushort[] INT_vectors = new ushort[] {0x40, 0x48, 0x50, 0x58, 0x60, 0x00};
public ushort int_src;
public byte int_clear;
public int stop_time;
public bool stop_check;
public bool is_GBC; // GBC automatically adds a NOP to avoid the HALT bug (according to Sinimas)

View File

@ -58,6 +58,7 @@ namespace BizHawk.Emulation.Common.Components.LR35902
public const ushort EI_RETI = 43; // reti has no delay in interrupt enable
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 LR35902()
{
@ -520,15 +521,14 @@ namespace BizHawk.Emulation.Common.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
if (interrupt_src.Bit(0) && interrupt_enable.Bit(0)) { int_src = 0; interrupt_src -= 1; }
else if (interrupt_src.Bit(1) && interrupt_enable.Bit(1)) { int_src = 1; interrupt_src -= 2; }
else if (interrupt_src.Bit(2) && interrupt_enable.Bit(2)) { int_src = 2; interrupt_src -= 4; }
else if (interrupt_src.Bit(3) && interrupt_enable.Bit(3)) { int_src = 3; interrupt_src -= 8; }
else if (interrupt_src.Bit(4) && interrupt_enable.Bit(4)) { int_src = 4; interrupt_src -= 16; }
else { int_src = 5; }
if ((interrupt_src & interrupt_enable) == 0) { FlagI = false; }
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];
break;
@ -543,6 +543,12 @@ namespace BizHawk.Emulation.Common.Components.LR35902
}
Halt_bug_2 = false;
break;
case IRQ_CLEAR:
if (interrupt_src.Bit(int_src)) { interrupt_src -= int_clear; }
if ((interrupt_src & interrupt_enable) == 0) { FlagI = false; }
break;
}
TotalExecutedCycles++;
@ -591,23 +597,24 @@ namespace BizHawk.Emulation.Common.Components.LR35902
{
ser.BeginSection(nameof(LR35902));
ser.Sync(nameof(Regs), ref Regs, false);
ser.Sync("IRQ", ref interrupts_enabled);
ser.Sync(nameof(interrupts_enabled), ref interrupts_enabled);
ser.Sync(nameof(I_use), ref I_use);
ser.Sync(nameof(skip_once), ref skip_once);
ser.Sync(nameof(Halt_bug_2), ref Halt_bug_2);
ser.Sync(nameof(Halt_bug_3), ref Halt_bug_3);
ser.Sync("Halted", ref halted);
ser.Sync(nameof(halted), ref halted);
ser.Sync(nameof(TotalExecutedCycles), ref TotalExecutedCycles);
ser.Sync(nameof(EI_pending), ref EI_pending);
ser.Sync(nameof(int_src), ref int_src);
ser.Sync(nameof(int_clear), ref int_clear);
ser.Sync(nameof(stop_time), ref stop_time);
ser.Sync(nameof(stop_check), ref stop_check);
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("CB Prefix", ref CB_prefix);
ser.Sync("Stopped", ref stopped);
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);