From a78a94331260e2c2d05e38bb0c65a271bb6cd2a2 Mon Sep 17 00:00:00 2001 From: nclok1405 <155463060+nclok1405@users.noreply.github.com> Date: Mon, 26 May 2025 14:08:50 +0900 Subject: [PATCH] Frame Advance Alternative Control Scheme * Remaps Frame Advance controls. Uses Controller Port 4. * Push START button to toggle Frame Advance. * Push A button to advance a frame. * Hold L button to run the game normally until L button is released. * Hold R button to advance a frame every half second. --- soh/soh/SohGui/SohMenuDevTools.cpp | 7 +++++ soh/src/code/z_frame_advance.c | 49 ++++++++++++++++++++++-------- soh/src/code/z_play.c | 9 +++++- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/soh/soh/SohGui/SohMenuDevTools.cpp b/soh/soh/SohGui/SohMenuDevTools.cpp index 2a0fcd62a..3065e3214 100644 --- a/soh/soh/SohGui/SohMenuDevTools.cpp +++ b/soh/soh/SohGui/SohMenuDevTools.cpp @@ -105,6 +105,13 @@ void SohMenu::AddMenuDevTools() { } }) .SameLine(true); + AddWidget(path, "Frame Advance Alternative Control Scheme", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_DEVELOPER_TOOLS("FrameAdvanceAltScheme")) + .Options(CheckboxOptions().Tooltip("Remaps Frame Advance controls. Uses Controller Port 4.\n" + "Push START button to toggle Frame Advance.\n" + "Push A button to advance a frame.\n" + "Hold L button to run the game normally until L button is released.\n" + "Hold R button to advance a frame every half second.")); AddWidget(path, "Log Level", WIDGET_CVAR_COMBOBOX) .CVar(CVAR_DEVELOPER_TOOLS("LogLevel")) .Options(ComboboxOptions() diff --git a/soh/src/code/z_frame_advance.c b/soh/src/code/z_frame_advance.c index ecddb55e6..4f70f4257 100644 --- a/soh/src/code/z_frame_advance.c +++ b/soh/src/code/z_frame_advance.c @@ -14,18 +14,43 @@ 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 (CHECK_BTN_ALL(input->cur.button, BTN_R) && CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { - frameAdvCtx->enabled = !frameAdvCtx->enabled; - } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("FrameAdvanceAltScheme"), 0) != 0) { + // Frame Advance Alternative Control Scheme - if (!frameAdvCtx->enabled || CVarGetInteger(CVAR_DEVELOPER_TOOLS("FrameAdvanceTick"), 0) || - (CHECK_BTN_ALL(input->cur.button, BTN_Z) && - (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; - } + // Push START to toggle the frame advance mode. + if (CHECK_BTN_ALL(input->press.button, BTN_START)) { + frameAdvCtx->enabled = !frameAdvCtx->enabled; + } - return false; + // 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 (CHECK_BTN_ALL(input->cur.button, BTN_R) && CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { + frameAdvCtx->enabled = !frameAdvCtx->enabled; + } + + if (!frameAdvCtx->enabled || CVarGetInteger(CVAR_DEVELOPER_TOOLS("FrameAdvanceTick"), 0) || + (CHECK_BTN_ALL(input->cur.button, BTN_Z) && + (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; + } } diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index dfc832fc7..785061384 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -693,6 +693,7 @@ 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; @@ -730,7 +731,13 @@ 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 (FrameAdvance_Update(&play->frameAdvCtx, &input[1])) { + 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 ((play->transitionMode == TRANS_MODE_OFF) && (play->transitionTrigger != TRANS_TRIGGER_OFF)) { play->transitionMode = TRANS_MODE_SETUP; }