diff --git a/Core/display.c b/Core/display.c index 94a73b47..2ca78d86 100755 --- a/Core/display.c +++ b/Core/display.c @@ -318,7 +318,13 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) if (gb->io_registers[GB_IO_STAT] & 0x20) { gb->stat_interrupt_line = true; } - display_vblank(gb); + if (gb->frame_skip_state == GB_FRAMESKIP_LCD_TURNED_ON) { + gb->frame_skip_state = GB_FRAMESKIP_FIRST_FRAME_SKIPPED; + } + else { + gb->frame_skip_state = GB_FRAMESKIP_SECOND_FRAME_RENDERED; + display_vblank(gb); + } } /* Handle STAT changes for lines 0-143 */ diff --git a/Core/gb.h b/Core/gb.h index edf52149..43a64d7a 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -365,6 +365,14 @@ struct GB_gameboy_internal_s { bool stat_interrupt_line; uint8_t effective_scx; uint8_t current_window_line; + /* The LCDC will skip the first frame it renders after turning it on, unless the previous + frame was skipped as well. + See https://www.reddit.com/r/EmuDev/comments/6exyxu/ */ + enum { + GB_FRAMESKIP_LCD_TURNED_ON, + GB_FRAMESKIP_FIRST_FRAME_SKIPPED, + GB_FRAMESKIP_SECOND_FRAME_RENDERED, + } frame_skip_state; ); /* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */ diff --git a/Core/memory.c b/Core/memory.c index da9f0e59..18c46eb6 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -439,6 +439,9 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) /* It appears that there's a slight delay after enabling the screen? */ /* Todo: verify this. */ gb->display_cycles = gb->cgb_double_speed? -2 : -4; + if (gb->frame_skip_state == GB_FRAMESKIP_SECOND_FRAME_RENDERED) { + gb->frame_skip_state = GB_FRAMESKIP_LCD_TURNED_ON; + } } else if (!(value & 0x80) && (gb->io_registers[GB_IO_LCDC] & 0x80)) { /* Sync after turning off LCD */