소스 검색

Simplify timers and automagically correct for time jumps

master
Nathaniel Walizer 11 달 전
부모
커밋
e1f3765cae
3개의 변경된 파일30개의 추가작업 그리고 36개의 파일을 삭제
  1. +11
    -6
      src/nese.c
  2. +13
    -13
      src/sdl_timer.c
  3. +6
    -17
      src/timer.h

+ 11
- 6
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;



+ 13
- 13
src/sdl_timer.c 파일 보기

@@ -1,21 +1,21 @@
#include <time.h>

#include "time.h"
#include "timer.h"

#include <SDL2/SDL.h>


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;
}

+ 6
- 17
src/timer.h 파일 보기

@@ -1,31 +1,20 @@
#ifndef NESE_TIMER_H_
#define NESE_TIMER_H_

#include <time.h>
#include <stdint.h>


#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_

불러오는 중...
취소
저장