From e47e1ede47c8f4537082991c09fc4d0a1de328a6 Mon Sep 17 00:00:00 2001 From: MysterD Date: Sat, 28 May 2022 20:13:02 -0700 Subject: [PATCH] Made capped framerates and vsync smoother --- src/game/game_init.c | 5 +- src/game/spawn_object.c | 2 +- src/pc/controller/controller_keyboard_debug.c | 4 +- src/pc/pc_main.c | 49 ++++++++----------- 4 files changed, 27 insertions(+), 33 deletions(-) diff --git a/src/game/game_init.c b/src/game/game_init.c index 2eff4276..868e48e3 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -300,7 +300,10 @@ void display_and_vsync(void) { gGoddardVblankCallback(); gGoddardVblankCallback = NULL; } - send_display_list(&gGfxPool->spTask); + + // we only produce interpolated frames now + //send_display_list(&gGfxPool->spTask); + profiler_log_thread5_time(AFTER_DISPLAY_LISTS); osRecvMesg(&gGameVblankQueue, &D_80339BEC, OS_MESG_BLOCK); osViSwapBuffer((void *) PHYSICAL_TO_VIRTUAL(gPhysicalFrameBuffers[sCurrFBNum])); diff --git a/src/game/spawn_object.c b/src/game/spawn_object.c index 9daccd4b..fa3e098c 100644 --- a/src/game/spawn_object.c +++ b/src/game/spawn_object.c @@ -59,7 +59,7 @@ void unused_init_free_list(struct LinkedList *usedList, struct LinkedList **pFre */ struct LinkedList *unused_try_allocate(struct LinkedList *destList, struct LinkedList *freeList) { - if (!destList || !freeList) { return; } + if (!destList || !freeList) { return NULL; } struct LinkedList *node = freeList->next; if (node != NULL) { diff --git a/src/pc/controller/controller_keyboard_debug.c b/src/pc/controller/controller_keyboard_debug.c index bc8bcdff..6c2f5614 100644 --- a/src/pc/controller/controller_keyboard_debug.c +++ b/src/pc/controller/controller_keyboard_debug.c @@ -47,14 +47,14 @@ static void debug_warp_level1() { } static void debug_warp_level2() { - extern f32 gGameSpeed; + extern f64 gGameSpeed; gGameSpeed = MAX(gGameSpeed - 0.1f, 0.1f); printf("GAME SPEED: %f\n", gGameSpeed); //dynos_warp_to_level(gCurrLevelNum, gCurrAreaIndex^3, 1); } static void debug_warp_level3() { - extern f32 gGameSpeed; + extern f64 gGameSpeed; gGameSpeed = MIN(gGameSpeed + 0.1f, 10.0f); printf("GAME SPEED: %f\n", gGameSpeed); //dynos_warp_to_level(LEVEL_CASTLE_GROUNDS, 1, 1); diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index 42fb17c0..91c26ac0 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -38,6 +38,7 @@ #include "controller/controller_keyboard.h" #include "fs/fs.h" +#include "game/display.h" // for gGlobalTimer #include "game/game_init.h" #include "game/main.h" #include "game/rumble_init.h" @@ -73,7 +74,7 @@ u32 gNumVblanks = 0; u8 gRenderingInterpolated = 0; f32 gRenderingDelta = 0; -f32 gGameSpeed = 1.0f; // TODO: should probably remove +f64 gGameSpeed = 1.0f; // TODO: should probably remove #define FRAMERATE 30 static const f64 sFrameTime = (1.0 / ((double)FRAMERATE)); @@ -100,7 +101,6 @@ void set_vblank_handler(UNUSED s32 index, UNUSED struct VblankHandler *handler, static bool inited = false; -#include "game/display.h" // for gGlobalTimer void send_display_list(struct SPTask *spTask) { if (!inited) return; gfx_run((Gfx *)spTask->task.t.data_ptr); @@ -160,18 +160,6 @@ static inline void patch_interpolations(f32 delta) { patch_djui_hud(delta); } -static void delay_frame(void) { - if (configUncappedFramerate) { return; } - static f32 sDelayRounding = 0; - f64 targetDelta = 1.0 / (f64)configFrameLimit; - - f64 actualDelta = clock_elapsed_f64() - sLastFrameTimeStart; - if (actualDelta < targetDelta) { - f64 delay = sDelayRounding + ((targetDelta - actualDelta) * 1000.0); - sDelayRounding = delay - (u32)delay; - wm_api->delay((u32)delay); - } -} void produce_interpolation_frames_and_delay(void) { gRenderingInterpolated = true; @@ -179,28 +167,37 @@ void produce_interpolation_frames_and_delay(void) { // sanity check target time to deal with hangs and such f64 curTime = clock_elapsed_f64(); if (fabs(sFrameTargetTime - curTime) > 1) { - sFrameTargetTime = curTime; + sFrameTargetTime = curTime - 0.01f; } - delay_frame(); - u64 frames = 1; + u64 frames = 0; while ((curTime = clock_elapsed_f64()) < sFrameTargetTime) { - sLastFrameTimeStart = curTime; + // interpolate and render gfx_start_frame(); - f32 delta = (configWindow.vsync || !configUncappedFramerate) - ? frames / sAvgFrames - : MIN((curTime - sFrameTimeStart) / (sFrameTargetTime - sFrameTimeStart), 1); + f32 delta = MIN((curTime - sFrameTimeStart) / (sFrameTargetTime - sFrameTimeStart), 1); gRenderingDelta = delta; patch_interpolations(delta); send_display_list(gGfxSPTask); gfx_end_frame(); + + // delay + if (!configUncappedFramerate) { + f64 targetDelta = 1.0 / (f64)configFrameLimit; + f64 now = clock_elapsed_f64(); + f64 actualDelta = now - curTime; + if (actualDelta < targetDelta) { + f64 delay = ((targetDelta - actualDelta) * 1000.0); + wm_api->delay((u32)delay); + } + } + frames++; - delay_frame(); } f32 fps = frames / (clock_elapsed_f64() - sFrameTimeStart); - sAvgFps = sAvgFps * 0.99 + fps * 0.01; + sAvgFps = sAvgFps * 0.6 + fps * 0.4; sAvgFrames = sAvgFrames * 0.9 + frames * 0.1; + sFrameTimeStart = sFrameTargetTime; sFrameTargetTime += sFrameTime * gGameSpeed; gRenderingInterpolated = false; @@ -210,11 +207,7 @@ void produce_interpolation_frames_and_delay(void) { void produce_one_frame(void) { network_update(); - sFrameTimeStart = clock_elapsed_f64(); - sLastFrameTimeStart = sFrameTimeStart; - patch_interpolations_before(); - gfx_start_frame(); const f32 master_mod = (f32)configMasterVolume / 127.0f; set_sequence_player_volume(SEQ_PLAYER_LEVEL, (f32)configMusicVolume / 127.0f * master_mod); @@ -240,8 +233,6 @@ void produce_one_frame(void) { audio_api->play((u8 *)audio_buffer, 2 * num_audio_samples * 4); - gfx_end_frame(); - produce_interpolation_frames_and_delay(); }