diff --git a/soh/soh/Enhancements/debugger/valueViewer.cpp b/soh/soh/Enhancements/debugger/valueViewer.cpp index 14a571dac..579b353b2 100644 --- a/soh/soh/Enhancements/debugger/valueViewer.cpp +++ b/soh/soh/Enhancements/debugger/valueViewer.cpp @@ -1,5 +1,6 @@ #include "valueViewer.h" #include "../../UIWidgets.hpp" +#include "soh/Enhancements/stairs.h" extern "C" { #include @@ -14,26 +15,33 @@ s32 GfxPrint_Printf(GfxPrint* printer, const char* fmt, ...); ImVec4 WHITE = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); +static u32 stairsOutMaxFree; +static u32 stairsOutFree; +static u32 stairsOutAlloc; + std::vector valueTable = { - { "Time", "gSaveContext.dayTime", "TIME:", TYPE_U16, false, []() -> void* { return &gSaveContext.dayTime; }, WHITE }, - { "Age", "gSaveContext.linkAge", "AGE:", TYPE_S32, false, []() -> void* { return &gSaveContext.linkAge; }, WHITE }, - { "Health", "gSaveContext.health", "HP:", TYPE_S16, false, []() -> void* { return &gSaveContext.health; }, WHITE }, - { "Navi Timer", "gSaveContext.naviTimer", "NAVI:", TYPE_U16, false, []() -> void* { return &gSaveContext.naviTimer; }, WHITE }, - { "Scene ID", "play->sceneNum", "SCENE:", TYPE_S16, true, []() -> void* { return &gPlayState->sceneNum; }, WHITE }, - { "Room ID", "play->roomCtx.curRoom.num", "ROOM:", TYPE_S8, true, []() -> void* { return &gPlayState->roomCtx.curRoom.num; }, WHITE }, - { "Entrance ID", "gSaveContext.entranceIndex", "ENTR:", TYPE_S32, false, []() -> void* { return &gSaveContext.entranceIndex; }, WHITE }, - { "Cutscene ID", "gSaveContext.cutsceneIndex", "CUTS:", TYPE_S32, false, []() -> void* { return &gSaveContext.cutsceneIndex; }, WHITE }, - { "Link X", "Player->actor.world.pos.x", "X:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.world.pos.x; }, WHITE }, - { "Link Y", "Player->actor.world.pos.y", "Y:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.world.pos.y; }, WHITE }, - { "Link Z", "Player->actor.world.pos.z", "Z:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.world.pos.z; }, WHITE }, - { "Link Yaw", "Player->actor.world.rot.y", "ROT:", TYPE_S16, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.world.rot.y; }, WHITE }, - { "Link Velocity", "Player->linearVelocity", "V:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->linearVelocity; }, WHITE }, - { "Link X Velocity", "Player->actor.velocity.x", "XV:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.velocity.x; }, WHITE }, - { "Link Y Velocity", "Player->actor.velocity.y", "YV:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.velocity.y; }, WHITE }, - { "Link Z Velocity", "Player->actor.velocity.z", "ZV:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.velocity.z; }, WHITE }, - { "Text ID", "play->msgCtx.textId", "TEXTID:", TYPE_U16, true, []() -> void* { return &gPlayState->msgCtx.textId; }, WHITE }, - { "Analog Stick X", "play->state.input->cur.stick_x", "AX:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_x; }, WHITE }, - { "Analog Stick Y", "play->state.input->cur.stick_y", "AY:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_y; }, WHITE }, + { "Time", "gSaveContext.dayTime", "TIME:", TYPE_U16, false, []() -> void* { return &gSaveContext.dayTime; }, WHITE }, + { "Age", "gSaveContext.linkAge", "AGE:", TYPE_S32, false, []() -> void* { return &gSaveContext.linkAge; }, WHITE }, + { "Health", "gSaveContext.health", "HP:", TYPE_S16, false, []() -> void* { return &gSaveContext.health; }, WHITE }, + { "Navi Timer", "gSaveContext.naviTimer", "NAVI:", TYPE_U16, false, []() -> void* { return &gSaveContext.naviTimer; }, WHITE }, + { "Scene ID", "play->sceneNum", "SCENE:", TYPE_S16, true, []() -> void* { return &gPlayState->sceneNum; }, WHITE }, + { "Room ID", "play->roomCtx.curRoom.num", "ROOM:", TYPE_S8, true, []() -> void* { return &gPlayState->roomCtx.curRoom.num; }, WHITE }, + { "Entrance ID", "gSaveContext.entranceIndex", "ENTR:", TYPE_S32, false, []() -> void* { return &gSaveContext.entranceIndex; }, WHITE }, + { "Cutscene ID", "gSaveContext.cutsceneIndex", "CUTS:", TYPE_S32, false, []() -> void* { return &gSaveContext.cutsceneIndex; }, WHITE }, + { "Link X", "Player->actor.world.pos.x", "X:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.world.pos.x; }, WHITE }, + { "Link Y", "Player->actor.world.pos.y", "Y:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.world.pos.y; }, WHITE }, + { "Link Z", "Player->actor.world.pos.z", "Z:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.world.pos.z; }, WHITE }, + { "Link Yaw", "Player->actor.world.rot.y", "ROT:", TYPE_S16, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.world.rot.y; }, WHITE }, + { "Link Velocity", "Player->linearVelocity", "V:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->linearVelocity; }, WHITE }, + { "Link X Velocity", "Player->actor.velocity.x", "XV:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.velocity.x; }, WHITE }, + { "Link Y Velocity", "Player->actor.velocity.y", "YV:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.velocity.y; }, WHITE }, + { "Link Z Velocity", "Player->actor.velocity.z", "ZV:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.velocity.z; }, WHITE }, + { "Text ID", "play->msgCtx.textId", "TEXTID:", TYPE_U16, true, []() -> void* { return &gPlayState->msgCtx.textId; }, WHITE }, + { "Analog Stick X", "play->state.input->cur.stick_x", "AX:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_x; }, WHITE }, + { "Analog Stick Y", "play->state.input->cur.stick_y", "AY:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_y; }, WHITE }, + { "Stairs: outMaxFree", "", "STAIR-OM:", TYPE_U32, true, []() -> void* { StairsArena_GetSizes(&stairsOutMaxFree, &stairsOutFree, &stairsOutAlloc); return &stairsOutMaxFree; }, WHITE }, + { "Stairs: outFree", "", "STAIR-OF:", TYPE_U32, true, []() -> void* { StairsArena_GetSizes(&stairsOutMaxFree, &stairsOutFree, &stairsOutAlloc); return &stairsOutFree; }, WHITE }, + { "Stairs: outAlloc", "", "STAIR-OA:", TYPE_U32, true, []() -> void* { StairsArena_GetSizes(&stairsOutMaxFree, &stairsOutFree, &stairsOutAlloc); return &stairsOutAlloc; }, WHITE }, /* TODO: Find these (from GZ) "XZ Units Traveled (Camera based speed variable)" f32 0x801C9018 "Movement Angle" x16 0x801DBB1C diff --git a/soh/soh/Enhancements/gameplaystats.cpp b/soh/soh/Enhancements/gameplaystats.cpp index efcf44efb..7a7b32058 100644 --- a/soh/soh/Enhancements/gameplaystats.cpp +++ b/soh/soh/Enhancements/gameplaystats.cpp @@ -14,6 +14,7 @@ extern "C" { #include #include #include "soh/Enhancements/enhancementTypes.h" +#include "soh/Enhancements/stairs.h" extern "C" { #include diff --git a/soh/soh/Enhancements/stairs.cpp b/soh/soh/Enhancements/stairs.cpp new file mode 100644 index 000000000..b800d4161 --- /dev/null +++ b/soh/soh/Enhancements/stairs.cpp @@ -0,0 +1,675 @@ +#include "stairs.h" +#include + +struct ActorIdAllocTypePair { + u16 id; + u16 allocType; +}; + +#define DEFINE_ACTOR_INTERNAL(name, id, allocType) { id, allocType }, +#define DEFINE_ACTOR(name, id, allocType) { id, allocType }, +#define DEFINE_ACTOR_UNSET(_0) + +static const std::vector stairActorTable = { +#include "tables/actor_table.h" +}; + +#undef DEFINE_ACTOR_INTERNAL +#undef DEFINE_ACTOR_UNSET +#undef DEFINE_ACTOR + +// Original size subtracted by various constant allocations which are always made on init, so those allocations don't need to be made there +size_t stairsAllocSize = 0x1D4790 - 0x26960 - 0x2200 - (0x55 * 0x60) - (3 * (48 * 16) / 2) - (4 * (32 * 32 * 4)) - 0x1000 - (20 * sizeof(MtxF)); +Arena sStairsArena; + +// using sizes from the debug rom +std::unordered_map actorOverlaySizes = { + { ACTOR_PLAYER, 0x0}, + { ACTOR_EN_TEST, 0x58B0}, + { ACTOR_EN_GIRLA, 0x2F90}, + { ACTOR_EN_PART, 0x16D0}, + { ACTOR_EN_LIGHT, 0xE90}, + { ACTOR_EN_DOOR, 0xE60}, + { ACTOR_EN_BOX, 0x1D50}, + { ACTOR_BG_DY_YOSEIZO, 0x30F0}, + { ACTOR_BG_HIDAN_FIREWALL, 0x7E0}, + { ACTOR_EN_POH, 0x4370}, + { ACTOR_EN_OKUTA, 0x2640}, + { ACTOR_BG_YDAN_SP, 0x1810}, + { ACTOR_EN_BOM, 0xF60}, + { ACTOR_EN_WALLMAS, 0x1B00}, + { ACTOR_EN_DODONGO, 0x2D80}, + { ACTOR_EN_FIREFLY, 0x2210}, + { ACTOR_EN_HORSE, 0xC260}, + { ACTOR_EN_ITEM00, 0x0}, + { ACTOR_EN_ARROW, 0x17E0}, + { ACTOR_EN_ELF, 0x4AF0}, + { ACTOR_EN_NIW, 0x3800}, + { ACTOR_EN_TITE, 0x2E80}, + { ACTOR_EN_REEBA, 0x1C60}, + { ACTOR_EN_PEEHAT, 0x3810}, + { ACTOR_EN_BUTTE, 0x1670}, + { ACTOR_EN_INSECT, 0x2640}, + { ACTOR_EN_FISH, 0x2290}, + { ACTOR_EN_HOLL, 0x1020}, + { ACTOR_EN_SCENE_CHANGE, 0x1B0}, + { ACTOR_EN_ZF, 0x6AF0}, + { ACTOR_EN_HATA, 0x580}, + { ACTOR_BOSS_DODONGO, 0x9C30}, + { ACTOR_BOSS_GOMA, 0x60F0}, + { ACTOR_EN_ZL1, 0x3E50}, + { ACTOR_EN_VIEWER, 0x3260}, + { ACTOR_EN_GOMA, 0x2DE0}, + { ACTOR_BG_PUSHBOX, 0x370}, + { ACTOR_EN_BUBBLE, 0x1470}, + { ACTOR_DOOR_SHUTTER, 0x2380}, + { ACTOR_EN_DODOJR, 0x1E90}, + { ACTOR_EN_BDFIRE, 0xC30}, + { ACTOR_EN_BOOM, 0x940}, + { ACTOR_EN_TORCH2, 0x27F0}, + { ACTOR_EN_BILI, 0x2310}, + { ACTOR_EN_TP, 0x1F10}, + { ACTOR_EN_ST, 0x2CB0}, + { ACTOR_EN_BW, 0x3400}, + { ACTOR_EN_A_OBJ, 0x0}, + { ACTOR_EN_EIYER, 0x1C90}, + { ACTOR_EN_RIVER_SOUND, 0x980}, + { ACTOR_EN_HORSE_NORMAL, 0x2680}, + { ACTOR_EN_OSSAN, 0x7280}, + { ACTOR_BG_TREEMOUTH, 0x16E0}, + { ACTOR_BG_DODOAGO, 0xE30}, + { ACTOR_BG_HIDAN_DALM, 0x840}, + { ACTOR_BG_HIDAN_HROCK, 0x830}, + { ACTOR_EN_HORSE_GANON, 0xD70}, + { ACTOR_BG_HIDAN_ROCK, 0x1180}, + { ACTOR_BG_HIDAN_RSEKIZOU, 0xCC0}, + { ACTOR_BG_HIDAN_SEKIZOU, 0x1510}, + { ACTOR_BG_HIDAN_SIMA, 0xFF0}, + { ACTOR_BG_HIDAN_SYOKU, 0x450}, + { ACTOR_EN_XC, 0x6BE0}, + { ACTOR_BG_HIDAN_CURTAIN, 0xC80}, + { ACTOR_BG_SPOT00_HANEBASI, 0x1240}, + { ACTOR_EN_MB, 0x4200}, + { ACTOR_EN_BOMBF, 0x1520}, + { ACTOR_EN_ZL2, 0x4A20}, + { ACTOR_BG_HIDAN_FSLIFT, 0x4B0}, + { ACTOR_EN_OE2, 0xC0}, + { ACTOR_BG_YDAN_HASI, 0x840}, + { ACTOR_BG_YDAN_MARUTA, 0x6D0}, + { ACTOR_BOSS_GANONDROF, 0x53D0}, + { ACTOR_EN_AM, 0x2450}, + { ACTOR_EN_DEKUBABA, 0x3D90}, + { ACTOR_EN_M_FIRE1, 0x1A0}, + { ACTOR_EN_M_THUNDER, 0x16B0}, + { ACTOR_BG_DDAN_JD, 0x640}, + { ACTOR_BG_BREAKWALL, 0xED0}, + { ACTOR_EN_JJ, 0x1610}, + { ACTOR_EN_HORSE_ZELDA, 0xAD0}, + { ACTOR_BG_DDAN_KD, 0x910}, + { ACTOR_DOOR_WARP1, 0x4530}, + { ACTOR_OBJ_SYOKUDAI, 0xCF0}, + { ACTOR_ITEM_B_HEART, 0x4A0}, + { ACTOR_EN_DEKUNUTS, 0x17E0}, + { ACTOR_BG_MENKURI_KAITEN, 0x180}, + { ACTOR_BG_MENKURI_EYE, 0x540}, + { ACTOR_EN_VALI, 0x2800}, + { ACTOR_BG_MIZU_MOVEBG, 0x1220}, + { ACTOR_BG_MIZU_WATER, 0xED0}, + { ACTOR_ARMS_HOOK, 0xE10}, + { ACTOR_EN_FHG, 0x2D60}, + { ACTOR_BG_MORI_HINERI, 0xE70}, + { ACTOR_EN_BB, 0x3D50}, + { ACTOR_BG_TOKI_HIKARI, 0xF40}, + { ACTOR_EN_YUKABYUN, 0x690}, + { ACTOR_BG_TOKI_SWD, 0x16C0}, + { ACTOR_EN_FHG_FIRE, 0x29C0}, + { ACTOR_BG_MJIN, 0x440}, + { ACTOR_BG_HIDAN_KOUSI, 0x6C0}, + { ACTOR_DOOR_TOKI, 0x160}, + { ACTOR_BG_HIDAN_HAMSTEP, 0x10F0}, + { ACTOR_EN_BIRD, 0x4B0}, + { ACTOR_EN_WOOD02, 0x1270}, + { ACTOR_EN_LIGHTBOX, 0x470}, + { ACTOR_EN_PU_BOX, 0x340}, + { ACTOR_EN_TRAP, 0x1290}, + { ACTOR_EN_AROW_TRAP, 0x150}, + { ACTOR_EN_VASE, 0xF0}, + { ACTOR_EN_TA, 0x3AC0}, + { ACTOR_EN_TK, 0x1F90}, + { ACTOR_BG_MORI_BIGST, 0xC40}, + { ACTOR_BG_MORI_ELEVATOR, 0xD60}, + { ACTOR_BG_MORI_KAITENKABE, 0x7B0}, + { ACTOR_BG_MORI_RAKKATENJO, 0xCA0}, + { ACTOR_EN_VM, 0x1990}, + { ACTOR_DEMO_EFFECT, 0x6440}, + { ACTOR_DEMO_KANKYO, 0x4150}, + { ACTOR_BG_HIDAN_FWBIG, 0xD50}, + { ACTOR_EN_FLOORMAS, 0x3490}, + { ACTOR_EN_HEISHI1, 0x1BD0}, + { ACTOR_EN_RD, 0x28D0}, + { ACTOR_EN_PO_SISTERS, 0x4DC0}, + { ACTOR_BG_HEAVY_BLOCK, 0x1A10}, + { ACTOR_BG_PO_EVENT, 0x1EA0}, + { ACTOR_OBJ_MURE, 0x14A0}, + { ACTOR_EN_SW, 0x3900}, + { ACTOR_BOSS_FD, 0x78B0}, + { ACTOR_OBJECT_KANKYO, 0x35D0}, + { ACTOR_EN_DU, 0x1AC0}, + { ACTOR_EN_FD, 0x2DF0}, + { ACTOR_EN_HORSE_LINK_CHILD, 0x1E80}, + { ACTOR_DOOR_ANA, 0x6F0}, + { ACTOR_BG_SPOT02_OBJECTS, 0x1480}, + { ACTOR_BG_HAKA, 0x740}, + { ACTOR_MAGIC_WIND, 0x1F50}, + { ACTOR_MAGIC_FIRE, 0x2390}, + { ACTOR_EN_RU1, 0x7940}, + { ACTOR_BOSS_FD2, 0x4200}, + { ACTOR_EN_FD_FIRE, 0xDB0}, + { ACTOR_EN_DH, 0x1B40}, + { ACTOR_EN_DHA, 0xFF0}, + { ACTOR_EN_RL, 0x1190}, + { ACTOR_EN_ENCOUNT1, 0x1270}, + { ACTOR_DEMO_DU, 0x39E0}, + { ACTOR_DEMO_IM, 0x42A0}, + { ACTOR_DEMO_TRE_LGT, 0x830}, + { ACTOR_EN_FW, 0x1820}, + { ACTOR_BG_VB_SIMA, 0x7A0}, + { ACTOR_EN_VB_BALL, 0x1260}, + { ACTOR_BG_HAKA_MEGANE, 0x3F0}, + { ACTOR_BG_HAKA_MEGANEBG, 0x6B0}, + { ACTOR_BG_HAKA_SHIP, 0xBA0}, + { ACTOR_BG_HAKA_SGAMI, 0xC20}, + { ACTOR_EN_HEISHI2, 0x27A0}, + { ACTOR_EN_ENCOUNT2, 0x1510}, + { ACTOR_EN_FIRE_ROCK, 0x1450}, + { ACTOR_EN_BROB, 0x10F0}, + { ACTOR_MIR_RAY, 0x1A30}, + { ACTOR_BG_SPOT09_OBJ, 0x6A0}, + { ACTOR_BG_SPOT18_OBJ, 0xAC0}, + { ACTOR_BOSS_VA, 0x17690}, + { ACTOR_BG_HAKA_TUBO, 0xAB0}, + { ACTOR_BG_HAKA_TRAP, 0x15B0}, + { ACTOR_BG_HAKA_HUTA, 0xA80}, + { ACTOR_BG_HAKA_ZOU, 0x11D0}, + { ACTOR_BG_SPOT17_FUNEN, 0x310}, + { ACTOR_EN_SYATEKI_ITM, 0x11C0}, + { ACTOR_EN_SYATEKI_MAN, 0x1080}, + { ACTOR_EN_TANA, 0x430}, + { ACTOR_EN_NB, 0x49F0}, + { ACTOR_BOSS_MO, 0x10AD0}, + { ACTOR_EN_SB, 0x1480}, + { ACTOR_EN_BIGOKUTA, 0x2C40}, + { ACTOR_EN_KAREBABA, 0x1A60}, + { ACTOR_BG_BDAN_OBJECTS, 0x1370}, + { ACTOR_DEMO_SA, 0x2DD0}, + { ACTOR_DEMO_GO, 0xE00}, + { ACTOR_EN_IN, 0x2E70}, + { ACTOR_EN_TR, 0x1970}, + { ACTOR_BG_SPOT16_BOMBSTONE, 0x1810}, + { ACTOR_BG_HIDAN_KOWARERUKABE, 0x1060}, + { ACTOR_BG_BOMBWALL, 0x990}, + { ACTOR_BG_SPOT08_ICEBLOCK, 0x1180}, + { ACTOR_EN_RU2, 0x3010}, + { ACTOR_OBJ_DEKUJR, 0x6E0}, + { ACTOR_BG_MIZU_UZU, 0x1D0}, + { ACTOR_BG_SPOT06_OBJECTS, 0x14B0}, + { ACTOR_BG_ICE_OBJECTS, 0xF30}, + { ACTOR_BG_HAKA_WATER, 0x8C0}, + { ACTOR_EN_MA2, 0x1100}, + { ACTOR_EN_BOM_CHU, 0x1730}, + { ACTOR_EN_HORSE_GAME_CHECK, 0x1110}, + { ACTOR_BOSS_TW, 0x165F0}, + { ACTOR_EN_RR, 0x27D0}, + { ACTOR_EN_BA, 0x1F90}, + { ACTOR_EN_BX, 0xBB0}, + { ACTOR_EN_ANUBICE, 0x1480}, + { ACTOR_EN_ANUBICE_FIRE, 0xE60}, + { ACTOR_BG_MORI_HASHIGO, 0xB00}, + { ACTOR_BG_MORI_HASHIRA4, 0x770}, + { ACTOR_BG_MORI_IDOMIZU, 0x780}, + { ACTOR_BG_SPOT16_DOUGHNUT, 0x780}, + { ACTOR_BG_BDAN_SWITCH, 0x1540}, + { ACTOR_EN_MA1, 0x1310}, + { ACTOR_BOSS_GANON, 0x266D0}, + { ACTOR_BOSS_SST, 0xC700}, + { ACTOR_EN_NY, 0x1AF0}, + { ACTOR_EN_FR, 0x2E70}, + { ACTOR_ITEM_SHIELD, 0xAB0}, + { ACTOR_BG_ICE_SHELTER, 0x1380}, + { ACTOR_EN_ICE_HONO, 0x1320}, + { ACTOR_ITEM_OCARINA, 0x7F0}, + { ACTOR_MAGIC_DARK, 0x19A0}, + { ACTOR_DEMO_6K, 0x3180}, + { ACTOR_EN_ANUBICE_TAG, 0x3D0}, + { ACTOR_BG_HAKA_GATE, 0x11D0}, + { ACTOR_BG_SPOT15_SAKU, 0x3E0}, + { ACTOR_BG_JYA_GOROIWA, 0x750}, + { ACTOR_BG_JYA_ZURERUKABE, 0x830}, + { ACTOR_BG_JYA_COBRA, 0x2080}, + { ACTOR_BG_JYA_KANAAMI, 0x460}, + { ACTOR_FISHING, 0x1B7B0}, + { ACTOR_OBJ_OSHIHIKI, 0x1E50}, + { ACTOR_BG_GATE_SHUTTER, 0x560}, + { ACTOR_EFF_DUST, 0x14E0}, + { ACTOR_BG_SPOT01_FUSYA, 0x320}, + { ACTOR_BG_SPOT01_IDOHASHIRA, 0xE00}, + { ACTOR_BG_SPOT01_IDOMIZU, 0x3A0}, + { ACTOR_BG_PO_SYOKUDAI, 0xA30}, + { ACTOR_BG_GANON_OTYUKA, 0x2840}, + { ACTOR_BG_SPOT15_RRBOX, 0xEF0}, + { ACTOR_BG_UMAJUMP, 0x180}, + { ACTOR_ARROW_FIRE, 0x1FC0}, + { ACTOR_ARROW_ICE, 0x1FE0}, + { ACTOR_ARROW_LIGHT, 0x1FF0}, + { ACTOR_ITEM_ETCETERA, 0x9F0}, + { ACTOR_OBJ_KIBAKO, 0xD30}, + { ACTOR_OBJ_TSUBO, 0x1090}, + { ACTOR_EN_WONDER_ITEM, 0x1090}, + { ACTOR_EN_IK, 0x4CA0}, + { ACTOR_DEMO_IK, 0x18E0}, + { ACTOR_EN_SKJ, 0x3C00}, + { ACTOR_EN_SKJNEEDLE, 0x3C0}, + { ACTOR_EN_G_SWITCH, 0x1EA0}, + { ACTOR_DEMO_EXT, 0xAB0}, + { ACTOR_DEMO_SHD, 0x2490}, + { ACTOR_EN_DNS, 0x1590}, + { ACTOR_ELF_MSG, 0xBE0}, + { ACTOR_EN_HONOTRAP, 0x16C0}, + { ACTOR_EN_TUBO_TRAP, 0xDC0}, + { ACTOR_OBJ_ICE_POLY, 0xA40}, + { ACTOR_BG_SPOT03_TAKI, 0x990}, + { ACTOR_BG_SPOT07_TAKI, 0x6A0}, + { ACTOR_EN_FZ, 0x2100}, + { ACTOR_EN_PO_RELAY, 0x1850}, + { ACTOR_BG_RELAY_OBJECTS, 0x790}, + { ACTOR_EN_DIVING_GAME, 0x1AE0}, + { ACTOR_EN_KUSA, 0x15B0}, + { ACTOR_OBJ_BEAN, 0x29E0}, + { ACTOR_OBJ_BOMBIWA, 0x570}, + { ACTOR_OBJ_SWITCH, 0x20A0}, + { ACTOR_OBJ_ELEVATOR, 0x490}, + { ACTOR_OBJ_LIFT, 0xAD0}, + { ACTOR_OBJ_HSBLOCK, 0x700}, + { ACTOR_EN_OKARINA_TAG, 0x1940}, + { ACTOR_EN_YABUSAME_MARK, 0xC00}, + { ACTOR_EN_GOROIWA, 0x2680}, + { ACTOR_EN_EX_RUPPY, 0x12B0}, + { ACTOR_EN_TORYO, 0xC70}, + { ACTOR_EN_DAIKU, 0x17F0}, + { ACTOR_EN_NWC, 0xAD0}, + { ACTOR_EN_BLKOBJ, 0x670}, + { ACTOR_ITEM_INBOX, 0x150}, + { ACTOR_EN_GE1, 0x2260}, + { ACTOR_OBJ_BLOCKSTOP, 0x190}, + { ACTOR_EN_SDA, 0x1900}, + { ACTOR_EN_CLEAR_TAG, 0xB850}, + { ACTOR_EN_NIW_LADY, 0x1E10}, + { ACTOR_EN_GM, 0xE90}, + { ACTOR_EN_MS, 0x700}, + { ACTOR_EN_HS, 0xC00}, + { ACTOR_BG_INGATE, 0x420}, + { ACTOR_EN_KANBAN, 0x33B0}, + { ACTOR_EN_HEISHI3, 0xA90}, + { ACTOR_EN_SYATEKI_NIW, 0x21B0}, + { ACTOR_EN_ATTACK_NIW, 0x1250}, + { ACTOR_BG_SPOT01_IDOSOKO, 0x2C0}, + { ACTOR_EN_SA, 0x2290}, + { ACTOR_EN_WONDER_TALK, 0xDE0}, + { ACTOR_BG_GJYO_BRIDGE, 0x570}, + { ACTOR_EN_DS, 0xC00}, + { ACTOR_EN_MK, 0xE70}, + { ACTOR_EN_BOM_BOWL_MAN, 0x1810}, + { ACTOR_EN_BOM_BOWL_PIT, 0x9F0}, + { ACTOR_EN_OWL, 0x3EB0}, + { ACTOR_EN_ISHI, 0x9220}, + { ACTOR_OBJ_HANA, 0x300}, + { ACTOR_OBJ_LIGHTSWITCH, 0x16D0}, + { ACTOR_OBJ_MURE2, 0xA90}, + { ACTOR_EN_GO, 0x47C0}, + { ACTOR_EN_FU, 0xD90}, + { ACTOR_EN_CHANGER, 0xF20}, + { ACTOR_BG_JYA_MEGAMI, 0x1310}, + { ACTOR_BG_JYA_LIFT, 0x590}, + { ACTOR_BG_JYA_BIGMIRROR, 0xAC0}, + { ACTOR_BG_JYA_BOMBCHUIWA, 0xD00}, + { ACTOR_BG_JYA_AMISHUTTER, 0x420}, + { ACTOR_BG_JYA_BOMBIWA, 0x750}, + { ACTOR_BG_SPOT18_BASKET, 0x1070}, + { ACTOR_EN_GANON_ORGAN, 0x7180}, + { ACTOR_EN_SIOFUKI, 0xE20}, + { ACTOR_EN_STREAM, 0x610}, + { ACTOR_EN_MM, 0x16E0}, + { ACTOR_EN_KO, 0x41F0}, + { ACTOR_EN_KZ, 0x15F0}, + { ACTOR_EN_WEATHER_TAG, 0x1270}, + { ACTOR_BG_SST_FLOOR, 0x5F0}, + { ACTOR_EN_ANI, 0xDB0}, + { ACTOR_EN_EX_ITEM, 0x1570}, + { ACTOR_BG_JYA_IRONOBJ, 0xEA0}, + { ACTOR_EN_JS, 0x990}, + { ACTOR_EN_JSJUTAN, 0x59D0}, + { ACTOR_EN_CS, 0x1280}, + { ACTOR_EN_MD, 0x26B0}, + { ACTOR_EN_HY, 0x3A40}, + { ACTOR_EN_GANON_MANT, 0x42A0}, + { ACTOR_EN_OKARINA_EFFECT, 0x5C0}, + { ACTOR_EN_MAG, 0x2550}, + { ACTOR_DOOR_GERUDO, 0x670}, + { ACTOR_ELF_MSG2, 0x820}, + { ACTOR_DEMO_GT, 0x5C90}, + { ACTOR_EN_PO_FIELD, 0x3C40}, + { ACTOR_EFC_ERUPC, 0xC20}, + { ACTOR_BG_ZG, 0x570}, + { ACTOR_EN_HEISHI4, 0x1130}, + { ACTOR_EN_ZL3, 0x8400}, + { ACTOR_BOSS_GANON2, 0x13700}, + { ACTOR_EN_KAKASI, 0xEA0}, + { ACTOR_EN_TAKARA_MAN, 0x9D0}, + { ACTOR_OBJ_MAKEOSHIHIKI, 0x590}, + { ACTOR_OCEFF_SPOT, 0x1070}, + { ACTOR_END_TITLE, 0x4280}, + { ACTOR_EN_TORCH, 0xF0}, + { ACTOR_DEMO_EC, 0x3AA0}, + { ACTOR_SHOT_SUN, 0x740}, + { ACTOR_EN_DY_EXTRA, 0x6A0}, + { ACTOR_EN_WONDER_TALK2, 0x10A0}, + { ACTOR_EN_GE2, 0x1A50}, + { ACTOR_OBJ_ROOMTIMER, 0x240}, + { ACTOR_EN_SSH, 0x2620}, + { ACTOR_EN_STH, 0x4260}, + { ACTOR_OCEFF_WIPE, 0xE20}, + { ACTOR_OCEFF_STORM, 0x1CB0}, + { ACTOR_EN_WEIYER, 0x1A20}, + { ACTOR_BG_SPOT05_SOKO, 0x310}, + { ACTOR_BG_JYA_1FLIFT, 0x760}, + { ACTOR_BG_JYA_HAHENIRON, 0x7E0}, + { ACTOR_BG_SPOT12_GATE, 0x490}, + { ACTOR_BG_SPOT12_SAKU, 0x540}, + { ACTOR_EN_HINTNUTS, 0x1A10}, + { ACTOR_EN_NUTSBALL, 0x690}, + { ACTOR_BG_SPOT00_BREAK, 0x1A0}, + { ACTOR_EN_SHOPNUTS, 0xF70}, + { ACTOR_EN_IT, 0x180}, + { ACTOR_EN_GELDB, 0x5440}, + { ACTOR_OCEFF_WIPE2, 0x1840}, + { ACTOR_OCEFF_WIPE3, 0x1820}, + { ACTOR_EN_NIW_GIRL, 0xCC0}, + { ACTOR_EN_DOG, 0x1200}, + { ACTOR_EN_SI, 0x4F0}, + { ACTOR_BG_SPOT01_OBJECTS2, 0x520}, + { ACTOR_OBJ_COMB, 0x8C0}, + { ACTOR_BG_SPOT11_BAKUDANKABE, 0x670}, + { ACTOR_OBJ_KIBAKO2, 0x700}, + { ACTOR_EN_DNT_DEMO, 0x1200}, + { ACTOR_EN_DNT_JIJI, 0x17E0}, + { ACTOR_EN_DNT_NOMAL, 0x3100}, + { ACTOR_EN_GUEST, 0xB30}, + { ACTOR_BG_BOM_GUARD, 0x280}, + { ACTOR_EN_HS2, 0x610}, + { ACTOR_DEMO_KEKKAI, 0x1490}, + { ACTOR_BG_SPOT08_BAKUDANKABE, 0x690}, + { ACTOR_BG_SPOT17_BAKUDANKABE, 0x840}, + { ACTOR_OBJ_MURE3, 0x7B0}, + { ACTOR_EN_TG, 0x720}, + { ACTOR_EN_MU, 0x970}, + { ACTOR_EN_GO2, 0x6190}, + { ACTOR_EN_WF, 0x43B0}, + { ACTOR_EN_SKB, 0x1910}, + { ACTOR_DEMO_GJ, 0x3F40}, + { ACTOR_DEMO_GEFF, 0xAF0}, + { ACTOR_BG_GND_FIREMEIRO, 0x5E0}, + { ACTOR_BG_GND_DARKMEIRO, 0x890}, + { ACTOR_BG_GND_SOULMEIRO, 0x8F0}, + { ACTOR_BG_GND_NISEKABE, 0x170}, + { ACTOR_BG_GND_ICEBLOCK, 0x11B0}, + { ACTOR_EN_GB, 0x17F0}, + { ACTOR_EN_GS, 0x1F00}, + { ACTOR_BG_MIZU_BWALL, 0x17B0}, + { ACTOR_BG_MIZU_SHUTTER, 0x890}, + { ACTOR_EN_DAIKU_KAKARIKO, 0x14B0}, + { ACTOR_BG_BOWL_WALL, 0xA80}, + { ACTOR_EN_WALL_TUBO, 0x730}, + { ACTOR_EN_PO_DESERT, 0xE50}, + { ACTOR_EN_CROW, 0x1670}, + { ACTOR_DOOR_KILLER, 0x1650}, + { ACTOR_BG_SPOT11_OASIS, 0x7A0}, + { ACTOR_BG_SPOT18_FUTA, 0x190}, + { ACTOR_BG_SPOT18_SHUTTER, 0x540}, + { ACTOR_EN_MA3, 0x1060}, + { ACTOR_EN_COW, 0x1440}, + { ACTOR_BG_ICE_TURARA, 0x820}, + { ACTOR_BG_ICE_SHUTTER, 0x460}, + { ACTOR_EN_KAKASI2, 0xD10}, + { ACTOR_EN_KAKASI3, 0x1280}, + { ACTOR_OCEFF_WIPE4, 0x10B0}, + { ACTOR_EN_EG, 0x210}, + { ACTOR_BG_MENKURI_NISEKABE, 0x150}, + { ACTOR_EN_ZO, 0x27A0}, + { ACTOR_OBJ_MAKEKINSUTA, 0x2A0}, + { ACTOR_EN_GE3, 0xCF0}, + { ACTOR_OBJ_TIMEBLOCK, 0xDC0}, + { ACTOR_OBJ_HAMISHI, 0x8D0}, + { ACTOR_EN_ZL4, 0x4A70}, + { ACTOR_EN_MM2, 0xED0}, + { ACTOR_BG_JYA_BLOCK, 0x300}, + { ACTOR_OBJ_WARP2BLOCK, 0xCB0}, +}; + +std::unordered_set registeredStairOverlays; + +std::unordered_map generalPtrMap; +std::unordered_map overlayRPtrMap; +std::unordered_map overlayPtrMap; +std::unordered_map mallocRPtrMap; + +void* absolutePtr = nullptr; + +s32 absoluteSpaceFlag = 0; + +u16 Stairs_GetAllocType(u16 id) { + for (const ActorIdAllocTypePair& pair : stairActorTable) { + if (pair.id == id) { + return pair.allocType; + } + } + return 0xFFFF; +} + +s32 Stairs_RegisterOverlay(u16 id) { + if (registeredStairOverlays.contains(id)) { + return false; + } + registeredStairOverlays.insert(id); + return true; +} + +s32 Stairs_GetOverlayRegistered(u16 id) { + return registeredStairOverlays.contains(id); +} + +s32 Stairs_UnregisterOverlay(u16 id) { + if (registeredStairOverlays.contains(id)) { + registeredStairOverlays.erase(id); + return true; + } + return false; +} + +s32 Stairs_RegisterAbsoluteSpace() { + if (absoluteSpaceFlag) { + return false; + } + absoluteSpaceFlag = true; + return true; +} + +s32 Stairs_GetAbsoluteSpace() { + return absoluteSpaceFlag; +} + +void Stairs_UnregisterAbsoluteSpace() { + absoluteSpaceFlag = false; +} + +size_t Stairs_GetOverlaySize(u16 id) { + return actorOverlaySizes[id]; +} + +size_t Stairs_GetSize() { + return stairsAllocSize; +} + +s32 Stairs_DecreaseSize(size_t size) { + if (size > stairsAllocSize) { + return false; + } + stairsAllocSize -= size; + return true; +} + +void* StairsArena_Malloc(size_t size) { + void* ptr = __osMalloc(&sStairsArena, size); + + // StairsArena_CheckPointer(ptr, size, "stairs_malloc", "確保"); // "Secure" + return ptr; +} + +void* StairsArena_MallocGeneral(size_t size, uintptr_t id) { + void* ptr = __osMalloc(&sStairsArena, size); + generalPtrMap[id] = (uintptr_t)ptr; + + // StairsArena_CheckPointer(ptr, size, "stairs_malloc", "確保"); // "Secure" + return ptr; +} + +void* StairsArena_MallocROverlay(size_t size, u16 id) { + void* ptr = __osMallocR(&sStairsArena, size); + overlayRPtrMap[id] = (uintptr_t)ptr; + + // StairsArena_CheckPointer(ptr, size, "stairs_malloc", "確保"); // "Secure" + return ptr; +} + +void* StairsArena_MallocOverlay(size_t size, u16 id) { + void* ptr = __osMalloc(&sStairsArena, size); + overlayPtrMap[id] = (uintptr_t)ptr; + + // StairsArena_CheckPointer(ptr, size, "stairs_malloc", "確保"); // "Secure" + return ptr; +} + +void* StairsArena_MallocR(size_t size) { + void* ptr = __osMallocR(&sStairsArena, size); + + // StairsArena_CheckPointer(ptr, size, "stairs_malloc_r", "確保"); // "Secure" + return ptr; +} + +void* StairsArena_MallocRGeneral(size_t size, uintptr_t id) { + void* ptr = __osMallocR(&sStairsArena, size); + mallocRPtrMap[id] = (uintptr_t)ptr; + + // StairsArena_CheckPointer(ptr, size, "stairs_malloc_r", "確保"); // "Secure" + return ptr; +} + +void* StairsArena_MallocRAbsolute(size_t size) { + absolutePtr = __osMallocR(&sStairsArena, size); + + // StairsArena_CheckPointer(ptr, size, "stairs_malloc_r", "確保"); // "Secure" + return absolutePtr; +} + +void* StairsArena_Realloc(void* ptr, size_t newSize) { + ptr = __osRealloc(&sStairsArena, ptr, newSize); + // StairsArena_CheckPointer(ptr, newSize, "stairs_realloc", "再確保"); // "Re-securing" + return ptr; +} + +void StairsArena_Free(void* ptr) { + __osFree(&sStairsArena, ptr); +} + +void StairsArena_FreeGeneral(uintptr_t id) { + void* ptr = (void*)generalPtrMap[id]; + if (ptr) { + __osFree(&sStairsArena, ptr); + } + generalPtrMap[id] = 0; +} + +void StairsArena_FreeMallocROverlay(u16 id) { + void* ptr = (void*)overlayRPtrMap[id]; + if (ptr) { + __osFree(&sStairsArena, ptr); + } + overlayRPtrMap[id] = 0; +} + +void StairsArena_FreeOverlay(u16 id) { + void* ptr = (void*)overlayPtrMap[id]; + if (ptr) { + __osFree(&sStairsArena, ptr); + } + overlayPtrMap[id] = 0; +} + +void StairsArena_FreeMallocR(u16 id) { + void* ptr = (void*)mallocRPtrMap[id]; + if (ptr) { + __osFree(&sStairsArena, ptr); + } + mallocRPtrMap[id] = 0; +} + +void StairsArena_FreeAbsolute() { + __osFree(&sStairsArena, absolutePtr); + absolutePtr = nullptr; +} + +void* StairsArena_Calloc(size_t num, size_t size) { + void* ret; + size_t n = num * size; + + ret = __osMalloc(&sStairsArena, n); + if (ret != NULL) { + memset(ret, 0,n); + } + + // StairsArena_CheckPointer(ret, n, "stairs_calloc", "確保"); + return ret; +} + +void StairsArena_Display() { + osSyncPrintf("ゼルダヒープ表示\n"); // "Zelda heap display" + __osDisplayArena(&sStairsArena); +} + +void StairsArena_GetSizes(u32* outMaxFree, u32* outFree, u32* outAlloc) { + ArenaImpl_GetSizes(&sStairsArena, outMaxFree, outFree, outAlloc); +} + +void StairsArena_Check() { + __osCheckArena(&sStairsArena); +} + +void StairsArena_Init(void* start, size_t size) { + __osMallocInit(&sStairsArena, start, size); +} + +void StairsArena_Cleanup() { + __osMallocCleanup(&sStairsArena); + registeredStairOverlays.clear(); + generalPtrMap.clear(); + overlayRPtrMap.clear(); + overlayPtrMap.clear(); + mallocRPtrMap.clear(); + absolutePtr = nullptr; + absoluteSpaceFlag = 0; + // Original size subtracted by various constant allocations which are always made on init, so those allocations don't need to be made there + stairsAllocSize = 0x1D4790 - 0x26960 - 0x2200 - (0x55 * 0x60) - (3 * (48 * 16) / 2) - (4 * (32 * 32 * 4)) - 0x1000 - (20 * sizeof(MtxF)); +} + +u8 StairsArena_IsInitalized() { + return __osMallocIsInitalized(&sStairsArena); +} diff --git a/soh/soh/Enhancements/stairs.h b/soh/soh/Enhancements/stairs.h new file mode 100644 index 000000000..c8bd3f84b --- /dev/null +++ b/soh/soh/Enhancements/stairs.h @@ -0,0 +1,58 @@ +#ifndef STAIRS_H +#define STAIRS_H + +#include "global.h" + + +#define STAIRS_ACTOROVL_ABSOLUTE_SPACE_SIZE 0x27A0 +#define STAIRS_ACTOROVL_ALLOC_ABSOLUTE (1 << 0) +#define STAIRS_ACTOROVL_ALLOC_PERSISTENT (1 << 1) + +// This value is based on the ZeldaArena size created on play init with default GameAlloc size +// #define STAIRS_ALLOC_SIZE 560064 +// #define STAIRS_ALLOC_SIZE 0x88BC0 + +#ifdef __cplusplus +extern "C" { +#endif + +u16 Stairs_GetAllocType(u16 id); +s32 Stairs_RegisterOverlay(u16 id); +s32 Stairs_GetOverlayRegistered(u16 id); +s32 Stairs_UnregisterOverlay(u16 id); +s32 Stairs_RegisterAbsoluteSpace(); +s32 Stairs_GetAbsoluteSpace(); +void Stairs_UnregisterAbsoluteSpace(); +size_t Stairs_GetOverlaySize(u16 id); + +size_t Stairs_GetSize(); +s32 Stairs_DecreaseSize(size_t size); + +void* StairsArena_Malloc(size_t size); +void* StairsArena_MallocR(size_t size); +void* StairsArena_Realloc(void* ptr, size_t newSize); +void StairsArena_Free(void* ptr); +void* StairsArena_Calloc(size_t num, size_t size); +void StairsArena_Display(); +void StairsArena_GetSizes(u32* outMaxFree, u32* outFree, u32* outAlloc); +void StairsArena_Check(); +void StairsArena_Init(void* start, size_t size); +void StairsArena_Cleanup(); +u8 StairsArena_IsInitalized(); + +void* StairsArena_MallocGeneral(size_t size, uintptr_t id); +void* StairsArena_MallocROverlay(size_t size, u16 id); +void* StairsArena_MallocOverlay(size_t size, u16 id); +void* StairsArena_MallocRGeneral(size_t size, uintptr_t id); +void* StairsArena_MallocRAbsolute(size_t size); +void StairsArena_FreeGeneral(uintptr_t id); +void StairsArena_FreeMallocROverlay(u16 id); +void StairsArena_FreeOverlay(u16 id); +void StairsArena_FreeMallocR(u16 id); +void StairsArena_FreeAbsolute(); + +#ifdef __cplusplus +} +#endif + +#endif //STAIRS_H \ No newline at end of file diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 9adbabadf..c0d368322 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1285,6 +1285,8 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("Restore a bug from NTSC 1.0 that allows bypassing Bongo Bongo's intro cutscene to quickly kill him"); UIWidgets::PaddedEnhancementCheckbox("Original RBA Values", "gRestoreRBAValues", true, false); UIWidgets::Tooltip("Restores the original outcomes when performing Reverse Bottle Adventure."); + UIWidgets::PaddedEnhancementCheckbox("Simulate N64 Heap", "gSimulateHeap", true, false); + UIWidgets::Tooltip("This restores heap fragmentation glitches, such as causing the Royal Tomb to not load when reloading its graveyard room."); ImGui::EndMenu(); } @@ -1633,7 +1635,8 @@ extern std::shared_ptr mMessageViewerWindow; void DrawDeveloperToolsMenu() { if (ImGui::BeginMenu("Developer Tools")) { ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0)); - + UIWidgets::EnhancementCheckbox("Stairs heap display", "gStairsDisplay"); + UIWidgets::Tooltip("Visualises the stair heap"); UIWidgets::EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled"); UIWidgets::Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad Right, and open the debug menu with L on the pause screen"); if (CVarGetInteger("gDebugEnabled", 0)) { diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index ec14f13b5..674c78632 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -11,6 +11,7 @@ #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/nametag.h" +#include "soh/Enhancements/stairs.h" #include "soh/ActorDB.h" @@ -3106,6 +3107,13 @@ void func_80031C3C(ActorContext* actorCtx, PlayState* play) { actorCtx->absoluteSpace = NULL; } + if (CVarGetInteger("gStairs", 0)) { + if (Stairs_GetAbsoluteSpace()) { + StairsArena_FreeAbsolute(); + Stairs_UnregisterAbsoluteSpace(); + } + } + Play_SaveSceneFlags(play); func_80030488(play); } @@ -3173,6 +3181,22 @@ void Actor_FreeOverlay(ActorDBEntry* dbEntry) { dbEntry->reset(); } + if (CVarGetInteger("gStairs", 0)) { + if (Stairs_GetOverlayRegistered(dbEntry->id)) { + u16 allocType = Stairs_GetAllocType(dbEntry->id); + + if (allocType & STAIRS_ACTOROVL_ALLOC_PERSISTENT) { + // Persistent, do not de-allocate + } else if (allocType & STAIRS_ACTOROVL_ALLOC_ABSOLUTE) { + // Unregister but do not de-allocate + Stairs_UnregisterOverlay(dbEntry->id); + } else { + StairsArena_FreeOverlay(dbEntry->id); + Stairs_UnregisterOverlay(dbEntry->id); + } + } + } + if (HREG(20) != 0) { osSyncPrintf("アクタークライアントが0になりました\n"); // "Actor client is now 0" } @@ -3219,6 +3243,28 @@ Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 pos return NULL; } + if (CVarGetInteger("gStairs", 0)) { + u16 allocType = Stairs_GetAllocType(dbEntry->id); + size_t overlaySize = Stairs_GetOverlaySize(dbEntry->id); + void* loadedRamAddr = NULL; + if (Stairs_RegisterOverlay(actorId)) { + if (allocType == 0xFFFF) { + + } else if (allocType & STAIRS_ACTOROVL_ALLOC_ABSOLUTE) { + if (Stairs_RegisterAbsoluteSpace()) { + loadedRamAddr = StairsArena_MallocRAbsolute(STAIRS_ACTOROVL_ABSOLUTE_SPACE_SIZE); + } + } else if (allocType & STAIRS_ACTOROVL_ALLOC_PERSISTENT) { + loadedRamAddr = StairsArena_MallocROverlay(overlaySize, dbEntry->id); + } else { + loadedRamAddr = StairsArena_MallocOverlay(overlaySize, dbEntry->id); + } + if (loadedRamAddr == NULL) { + return NULL; + } + } + } + objBankIndex = Object_GetIndex(&gPlayState->objectCtx, dbEntry->objectId); if (objBankIndex < 0 && (!gMapLoading || CVarGetInteger("gRandomizedEnemies", 0))) { @@ -3244,6 +3290,14 @@ Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 pos return NULL; } + if ((CVarGetInteger("gStairs", 0))) { + if (StairsArena_MallocGeneral(dbEntry->instanceSize, (uintptr_t)actor) == NULL) { + Actor_FreeOverlay(dbEntry); + actor = NULL; + return NULL; + } + } + assert(dbEntry->numLoaded < 255); dbEntry->numLoaded++; @@ -3385,6 +3439,10 @@ Actor* Actor_Delete(ActorContext* actorCtx, Actor* actor, PlayState* play) { newHead = Actor_RemoveFromCategory(play, actorCtx, actor); + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)actor); + } + ZELDA_ARENA_FREE_DEBUG(actor); dbEntry->numLoaded--; @@ -3556,14 +3614,23 @@ void BodyBreak_Alloc(BodyBreak* bodyBreak, s32 count, PlayState* play) { matricesSize = (count + 1) * sizeof(*bodyBreak->matrices); bodyBreak->matrices = ZELDA_ARENA_MALLOC_DEBUG(matricesSize); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(matricesSize, (uintptr_t)bodyBreak->matrices); + } if (bodyBreak->matrices != NULL) { dListsSize = (count + 1) * sizeof(*bodyBreak->dLists); bodyBreak->dLists = ZELDA_ARENA_MALLOC_DEBUG(dListsSize); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(dListsSize, (uintptr_t)bodyBreak->dLists); + } if (bodyBreak->dLists != NULL) { objectIdsSize = (count + 1) * sizeof(*bodyBreak->objectIds); bodyBreak->objectIds = ZELDA_ARENA_MALLOC_DEBUG(objectIdsSize); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(objectIdsSize, (uintptr_t)bodyBreak->objectIds); + } if (bodyBreak->objectIds != NULL) { memset((u8*)bodyBreak->matrices,0, matricesSize); @@ -3576,14 +3643,23 @@ void BodyBreak_Alloc(BodyBreak* bodyBreak, s32 count, PlayState* play) { } if (bodyBreak->matrices != NULL) { + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)bodyBreak->matrices); + } ZELDA_ARENA_FREE_DEBUG(bodyBreak->matrices); } if (bodyBreak->dLists != NULL) { + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)bodyBreak->dLists); + } ZELDA_ARENA_FREE_DEBUG(bodyBreak->dLists); } if (bodyBreak->objectIds != NULL) { + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)bodyBreak->objectIds); + } ZELDA_ARENA_FREE_DEBUG(bodyBreak->objectIds); } } @@ -3651,6 +3727,12 @@ s32 BodyBreak_SpawnParts(Actor* actor, BodyBreak* bodyBreak, PlayState* play, s1 bodyBreak->val = BODYBREAK_STATUS_FINISHED; + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)bodyBreak->matrices); + StairsArena_FreeGeneral((uintptr_t)bodyBreak->dLists); + StairsArena_FreeGeneral((uintptr_t)bodyBreak->objectIds); + } + ZELDA_ARENA_FREE_DEBUG(bodyBreak->matrices); ZELDA_ARENA_FREE_DEBUG(bodyBreak->dLists); ZELDA_ARENA_FREE_DEBUG(bodyBreak->objectIds); diff --git a/soh/src/code/z_bgcheck.c b/soh/src/code/z_bgcheck.c index 064d59860..f36b3e93c 100644 --- a/soh/src/code/z_bgcheck.c +++ b/soh/src/code/z_bgcheck.c @@ -4,6 +4,8 @@ #include #include +#include "soh/Enhancements/stairs.h" + #define SS_NULL 0xFFFF // bccFlags @@ -2454,6 +2456,10 @@ void SSNodeList_Alloc(PlayState* play, SSNodeList* this, s32 tblMax, s32 numPoly this->polyCheckTbl = GAMESTATE_ALLOC_MC(&play->state, numPolys); + if (CVarGetInteger("gStairs", 0)) { + Stairs_DecreaseSize(numPolys); + } + assert(this->polyCheckTbl != NULL); } diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index 90634ea31..32fba4450 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -7,6 +7,7 @@ #include "overlays/actors/ovl_En_Horse/z_en_horse.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/stairs.h" s16 Camera_ChangeSettingFlags(Camera* camera, s16 setting, s16 flags); s32 Camera_ChangeModeFlags(Camera* camera, s16 mode, u8 flags); @@ -6926,6 +6927,9 @@ s32 Camera_Special9(Camera* camera) { Camera* Camera_Create(View* view, CollisionContext* colCtx, PlayState* play) { Camera* newCamera = ZELDA_ARENA_MALLOC_DEBUG(sizeof(*newCamera)); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(sizeof(Camera), (uintptr_t)newCamera); + } if (newCamera != NULL) { osSyncPrintf(VT_FGCOL(BLUE) "camera: create --- allocate %d byte" VT_RST "\n", sizeof(*newCamera) * 4); @@ -6939,6 +6943,9 @@ Camera* Camera_Create(View* view, CollisionContext* colCtx, PlayState* play) { void Camera_Destroy(Camera* camera) { if (camera != NULL) { osSyncPrintf(VT_FGCOL(BLUE) "camera: destroy ---" VT_RST "\n"); + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)camera); + } ZELDA_ARENA_FREE_DEBUG(camera); } else { osSyncPrintf(VT_COL(YELLOW, BLACK) "camera: destroy: already cleared\n" VT_RST); diff --git a/soh/src/code/z_collision_check.c b/soh/src/code/z_collision_check.c index c4716c947..550ab98cf 100644 --- a/soh/src/code/z_collision_check.c +++ b/soh/src/code/z_collision_check.c @@ -2,6 +2,7 @@ #include "vt.h" #include "overlays/effects/ovl_Effect_Ss_HitMark/z_eff_ss_hitmark.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/stairs.h" #include typedef s32 (*ColChkResetFunc)(PlayState*, Collider*); @@ -339,6 +340,9 @@ s32 Collider_FreeJntSph(PlayState* play, ColliderJntSph* collider) { collider->count = 0; if (collider->elements != NULL) { ZELDA_ARENA_FREE_DEBUG(collider->elements); + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)collider->elements); + } } collider->elements = NULL; return 1; @@ -370,6 +374,9 @@ s32 Collider_SetJntSphToActor(PlayState* play, ColliderJntSph* dest, ColliderJnt Collider_SetBaseToActor(play, &dest->base, &src->base); dest->count = src->count; dest->elements = ZELDA_ARENA_MALLOC_DEBUG(src->count * sizeof(ColliderJntSphElement)); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(src->count * sizeof(ColliderJntSphElement), (uintptr_t)dest->elements); + } if (dest->elements == NULL) { dest->count = 0; @@ -399,6 +406,9 @@ s32 Collider_SetJntSphAllocType1(PlayState* play, ColliderJntSph* dest, Actor* a Collider_SetBaseType1(play, &dest->base, actor, &src->base); dest->count = src->count; dest->elements = ZELDA_ARENA_MALLOC_DEBUG(src->count * sizeof(ColliderJntSphElement)); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(src->count * sizeof(ColliderJntSphElement),(uintptr_t)dest->elements); + } if (dest->elements == NULL) { dest->count = 0; @@ -427,6 +437,9 @@ s32 Collider_SetJntSphAlloc(PlayState* play, ColliderJntSph* dest, Actor* actor, Collider_SetBase(play, &dest->base, actor, &src->base); dest->count = src->count; dest->elements = ZELDA_ARENA_MALLOC_DEBUG(src->count * sizeof(ColliderJntSphElement)); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(src->count * sizeof(ColliderJntSphElement),(uintptr_t)dest->elements); + } if (dest->elements == NULL) { dest->count = 0; @@ -704,6 +717,9 @@ s32 Collider_FreeTris(PlayState* play, ColliderTris* tris) { tris->count = 0; if (tris->elements != NULL) { + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)tris->elements); + } ZELDA_ARENA_FREE_DEBUG(tris->elements); } tris->elements = NULL; @@ -737,6 +753,10 @@ s32 Collider_SetTrisAllocType1(PlayState* play, ColliderTris* dest, Actor* actor Collider_SetBaseType1(play, &dest->base, actor, &src->base); dest->count = src->count; dest->elements = ZELDA_ARENA_MALLOC_DEBUG(dest->count * sizeof(ColliderTrisElement)); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(dest->count * sizeof(ColliderTrisElement),(uintptr_t)dest->elements); + } + if (dest->elements == NULL) { dest->count = 0; osSyncPrintf(VT_FGCOL(RED)); @@ -763,6 +783,9 @@ s32 Collider_SetTrisAlloc(PlayState* play, ColliderTris* dest, Actor* actor, Col Collider_SetBase(play, &dest->base, actor, &src->base); dest->count = src->count; dest->elements = ZELDA_ARENA_MALLOC_DEBUG(dest->count * sizeof(ColliderTrisElement)); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(dest->count * sizeof(ColliderTrisElement),(uintptr_t)dest->elements); + } if (dest->elements == NULL) { osSyncPrintf(VT_FGCOL(RED)); diff --git a/soh/src/code/z_construct.c b/soh/src/code/z_construct.c index c8a340492..33c703bc4 100644 --- a/soh/src/code/z_construct.c +++ b/soh/src/code/z_construct.c @@ -2,6 +2,8 @@ #include #include +#include "soh/Enhancements/stairs.h" + void func_80110990(PlayState* play) { Map_Destroy(play); } @@ -36,6 +38,10 @@ void func_801109B0(PlayState* play) { interfaceCtx->parameterSegment = GAMESTATE_ALLOC_MC(&play->state, parameterSize); + if (CVarGetInteger("gStairs", 0)) { + Stairs_DecreaseSize(parameterSize); + } + osSyncPrintf("parameter->parameterSegment=%x\n", interfaceCtx->parameterSegment); assert(interfaceCtx->parameterSegment != NULL); diff --git a/soh/src/code/z_effect_soft_sprite.c b/soh/src/code/z_effect_soft_sprite.c index ee6c7e951..4236500cf 100644 --- a/soh/src/code/z_effect_soft_sprite.c +++ b/soh/src/code/z_effect_soft_sprite.c @@ -2,6 +2,7 @@ #include "vt.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/stairs.h" #include EffectSsInfo sEffectSsInfo = { 0 }; // "EffectSS2Info" @@ -55,6 +56,9 @@ void EffectSs_ClearAll(PlayState* play) { addr = overlay->loadedRamAddr; if (addr != NULL) { + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)addr); + } ZELDA_ARENA_FREE_DEBUG(addr); } @@ -193,6 +197,9 @@ void EffectSs_Spawn(PlayState* play, s32 type, s32 priority, void* initParams) { } else { if (overlayEntry->loadedRamAddr == NULL) { overlayEntry->loadedRamAddr = ZELDA_ARENA_MALLOC_RDEBUG(overlaySize); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocRGeneral(overlaySize, (uintptr_t)overlayEntry->loadedRamAddr); + } if (overlayEntry->loadedRamAddr == NULL) { osSyncPrintf(VT_FGCOL(RED)); diff --git a/soh/src/code/z_fcurve_data_skelanime.c b/soh/src/code/z_fcurve_data_skelanime.c index b75c34a61..e05ba9355 100644 --- a/soh/src/code/z_fcurve_data_skelanime.c +++ b/soh/src/code/z_fcurve_data_skelanime.c @@ -1,6 +1,8 @@ #include "global.h" #include +#include "soh/Enhancements/stairs.h" + void SkelCurve_Clear(SkelAnimeCurve* skelCurve) { skelCurve->limbCount = 0; skelCurve->limbList = NULL; @@ -25,6 +27,9 @@ s32 SkelCurve_Init(PlayState* play, SkelAnimeCurve* skelCurve, SkelCurveLimbList skelCurve->limbList = SEGMENTED_TO_VIRTUAL(limbList->limbs); skelCurve->transforms = ZELDA_ARENA_MALLOC_DEBUG(sizeof(*skelCurve->transforms) * skelCurve->limbCount); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(sizeof(*skelCurve->transforms) * skelCurve->limbCount, (uintptr_t)skelCurve->transforms); + } assert(skelCurve->transforms != NULL); skelCurve->animCurFrame = 0.0f; return 1; @@ -32,6 +37,9 @@ s32 SkelCurve_Init(PlayState* play, SkelAnimeCurve* skelCurve, SkelCurveLimbList void SkelCurve_Destroy(PlayState* play, SkelAnimeCurve* skelCurve) { if (skelCurve->transforms != NULL) { + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)skelCurve->transforms); + } ZELDA_ARENA_FREE_DEBUG(skelCurve->transforms); } } diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index d6c84e355..6648af283 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -12,11 +12,13 @@ #include #include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/stairs.h" #include #include #include +// #include void* D_8012D1F0 = NULL; //UNK_TYPE D_8012D1F4 = 0; // unused @@ -221,6 +223,10 @@ void Play_Destroy(GameState* thisx) { KaleidoScopeCall_Destroy(play); KaleidoManager_Destroy(); ZeldaArena_Cleanup(); + + // #Region [SoH] Stairs + StairsArena_Cleanup(); + Fault_RemoveClient(&D_801614B8); disableBetaQuest(); gPlayState = NULL; @@ -472,14 +478,24 @@ void Play_Init(GameState* thisx) { gPlayState = play; //play->state.gfxCtx = NULL; uintptr_t zAlloc; + uintptr_t stairsAlloc; uintptr_t zAllocAligned; + uintptr_t stairsAllocAligned; size_t zAllocSize; + size_t stairsAllocSize; Player* player; s32 playerStartCamId; s32 i; u8 tempSetupIndex; s32 pad[2]; + // #Region [SoH] Stairs + if (CVarGetInteger("gSimulateHeap", 0)) { + CVarSetInteger("gStairs", 1); + } else { + CVarSetInteger("gStairs", 0); + } + // Skip Child Stealth when option is enabled, Zelda's Letter isn't obtained and Impa's reward hasn't been received // eventChkInf[4] & 1 = Got Zelda's Letter // eventChkInf[5] & 0x200 = Got Impa's reward @@ -664,6 +680,15 @@ void Play_Init(GameState* thisx) { D_801614B0.a = 0; Flags_UnsetAllEnv(play); + // #Region [SoH] Stairs + // Stairs Heap + if (CVarGetInteger("gStairs", 0)) { + stairsAllocSize = Stairs_GetSize(); + stairsAlloc = GAMESTATE_ALLOC_MC(&play->state, stairsAllocSize); + stairsAllocAligned = (stairsAlloc + 8) & ~0xF; + StairsArena_Init(stairsAllocAligned, stairsAllocSize - stairsAllocAligned + stairsAlloc); + } + osSyncPrintf("ZELDA ALLOC SIZE=%x\n", THA_GetSize(&play->state.tha)); zAllocSize = THA_GetSize(&play->state.tha); zAlloc = GAMESTATE_ALLOC_MC(&play->state, zAllocSize); diff --git a/soh/src/code/z_room.c b/soh/src/code/z_room.c index de068ae6c..e794109cf 100644 --- a/soh/src/code/z_room.c +++ b/soh/src/code/z_room.c @@ -5,6 +5,7 @@ #include "global.h" #include "vt.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" +#include "soh/Enhancements/stairs.h" #include #include @@ -566,6 +567,11 @@ u32 func_80096FE8(PlayState* play, RoomContext* roomCtx) { // "Room buffer size=%08x(%5.1fK)" osSyncPrintf("部屋バッファサイズ=%08x(%5.1fK)\n", maxRoomSize, maxRoomSize / 1024.0f); roomCtx->bufPtrs[0] = GAMESTATE_ALLOC_MC(&play->state, maxRoomSize); + + if (CVarGetInteger("gStairs", 0)) { + Stairs_DecreaseSize(maxRoomSize); + } + // "Room buffer initial pointer=%08x" osSyncPrintf("部屋バッファ開始ポインタ=%08x\n", roomCtx->bufPtrs[0]); roomCtx->bufPtrs[1] = (void*)((intptr_t)roomCtx->bufPtrs[0] + maxRoomSize); diff --git a/soh/src/code/z_scene.c b/soh/src/code/z_scene.c index eeff423d7..f21941913 100644 --- a/soh/src/code/z_scene.c +++ b/soh/src/code/z_scene.c @@ -3,6 +3,8 @@ #include "soh/ActorDB.h" #include +#include "soh/Enhancements/stairs.h" + RomFile sNaviMsgFiles[]; s32 Object_Spawn(ObjectContext* objectCtx, s16 objectId) { @@ -71,6 +73,11 @@ void Object_InitBank(PlayState* play, ObjectContext* objectCtx) { objectCtx->spaceStart = objectCtx->status[0].segment = GAMESTATE_ALLOC_MC(&play->state, spaceSize); + + if (CVarGetInteger("gStairs", 0)) { + Stairs_DecreaseSize(spaceSize); + } + objectCtx->spaceEnd = (void*)((uintptr_t)objectCtx->spaceStart + spaceSize); objectCtx->mainKeepIndex = Object_Spawn(objectCtx, OBJECT_GAMEPLAY_KEEP); diff --git a/soh/src/code/z_skelanime.c b/soh/src/code/z_skelanime.c index 2123c2d3b..5ddc18930 100644 --- a/soh/src/code/z_skelanime.c +++ b/soh/src/code/z_skelanime.c @@ -4,6 +4,8 @@ #include #include +#include "soh/Enhancements/stairs.h" + #define ANIM_INTERP 1 s32 LinkAnimation_Loop(PlayState* play, SkelAnime* skelAnime); @@ -1132,6 +1134,10 @@ void SkelAnime_InitLink(PlayState* play, SkelAnime* skelAnime, FlexSkeletonHeade if (jointTable == NULL) { skelAnime->jointTable = ZELDA_ARENA_MALLOC_DEBUG(allocSize); skelAnime->morphTable = ZELDA_ARENA_MALLOC_DEBUG(allocSize); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(allocSize, (uintptr_t)skelAnime->jointTable); + StairsArena_MallocGeneral(allocSize, (uintptr_t)skelAnime->morphTable); + } } else { assert(limbBufCount == limbCount); @@ -1466,6 +1472,10 @@ s32 SkelAnime_Init(PlayState* play, SkelAnime* skelAnime, SkeletonHeader* skelet ZELDA_ARENA_MALLOC_DEBUG(skelAnime->limbCount * sizeof(*skelAnime->jointTable)); skelAnime->morphTable = ZELDA_ARENA_MALLOC_DEBUG(skelAnime->limbCount * sizeof(*skelAnime->morphTable)); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(skelAnime->limbCount * sizeof(*skelAnime->jointTable), (uintptr_t)skelAnime->jointTable); + StairsArena_MallocGeneral(skelAnime->limbCount * sizeof(*skelAnime->morphTable), (uintptr_t)skelAnime->morphTable); + } } else { assert(limbCount == skelAnime->limbCount); skelAnime->jointTable = jointTable; @@ -1503,6 +1513,10 @@ s32 SkelAnime_InitFlex(PlayState* play, SkelAnime* skelAnime, FlexSkeletonHeader skelAnime->morphTable = ZELDA_ARENA_MALLOC_DEBUG(skelAnime->limbCount * sizeof(*skelAnime->morphTable)); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(skelAnime->limbCount * sizeof(*skelAnime->jointTable), (uintptr_t)skelAnime->jointTable); + StairsArena_MallocGeneral(skelAnime->limbCount * sizeof(*skelAnime->morphTable), (uintptr_t)skelAnime->morphTable); + } } else { assert(limbCount == skelAnime->limbCount); skelAnime->jointTable = jointTable; @@ -1537,6 +1551,10 @@ s32 SkelAnime_InitSkin(PlayState* play, SkelAnime* skelAnime, SkeletonHeader* sk ZELDA_ARENA_MALLOC_DEBUG(skelAnime->limbCount * sizeof(*skelAnime->jointTable)); skelAnime->morphTable = ZELDA_ARENA_MALLOC_DEBUG(skelAnime->limbCount * sizeof(*skelAnime->morphTable)); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(skelAnime->limbCount * sizeof(*skelAnime->jointTable), (uintptr_t)skelAnime->jointTable); + StairsArena_MallocGeneral(skelAnime->limbCount * sizeof(*skelAnime->morphTable), (uintptr_t)skelAnime->morphTable); + } if ((skelAnime->jointTable == NULL) || (skelAnime->morphTable == NULL)) { osSyncPrintf(VT_FGCOL(RED)); // "Memory allocation error" @@ -1939,12 +1957,18 @@ s32 Animation_OnFrame(SkelAnime* skelAnime, f32 frame) { */ void SkelAnime_Free(SkelAnime* skelAnime, PlayState* play) { if (skelAnime->jointTable != NULL) { + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)skelAnime->jointTable); + } ZELDA_ARENA_FREE_DEBUG(skelAnime->jointTable); } else { osSyncPrintf("now_joint あきまへん!!\n"); // "now_joint is freed! !" } if (skelAnime->morphTable != NULL) { + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)skelAnime->morphTable); + } ZELDA_ARENA_FREE_DEBUG(skelAnime->morphTable); } else { osSyncPrintf("morf_joint あきまへん!!\n"); // "morf_joint is freed !!" diff --git a/soh/src/code/z_skin_awb.c b/soh/src/code/z_skin_awb.c index d0ebe75b4..2cd58dbc1 100644 --- a/soh/src/code/z_skin_awb.c +++ b/soh/src/code/z_skin_awb.c @@ -2,6 +2,8 @@ #include "overlays/actors/ovl_En_fHG/z_en_fhg.h" #include +#include "soh/Enhancements/stairs.h" + /** * Initialises the Vtx buffers used for limb at index `limbIndex` */ @@ -53,6 +55,9 @@ void Skin_Init(PlayState* play, Skin* skin, SkeletonHeader* skeletonHeader, Anim limbCount = skin->skeletonHeader->limbCount; skin->vtxTable = ZELDA_ARENA_MALLOC_DEBUG(limbCount * sizeof(SkinLimbVtx)); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(limbCount * sizeof(SkinLimbVtx), (uintptr_t)skin->vtxTable); + } assert(skin->vtxTable != NULL); @@ -72,11 +77,17 @@ void Skin_Init(PlayState* play, Skin* skin, SkeletonHeader* skeletonHeader, Anim vtxEntry->buf[0] = ZELDA_ARENA_MALLOC_DEBUG(animatedLimbData->totalVtxCount * sizeof(Vtx)); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(animatedLimbData->totalVtxCount * sizeof(Vtx), (uintptr_t)vtxEntry->buf[0]); + } assert(vtxEntry->buf[0] != NULL); vtxEntry->buf[1] = ZELDA_ARENA_MALLOC_DEBUG(animatedLimbData->totalVtxCount * sizeof(Vtx)); assert(vtxEntry->buf[1] != NULL); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(animatedLimbData->totalVtxCount * sizeof(Vtx), (uintptr_t)vtxEntry->buf[1]); + } Skin_InitAnimatedLimb(play, skin, i); } @@ -94,16 +105,25 @@ void Skin_Free(PlayState* play, Skin* skin) { for (i = 0; i < skin->limbCount; i++) { if (skin->vtxTable[i].buf[0] != NULL) { + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)skin->vtxTable[i].buf[0]); + } ZELDA_ARENA_FREE_DEBUG(skin->vtxTable[i].buf[0]); skin->vtxTable[i].buf[0] = NULL; } if (skin->vtxTable[i].buf[1] != NULL) { + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)skin->vtxTable[i].buf[1]); + } ZELDA_ARENA_FREE_DEBUG(skin->vtxTable[i].buf[1]); skin->vtxTable[i].buf[1] = NULL; } } if (skin->vtxTable != NULL) { + if (CVarGetInteger("gStairs", 0)) { + StairsArena_FreeGeneral((uintptr_t)skin->vtxTable); + } ZELDA_ARENA_FREE_DEBUG(skin->vtxTable); } diff --git a/soh/src/code/z_vr_box.c b/soh/src/code/z_vr_box.c index ff2622187..61c983bdd 100644 --- a/soh/src/code/z_vr_box.c +++ b/soh/src/code/z_vr_box.c @@ -71,6 +71,8 @@ #include "assets/textures/skyboxes/vr_holy1_static.h" #include "assets/textures/skyboxes/vr_holy1_pal_static.h" +#include "soh/Enhancements/stairs.h" + u32 D_8012AC90[4] = { 0x00000000, @@ -605,6 +607,15 @@ void Skybox_Setup(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) { u8 sp40; // imageIdx2 uintptr_t start; s32 phi_v1; + + // todo: figure out correct 'size' rather than 0x10000 (seems quite large?) + // if (CVarGetInteger("gStairs", 0)) { + // if (skyboxId == SKYBOX_NORMAL_SKY || skyboxId == SKYBOX_OVERCAST_SUNSET || skyboxId == SKYBOX_CUTSCENE_MAP) { + // Stairs_DecreaseSize(0x10000 * 4); + // } else { + // Stairs_DecreaseSize(0x10000 * 2); + // } + // } switch (skyboxId) { @@ -969,23 +980,43 @@ void Skybox_Init(GameState* state, SkyboxContext* skyboxCtx, s16 skyboxId) { skyboxCtx->dListBuf = GAMESTATE_ALLOC_MC(state, 8 * 150 * sizeof(Gfx)); assert(skyboxCtx->dListBuf != NULL); + if (CVarGetInteger("gStairs", 0)) { + Stairs_DecreaseSize(8 * 150 * sizeof(Gfx)); + } + skyboxCtx->roomVtx = GAMESTATE_ALLOC_MC(state, 256 * sizeof(Vtx)); assert(skyboxCtx->roomVtx != NULL); + if (CVarGetInteger("gStairs", 0)) { + Stairs_DecreaseSize(256 * sizeof(Vtx)); + } + func_800AEFC8(skyboxCtx, skyboxId); } else { skyboxCtx->dListBuf = GAMESTATE_ALLOC_MC(state, 12 * 150 * sizeof(Gfx)); assert(skyboxCtx->dListBuf != NULL); + if (CVarGetInteger("gStairs", 0)) { + Stairs_DecreaseSize(12 * 150 * sizeof(Gfx)); + } + if (skyboxId == SKYBOX_CUTSCENE_MAP) { skyboxCtx->roomVtx = GAMESTATE_ALLOC_MC(state, 192 * sizeof(Vtx)); assert(skyboxCtx->roomVtx != NULL); + if (CVarGetInteger("gStairs", 0)) { + Stairs_DecreaseSize(192 * sizeof(Gfx)); + } + func_800AF178(skyboxCtx, 6); } else { skyboxCtx->roomVtx = GAMESTATE_ALLOC_MC(state, 160 * sizeof(Vtx)); assert(skyboxCtx->roomVtx != NULL); + if (CVarGetInteger("gStairs", 0)) { + Stairs_DecreaseSize(160 * sizeof(Vtx)); + } + func_800AF178(skyboxCtx, 5); } } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index db8e2e3e4..f38c1b9c0 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -29,6 +29,7 @@ #include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/randomizer/randomizer_grotto.h" +#include "soh/Enhancements/stairs.h" #include "soh/frame_interpolation.h" #include @@ -10198,6 +10199,9 @@ void Player_Init(Actor* thisx, PlayState* play2) { } Player_InitCommon(this, play, gPlayerSkelHeaders[((void)0, gSaveContext.linkAge)]); this->giObjectSegment = (void*)(((uintptr_t)ZELDA_ARENA_MALLOC_DEBUG(0x3008) + 8) & ~0xF); + if ((CVarGetInteger("gStairs", 0))) { + StairsArena_MallocGeneral(0x3008, (uintptr_t)this->giObjectSegment); + } sp50 = gSaveContext.respawnFlag;