Made capped framerates and vsync smoother

This commit is contained in:
MysterD 2022-05-28 20:13:02 -07:00
parent 123abbbc37
commit e47e1ede47
4 changed files with 27 additions and 33 deletions

View File

@ -300,7 +300,10 @@ void display_and_vsync(void) {
gGoddardVblankCallback(); gGoddardVblankCallback();
gGoddardVblankCallback = NULL; 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); profiler_log_thread5_time(AFTER_DISPLAY_LISTS);
osRecvMesg(&gGameVblankQueue, &D_80339BEC, OS_MESG_BLOCK); osRecvMesg(&gGameVblankQueue, &D_80339BEC, OS_MESG_BLOCK);
osViSwapBuffer((void *) PHYSICAL_TO_VIRTUAL(gPhysicalFrameBuffers[sCurrFBNum])); osViSwapBuffer((void *) PHYSICAL_TO_VIRTUAL(gPhysicalFrameBuffers[sCurrFBNum]));

View File

@ -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 *unused_try_allocate(struct LinkedList *destList,
struct LinkedList *freeList) { struct LinkedList *freeList) {
if (!destList || !freeList) { return; } if (!destList || !freeList) { return NULL; }
struct LinkedList *node = freeList->next; struct LinkedList *node = freeList->next;
if (node != NULL) { if (node != NULL) {

View File

@ -47,14 +47,14 @@ static void debug_warp_level1() {
} }
static void debug_warp_level2() { static void debug_warp_level2() {
extern f32 gGameSpeed; extern f64 gGameSpeed;
gGameSpeed = MAX(gGameSpeed - 0.1f, 0.1f); gGameSpeed = MAX(gGameSpeed - 0.1f, 0.1f);
printf("GAME SPEED: %f\n", gGameSpeed); printf("GAME SPEED: %f\n", gGameSpeed);
//dynos_warp_to_level(gCurrLevelNum, gCurrAreaIndex^3, 1); //dynos_warp_to_level(gCurrLevelNum, gCurrAreaIndex^3, 1);
} }
static void debug_warp_level3() { static void debug_warp_level3() {
extern f32 gGameSpeed; extern f64 gGameSpeed;
gGameSpeed = MIN(gGameSpeed + 0.1f, 10.0f); gGameSpeed = MIN(gGameSpeed + 0.1f, 10.0f);
printf("GAME SPEED: %f\n", gGameSpeed); printf("GAME SPEED: %f\n", gGameSpeed);
//dynos_warp_to_level(LEVEL_CASTLE_GROUNDS, 1, 1); //dynos_warp_to_level(LEVEL_CASTLE_GROUNDS, 1, 1);

View File

@ -38,6 +38,7 @@
#include "controller/controller_keyboard.h" #include "controller/controller_keyboard.h"
#include "fs/fs.h" #include "fs/fs.h"
#include "game/display.h" // for gGlobalTimer
#include "game/game_init.h" #include "game/game_init.h"
#include "game/main.h" #include "game/main.h"
#include "game/rumble_init.h" #include "game/rumble_init.h"
@ -73,7 +74,7 @@ u32 gNumVblanks = 0;
u8 gRenderingInterpolated = 0; u8 gRenderingInterpolated = 0;
f32 gRenderingDelta = 0; f32 gRenderingDelta = 0;
f32 gGameSpeed = 1.0f; // TODO: should probably remove f64 gGameSpeed = 1.0f; // TODO: should probably remove
#define FRAMERATE 30 #define FRAMERATE 30
static const f64 sFrameTime = (1.0 / ((double)FRAMERATE)); 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; static bool inited = false;
#include "game/display.h" // for gGlobalTimer
void send_display_list(struct SPTask *spTask) { void send_display_list(struct SPTask *spTask) {
if (!inited) return; if (!inited) return;
gfx_run((Gfx *)spTask->task.t.data_ptr); gfx_run((Gfx *)spTask->task.t.data_ptr);
@ -160,18 +160,6 @@ static inline void patch_interpolations(f32 delta) {
patch_djui_hud(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) { void produce_interpolation_frames_and_delay(void) {
gRenderingInterpolated = true; gRenderingInterpolated = true;
@ -179,28 +167,37 @@ void produce_interpolation_frames_and_delay(void) {
// sanity check target time to deal with hangs and such // sanity check target time to deal with hangs and such
f64 curTime = clock_elapsed_f64(); f64 curTime = clock_elapsed_f64();
if (fabs(sFrameTargetTime - curTime) > 1) { 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) { while ((curTime = clock_elapsed_f64()) < sFrameTargetTime) {
sLastFrameTimeStart = curTime; // interpolate and render
gfx_start_frame(); gfx_start_frame();
f32 delta = (configWindow.vsync || !configUncappedFramerate) f32 delta = MIN((curTime - sFrameTimeStart) / (sFrameTargetTime - sFrameTimeStart), 1);
? frames / sAvgFrames
: MIN((curTime - sFrameTimeStart) / (sFrameTargetTime - sFrameTimeStart), 1);
gRenderingDelta = delta; gRenderingDelta = delta;
patch_interpolations(delta); patch_interpolations(delta);
send_display_list(gGfxSPTask); send_display_list(gGfxSPTask);
gfx_end_frame(); 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++; frames++;
delay_frame();
} }
f32 fps = frames / (clock_elapsed_f64() - sFrameTimeStart); 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; sAvgFrames = sAvgFrames * 0.9 + frames * 0.1;
sFrameTimeStart = sFrameTargetTime;
sFrameTargetTime += sFrameTime * gGameSpeed; sFrameTargetTime += sFrameTime * gGameSpeed;
gRenderingInterpolated = false; gRenderingInterpolated = false;
@ -210,11 +207,7 @@ void produce_interpolation_frames_and_delay(void) {
void produce_one_frame(void) { void produce_one_frame(void) {
network_update(); network_update();
sFrameTimeStart = clock_elapsed_f64();
sLastFrameTimeStart = sFrameTimeStart;
patch_interpolations_before(); patch_interpolations_before();
gfx_start_frame();
const f32 master_mod = (f32)configMasterVolume / 127.0f; const f32 master_mod = (f32)configMasterVolume / 127.0f;
set_sequence_player_volume(SEQ_PLAYER_LEVEL, (f32)configMusicVolume / 127.0f * master_mod); 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); audio_api->play((u8 *)audio_buffer, 2 * num_audio_samples * 4);
gfx_end_frame();
produce_interpolation_frames_and_delay(); produce_interpolation_frames_and_delay();
} }