Improved accuracy of the halt bug

This commit is contained in:
Lior Halphon 2018-05-12 22:13:52 +03:00
parent 4527d9ee39
commit 1fcde88d8a
2 changed files with 21 additions and 5 deletions

View File

@ -269,6 +269,7 @@ struct GB_gameboy_internal_s {
bool boot_rom_finished; bool boot_rom_finished;
bool ime_toggle; /* ei has delayed a effect.*/ bool ime_toggle; /* ei has delayed a effect.*/
bool halt_bug; bool halt_bug;
bool just_halted;
/* Misc state */ /* Misc state */
bool infrared_input; bool infrared_input;

View File

@ -750,12 +750,26 @@ static void cp_a_r(GB_gameboy_t *gb, uint8_t opcode)
static void halt(GB_gameboy_t *gb, uint8_t opcode) static void halt(GB_gameboy_t *gb, uint8_t opcode)
{ {
assert(gb->pending_cycles == 4);
gb->pending_cycles = 0;
GB_advance_cycles(gb, 1);
GB_advance_cycles(gb, 1);
GB_advance_cycles(gb, 1);
GB_advance_cycles(gb, 1);
gb->halted = true; gb->halted = true;
/* Despite what some online documentations say, the HALT bug also happens on a CGB, in both CGB and DMG modes. */ /* Despite what some online documentations say, the HALT bug also happens on a CGB, in both CGB and DMG modes. */
if (!gb->ime && (gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F) != 0) { if (((gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F) != 0)) {
gb->halted = false; if (gb->ime) {
gb->halt_bug = true; gb->halted = false;
gb->pc--;
}
else {
gb->halted = false;
gb->halt_bug = true;
}
} }
gb->just_halted = true;
} }
static void pop_rr(GB_gameboy_t *gb, uint8_t opcode) static void pop_rr(GB_gameboy_t *gb, uint8_t opcode)
@ -1321,15 +1335,16 @@ void GB_cpu_run(GB_gameboy_t *gb)
return; return;
} }
if (gb->halted && !gb->is_cgb) { if (gb->halted && !gb->is_cgb && !gb->just_halted) {
GB_advance_cycles(gb, 2); GB_advance_cycles(gb, 2);
} }
uint8_t interrupt_queue = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F; uint8_t interrupt_queue = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F;
if (gb->halted) { if (gb->halted) {
GB_advance_cycles(gb, gb->is_cgb? 4 : 2); GB_advance_cycles(gb, (gb->is_cgb || gb->just_halted) ? 4 : 2);
} }
gb->just_halted = false;
bool effecitve_ime = gb->ime; bool effecitve_ime = gb->ime;
if (gb->ime_toggle) { if (gb->ime_toggle) {