summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Leggett <chris@leggett.dev>2026-03-20 03:40:35 +0000
committerGitHub <noreply@github.com>2026-03-20 03:40:35 +0000
commitf2c34d8c112247d63ddb99702b2caf716ff77516 (patch)
treec9e6327694508da4f6777a80b1b0f426f40a1f63
parent38e684fda3c8582f7beae91953cbaaa0563ed6c2 (diff)
Fix Entrance Rando Grotto Voidout Crash when voiding back to an area with a background image (#6379)
Hookify bgimage load cam check and add it to entrance rando
-rw-r--r--soh/soh/Enhancements/Cheats/UnrestrictedItems.cpp6
-rw-r--r--soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h8
-rw-r--r--soh/soh/Enhancements/randomizer/entrance.cpp36
-rw-r--r--soh/soh/Network/CrowdControl/CrowdControl.cpp11
-rw-r--r--soh/src/code/z_room.c42
5 files changed, 79 insertions, 24 deletions
diff --git a/soh/soh/Enhancements/Cheats/UnrestrictedItems.cpp b/soh/soh/Enhancements/Cheats/UnrestrictedItems.cpp
index 0b5aaebbc..d6f92fea8 100644
--- a/soh/soh/Enhancements/Cheats/UnrestrictedItems.cpp
+++ b/soh/soh/Enhancements/Cheats/UnrestrictedItems.cpp
@@ -21,6 +21,12 @@ void OnGameFrameUpdateUnrestrictedItems() {
void RegisterUnrestrictedItems() {
COND_HOOK(OnGameFrameUpdate, CVAR_UNRESTRICTED_ITEMS_VALUE, OnGameFrameUpdateUnrestrictedItems);
+ COND_VB_SHOULD(VB_SHOULD_LOAD_BG_IMAGE, CVAR_UNRESTRICTED_ITEMS_VALUE, {
+ int32_t* camId = va_arg(args, int*);
+ if (*camId == -1) {
+ *should = false;
+ }
+ });
}
static RegisterShipInitFunc initFunc(RegisterUnrestrictedItems, { CVAR_UNRESTRICTED_ITEMS_NAME });
diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
index c55d830c1..938aa9338 100644
--- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
+++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
@@ -2720,6 +2720,14 @@ typedef enum {
// - `*BgHakaHuta`
// - `*PlayState`
VB_HAKA_HUTA_SPAWN_REDEAD,
+
+ // #### `result`
+ // ```c
+ // true
+ // ```
+ // #### `args`
+ // - `*int32_t (camId)`
+ VB_SHOULD_LOAD_BG_IMAGE
} GIVanillaBehavior;
#endif
diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp
index f1532352f..9af7ddba7 100644
--- a/soh/soh/Enhancements/randomizer/entrance.cpp
+++ b/soh/soh/Enhancements/randomizer/entrance.cpp
@@ -4,9 +4,18 @@
#include "3drando/pool_functions.hpp"
#include "3drando/item_pool.hpp"
#include "../debugger/performanceTimer.h"
+#include "soh/Enhancements/gameconsole.h"
+#include "z64camera.h"
+#include "z64scene.h"
#include <spdlog/spdlog.h>
+extern "C" {
+#include "variables.h"
+#include "macros.h"
+#include "functions.h"
+}
+
namespace Rando {
EntranceLinkInfo NO_RETURN_ENTRANCE = { EntranceType::None, RR_NONE, RR_NONE, -1 };
@@ -1727,3 +1736,30 @@ const Entrance* EntranceShuffler::GetEntranceByIndex(int16_t index) {
extern "C" EntranceOverride* Randomizer_GetEntranceOverrides() {
return Rando::Context::GetInstance()->GetEntranceShuffler()->entranceOverrides.data();
}
+
+static SceneID backedUpScene = (SceneID)0xFF;
+static Camera backupCamera;
+
+void RegisterEntranceShuffleHooks() {
+ COND_VB_SHOULD(VB_SHOULD_LOAD_BG_IMAGE, IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_ENTRANCES), {
+ int32_t* camId = va_arg(args, int*);
+ Camera* camera = GET_ACTIVE_CAM(gPlayState);
+ if (*camId == -1) {
+ if (backedUpScene != gPlayState->sceneNum) {
+ *should = false;
+ return;
+ }
+ memcpy(camera, &backupCamera, sizeof(Camera));
+ Camera_ChangeMode(camera, CAM_MODE_TALK);
+ *should = false;
+ } else if (backedUpScene != gPlayState->sceneNum) {
+ memcpy(&backupCamera, camera, sizeof(Camera));
+ backedUpScene = (SceneID)gPlayState->sceneNum;
+ }
+ });
+
+ COND_HOOK(OnLoadGame, IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_ENTRANCES),
+ [](int32_t) { backedUpScene = (SceneID)0xFF; });
+}
+
+static RegisterShipInitFunc initFunc(RegisterEntranceShuffleHooks, { "IS_RANDO" });
diff --git a/soh/soh/Network/CrowdControl/CrowdControl.cpp b/soh/soh/Network/CrowdControl/CrowdControl.cpp
index 9709fc452..f91d8d52f 100644
--- a/soh/soh/Network/CrowdControl/CrowdControl.cpp
+++ b/soh/soh/Network/CrowdControl/CrowdControl.cpp
@@ -627,3 +627,14 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) {
return effect;
}
+
+void RegisterCrowdControlHooks() {
+ COND_VB_SHOULD(VB_SHOULD_LOAD_BG_IMAGE, CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("Enabled"), 0), {
+ int32_t* camId = va_arg(args, int*);
+ if (*camId == -1) {
+ *should = false;
+ }
+ });
+}
+
+static RegisterShipInitFunc initFunc(RegisterCrowdControlHooks, { CVAR_REMOTE_CROWD_CONTROL("Enabled") });
diff --git a/soh/src/code/z_room.c b/soh/src/code/z_room.c
index 8b4f31eba..317ee0775 100644
--- a/soh/src/code/z_room.c
+++ b/soh/src/code/z_room.c
@@ -413,34 +413,28 @@ BgImage* func_80096A74(PolygonType1* polygon1, PlayState* play) {
camera = GET_ACTIVE_CAM(play);
camId = camera->camDataIdx;
- if (camId == -1 && (CVarGetInteger(CVAR_CHEAT("NoRestrictItems"), 0) ||
- (CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("Enabled"), 0)))) {
- // This prevents a crash when using items that change the
- // camera (such as din's fire), voiding out or dying on
- // scenes with prerendered backgrounds.
- return NULL;
- }
-
- // jfifid
- camId2 = func_80041C10(&play->colCtx, camId, BGCHECK_SCENE)[2].y;
- if (camId2 >= 0) {
- camId = camId2;
- }
+ if (GameInteractor_Should(VB_SHOULD_LOAD_BG_IMAGE, true, &camId)) {
+ // jfifid
+ camId2 = func_80041C10(&play->colCtx, camId, BGCHECK_SCENE)[2].y;
+ if (camId2 >= 0) {
+ camId = camId2;
+ }
- player = GET_PLAYER(play);
- player->actor.params = (player->actor.params & 0xFF00) | camId;
+ player = GET_PLAYER(play);
+ player->actor.params = (player->actor.params & 0xFF00) | camId;
- bgImage = SEGMENTED_TO_VIRTUAL(polygon1->multi.list);
- for (i = 0; i < polygon1->multi.count; i++) {
- if (bgImage->id == camId) {
- return bgImage;
+ bgImage = SEGMENTED_TO_VIRTUAL(polygon1->multi.list);
+ for (i = 0; i < polygon1->multi.count; i++) {
+ if (bgImage->id == camId) {
+ return bgImage;
+ }
+ bgImage++;
}
- bgImage++;
- }
- // "z_room.c: Data consistent with camera id does not exist camid=%d"
- osSyncPrintf(VT_COL(RED, WHITE) "z_room.c:カメラIDに一致するデータが存在しません camid=%d\n" VT_RST, camId);
- LOG_HUNGUP_THREAD();
+ // "z_room.c: Data consistent with camera id does not exist camid=%d"
+ osSyncPrintf(VT_COL(RED, WHITE) "z_room.c:カメラIDに一致するデータが存在しません camid=%d\n" VT_RST, camId);
+ LOG_HUNGUP_THREAD();
+ }
return NULL;
}