From ff5dd7f50cba55c7c0a342ad5a5fa4f5b1ac65aa Mon Sep 17 00:00:00 2001 From: Mr-Wiseguy Date: Fri, 15 Mar 2024 01:17:56 -0400 Subject: [PATCH] Patch giants cutscene to fix music desync, update RT64 --- lib/RT64-HLE | 2 +- patches/fixes.c | 41 +++++++++++++++++++++++++++++++++++++++++ patches/ui_patches.c | 15 +++++++++++++-- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/lib/RT64-HLE b/lib/RT64-HLE index 33b5686..97502ff 160000 --- a/lib/RT64-HLE +++ b/lib/RT64-HLE @@ -1 +1 @@ -Subproject commit 33b5686c649bb501884d114192924233957c9a49 +Subproject commit 97502ffed099612b59ce23a886d78873d9c6e9ef diff --git a/patches/fixes.c b/patches/fixes.c index f66ef1b..1341c2c 100644 --- a/patches/fixes.c +++ b/patches/fixes.c @@ -1,5 +1,6 @@ #include "patches.h" #include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" +#include "overlays/actors/ovl_En_Fall/z_en_fall.h" #define PAGE_BG_WIDTH (PAGE_BG_COLS * PAGE_BG_QUAD_WIDTH) #define PAGE_BG_HEIGHT (PAGE_BG_ROWS * PAGE_BG_QUAD_HEIGHT) @@ -257,3 +258,43 @@ Gfx* KaleidoScope_DrawPageSections(Gfx* gfx, Vtx* vertices, TexturePtr* textures return gfx; } + +typedef void (*CutsceneHandler)(PlayState* play, CutsceneContext* csCtx); +extern CutsceneHandler sScriptedCutsceneHandlers[]; +void Cutscene_SetupScripted(PlayState* play, CutsceneContext* csCtx); + +int extra_vis = 0; + +// @recomp Patch the giants cutscene to make certain frames take longer to mimic performance on console. +// This prevents the music from desyncing from the cutscene as it was designed around the console's frame times. +void Cutscene_UpdateScripted(PlayState* play, CutsceneContext* csCtx) { + if ((gSaveContext.cutsceneTrigger != 0) && (play->transitionTrigger == TRANS_TRIGGER_START)) { + gSaveContext.cutsceneTrigger = 0; + } + + if ((gSaveContext.cutsceneTrigger != 0) && (csCtx->state == CS_STATE_IDLE)) { + gSaveContext.save.cutsceneIndex = 0xFFFD; + gSaveContext.cutsceneTrigger = 1; + } + + if (gSaveContext.save.cutsceneIndex >= 0xFFF0) { + Cutscene_SetupScripted(play, csCtx); + sScriptedCutsceneHandlers[csCtx->state](play, csCtx); + } + + // @recomp Insert extra VI interrupt delays on certain frames of the giants cutscene to match console + // framerates. This prevents the music from desyncing with the cutscene. + if (play->sceneId == SCENE_00KEIKOKU && gSaveContext.sceneLayer == 1) { + s32 curFrame = play->csCtx.curFrame; + s32 scriptIndex = play->csCtx.scriptIndex; + // These regions of lag were determined by measuring framerate on console, though they pretty clearly + // correspond to specific camera angles and effects active during the cutscene. + if ( + (scriptIndex == 0 && curFrame >= 1123 && curFrame <= 1381) || + (scriptIndex != 0 && curFrame >= 4 && curFrame <= 85) || + (scriptIndex != 0 && curFrame >= 431 && curFrame <= 490) + ) { + extra_vis = 1; + } + } +} diff --git a/patches/ui_patches.c b/patches/ui_patches.c index 097f20a..49b7629 100644 --- a/patches/ui_patches.c +++ b/patches/ui_patches.c @@ -58,8 +58,6 @@ void Graph_SetNextGfxPool(GraphicsContext* gfxCtx) { // @recomp Enable RT64 extended GBI mode and set the current framerate OPEN_DISPS(gfxCtx); gEXEnable(POLY_OPA_DISP++); - gEXSetRefreshRate(POLY_OPA_DISP++, 60 / gFramerateDivisor); - // gEXPrint(POLY_OPA_DISP++); CLOSE_DISPS(gfxCtx); } @@ -78,6 +76,9 @@ extern volatile OSTime gRDPTimeAcc; extern OSTime sGraphPrevUpdateEndTime; extern volatile OSTime gGraphUpdatePeriod; + +extern int extra_vis; + // @recomp Modified to report errors instead of skipping frames. /** * Run the game state logic, then finalize the gfx buffer @@ -92,6 +93,9 @@ void Graph_ExecuteAndDraw(GraphicsContext* gfxCtx, GameState* gameState) { GameState_Update(gameState); OPEN_DISPS(gfxCtx); + + // @recomp Send the current framerate to RT64, including any extra VI interrupt periods. + gEXSetRefreshRate(POLY_OPA_DISP++, 60 / (gameState->framerateDivisor + extra_vis)); gSPEndDisplayList(WORK_DISP++); gSPEndDisplayList(POLY_OPA_DISP++); @@ -147,10 +151,17 @@ void Graph_ExecuteAndDraw(GraphicsContext* gfxCtx, GameState* gameState) { } if (!problem) { + // @recomp Temporarily adjust the framerate divisor to include any extra VI interrupt periods. + u8 old_divisor = gameState->framerateDivisor; + gameState->framerateDivisor += extra_vis; Graph_TaskSet00(gfxCtx, gameState); + // @recomp Restore the old framerate divisor. + gameState->framerateDivisor = old_divisor; gfxCtx->gfxPoolIdx++; gfxCtx->framebufferIndex++; } + // @recomp Clear any extra VI interrupt periods. + extra_vis = 0; { OSTime time = osGetTime();