Fix a regression in speed switch timing, reset DIV on speed switch, better odd-mode detection and avoidance

This commit is contained in:
Lior Halphon 2020-12-25 20:40:39 +02:00
parent 159d9d0348
commit 4bbd27735f
3 changed files with 15 additions and 10 deletions

View File

@ -895,6 +895,7 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
if ((value & 0x80) && !(gb->io_registers[GB_IO_LCDC] & 0x80)) {
gb->display_cycles = 0;
gb->display_state = 0;
gb->double_speed_alignment = 0;
if (GB_is_sgb(gb)) {
gb->frame_skip_state = GB_FRAMESKIP_SECOND_FRAME_RENDERED;
}

View File

@ -332,6 +332,7 @@ static void nop(GB_gameboy_t *gb, uint8_t opcode)
static void enter_stop_mode(GB_gameboy_t *gb)
{
GB_write_memory(gb, 0xFF00 + GB_IO_DIV, 0);
gb->stopped = true;
gb->oam_ppu_blocked = !gb->oam_read_blocked;
gb->vram_ppu_blocked = !gb->vram_read_blocked;
@ -340,30 +341,30 @@ static void enter_stop_mode(GB_gameboy_t *gb)
static void leave_stop_mode(GB_gameboy_t *gb)
{
/* The CPU takes more time to wake up then the other components */
for (unsigned i = 0x200; i--;) {
GB_advance_cycles(gb, 0x10);
}
gb->stopped = false;
gb->oam_ppu_blocked = false;
gb->vram_ppu_blocked = false;
gb->cgb_palettes_ppu_blocked = false;
/* The CPU takes more time to wake up then the other components */
for (unsigned i = 0x2000; i--;) {
GB_advance_cycles(gb, 0x10);
}
GB_write_memory(gb, 0xFF00 + GB_IO_DIV, 0);
}
static void stop(GB_gameboy_t *gb, uint8_t opcode)
{
if (gb->io_registers[GB_IO_KEY1] & 0x1) {
if (gb->cgb_double_speed && gb->io_registers[GB_IO_LCDC] & 0x80) {
GB_log(gb, "Returning from double speed mode while the PPU is on may trigger odd-mode\n");
}
flush_pending_cycles(gb);
bool needs_alignment = false;
GB_advance_cycles(gb, 0x4);
/* Make sure we keep the CPU ticks aligned correctly when returning from double speed mode */
if (gb->double_speed_alignment & 7) {
GB_advance_cycles(gb, 0x4);
needs_alignment = true;
GB_log(gb, "ROM triggered PPU odd mode, which is currently not supported. Reverting to even-mode.\n");
}
gb->cgb_double_speed ^= true;
@ -388,7 +389,6 @@ static void stop(GB_gameboy_t *gb, uint8_t opcode)
enter_stop_mode(gb);
}
}
/* Todo: is PC being actually read? */
gb->pc++;
}

View File

@ -157,7 +157,9 @@ static void GB_set_internal_div_counter(GB_gameboy_t *gb, uint32_t value)
static void GB_timers_run(GB_gameboy_t *gb, uint8_t cycles)
{
if (gb->stopped) {
if (GB_is_cgb(gb)) {
gb->apu.apu_cycles += 4 << !gb->cgb_double_speed;
}
return;
}
@ -248,7 +250,9 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
}
// Not affected by speed boost
if (gb->io_registers[GB_IO_LCDC] & 0x80) {
gb->double_speed_alignment += cycles;
}
gb->hdma_cycles += cycles;
gb->apu_output.sample_cycles += cycles;
gb->cycles_since_last_sync += cycles;