GB: Improved EI and IRQ behavior

Passes ei_sequence, ei_timing, ie_push, rapid_di_ei, reti_intr_timing
This commit is contained in:
Sour 2020-05-23 12:38:31 -04:00
parent 32db3f9d15
commit bc90c489c1
2 changed files with 23 additions and 3 deletions

View file

@ -49,18 +49,32 @@ void GbCpu::Exec()
if(irqVector) {
if(_state.IME) {
uint16_t oldPc = _state.PC;
_memoryManager->ClearIrqRequest(irqVector);
IncCycleCount();
IncCycleCount();
PushWord(_state.PC);
PushByte(_state.PC >> 8);
irqVector = _memoryManager->ProcessIrqRequests(); //Check IRQ line again before jumping (ie_push)
PushByte((uint8_t)_state.PC);
IncCycleCount();
switch(irqVector) {
case 0:
//IRQ request bit is no longer set, jump to $0000 (ie_push test)
_state.PC = 0;
break;
case GbIrqSource::VerticalBlank: _state.PC = 0x40; break;
case GbIrqSource::LcdStat: _state.PC = 0x48; break;
case GbIrqSource::Timer: _state.PC = 0x50; break;
case GbIrqSource::Serial: _state.PC = 0x58; break;
case GbIrqSource::Joypad: _state.PC = 0x60; break;
}
if(irqVector) {
//Only clear IRQ bit if an IRQ was processed
_memoryManager->ClearIrqRequest(irqVector);
}
_state.IME = false;
_console->ProcessInterrupt<CpuType::Gameboy>(oldPc, _state.PC, false);
}
@ -72,6 +86,11 @@ void GbCpu::Exec()
return;
}
if(_state.EiPending) {
_state.EiPending = false;
_state.IME = true;
}
ExecOpCode(ReadOpCode());
}
@ -1083,7 +1102,7 @@ void GbCpu::CCF()
void GbCpu::EI()
{
_state.IME = true;
_state.EiPending = true;
}
void GbCpu::DI()

View file

@ -19,6 +19,7 @@ struct GbCpuState
uint8_t H;
uint8_t L;
bool EiPending;
bool IME;
bool Halted;
};