Skip to content
Open

Stairs #6964

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
715 changes: 715 additions & 0 deletions soh/soh/Enhancements/heap_sim.cpp

Large diffs are not rendered by default.

31 changes: 31 additions & 0 deletions soh/soh/Enhancements/heap_sim.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef HEAP_SIM_H
#define HEAP_SIM_H

#include "global.h"
#include "soh/ActorDB.h"

#ifdef __cplusplus
extern "C" {
#endif

// Heap sim: heap pressure simulator. Mirrors every ZeldaArena/GameState
// allocation into a shadow arena sized like N64 heap.

void HeapSim_BeginSimulation(void);
void HeapSim_InitArena(GameState* gameState);
void HeapSim_Cleanup(void);
s32 HeapSim_MirrorMalloc(void* ptr, size_t size);
s32 HeapSim_MirrorMallocR(void* ptr, size_t size);
void HeapSim_MirrorFree(void* ptr);
void HeapSim_MirrorGameAlloc(void* ptr, size_t size);
void HeapSim_MirrorMapMarkLoad(void);
s32 HeapSim_MirrorEffectSsOverlay(s32 type);
s32 HeapSim_RegisterActorOverlayIfNeeded(ActorDBEntry* dbEntry);
void HeapSim_UnregisterActorOverlayIfNeeded(ActorDBEntry* dbEntry);
void HeapSim_FreeAbsoluteSpace(void);

#ifdef __cplusplus
}
#endif

#endif // HEAP_SIM_H
4 changes: 4 additions & 0 deletions soh/soh/SohGui/SohMenuEnhancements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,10 @@ void SohMenu::AddMenuEnhancements() {
.DefaultIndex(GIM_DISABLED)
.Tooltip("Restores Get Item Manipulation.\n"
"NTSC and PAL have separate tables."));
AddWidget(path, "Simulate N64 Heap", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("SimulateN64Heap"))
.Options(CheckboxOptions().Tooltip("This restores heap fragmentation glitches, such as the Royal Tomb not "
"loading when reloading graveyard room. Takes effect on next scene load."));

AddWidget(path, "Misc Restorations", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Fix L&Z Page Switch in Pause Menu", WIDGET_CVAR_CHECKBOX)
Expand Down
2 changes: 2 additions & 0 deletions soh/src/code/game.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <libultraship/bridge/resourcebridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/Enhancements/heap_sim.h"
#include "soh/ResourceManagerHelpers.h"

#include "message_data_static.h"
Expand Down Expand Up @@ -530,6 +531,7 @@ void* GameState_Alloc(GameState* gameState, size_t size, char* file, s32 line) {
osSyncPrintf(VT_FGCOL(GREEN));
osSyncPrintf("game_alloc(%08x) %08x-%08x [%s:%d]\n", size, ret, (uintptr_t)ret + size, file, line);
osSyncPrintf(VT_RST);
HeapSim_MirrorGameAlloc(ret, size);
}
return ret;
}
Expand Down
10 changes: 10 additions & 0 deletions soh/src/code/z_actor.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/Enhancements/nametag.h"
#include "soh/Enhancements/heap_sim.h"

#include "soh/ActorDB.h"
#include "soh/OTRGlobals.h"
Expand Down Expand Up @@ -3236,6 +3237,8 @@ void func_80031C3C(ActorContext* actorCtx, PlayState* play) {
actorCtx->absoluteSpace = NULL;
}

HeapSim_FreeAbsoluteSpace();

Play_SaveSceneFlags(play);
func_80030488(play);
}
Expand Down Expand Up @@ -3303,6 +3306,8 @@ void Actor_FreeOverlay(ActorDBEntry* dbEntry) {
dbEntry->reset();
}

HeapSim_UnregisterActorOverlayIfNeeded(dbEntry);

if (HREG(20) != 0) {
osSyncPrintf("アクタークライアントが0になりました\n"); // "Actor client is now 0"
}
Expand Down Expand Up @@ -3341,6 +3346,11 @@ Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 pos
return NULL;
}

// Heap sim: fail the spawn if the overlay would not have fit on the N64 heap
if (!HeapSim_RegisterActorOverlayIfNeeded(dbEntry)) {
return NULL;
}

objBankIndex = Object_GetIndex(&gPlayState->objectCtx, dbEntry->objectId);

if (objBankIndex < 0 && (!gMapLoading || CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), 0))) {
Expand Down
5 changes: 5 additions & 0 deletions soh/src/code/z_effect_soft_sprite.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "vt.h"

#include "soh/frame_interpolation.h"
#include "soh/Enhancements/heap_sim.h"
#include <assert.h>

EffectSsInfo sEffectSsInfo = { 0 }; // "EffectSS2Info"
Expand Down Expand Up @@ -187,6 +188,10 @@ void EffectSs_Spawn(PlayState* play, s32 type, s32 priority, void* initParams) {
overlaySize = (uintptr_t)overlayEntry->vramEnd - (uintptr_t)overlayEntry->vramStart;

if (overlayEntry->vramStart == NULL) {
// Heap sim: fail the spawn if the overlay would not have fit on the N64 heap
if (!HeapSim_MirrorEffectSsOverlay(type)) {
return;
}
// "Not an overlay"
osSyncPrintf("EffectSoftSprite2_makeEffect():オーバーレイではありません。\n");
initInfo = overlayEntry->initInfo;
Expand Down
12 changes: 12 additions & 0 deletions soh/src/code/z_malloc.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "global.h"
#include <string.h>

#include "soh/Enhancements/heap_sim.h"

#define LOG_SEVERITY_NOLOG 0
#define LOG_SEVERITY_ERROR 2
#define LOG_SEVERITY_VERBOSE 3
Expand Down Expand Up @@ -31,6 +33,10 @@ void* ZeldaArena_Malloc(size_t size) {
void* ZeldaArena_MallocDebug(size_t size, const char* file, s32 line) {
void* ptr = __osMallocDebug(&sZeldaArena, size, file, line);

if (!HeapSim_MirrorMalloc(ptr, size)) {
__osFreeDebug(&sZeldaArena, ptr, file, line);
ptr = NULL;
}
ZeldaArena_CheckPointer(ptr, size, "zelda_malloc_DEBUG", "確保"); // "Secure"
return ptr;
}
Expand All @@ -45,6 +51,11 @@ void* ZeldaArena_MallocR(size_t size) {
void* ZeldaArena_MallocRDebug(size_t size, const char* file, s32 line) {
void* ptr = __osMallocRDebug(&sZeldaArena, size, file, line);

if (!HeapSim_MirrorMallocR(ptr, size)) {
// would have failed on N64, fail for real
__osFreeDebug(&sZeldaArena, ptr, file, line);
ptr = NULL;
}
ZeldaArena_CheckPointer(ptr, size, "zelda_malloc_r_DEBUG", "確保"); // "Secure"
return ptr;
}
Expand All @@ -66,6 +77,7 @@ void ZeldaArena_Free(void* ptr) {
}

void ZeldaArena_FreeDebug(void* ptr, const char* file, s32 line) {
HeapSim_MirrorFree(ptr);
__osFreeDebug(&sZeldaArena, ptr, file, line);
}

Expand Down
4 changes: 4 additions & 0 deletions soh/src/code/z_map_mark.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "soh/ResourceManagerHelpers.h"
#include "soh/Enhancements/cosmetics/cosmeticsTypes.h"
#include "soh/Enhancements/savestate_serialize.h"
#include "soh/Enhancements/heap_sim.h"

typedef struct {
/* 0x00 */ void* texture;
Expand Down Expand Up @@ -62,6 +63,9 @@ static MapMarkData** sLoadedMarkDataTable;
SHIP_SAVESTATE_DEFINE(MapMark, MAP_MARK_SHIP_SAVESTATE_FIELDS)

void MapMark_Init(PlayState* play) {
// Heap sim: N64 game-allocs the map mark data overlay here
HeapSim_MirrorMapMarkLoad();

// MapMarkDataOverlay* overlay = &sMapMarkDataOvl;
// u32 overlaySize = (uintptr_t)overlay->vramEnd - (uintptr_t)overlay->vramStart;

Expand Down
7 changes: 7 additions & 0 deletions soh/src/code/z_play.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h>
#include "soh/Enhancements/enhancementTypes.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/Enhancements/heap_sim.h"
#include "soh/OTRGlobals.h"
#include "soh/ResourceManagerHelpers.h"
#include "soh/SaveManager.h"
Expand Down Expand Up @@ -236,6 +237,7 @@ void Play_Destroy(GameState* thisx) {
KaleidoScopeCall_Destroy(play);
KaleidoManager_Destroy();
ZeldaArena_Cleanup();
HeapSim_Cleanup();

Fault_RemoveClient(&D_801614B8);

Expand Down Expand Up @@ -389,6 +391,8 @@ void Play_Init(GameState* thisx) {
// This is to avoid some parts of the game, like loading actors, causing OoM
// This is potionally unavoidable due to struct size differences, but is x2 the right amount?
GameState_Realloc(&play->state, 0x1D4790 * 2);
// Heap sim: start tracking game allocs against the original (undoubled) heap size
HeapSim_BeginSimulation();
KaleidoManager_Init(play);
View_Init(&play->view, gfxCtx);
Audio_SetExtraFilter(0);
Expand Down Expand Up @@ -548,6 +552,9 @@ void Play_Init(GameState* thisx) {
gVisMonoColor.a = 0;
Flags_UnsetAllEnv(play);

// Heap sim: whatever is left of the simulated heap becomes the shadow ZeldaArena
HeapSim_InitArena(&play->state);

osSyncPrintf("ZELDA ALLOC SIZE=%x\n", THA_GetSize(&play->state.tha));
zAllocSize = THA_GetSize(&play->state.tha);
zAlloc = (uintptr_t)GAMESTATE_ALLOC_MC(&play->state, zAllocSize);
Expand Down
Loading