GBHawk: controller IRQs enabled by write delayed 4 cycles

This commit is contained in:
alyosha-tas 2020-05-22 12:17:42 -04:00
parent f03fb06370
commit 78f0b9252d
4 changed files with 32 additions and 12 deletions

View File

@ -14,15 +14,13 @@ namespace BizHawk.Emulation.Cores.Components.LR35902
OP }; OP };
} }
private void INC_16(ushort srcL, ushort srcH) private void INC_16(ushort src_l, ushort src_h)
{ {
cur_instr = new[] cur_instr = new[]
{IDLE, {IDLE,
IDLE, IDLE,
IDLE, IDLE,
INC16, INC16, src_l, src_h,
srcL,
srcH,
IDLE, IDLE,
IDLE, IDLE,
HALT_CHK, HALT_CHK,
@ -35,9 +33,7 @@ namespace BizHawk.Emulation.Cores.Components.LR35902
{IDLE, {IDLE,
IDLE, IDLE,
IDLE, IDLE,
DEC16, DEC16, src_l, src_h,
src_l,
src_h,
IDLE, IDLE,
IDLE, IDLE,
HALT_CHK, HALT_CHK,

View File

@ -18,6 +18,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
public bool in_vblank; public bool in_vblank;
public bool vblank_rise; public bool vblank_rise;
public bool controller_was_checked; public bool controller_was_checked;
public bool delays_to_process;
public int controller_delay_cd;
public bool FrameAdvance(IController controller, bool render, bool rendersound) public bool FrameAdvance(IController controller, bool render, bool rendersound)
{ {
@ -108,12 +110,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
serialport.serial_transfer_tick(); serialport.serial_transfer_tick();
cpu.ExecuteOne(); cpu.ExecuteOne();
timer.tick(); timer.tick();
if (delays_to_process) { process_delays(); }
} }
if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); } if (ppu.DMA_start && !cpu.halted && !cpu.stopped) { ppu.DMA_tick(); }
serialport.serial_transfer_tick(); serialport.serial_transfer_tick();
cpu.ExecuteOne(); cpu.ExecuteOne();
timer.tick(); timer.tick();
if (delays_to_process) { process_delays(); }
} }
else else
{ {
@ -121,10 +125,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
{ {
cpu.TotalExecutedCycles++; cpu.TotalExecutedCycles++;
timer.tick(); timer.tick();
if (delays_to_process) { process_delays(); }
} }
cpu.TotalExecutedCycles++; cpu.TotalExecutedCycles++;
timer.tick(); timer.tick();
if (delays_to_process) { process_delays(); }
} }
if (in_vblank && !in_vblank_old) if (in_vblank && !in_vblank_old)
@ -186,6 +192,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
serialport.serial_transfer_tick(); serialport.serial_transfer_tick();
cpu.ExecuteOne(); cpu.ExecuteOne();
timer.tick(); timer.tick();
if (delays_to_process) { process_delays(); }
if (double_speed) if (double_speed)
{ {
@ -193,17 +200,20 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
serialport.serial_transfer_tick(); serialport.serial_transfer_tick();
cpu.ExecuteOne(); cpu.ExecuteOne();
timer.tick(); timer.tick();
if (delays_to_process) { process_delays(); }
} }
} }
else else
{ {
cpu.TotalExecutedCycles++; cpu.TotalExecutedCycles++;
timer.tick(); timer.tick();
if (delays_to_process) { process_delays(); }
if (double_speed) if (double_speed)
{ {
cpu.TotalExecutedCycles++; cpu.TotalExecutedCycles++;
timer.tick(); timer.tick();
if (delays_to_process) { process_delays(); }
} }
} }
@ -251,6 +261,18 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
REG_FF0F |= 0x10; REG_FF0F |= 0x10;
} }
} }
public void process_delays()
{
// triggering an interrupt with a write to the control register takes 4 cycles to trigger interrupt
controller_delay_cd--;
if (controller_delay_cd == 0)
{
if (REG_FFFF.Bit(4)) { cpu.FlagI = true; }
REG_FF0F |= 0x10;
delays_to_process = false;
}
}
// Switch Speed (GBC only) // Switch Speed (GBC only)
public int SpeedFunc(int temp) public int SpeedFunc(int temp)

View File

@ -38,6 +38,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
ser.Sync(nameof(controller_was_checked), ref controller_was_checked); ser.Sync(nameof(controller_was_checked), ref controller_was_checked);
ser.Sync(nameof(GB_bios_register), ref GB_bios_register); ser.Sync(nameof(GB_bios_register), ref GB_bios_register);
ser.Sync(nameof(input_register), ref input_register); ser.Sync(nameof(input_register), ref input_register);
ser.Sync(nameof(delays_to_process), ref delays_to_process);
ser.Sync(nameof(controller_delay_cd), ref controller_delay_cd);
ser.Sync(nameof(REG_FFFF), ref REG_FFFF); ser.Sync(nameof(REG_FFFF), ref REG_FFFF);
ser.Sync(nameof(REG_FF0F), ref REG_FF0F); ser.Sync(nameof(REG_FF0F), ref REG_FF0F);

View File

@ -267,13 +267,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
} }
// check for interrupts // check for interrupts
// if an interrupt is triggered, it is delayed by 4 cycles
if (((contr_prev & 8) > 0) && ((input_register & 8) == 0) || if (((contr_prev & 8) > 0) && ((input_register & 8) == 0) ||
((contr_prev & 4) > 0) && ((input_register & 4) == 0) || ((contr_prev & 4) > 0) && ((input_register & 4) == 0) ||
((contr_prev & 2) > 0) && ((input_register & 2) == 0) || ((contr_prev & 2) > 0) && ((input_register & 2) == 0) ||
((contr_prev & 1) > 0) && ((input_register & 1) == 0)) ((contr_prev & 1) > 0) && ((input_register & 1) == 0))
{ {
if (REG_FFFF.Bit(4)) { cpu.FlagI = true; } controller_delay_cd = 4; delays_to_process = true;
REG_FF0F |= 0x10;
} }
break; break;