瀏覽代碼

Enforce realtime rendering

- Master clock cycles are truncated to nanoseconds, but this should
   be within tolerance of actual hardware implementations
master
Nathaniel Walizer 1 年之前
父節點
當前提交
889e8526bd
共有 2 個檔案被更改,包括 39 行新增13 行删除
  1. +38
    -1
      src/nese.c
  2. +1
    -12
      src/sdl_render.c

+ 38
- 1
src/nese.c 查看文件

@@ -1,5 +1,6 @@
#include <limits.h>
#include <stdlib.h>
#include <time.h>

#include "ines.h"
#include "render.h"
@@ -33,6 +34,23 @@ void e6502_dump_stack(e6502_Core* core, FILE* file) {
}


#define NS_PER_S (1000U * 1000U * 1000U)
/*
static 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);
}
*/
static 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;
}

extern nes_Renderer sdl_renderer;

static nes sys = {0};
@@ -54,6 +72,10 @@ int main(int argc, char* argv[]) {
nes_init(&sys);
nes_reset(&sys);

struct timespec t_target = {0};
clock_gettime(CLOCK_MONOTONIC, &t_target);
uint64_t cycle_last_frame = 0;

uint64_t total_cycles = 0;
int last_frame_rendered = -1;
for (int i = 0; i < n_loops && status == 0; ++i) {
@@ -68,11 +90,26 @@ int main(int argc, char* argv[]) {
us_run, run,
status == 0 ? "OK" : "Halted");
*/
// TODO: Check VBlank or scanline?
if ( status == 0 &&
sys.ppu.frame != last_frame_rendered) {
// TODO: Check VBlank or scanline?
status = nes_render(rend, &sys.ppu);
last_frame_rendered = sys.ppu.frame;

// Sleep to catch up to master clock
uint64_t elapsed_cycles = total_cycles -
cycle_last_frame;
int elapsed_ns = ( elapsed_cycles *
nes_clock_master_den *
NS_PER_S ) /
nes_clock_master_num;

t_add_ns(&t_target, &t_target, elapsed_ns);

clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
&t_target, NULL);

cycle_last_frame = total_cycles;
}
}



+ 1
- 12
src/sdl_render.c 查看文件

@@ -366,18 +366,7 @@ static int sdl_render(nes_Renderer* rend, nes_ppu* ppu) {
SDL_DestroyTexture(texture);
}

/*
// HACK: THIS IS TERRIBLE
static uint32_t last_ms = 0;
uint32_t now_ms = SDL_GetTicks();
if (last_ms != 0) {
int delay = (last_ms + (1000 / 35)) - now_ms;
if (delay > 0) SDL_Delay(delay);
// else fprintf(stderr, "Delta %d\n", now_ms - last_ms);
}
last_ms = now_ms;
*/

// TODO: Handle this in the input loop, or anywhere else
SDL_Event event = {0};
return (1 == SDL_PollEvent(&event) && event.type == SDL_QUIT) ?
-1 : 0;


Loading…
取消
儲存