Implemented LCD first-frame-skip behavior, fixes a visual glitch in Pokémon Pinball

This commit is contained in:
Lior Halphon 2017-06-03 16:42:42 +03:00
parent 48acc09e91
commit d72807dd67
3 changed files with 18 additions and 1 deletions

View File

@ -318,8 +318,14 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles)
if (gb->io_registers[GB_IO_STAT] & 0x20) { if (gb->io_registers[GB_IO_STAT] & 0x20) {
gb->stat_interrupt_line = true; gb->stat_interrupt_line = true;
} }
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); display_vblank(gb);
} }
}
/* Handle STAT changes for lines 0-143 */ /* Handle STAT changes for lines 0-143 */
else if (gb->display_cycles < LINES * LINE_LENGTH ) { else if (gb->display_cycles < LINES * LINE_LENGTH ) {

View File

@ -365,6 +365,14 @@ struct GB_gameboy_internal_s {
bool stat_interrupt_line; bool stat_interrupt_line;
uint8_t effective_scx; uint8_t effective_scx;
uint8_t current_window_line; 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 */ /* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */

View File

@ -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? */ /* It appears that there's a slight delay after enabling the screen? */
/* Todo: verify this. */ /* Todo: verify this. */
gb->display_cycles = gb->cgb_double_speed? -2 : -4; 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)) { else if (!(value & 0x80) && (gb->io_registers[GB_IO_LCDC] & 0x80)) {
/* Sync after turning off LCD */ /* Sync after turning off LCD */