Vanilla bugfix, Deku Shield burning drop crash (#6810)

This commit is contained in:
djevangelia
2026-06-24 23:57:28 +02:00
committed by GitHub
parent f95c23ef69
commit 4b6678b82c
3 changed files with 26 additions and 0 deletions
+15
View File
@@ -3,6 +3,9 @@
#include "soh/ShipInit.hpp"
extern "C" {
#include "macros.h"
#include "functions.h"
#include "variables.h"
extern void Player_UseItem(PlayState*, Player*, s32);
extern PlayState* gPlayState;
}
@@ -20,6 +23,17 @@ void RegisterFixOutsideTotCrash() {
});
}
// Vanilla bug: `Actor_Item_Shield` (dropped Deku Shield when burning) assumes that segment 12
// contains Link display list `gCullBackDList`. If an actor is drawn between player and shield
// that uses segment 12 (such as Jabu-Jabu tentacles), the game will crash on Deku Shield drop.
// Fix: Re-set segment 12 to the required display list.
void RegisterFixDekuShieldDropCrash() {
COND_VB_SHOULD(VB_ITEMSHIELD_DRAW, true, {
GraphicsContext* __gfxCtx = gPlayState->state.gfxCtx;
gSPSegment(POLY_OPA_DISP++, 0x0C, (uintptr_t)SEGMENTED_TO_VIRTUAL(gCullBackDList));
});
}
// Vanilla bug: If Hookshot doesn't spawn, player is softlocked. (eg. use as child, no memory left)
// Fix: Change item to none if no spawn. (Ranged weapon state is removed by `Player_InitItemAction`)
void RegisterPreventHookshotNoSpawnSoftlock() {
@@ -45,5 +59,6 @@ void RegisterPreventHookshotParentSoftlock() {
}
static RegisterShipInitFunc initFuncFixOutsideTotCrash(RegisterFixOutsideTotCrash, { "" });
static RegisterShipInitFunc initFuncFixDekuShieldDropCrash(RegisterFixDekuShieldDropCrash, { "" });
static RegisterShipInitFunc initFuncHookshotNospawnSoftlock(RegisterPreventHookshotNoSpawnSoftlock, { "" });
static RegisterShipInitFunc initFuncHookshotParentSoftlock(RegisterPreventHookshotParentSoftlock, { "" });
@@ -3066,6 +3066,14 @@ typedef enum {
// - `*EnItem00`
VB_ITEM00_KILL,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - none
VB_ITEMSHIELD_DRAW,
// #### `result`
// ```c
// true
@@ -7,6 +7,8 @@
#include "vt.h"
#include "z_item_shield.h"
#include "objects/object_link_child/object_link_child.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS ACTOR_FLAG_UPDATE_CULLING_DISABLED
@@ -221,6 +223,7 @@ void ItemShield_Draw(Actor* thisx, PlayState* play) {
if (!(this->unk_19C & 2)) {
OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL_25Opa(play->state.gfxCtx);
GameInteractor_Should(VB_ITEMSHIELD_DRAW, true);
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, SEGMENTED_TO_VIRTUAL(gLinkChildDekuShieldDL));
CLOSE_DISPS(play->state.gfxCtx);