diff --git a/mm/2s2h/BenJsonConversions.hpp b/mm/2s2h/BenJsonConversions.hpp index 5de841855..190f5202f 100644 --- a/mm/2s2h/BenJsonConversions.hpp +++ b/mm/2s2h/BenJsonConversions.hpp @@ -23,11 +23,13 @@ void from_json(const json& j, DpadSaveInfo& dpadEquips) { void to_json(json& j, const ShipSaveInfo& shipSaveInfo) { j = json { { "dpadEquips", shipSaveInfo.dpadEquips }, + { "pauseSaveEntrance", shipSaveInfo.pauseSaveEntrance }, }; } void from_json(const json& j, ShipSaveInfo& shipSaveInfo) { j.at("dpadEquips").get_to(shipSaveInfo.dpadEquips); + j.at("pauseSaveEntrance").get_to(shipSaveInfo.pauseSaveEntrance); } void to_json(json& j, const ItemEquips& itemEquips) { diff --git a/mm/2s2h/DeveloperTools/SaveEditor.cpp b/mm/2s2h/DeveloperTools/SaveEditor.cpp index a411f920f..6d17522ac 100644 --- a/mm/2s2h/DeveloperTools/SaveEditor.cpp +++ b/mm/2s2h/DeveloperTools/SaveEditor.cpp @@ -347,6 +347,7 @@ void DrawGeneralTab() { } UIWidgets::Checkbox("Has Tatl", (bool*)&gSaveContext.save.hasTatl, { .color = UIWidgets::Colors::Gray }); + UIWidgets::Checkbox("Is Owl Save", (bool*)&gSaveContext.save.isOwlSave, { .color = UIWidgets::Colors::Gray }); ImGui::EndGroup(); ImGui::PopItemWidth(); diff --git a/mm/2s2h/SaveManager/Migrations/3.cpp b/mm/2s2h/SaveManager/Migrations/3.cpp new file mode 100644 index 000000000..011b746ab --- /dev/null +++ b/mm/2s2h/SaveManager/Migrations/3.cpp @@ -0,0 +1,15 @@ +#include "2s2h/SaveManager/SaveManager.h" +#include "z64.h" + +// For a short period of time, we hijacked the owl save location to store the pause save entrance. +// We want to instead use a new field, and migrate anyone that previously had this set. +void SaveManager_Migration_3(nlohmann::json& j) { + int32_t owlSaveLocation = j["save"]["owlSaveLocation"].template get(); + + if (owlSaveLocation > 9) { + j["save"]["shipSaveInfo"]["pauseSaveEntrance"] = owlSaveLocation; + j["save"]["owlSaveLocation"] = 0; + } else { + j["save"]["shipSaveInfo"]["pauseSaveEntrance"] = -1; + } +} diff --git a/mm/2s2h/SaveManager/SaveManager.cpp b/mm/2s2h/SaveManager/SaveManager.cpp index ce7698d87..2e427c2fd 100644 --- a/mm/2s2h/SaveManager/SaveManager.cpp +++ b/mm/2s2h/SaveManager/SaveManager.cpp @@ -42,14 +42,16 @@ const std::filesystem::path savesFolderPath(Ship::Context::GetPathRelativeToAppD // - Increment CURRENT_SAVE_VERSION // - Create the migration file in the Migrations folder with the name `{CURRENT_SAVE_VERSION}.cpp` // - Add the migration function definition below and add it to the `migrations` map with the key being the previous version -const uint32_t CURRENT_SAVE_VERSION = 2; +const uint32_t CURRENT_SAVE_VERSION = 3; void SaveManager_Migration_1(nlohmann::json& j); void SaveManager_Migration_2(nlohmann::json& j); +void SaveManager_Migration_3(nlohmann::json& j); const std::unordered_map> migrations = { { 0, SaveManager_Migration_1 }, { 1, SaveManager_Migration_2 }, + { 2, SaveManager_Migration_3 }, }; void SaveManager_MigrateSave(nlohmann::json& j) { diff --git a/mm/include/z64save.h b/mm/include/z64save.h index 3f4f61268..2228e372e 100644 --- a/mm/include/z64save.h +++ b/mm/include/z64save.h @@ -329,6 +329,7 @@ typedef struct DpadSaveInfo { // See `ShipSaveContext` for values on the SaveContext that aren't persisted. typedef struct ShipSaveInfo { DpadSaveInfo dpadEquips; + s32 pauseSaveEntrance; } ShipSaveInfo; // #endregion diff --git a/mm/src/code/z_sram_NES.c b/mm/src/code/z_sram_NES.c index 1f5d2417b..a59c6c06e 100644 --- a/mm/src/code/z_sram_NES.c +++ b/mm/src/code/z_sram_NES.c @@ -970,9 +970,6 @@ void Sram_InitNewSave(void) { memcpy(&gSaveContext.save.saveInfo.playerData, &sSaveDefaultPlayerData, sizeof(SavePlayerData)); memcpy(&gSaveContext.save.saveInfo.equips, &sSaveDefaultItemEquips, sizeof(ItemEquips)); - // #region 2S2H [Dpad] - memcpy(&gSaveContext.save.shipSaveInfo.dpadEquips, &sSaveDefaultDpadItemEquips, sizeof(DpadSaveInfo)); - // #endregion memcpy(&gSaveContext.save.saveInfo.inventory, &sSaveDefaultInventory, sizeof(Inventory)); memcpy(&gSaveContext.save.saveInfo.checksum, &sSaveDefaultChecksum, sizeof(gSaveContext.save.saveInfo.checksum)); @@ -985,6 +982,12 @@ void Sram_InitNewSave(void) { gSaveContext.nextCutsceneIndex = 0; gSaveContext.save.saveInfo.playerData.magicLevel = 0; + + // #region 2S2H + memcpy(&gSaveContext.save.shipSaveInfo.dpadEquips, &sSaveDefaultDpadItemEquips, sizeof(DpadSaveInfo)); + gSaveContext.save.shipSaveInfo.pauseSaveEntrance = -1; + // #endregion + Sram_GenerateRandomSaveFields(); } @@ -1178,9 +1181,6 @@ void Sram_InitDebugSave(void) { memcpy(&gSaveContext.save.saveInfo.playerData, &sSaveDebugPlayerData, sizeof(SavePlayerData)); memcpy(&gSaveContext.save.saveInfo.equips, &sSaveDebugItemEquips, sizeof(ItemEquips)); - // #region 2S2H [Dpad] - memcpy(&gSaveContext.save.shipSaveInfo.dpadEquips, &sSaveDefaultDpadItemEquips, sizeof(DpadSaveInfo)); - // #endregion memcpy(&gSaveContext.save.saveInfo.inventory, &sSaveDebugInventory, sizeof(Inventory)); memcpy(&gSaveContext.save.saveInfo.checksum, &sSaveDebugChecksum, sizeof(gSaveContext.save.saveInfo.checksum)); @@ -1208,6 +1208,11 @@ void Sram_InitDebugSave(void) { gSaveContext.save.saveInfo.permanentSceneFlags[SCENE_INSIDETOWER].switch0 = 1; gSaveContext.save.saveInfo.playerData.magicLevel = 0; + // #region 2S2H + memcpy(&gSaveContext.save.shipSaveInfo.dpadEquips, &sSaveDefaultDpadItemEquips, sizeof(DpadSaveInfo)); + gSaveContext.save.shipSaveInfo.pauseSaveEntrance = -1; + // #endregion + Sram_GenerateRandomSaveFields(); } @@ -1338,8 +1343,10 @@ void Sram_OpenSave(FileSelectState* fileSelect, SramContext* sramCtx) { gSaveContext.save.playerForm = PLAYER_FORM_HUMAN; } } else { - if (gSaveContext.save.owlSaveLocation > 9) { - gSaveContext.save.entrance = gSaveContext.save.owlSaveLocation; + // When a pauseSaveEntrance is available, prioritize it over the + // owlSaveLocation, this means the players last save was a pause save. + if (gSaveContext.save.shipSaveInfo.pauseSaveEntrance != -1) { + gSaveContext.save.entrance = gSaveContext.save.shipSaveInfo.pauseSaveEntrance; } else { gSaveContext.save.entrance = D_801C6A58[(void)0, gSaveContext.save.owlSaveLocation]; } diff --git a/mm/src/overlays/actors/ovl_player_actor/z_player.c b/mm/src/overlays/actors/ovl_player_actor/z_player.c index 8a5ba9339..2564dcbe0 100644 --- a/mm/src/overlays/actors/ovl_player_actor/z_player.c +++ b/mm/src/overlays/actors/ovl_player_actor/z_player.c @@ -10968,6 +10968,12 @@ void Player_Init(Actor* thisx, PlayState* play) { initMode = PLAYER_INITMODE_D; } + // When we have a pause save entrance, we need to override the init mode to ensure the loading is handled correctly + if (gSaveContext.save.shipSaveInfo.pauseSaveEntrance != -1) { + initMode = PLAYER_INITMODE_6; + gSaveContext.save.shipSaveInfo.pauseSaveEntrance = -1; + } + D_8085D2CC[initMode](play, this); if ((this->actor.draw != NULL) && gSaveContext.save.hasTatl && diff --git a/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c b/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c index 22e7172f8..6828f3840 100644 --- a/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c +++ b/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c @@ -3498,7 +3498,7 @@ void KaleidoScope_Update(PlayState* play) { Audio_PlaySfx(NA_SE_SY_PIECE_OF_HEART); if (CVarGetInteger("gEnhancements.Kaleido.PauseSave", 0)) { gSaveContext.save.isOwlSave = true; - gSaveContext.save.owlSaveLocation = gSaveContext.save.entrance; + gSaveContext.save.shipSaveInfo.pauseSaveEntrance = gSaveContext.save.entrance; } Play_SaveCycleSceneFlags(&play->state); gSaveContext.save.saveInfo.playerData.savedSceneId = play->sceneId; @@ -3510,6 +3510,8 @@ void KaleidoScope_Update(PlayState* play) { Sram_SetFlashPagesOwlSave(sramCtx, gFlashOwlSaveStartPages[gSaveContext.fileNum * 2], gFlashOwlSaveNumPages[gSaveContext.fileNum * 2]); Sram_StartWriteToFlashOwlSave(sramCtx); + gSaveContext.save.isOwlSave = false; + gSaveContext.save.shipSaveInfo.pauseSaveEntrance = -1; } else { Sram_SetFlashPagesDefault(sramCtx, gFlashSaveStartPages[gSaveContext.fileNum], gFlashSaveNumPages[gSaveContext.fileNum]);