diff --git a/Core/gb.c b/Core/gb.c index cc85c92..1021dd9 100644 --- a/Core/gb.c +++ b/Core/gb.c @@ -1854,15 +1854,6 @@ unsigned GB_time_to_alarm(GB_gameboy_t *gb) return alarm_time - current_time; } -void GB_set_rtc_mode(GB_gameboy_t *gb, GB_rtc_mode_t mode) -{ - if (gb->rtc_mode != mode) { - gb->rtc_mode = mode; - gb->rtc_cycles = 0; - gb->last_rtc_second = time(NULL); - } -} - bool GB_has_accelerometer(GB_gameboy_t *gb) { return gb->cartridge_type->mbc_type == GB_MBC7; diff --git a/Core/gb.h b/Core/gb.h index d5a6471..3c77aed 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -247,11 +247,6 @@ typedef enum { GB_BOOT_ROM_AGB, } GB_boot_rom_t; -typedef enum { - GB_RTC_MODE_SYNC_TO_HOST, - GB_RTC_MODE_ACCURATE, -} GB_rtc_mode_t; - #ifdef GB_INTERNAL #define LCDC_PERIOD 70224 #define CPU_FREQUENCY 0x400000 @@ -640,6 +635,7 @@ struct GB_gameboy_internal_s { uint64_t last_sync; uint64_t cycles_since_last_sync; // In 8MHz units GB_rtc_mode_t rtc_mode; + uint32_t rtc_second_length; /* Audio */ GB_apu_output_t apu_output; @@ -861,10 +857,7 @@ void GB_disconnect_serial(GB_gameboy_t *gb); /* For cartridges with an alarm clock */ unsigned GB_time_to_alarm(GB_gameboy_t *gb); // 0 if no alarm - -/* RTC emulation mode */ -void GB_set_rtc_mode(GB_gameboy_t *gb, GB_rtc_mode_t mode); - + /* For cartridges motion controls */ bool GB_has_accelerometer(GB_gameboy_t *gb); // In units of g (gravity's acceleration). diff --git a/Core/timing.c b/Core/timing.c index 001869c..f8ffd80 100644 --- a/Core/timing.c +++ b/Core/timing.c @@ -248,11 +248,32 @@ static void advance_serial(GB_gameboy_t *gb, uint8_t cycles) } +void GB_set_rtc_mode(GB_gameboy_t *gb, GB_rtc_mode_t mode) +{ + if (gb->rtc_mode != mode) { + gb->rtc_mode = mode; + gb->rtc_cycles = 0; + gb->last_rtc_second = time(NULL); + } +} + + +void GB_set_rtc_multiplier(GB_gameboy_t *gb, double multiplier) +{ + if (multiplier == 1) { + gb->rtc_second_length = 0; + return; + } + + gb->rtc_second_length = GB_get_unmultiplied_clock_rate(gb) * 2 * multiplier; +} + static void rtc_run(GB_gameboy_t *gb, uint8_t cycles) { if (gb->cartridge_type->mbc_type != GB_HUC3 && !gb->cartridge_type->has_rtc) return; gb->rtc_cycles += cycles; time_t current_time = 0; + uint32_t rtc_second_length = unlikely(gb->rtc_second_length)? gb->rtc_second_length : GB_get_unmultiplied_clock_rate(gb) * 2; switch (gb->rtc_mode) { case GB_RTC_MODE_SYNC_TO_HOST: @@ -266,8 +287,8 @@ static void rtc_run(GB_gameboy_t *gb, uint8_t cycles) gb->rtc_cycles -= cycles; return; } - if (gb->rtc_cycles < GB_get_unmultiplied_clock_rate(gb) * 2) return; - gb->rtc_cycles -= GB_get_unmultiplied_clock_rate(gb) * 2; + if (gb->rtc_cycles < rtc_second_length) return; + gb->rtc_cycles -= rtc_second_length; current_time = gb->last_rtc_second + 1; break; } diff --git a/Core/timing.h b/Core/timing.h index d5d7356..96b2082 100644 --- a/Core/timing.h +++ b/Core/timing.h @@ -2,13 +2,23 @@ #define timing_h #include "defs.h" +typedef enum { + GB_RTC_MODE_SYNC_TO_HOST, + GB_RTC_MODE_ACCURATE, +} GB_rtc_mode_t; + +/* RTC emulation mode */ +void GB_set_rtc_mode(GB_gameboy_t *gb, GB_rtc_mode_t mode); + +/* Speed multiplier for the RTC, mostly for TAS syncing */ +void GB_set_rtc_multiplier(GB_gameboy_t *gb, double multiplier); + #ifdef GB_INTERNAL internal void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles); internal void GB_emulate_timer_glitch(GB_gameboy_t *gb, uint8_t old_tac, uint8_t new_tac); internal bool GB_timing_sync_turbo(GB_gameboy_t *gb); /* Returns true if should skip frame */ internal void GB_timing_sync(GB_gameboy_t *gb); internal void GB_set_internal_div_counter(GB_gameboy_t *gb, uint16_t value); - enum { GB_TIMA_RUNNING = 0, GB_TIMA_RELOADING = 1,