From d72807dd672d0c6f5c39d1d8d6bf4729b7dad284 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sat, 3 Jun 2017 16:42:42 +0300 Subject: [PATCH] =?UTF-8?q?Implemented=20LCD=20first-frame-skip=20behavior?= =?UTF-8?q?,=20fixes=20a=20visual=20glitch=20in=20Pok=C3=A9mon=20Pinball?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/display.c | 8 +++++++- Core/gb.h | 8 ++++++++ Core/memory.c | 3 +++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Core/display.c b/Core/display.c index 94a73b4..2ca78d8 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 edf5214..43a64d7 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 da9f0e5..18c46eb 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 */