diff --git a/Core/memory.c b/Core/memory.c index 2d69fe5..762e169 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -1699,6 +1699,7 @@ bool GB_is_dma_active(GB_gameboy_t *gb) void GB_dma_run(GB_gameboy_t *gb) { if (gb->dma_current_dest == 0xa1) return; + if (unlikely(gb->halted || gb->stopped)) return; signed cycles = gb->dma_cycles + gb->dma_cycles_modulo; gb->in_dma_read = true; while (unlikely(cycles >= 4)) { diff --git a/Core/sm83_cpu.c b/Core/sm83_cpu.c index fdaf85d..1915705 100644 --- a/Core/sm83_cpu.c +++ b/Core/sm83_cpu.c @@ -372,6 +372,11 @@ static void stop(GB_gameboy_t *gb, uint8_t opcode) bool interrupt_pending = (gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F); // When entering with IF&IE, the 2nd byte of STOP is actually executed if (!exit_by_joyp) { + if (!immediate_exit) { + // TODO: verify this! + gb->dma_cycles = 4; + GB_dma_run(gb); + } enter_stop_mode(gb); } @@ -414,6 +419,9 @@ static void stop(GB_gameboy_t *gb, uint8_t opcode) if (immediate_exit) { leave_stop_mode(gb); if (!interrupt_pending) { + // TODO: verify this! + gb->dma_cycles = 4; + GB_dma_run(gb); gb->halted = true; gb->just_halted = true; } @@ -1004,7 +1012,6 @@ static void halt(GB_gameboy_t *gb, uint8_t opcode) gb->pending_cycles = 0; GB_advance_cycles(gb, 4); - gb->halted = true; /* Despite what some online documentations say, the HALT bug also happens on a CGB, in both CGB and DMG modes. */ if (((gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F) != 0)) { if (gb->ime) { @@ -1016,6 +1023,12 @@ static void halt(GB_gameboy_t *gb, uint8_t opcode) gb->halt_bug = true; } } + else { + // TODO: verify the timing! + gb->dma_cycles = 4; + GB_dma_run(gb); + gb->halted = true; + } gb->just_halted = true; } diff --git a/Core/timing.c b/Core/timing.c index e9b527c..7525eeb 100644 --- a/Core/timing.c +++ b/Core/timing.c @@ -384,7 +384,7 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles) } gb->apu.pcm_mask[0] = gb->apu.pcm_mask[1] = 0xFF; // Sort of hacky, but too many cross-component interactions to do it right // Affected by speed boost - gb->dma_cycles += cycles; + gb->dma_cycles = cycles; timers_run(gb, cycles); if (unlikely(!gb->stopped)) {