diff --git a/Core/display.c b/Core/display.c index 2ca78d8..4d9f9c0 100755 --- a/Core/display.c +++ b/Core/display.c @@ -203,7 +203,7 @@ static void display_vblank(GB_gameboy_t *gb) } } - if (!gb->disable_rendering && (!(gb->io_registers[GB_IO_LCDC] & 0x80) || gb->stopped)) { + if (!gb->disable_rendering && ((!(gb->io_registers[GB_IO_LCDC] & 0x80) || gb->stopped) || gb->frame_skip_state == GB_FRAMESKIP_LCD_TURNED_ON)) { /* LCD is off, set screen to white */ uint32_t white = gb->rgb_encode_callback(gb, 0xFF, 0xFF, 0xFF); for (unsigned i = 0; i < WIDTH * LINES; i++) { @@ -319,7 +319,13 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles) gb->stat_interrupt_line = true; } if (gb->frame_skip_state == GB_FRAMESKIP_LCD_TURNED_ON) { - gb->frame_skip_state = GB_FRAMESKIP_FIRST_FRAME_SKIPPED; + if (!gb->is_cgb) { + display_vblank(gb); + gb->frame_skip_state = GB_FRAMESKIP_SECOND_FRAME_RENDERED; + } + else { + gb->frame_skip_state = GB_FRAMESKIP_FIRST_FRAME_SKIPPED; + } } else { gb->frame_skip_state = GB_FRAMESKIP_SECOND_FRAME_RENDERED; diff --git a/Core/gb.h b/Core/gb.h index 43a64d7..f788ca0 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -365,12 +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. + /* The LCDC will skip the first frame it renders after turning it on. + On the CGB, a frame is not skipped if 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_LCD_TURNED_ON, // On a DMG, the LCD renders a blank screen during this state, + // on a CGB, the previous frame is repeated (which might be + // blank if the LCD was off for more than a few cycles) + GB_FRAMESKIP_FIRST_FRAME_SKIPPED, // This state is 'skipped' when emulating a DMG GB_FRAMESKIP_SECOND_FRAME_RENDERED, } frame_skip_state; );