summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEblo <7004497+Eblo@users.noreply.github.com>2025-06-28 16:15:43 -0400
committerGitHub <noreply@github.com>2025-06-28 14:15:43 -0600
commit5994836a12485eb9ec792e7802dd5ea9a18fa9b9 (patch)
treec1d1c23a3435d87ca638800beb368a15e44fe8a2
parent2660976951b72efafbee769722db6ce850436db5 (diff)
Fix BGM replay bug caused by enhancements that bypass normal scene transitions (#1169)
* Add enhancement to fix BGM replay bug * Only enable BGM fix when related enhancement is on * Fix ShipInit * Add VB_PLAY_SCENE_SEQUENCE * Remove unused vararg, invert should condition
-rw-r--r--mm/2s2h/Enhancements/Fixes/BgmReplay.cpp44
-rw-r--r--mm/2s2h/GameInteractor/GameInteractor.h1
-rw-r--r--mm/src/audio/code_8019AF00.c4
3 files changed, 49 insertions, 0 deletions
diff --git a/mm/2s2h/Enhancements/Fixes/BgmReplay.cpp b/mm/2s2h/Enhancements/Fixes/BgmReplay.cpp
new file mode 100644
index 000000000..22a0ecf7c
--- /dev/null
+++ b/mm/2s2h/Enhancements/Fixes/BgmReplay.cpp
@@ -0,0 +1,44 @@
+#include "public/bridge/consolevariablebridge.h"
+#include "2s2h/GameInteractor/GameInteractor.h"
+#include "2s2h/ShipInit.hpp"
+
+extern "C" {
+#include "variables.h"
+#include "functions.h"
+}
+
+#define CVAR_NAME_FASTER_SCENE_TRANSITIONS "gEnhancements.Timesavers.FasterSceneTransitions"
+#define CVAR_NAME_PAUSE_SAVE "gEnhancements.Saving.PauseSave"
+#define CVAR_NAME_DEBUG_MODE "gDeveloperTools.DebugEnabled"
+
+#define CVAR_FASTER_SCENE_TRANSITIONS CVarGetInteger(CVAR_NAME_FASTER_SCENE_TRANSITIONS, 0)
+#define CVAR_PAUSE_SAVE CVarGetInteger(CVAR_NAME_PAUSE_SAVE, 0)
+#define CVAR_DEBUG_MODE CVarGetInteger(CVAR_NAME_DEBUG_MODE, 0)
+
+/*
+ * When the player transitions from one scene to another, the main BGM sequence may fade out the volume, disable the
+ * player when the fadeTimer hits 0, then play a new BGM in the next scene. However, certain 2ship features prevent that
+ * fadeTimer from decrementing all the way to 0. This prevents the main BGM sequence player from being disabled in
+ * AudioScript_SequencePlayerProcessSound. The next sequence will play fine, but gActiveSeqs[SEQ_PLAYER_BGM_MAIN] will
+ * be in an invalid state. The result is that attempts to store and then replay the main BGM will play silence, as seen
+ * with mini-boss battles.
+ *
+ * This fix intercepts the point where the a scene BGM change plays and calls AudioScript_SequencePlayerDisable if any
+ * of the enhancements in question are enabled and this is a transition where a different BGM will play.
+ */
+
+void RegisterFixBgmReplay() {
+ COND_VB_SHOULD(VB_PLAY_SCENE_SEQUENCE, CVAR_FASTER_SCENE_TRANSITIONS || CVAR_PAUSE_SAVE || CVAR_DEBUG_MODE, {
+ u16 sRequestedSceneSeqId = *va_arg(args, u16*);
+ u16 sPrevMainBgmSeqId = *va_arg(args, u16*);
+ u16 seqId = *va_arg(args, u16*);
+ // Entering new scene that has different BGM to play. This is the same condition in Audio_PlaySceneSequence.
+ if (sRequestedSceneSeqId != seqId &&
+ ((seqId != NA_BGM_FINAL_HOURS) || (sPrevMainBgmSeqId == NA_BGM_DISABLED))) {
+ AudioScript_SequencePlayerDisable(&gAudioCtx.seqPlayers[SEQ_PLAYER_BGM_MAIN]);
+ }
+ });
+}
+
+static RegisterShipInitFunc initFunc(RegisterFixBgmReplay, { CVAR_NAME_FASTER_SCENE_TRANSITIONS, CVAR_NAME_PAUSE_SAVE,
+ CVAR_NAME_DEBUG_MODE });
diff --git a/mm/2s2h/GameInteractor/GameInteractor.h b/mm/2s2h/GameInteractor/GameInteractor.h
index f6d3ffb2b..be58335f1 100644
--- a/mm/2s2h/GameInteractor/GameInteractor.h
+++ b/mm/2s2h/GameInteractor/GameInteractor.h
@@ -243,6 +243,7 @@ typedef enum {
VB_SETUP_TRANSITION,
VB_BE_NEAR_DOOR,
VB_LOAD_PLAYER_ANIMATION_FRAME,
+ VB_PLAY_SCENE_SEQUENCE,
} GIVanillaBehavior;
typedef enum {
diff --git a/mm/src/audio/code_8019AF00.c b/mm/src/audio/code_8019AF00.c
index a0de0a53e..273698fb3 100644
--- a/mm/src/audio/code_8019AF00.c
+++ b/mm/src/audio/code_8019AF00.c
@@ -5478,6 +5478,10 @@ void Audio_StartMorningSceneSequence(u16 seqId) {
}
void Audio_PlaySceneSequence(u16 seqId, u8 dayMinusOne) {
+ if (GameInteractor_Should(VB_PLAY_SCENE_SEQUENCE, false, &sRequestedSceneSeqId, &sPrevMainBgmSeqId, &seqId)) {
+ return;
+ }
+
if (sRequestedSceneSeqId != seqId) {
if (seqId == NA_BGM_AMBIENCE) {
Audio_PlayAmbience(AMBIENCE_ID_08);