From ad54dc57b06c451206cadca05d7b2b943c178d7e Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sun, 21 Mar 2021 15:15:04 +0200 Subject: [PATCH] Improved time syncing when turning the LCD on and off, fixes #193 --- Core/memory.c | 1 + Core/timing.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Core/memory.c b/Core/memory.c index 8aacf41a..b1619a6b 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -919,6 +919,7 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) else if (gb->frame_skip_state == GB_FRAMESKIP_SECOND_FRAME_RENDERED) { gb->frame_skip_state = GB_FRAMESKIP_LCD_TURNED_ON; } + GB_timing_sync(gb); } else if (!(value & 0x80) && (gb->io_registers[GB_IO_LCDC] & 0x80)) { /* Sync after turning off LCD */ diff --git a/Core/timing.c b/Core/timing.c index dedc5a0a..18cf571c 100644 --- a/Core/timing.c +++ b/Core/timing.c @@ -64,11 +64,16 @@ void GB_timing_sync(GB_gameboy_t *gb) uint64_t target_nanoseconds = gb->cycles_since_last_sync * 1000000000LL / 2 / GB_get_clock_rate(gb); /* / 2 because we use 8MHz units */ int64_t nanoseconds = get_nanoseconds(); int64_t time_to_sleep = target_nanoseconds + gb->last_sync - nanoseconds; - if (time_to_sleep > 0 && time_to_sleep < LCDC_PERIOD * 1000000000LL / GB_get_clock_rate(gb)) { + if (time_to_sleep > 0 && time_to_sleep < LCDC_PERIOD * 1200000000LL / GB_get_clock_rate(gb)) { // +20% to be more forgiving nsleep(time_to_sleep); gb->last_sync += target_nanoseconds; } else { + if (-time_to_sleep < LCDC_PERIOD * 1200000000LL / GB_get_clock_rate(gb)) { + // We're running a bit too slow, but the difference is small enough, + // just skip this sync and let it even out + return; + } gb->last_sync = nanoseconds; }