From 54722284e1a16145af894614e60f94d05fc4f199 Mon Sep 17 00:00:00 2001 From: nclok1405 <155463060+nclok1405@users.noreply.github.com> Date: Tue, 17 Jun 2025 14:17:48 +0900 Subject: [PATCH] Converted the Frame Advance Alt Scheme to hooks --- .../Enhancements/FrameAdvanceAltScheme.cpp | 58 +++++++++++++++++++ .../vanilla-behavior/GIVanillaBehavior.h | 16 +++++ soh/src/code/z_frame_advance.c | 35 ++++------- soh/src/code/z_play.c | 9 +-- 4 files changed, 86 insertions(+), 32 deletions(-) create mode 100644 soh/soh/Enhancements/FrameAdvanceAltScheme.cpp diff --git a/soh/soh/Enhancements/FrameAdvanceAltScheme.cpp b/soh/soh/Enhancements/FrameAdvanceAltScheme.cpp new file mode 100644 index 000000000..11e94f50f --- /dev/null +++ b/soh/soh/Enhancements/FrameAdvanceAltScheme.cpp @@ -0,0 +1,58 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" +#include "soh/OTRGlobals.h" + +#include + +extern "C" { +#include "functions.h" +#include "macros.h" +#include "variables.h" + +extern PlayState* gPlayState; +} + +#define CVAR_FRAMEADVANCEALTSCHEME_NAME CVAR_DEVELOPER_TOOLS("FrameAdvanceAltScheme") +#define CVAR_FRAMEADVANCEALTSCHEME_DEFAULT 0 +#define CVAR_FRAMEADVANCEALTSCHEME_VALUE \ + CVarGetInteger(CVAR_FRAMEADVANCEALTSCHEME_NAME, CVAR_FRAMEADVANCEALTSCHEME_DEFAULT) + +void RegisterFrameAdvanceAltScheme() { + COND_VB_SHOULD(VB_FRAME_ADVANCE_BE_VANILLA, CVAR_FRAMEADVANCEALTSCHEME_VALUE, { + // Do not run vanilla Frame Advance codes. + *should = false; + }); + + COND_VB_SHOULD(VB_FRAME_ADVANCE_FREEZE_FRAME, CVAR_FRAMEADVANCEALTSCHEME_VALUE, { + FrameAdvanceContext* frameAdvCtx = va_arg(args, FrameAdvanceContext*); + Input* input = gPlayState->state.input; + bool runFrame = false; + + // Push START to toggle the frame advance mode. + if (CHECK_BTN_ALL(input[3].press.button, BTN_START)) { + frameAdvCtx->enabled = !frameAdvCtx->enabled; + if (frameAdvCtx->enabled) { + SPDLOG_DEBUG("Frame Advance is now enabled"); + } else { + SPDLOG_DEBUG("Frame Advance is now disabled"); + } + } + + // Push A to advance one frame. + // Hold L to run normally until L is released. + // Hold R to advance a frame every half second. + if (!frameAdvCtx->enabled || CVarGetInteger(CVAR_DEVELOPER_TOOLS("FrameAdvanceTick"), 0) || + CHECK_BTN_ALL(input[3].press.button, BTN_A) || CHECK_BTN_ALL(input[3].cur.button, BTN_L) || + CHECK_BTN_ALL(input[3].press.button, BTN_R) || + (CHECK_BTN_ALL(input[3].cur.button, BTN_R) && (++frameAdvCtx->timer >= 9))) { + CVarClear(CVAR_DEVELOPER_TOOLS("FrameAdvanceTick")); + frameAdvCtx->timer = 0; + runFrame = true; + } + + *should = !runFrame; + }); +} + +static RegisterShipInitFunc initFunc_FrameAdvanceAltScheme(RegisterFrameAdvanceAltScheme, + { CVAR_FRAMEADVANCEALTSCHEME_NAME }); diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 09defd088..b5cff9971 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -535,6 +535,22 @@ typedef enum { // - None VB_FIX_SAW_SOFTLOCK, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*FrameAdvanceContext` + VB_FRAME_ADVANCE_BE_VANILLA, + + // #### `result` + // ```c + // false + // ``` + // #### `args` + // - `*FrameAdvanceContext` + VB_FRAME_ADVANCE_FREEZE_FRAME, + // #### `result` // ```c // true diff --git a/soh/src/code/z_frame_advance.c b/soh/src/code/z_frame_advance.c index 4f70f4257..54aaff21f 100644 --- a/soh/src/code/z_frame_advance.c +++ b/soh/src/code/z_frame_advance.c @@ -1,4 +1,6 @@ #include "global.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" void FrameAdvance_Init(FrameAdvanceContext* frameAdvCtx) { frameAdvCtx->timer = 0; @@ -14,30 +16,8 @@ void FrameAdvance_Init(FrameAdvanceContext* frameAdvCtx) { * This function returns true when frame advance is not active (game will run normally) */ s32 FrameAdvance_Update(FrameAdvanceContext* frameAdvCtx, Input* input) { - if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("FrameAdvanceAltScheme"), 0) != 0) { - // Frame Advance Alternative Control Scheme - - // Push START to toggle the frame advance mode. - if (CHECK_BTN_ALL(input->press.button, BTN_START)) { - frameAdvCtx->enabled = !frameAdvCtx->enabled; - } - - // Push A to advance one frame. - // Hold L to run normally until L is released. - // Hold R to advance a frame every half second. - if (!frameAdvCtx->enabled || CVarGetInteger(CVAR_DEVELOPER_TOOLS("FrameAdvanceTick"), 0) || - CHECK_BTN_ALL(input->press.button, BTN_A) || CHECK_BTN_ALL(input->cur.button, BTN_L) || - CHECK_BTN_ALL(input->press.button, BTN_R) || - (CHECK_BTN_ALL(input->cur.button, BTN_R) && (++frameAdvCtx->timer >= 9))) { - CVarClear(CVAR_DEVELOPER_TOOLS("FrameAdvanceTick")); - frameAdvCtx->timer = 0; - return true; - } - - return false; - } else { - // Frame Advance Original Control Scheme - + if (GameInteractor_Should(VB_FRAME_ADVANCE_BE_VANILLA, true, frameAdvCtx)) { + // Vanilla Frame Advance if (CHECK_BTN_ALL(input->cur.button, BTN_R) && CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { frameAdvCtx->enabled = !frameAdvCtx->enabled; } @@ -53,4 +33,11 @@ s32 FrameAdvance_Update(FrameAdvanceContext* frameAdvCtx, Input* input) { return false; } + + // Call hooks and ask if we should freeze the frame + if (GameInteractor_Should(VB_FRAME_ADVANCE_FREEZE_FRAME, false, frameAdvCtx)) { + return false; + } + // No hooks said we should freeze the frame, so run the game normally + return true; } diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index 785061384..dfc832fc7 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -693,7 +693,6 @@ void Play_Update(PlayState* play) { Input* input = play->state.input; s32 isPaused; s32 pad1; - s32 frameAdvanceInputPort; if ((SREG(1) < 0) || (DREG(0) != 0)) { SREG(1) = 0; @@ -731,13 +730,7 @@ void Play_Update(PlayState* play) { gSegments[5] = VIRTUAL_TO_PHYSICAL(play->objectCtx.status[play->objectCtx.subKeepIndex].segment); gSegments[2] = VIRTUAL_TO_PHYSICAL(play->sceneSegment); - if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("FrameAdvanceAltScheme"), 0) != 0) { - frameAdvanceInputPort = 3; // Frame Advance Alternative Control Scheme. Uses P4 port. - } else { - frameAdvanceInputPort = 1; // Frame Advance Original Control Scheme. Uses P2 port. - } - - if (FrameAdvance_Update(&play->frameAdvCtx, &input[frameAdvanceInputPort])) { + if (FrameAdvance_Update(&play->frameAdvCtx, &input[1])) { if ((play->transitionMode == TRANS_MODE_OFF) && (play->transitionTrigger != TRANS_TRIGGER_OFF)) { play->transitionMode = TRANS_MODE_SETUP; }