From 54eb51d8db6fc79e7e4258f84b06bb2b0800a64f Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sat, 2 Sep 2017 22:08:20 +0300 Subject: [PATCH] Refined timer interrupt timing --- Core/gb.h | 1 + Core/timing.c | 4 +++- Core/z80_cpu.c | 7 +++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Core/gb.h b/Core/gb.h index 5965d51..a929762 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -332,6 +332,7 @@ struct GB_gameboy_internal_s { GB_PADDING(uint16_t, serial_cycles); uint16_t serial_cycles; /* This field changed its meaning in v0.10 */ uint16_t serial_length; + uint8_t delayed_interrupts; /* When an interrupt occurs while not aligned to a T-cycle, it must be "delayed" */ ); /* APU */ diff --git a/Core/timing.c b/Core/timing.c index 77348fe..72097c2 100644 --- a/Core/timing.c +++ b/Core/timing.c @@ -82,10 +82,13 @@ static void GB_ir_run(GB_gameboy_t *gb) static void advance_tima_state_machine(GB_gameboy_t *gb) { + gb->delayed_interrupts &= ~4; if (gb->tima_reload_state == GB_TIMA_RELOADED) { gb->tima_reload_state = GB_TIMA_RUNNING; } else if (gb->tima_reload_state == GB_TIMA_RELOADING) { + gb->io_registers[GB_IO_IF] |= 4; + gb->delayed_interrupts |= 4; // Timer interrupt is not aligned to a T-cycle and therefore is effective only the next one. gb->tima_reload_state = GB_TIMA_RELOADED; } } @@ -154,7 +157,6 @@ static void increase_tima(GB_gameboy_t *gb) gb->io_registers[GB_IO_TIMA]++; if (gb->io_registers[GB_IO_TIMA] == 0) { gb->io_registers[GB_IO_TIMA] = gb->io_registers[GB_IO_TMA]; - gb->io_registers[GB_IO_IF] |= 4; gb->tima_reload_state = GB_TIMA_RELOADING; } } diff --git a/Core/z80_cpu.c b/Core/z80_cpu.c index 6ea6a38..b6dde8a 100644 --- a/Core/z80_cpu.c +++ b/Core/z80_cpu.c @@ -1337,9 +1337,9 @@ static GB_opcode_t *opcodes[256] = { void GB_cpu_run(GB_gameboy_t *gb) { gb->vblank_just_occured = false; - bool interrupt = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F; + uint8_t interrupt_queue = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F & ~gb->delayed_interrupts; - if (interrupt) { + if (interrupt_queue) { gb->halted = false; } @@ -1354,9 +1354,8 @@ void GB_cpu_run(GB_gameboy_t *gb) gb->ime_toggle = false; } - if (effecitve_ime && interrupt) { + if (effecitve_ime && interrupt_queue) { uint8_t interrupt_bit = 0; - uint8_t interrupt_queue = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F; while (!(interrupt_queue & 1)) { interrupt_queue >>= 1; interrupt_bit++;