From e1f3765cae319e313fd86e83e05e1654fbb37dc4 Mon Sep 17 00:00:00 2001 From: Nathaniel Walizer Date: Sat, 11 Jan 2025 15:23:17 -0800 Subject: [PATCH] Simplify timers and automagically correct for time jumps --- src/nese.c | 17 +++++++++++------ src/sdl_timer.c | 26 +++++++++++++------------- src/timer.h | 23 ++++++----------------- 3 files changed, 30 insertions(+), 36 deletions(-) diff --git a/src/nese.c b/src/nese.c index d221352..a19c749 100644 --- a/src/nese.c +++ b/src/nese.c @@ -74,8 +74,7 @@ int main(int argc, char* argv[]) { nes_render(rend, &sys.ppu); - struct timespec t_target = {0}; - time_get(&t_target); + time_us t_target = time_now(); uint64_t cycle_last_frame = 0; uint64_t total_cycles = 0; @@ -92,14 +91,20 @@ int main(int argc, char* argv[]) { // Sleep to catch up to master clock uint64_t elapsed_cycles = total_cycles - cycle_last_frame; - int elapsed_ns = ( elapsed_cycles * + int elapsed_us = ( elapsed_cycles * nes_clock_master_den * - NS_PER_S ) / + US_PER_S ) / nes_clock_master_num; - t_add_ns(&t_target, &t_target, elapsed_ns); + t_target += elapsed_us; - time_sleep_until(&t_target); + time_us slept_us = time_sleep_until(t_target); + (void)slept_us; + + if (slept_us <= -elapsed_us) { + // We're way out of sync. + t_target = time_now(); + } cycle_last_frame = total_cycles; diff --git a/src/sdl_timer.c b/src/sdl_timer.c index b444882..eca8aa4 100644 --- a/src/sdl_timer.c +++ b/src/sdl_timer.c @@ -1,21 +1,21 @@ -#include - -#include "time.h" +#include "timer.h" #include -void time_get(struct timespec* ts) { - uint64_t time = SDL_GetTicks64(); - ts->tv_sec = time / 1000U; - ts->tv_nsec = (time % 1000U) * 1000U * 1000U; +time_us time_now(void) { + return (SDL_GetTicks64() * 1000U); +} + +void time_sleep(time_us sleep_us) { + SDL_Delay(sleep_us / 1000U); } -void time_sleep_until(const struct timespec* ts) { - uint64_t t_target = ( (ts->tv_sec * 1000ULL) + - (ts->tv_nsec / (1000U * 1000U))); - uint64_t t_now = SDL_GetTicks64(); - if (t_target > t_now) { - SDL_Delay(t_target - t_now); +time_us time_sleep_until(time_us t_target) { + time_us t_now = time_now(); + time_us t_diff = t_target - t_now; + if (t_diff > 0) { + time_sleep(t_diff); } + return t_diff; } diff --git a/src/timer.h b/src/timer.h index 81669c5..ebf23b4 100644 --- a/src/timer.h +++ b/src/timer.h @@ -1,31 +1,20 @@ #ifndef NESE_TIMER_H_ #define NESE_TIMER_H_ -#include +#include -#define NS_PER_S (1000U * 1000U * 1000U) +#define US_PER_S (1000U * 1000U) -static inline int t_diff_ns(const struct timespec* b, - const struct timespec* a) { - int sec = (b->tv_sec - a->tv_sec); - int nsec = (b->tv_nsec - a->tv_nsec); - return ((sec * NS_PER_S) + nsec); -} +typedef int64_t time_us; -static inline void t_add_ns(struct timespec* s, - const struct timespec* a, - int b) { - int nsec = a->tv_nsec + b; - s->tv_sec = a->tv_sec + (nsec / NS_PER_S); - s->tv_nsec = nsec % NS_PER_S; -} +time_us time_now(void); -void time_get(struct timespec*); +void time_sleep(time_us); -void time_sleep_until(const struct timespec*); +time_us time_sleep_until(time_us); #endif // NESE_TIME_H_