diff --git a/Cocoa/Document.m b/Cocoa/Document.m index 453e3c8..74ca598 100644 --- a/Cocoa/Document.m +++ b/Cocoa/Document.m @@ -131,7 +131,7 @@ static void boot_rom_load(GB_gameboy_t *gb, GB_boot_rom_t type) [self loadBootROM: type]; } -static void vblank(GB_gameboy_t *gb) +static void vblank(GB_gameboy_t *gb, GB_vblank_type_t type) { Document *self = (__bridge Document *)GB_get_user_data(gb); [self vblank]; diff --git a/Core/display.c b/Core/display.c index cfe0376..3e50d4c 100644 --- a/Core/display.c +++ b/Core/display.c @@ -106,7 +106,7 @@ typedef struct __attribute__((packed)) { uint8_t flags; } object_t; -void GB_display_vblank(GB_gameboy_t *gb) +void GB_display_vblank(GB_gameboy_t *gb, GB_vblank_type_t type) { gb->vblank_just_occured = true; gb->cycles_since_vblank_callback = 0; @@ -211,7 +211,7 @@ void GB_display_vblank(GB_gameboy_t *gb) GB_handle_rumble(gb); if (gb->vblank_callback) { - gb->vblank_callback(gb); + gb->vblank_callback(gb, type); } GB_timing_sync(gb); } @@ -1348,7 +1348,7 @@ void GB_display_run(GB_gameboy_t *gb, unsigned cycles, bool force) /* The PPU does not advance while in STOP mode on the DMG */ if (gb->stopped && !GB_is_cgb(gb)) { if (gb->cycles_since_vblank_callback >= LCDC_PERIOD) { - GB_display_vblank(gb); + GB_display_vblank(gb, GB_VBLANK_TYPE_ARTIFICIAL); } return; } @@ -1402,7 +1402,7 @@ void GB_display_run(GB_gameboy_t *gb, unsigned cycles, bool force) if (gb->cycles_since_vblank_callback < LCDC_PERIOD) { GB_SLEEP(gb, display, 1, LCDC_PERIOD - gb->cycles_since_vblank_callback); } - GB_display_vblank(gb); + GB_display_vblank(gb, GB_VBLANK_TYPE_LCD_OFF); gb->cgb_repeated_a_frame = true; } return; @@ -1889,7 +1889,7 @@ skip_slow_mode_3: // Todo: unverified timing gb->current_lcd_line++; if (gb->current_lcd_line == LINES && GB_is_sgb(gb)) { - GB_display_vblank(gb); + GB_display_vblank(gb, GB_VBLANK_TYPE_NORMAL_FRAME); } if (gb->icd_hreset_callback) { @@ -1931,13 +1931,13 @@ skip_slow_mode_3: if (gb->frame_skip_state == GB_FRAMESKIP_LCD_TURNED_ON) { if (GB_is_cgb(gb)) { - GB_display_vblank(gb); + GB_display_vblank(gb, GB_VBLANK_TYPE_NORMAL_FRAME); gb->frame_skip_state = GB_FRAMESKIP_FIRST_FRAME_SKIPPED; } else { if (!GB_is_sgb(gb) || gb->current_lcd_line < LINES) { gb->is_odd_frame ^= true; - GB_display_vblank(gb); + GB_display_vblank(gb, GB_VBLANK_TYPE_NORMAL_FRAME); } gb->frame_skip_state = GB_FRAMESKIP_SECOND_FRAME_RENDERED; } @@ -1945,7 +1945,7 @@ skip_slow_mode_3: else { if (!GB_is_sgb(gb) || gb->current_lcd_line < LINES) { gb->is_odd_frame ^= true; - GB_display_vblank(gb); + GB_display_vblank(gb, GB_VBLANK_TYPE_NORMAL_FRAME); } if (gb->frame_skip_state == GB_FRAMESKIP_FIRST_FRAME_SKIPPED) { gb->cgb_repeated_a_frame = true; diff --git a/Core/display.h b/Core/display.h index d50dc18..bf0c83d 100644 --- a/Core/display.h +++ b/Core/display.h @@ -5,12 +5,18 @@ #include #include +typedef enum { + GB_VBLANK_TYPE_NORMAL_FRAME, // An actual Vblank-triggered frame + GB_VBLANK_TYPE_LCD_OFF, // An artificial frame pushed while the LCD was off + GB_VBLANK_TYPE_ARTIFICIAL, // An artificial frame pushed for some other reason +} GB_vblank_type_t; + #ifdef GB_INTERNAL internal void GB_display_run(GB_gameboy_t *gb, unsigned cycles, bool force); internal void GB_palette_changed(GB_gameboy_t *gb, bool background_palette, uint8_t index); internal void GB_STAT_update(GB_gameboy_t *gb); internal void GB_lcd_off(GB_gameboy_t *gb); -internal void GB_display_vblank(GB_gameboy_t *gb); +internal void GB_display_vblank(GB_gameboy_t *gb, GB_vblank_type_t type); #define GB_display_sync(gb) GB_display_run(gb, 0, true) enum { diff --git a/Core/gb.h b/Core/gb.h index 5330461..1621149 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -283,7 +283,7 @@ typedef enum { #endif #endif -typedef void (*GB_vblank_callback_t)(GB_gameboy_t *gb); +typedef void (*GB_vblank_callback_t)(GB_gameboy_t *gb, GB_vblank_type_t type); typedef void (*GB_log_callback_t)(GB_gameboy_t *gb, const char *string, GB_log_attributes attributes); typedef char *(*GB_input_callback_t)(GB_gameboy_t *gb); typedef uint32_t (*GB_rgb_encode_callback_t)(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b); diff --git a/Core/memory.c b/Core/memory.c index f123e46..18f8cdf 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -1422,21 +1422,13 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) case GB_IO_LCDC: if ((value & 0x80) && !(gb->io_registers[GB_IO_LCDC] & 0x80)) { - if (value & 0x80) { - // LCD turned on - if (!gb->lcd_disabled_outside_of_vblank && - (gb->cycles_since_vblank_callback > 10 * 456 || GB_is_sgb(gb))) { - // Trigger a vblank here so we don't exceed LCDC_PERIOD - GB_display_vblank(gb); - } - } - else { - // LCD turned off - if (gb->current_line < 144) { - // ROM might be repeatedly disabling LCDC outside of vblank, avoid callback spam - gb->lcd_disabled_outside_of_vblank = true; - } + // LCD turned on + if (!gb->lcd_disabled_outside_of_vblank && + (gb->cycles_since_vblank_callback > 10 * 456 || GB_is_sgb(gb))) { + // Trigger a vblank here so we don't exceed LCDC_PERIOD + GB_display_vblank(gb, GB_VBLANK_TYPE_ARTIFICIAL); } + gb->display_cycles = 0; gb->display_state = 0; gb->double_speed_alignment = 0; diff --git a/QuickLook/get_image_for_rom.c b/QuickLook/get_image_for_rom.c index b9f87ed..f6e53fa 100755 --- a/QuickLook/get_image_for_rom.c +++ b/QuickLook/get_image_for_rom.c @@ -25,7 +25,7 @@ static void log_callback(GB_gameboy_t *gb, const char *string, GB_log_attributes } -static void vblank(GB_gameboy_t *gb) +static void vblank(GB_gameboy_t *gb, GB_vblank_type_t type) { struct local_data *local_data = (struct local_data *)GB_get_user_data(gb); diff --git a/SDL/main.c b/SDL/main.c index da8c40e..9a85661 100644 --- a/SDL/main.c +++ b/SDL/main.c @@ -462,7 +462,7 @@ static uint32_t rgb_encode(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b) return SDL_MapRGB(pixel_format, r, g, b); } -static void vblank(GB_gameboy_t *gb) +static void vblank(GB_gameboy_t *gb, GB_vblank_type_t type) { if (underclock_down && clock_mutliplier > 0.5) { clock_mutliplier -= 1.0/16; diff --git a/Tester/main.c b/Tester/main.c index a3add10..d4fb305 100755 --- a/Tester/main.c +++ b/Tester/main.c @@ -123,7 +123,7 @@ static void handle_buttons(GB_gameboy_t *gb) } -static void vblank(GB_gameboy_t *gb) +static void vblank(GB_gameboy_t *gb, GB_vblank_type_t type) { /* Detect common crashes and stop the test early */ if (frames < test_length - 1) { diff --git a/libretro/libretro.c b/libretro/libretro.c index e73ab61..3899864 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -248,12 +248,12 @@ static void audio_callback(GB_gameboy_t *gb, GB_sample_t *sample) output_audio_buffer.data[output_audio_buffer.size++] = sample->right; } -static void vblank1(GB_gameboy_t *gb) +static void vblank1(GB_gameboy_t *gb, GB_vblank_type_t type) { vblank1_occurred = true; } -static void vblank2(GB_gameboy_t *gb) +static void vblank2(GB_gameboy_t *gb, GB_vblank_type_t type) { vblank2_occurred = true; }