diff --git a/soh/soh/Enhancements/gameplaystats.cpp b/soh/soh/Enhancements/gameplaystats.cpp index a6d48a9a1..69b41974b 100644 --- a/soh/soh/Enhancements/gameplaystats.cpp +++ b/soh/soh/Enhancements/gameplaystats.cpp @@ -233,47 +233,54 @@ void LoadStatsVersion1() { [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.sohStats.locationsSkipped[i]); }); } -void SaveStats(SaveContext* saveContext) { - SaveManager::Instance->SaveData("buildVersion", saveContext->sohStats.buildVersion); - SaveManager::Instance->SaveData("buildVersionMajor", saveContext->sohStats.buildVersionMajor); - SaveManager::Instance->SaveData("buildVersionMinor", saveContext->sohStats.buildVersionMinor); - SaveManager::Instance->SaveData("buildVersionPatch", saveContext->sohStats.buildVersionPatch); +void SaveStats(SaveContext* saveContext, const std::string& subSection) { + if (subSection == "all") { + SaveManager::Instance->SaveData("buildVersion", saveContext->sohStats.buildVersion); + SaveManager::Instance->SaveData("buildVersionMajor", saveContext->sohStats.buildVersionMajor); + SaveManager::Instance->SaveData("buildVersionMinor", saveContext->sohStats.buildVersionMinor); + SaveManager::Instance->SaveData("buildVersionPatch", saveContext->sohStats.buildVersionPatch); - SaveManager::Instance->SaveData("heartPieces", saveContext->sohStats.heartPieces); - SaveManager::Instance->SaveData("heartContainers", saveContext->sohStats.heartContainers); - SaveManager::Instance->SaveArray("dungeonKeys", ARRAY_COUNT(saveContext->sohStats.dungeonKeys), [&](size_t i) { - SaveManager::Instance->SaveData("", saveContext->sohStats.dungeonKeys[i]); - }); - SaveManager::Instance->SaveData("playTimer", saveContext->sohStats.playTimer); - SaveManager::Instance->SaveData("pauseTimer", saveContext->sohStats.pauseTimer); - SaveManager::Instance->SaveArray( - "itemTimestamps", ARRAY_COUNT(saveContext->sohStats.itemTimestamp), - [&](size_t i) { SaveManager::Instance->SaveData("", saveContext->sohStats.itemTimestamp[i]); }); - SaveManager::Instance->SaveArray( - "sceneTimestamps", ARRAY_COUNT(saveContext->sohStats.sceneTimestamps), [&](size_t i) { - if (saveContext->sohStats.sceneTimestamps[i].scene != 254 && saveContext->sohStats.sceneTimestamps[i].room != 254) { - SaveManager::Instance->SaveStruct("", [&]() { - SaveManager::Instance->SaveData("scene", saveContext->sohStats.sceneTimestamps[i].scene); - SaveManager::Instance->SaveData("room", saveContext->sohStats.sceneTimestamps[i].room); - SaveManager::Instance->SaveData("sceneTime", saveContext->sohStats.sceneTimestamps[i].sceneTime); - SaveManager::Instance->SaveData("roomTime", saveContext->sohStats.sceneTimestamps[i].roomTime); - SaveManager::Instance->SaveData("isRoom", saveContext->sohStats.sceneTimestamps[i].isRoom); - }); - } + SaveManager::Instance->SaveData("heartPieces", saveContext->sohStats.heartPieces); + SaveManager::Instance->SaveData("heartContainers", saveContext->sohStats.heartContainers); + SaveManager::Instance->SaveArray("dungeonKeys", ARRAY_COUNT(saveContext->sohStats.dungeonKeys), [&](size_t i) { + SaveManager::Instance->SaveData("", saveContext->sohStats.dungeonKeys[i]); }); - SaveManager::Instance->SaveData("tsIdx", saveContext->sohStats.tsIdx); - SaveManager::Instance->SaveArray("counts", ARRAY_COUNT(saveContext->sohStats.count), [&](size_t i) { - SaveManager::Instance->SaveData("", saveContext->sohStats.count[i]); - }); - SaveManager::Instance->SaveArray( - "scenesDiscovered", ARRAY_COUNT(saveContext->sohStats.scenesDiscovered), - [&](size_t i) { SaveManager::Instance->SaveData("", saveContext->sohStats.scenesDiscovered[i]); }); - SaveManager::Instance->SaveArray( - "entrancesDiscovered", ARRAY_COUNT(saveContext->sohStats.entrancesDiscovered), - [&](size_t i) { SaveManager::Instance->SaveData("", saveContext->sohStats.entrancesDiscovered[i]); }); - SaveManager::Instance->SaveArray( - "locationsSkipped", ARRAY_COUNT(saveContext->sohStats.locationsSkipped), - [&](size_t i) { SaveManager::Instance->SaveData("", saveContext->sohStats.locationsSkipped[i]); }); + SaveManager::Instance->SaveData("playTimer", saveContext->sohStats.playTimer); + SaveManager::Instance->SaveData("pauseTimer", saveContext->sohStats.pauseTimer); + SaveManager::Instance->SaveArray( + "itemTimestamps", ARRAY_COUNT(saveContext->sohStats.itemTimestamp), + [&](size_t i) { SaveManager::Instance->SaveData("", saveContext->sohStats.itemTimestamp[i]); }); + SaveManager::Instance->SaveArray( + "sceneTimestamps", ARRAY_COUNT(saveContext->sohStats.sceneTimestamps), [&](size_t i) { + if (saveContext->sohStats.sceneTimestamps[i].scene != 254 && + saveContext->sohStats.sceneTimestamps[i].room != 254) { + SaveManager::Instance->SaveStruct("", [&]() { + SaveManager::Instance->SaveData("scene", saveContext->sohStats.sceneTimestamps[i].scene); + SaveManager::Instance->SaveData("room", saveContext->sohStats.sceneTimestamps[i].room); + SaveManager::Instance->SaveData("sceneTime", saveContext->sohStats.sceneTimestamps[i].sceneTime); + SaveManager::Instance->SaveData("roomTime", saveContext->sohStats.sceneTimestamps[i].roomTime); + SaveManager::Instance->SaveData("isRoom", saveContext->sohStats.sceneTimestamps[i].isRoom); + }); + } + }); + SaveManager::Instance->SaveData("tsIdx", saveContext->sohStats.tsIdx); + SaveManager::Instance->SaveArray("counts", ARRAY_COUNT(saveContext->sohStats.count), [&](size_t i) { + SaveManager::Instance->SaveData("", saveContext->sohStats.count[i]); + }); + SaveManager::Instance->SaveArray( + "locationsSkipped", ARRAY_COUNT(saveContext->sohStats.locationsSkipped), + [&](size_t i) { SaveManager::Instance->SaveData("", saveContext->sohStats.locationsSkipped[i]); }); + } + if (subSection == "entrances" || subSection == "all") { + SaveManager::Instance->SaveArray("entrancesDiscovered", ARRAY_COUNT(saveContext->sohStats.entrancesDiscovered), [&](size_t i) { + SaveManager::Instance->SaveData("", saveContext->sohStats.entrancesDiscovered[i]); + }); + } + if (subSection == "scenes" || subSection == "all") { + SaveManager::Instance->SaveArray("scenesDiscovered", ARRAY_COUNT(saveContext->sohStats.scenesDiscovered), [&](size_t i) { + SaveManager::Instance->SaveData("", saveContext->sohStats.scenesDiscovered[i]); + }); + } } void InitStats(bool isDebug) { diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c index 3c3712afa..26be88a24 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c @@ -769,6 +769,7 @@ void Entrance_SetSceneDiscovered(u8 sceneNum) { u32 sceneBit = 1 << (sceneNum - (idx * bitsPerIndex)); gSaveContext.sohStats.scenesDiscovered[idx] |= sceneBit; } + Save_SaveSection("sohStats.scenes"); } u8 Entrance_GetIsEntranceDiscovered(u16 entranceIndex) { @@ -801,4 +802,5 @@ void Entrance_SetEntranceDiscovered(u16 entranceIndex) { } } } + Save_SaveSection("sohStats.entrances"); } diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 873399080..ad53de5a2 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -279,7 +279,7 @@ void SaveManager::LoadRandomizerVersion2() { }); } -void SaveManager::SaveRandomizer(SaveContext* saveContext) { +void SaveManager::SaveRandomizer(SaveContext* saveContext, const std::string& subString) { if (!saveContext->n64ddFlag) return; @@ -709,26 +709,32 @@ void SaveManager::InitFileDebug() { } // Threaded SaveFile takes copy of gSaveContext for local unmodified storage -void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext, const std::string sectionString) { - /*nlohmann::json baseBlock; - - baseBlock["version"] = 1; - baseBlock["sections"] = nlohmann::json::object();*/ +void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext, const std::string& sectionString) { + saveBlock["version"] = 1; + size_t period = sectionString.find("."); + std::string section = sectionString; + std::string subsection = ""; + if (period != std::string::npos) { + subsection = sectionString.substr(period + 1, std::string::npos); + section = sectionString.substr(0, sectionString.length() - (subsection.length() + 1)); + } if (sectionString == "all") { for (auto& sectionHandler : sectionSaveHandlers) { - nlohmann::json& sectionBlock = saveBlock["sections"][sectionHandler.first]; - sectionBlock["version"] = sectionHandler.second.first; - sectionBlock["data"] = nlohmann::json::object(); + if (std::find(gameSaveRegistry.begin(), gameSaveRegistry.end(), sectionHandler.first) != gameSaveRegistry.end()) { + nlohmann::json& sectionBlock = saveBlock["sections"][sectionHandler.first]; + sectionBlock["version"] = sectionHandler.second.first; + sectionBlock["data"] = nlohmann::json::object(); - currentJsonContext = §ionBlock["data"]; - sectionHandler.second.second(saveContext); + currentJsonContext = §ionBlock["data"]; + sectionHandler.second.second(saveContext, "all"); + } } - } else if (sectionSaveHandlers.contains(sectionString) && std::find(gameSaveRegistry.begin(), gameSaveRegistry.end(), sectionString) != gameSaveRegistry.end()) { - SectionSaveHandler handler = sectionSaveHandlers.find(sectionString)->second; - nlohmann::json& sectionBlock = saveBlock["sections"][sectionString]; + } else if (sectionSaveHandlers.contains(section)) { + SectionSaveHandler handler = sectionSaveHandlers.find(section)->second; + nlohmann::json& sectionBlock = saveBlock["sections"][section]; sectionBlock["version"] = handler.first; currentJsonContext = §ionBlock["data"]; - handler.second(saveContext); + handler.second(saveContext, subsection); } else { return; } @@ -748,14 +754,18 @@ void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext, const GameInteractor::Instance->ExecuteHooks(fileNum); } -void SaveManager::SaveFile(int fileNum) { +void SaveManager::SaveSection(int fileNum, const std::string& sectionString) { if (fileNum == 0xFF) { return; } // Can't think of any time the promise would be needed, so use push_task instead of submit auto saveContext = new SaveContext; memcpy(saveContext, &gSaveContext, sizeof(gSaveContext)); - smThreadPool->push_task_back(&SaveManager::SaveFileThreaded, this, fileNum, saveContext, "all"); + smThreadPool->push_task_back(&SaveManager::SaveFileThreaded, this, fileNum, saveContext, sectionString); +} + +void SaveManager::SaveFile(int fileNum) { + SaveSection(fileNum, "all"); } void SaveManager::SaveGlobal() { @@ -1616,7 +1626,7 @@ void SaveManager::LoadBaseVersion4() { SaveManager::Instance->LoadData("dogParams", gSaveContext.dogParams); } -void SaveManager::SaveBase(SaveContext* saveContext) { +void SaveManager::SaveBase(SaveContext* saveContext, const std::string& subString) { SaveManager::Instance->SaveData("entranceIndex", saveContext->entranceIndex); SaveManager::Instance->SaveData("linkAge", saveContext->linkAge); SaveManager::Instance->SaveData("cutsceneIndex", saveContext->cutsceneIndex); @@ -2281,6 +2291,10 @@ extern "C" void Save_SaveFile(void) { SaveManager::Instance->SaveFile(gSaveContext.fileNum); } +extern "C" void Save_SaveSection(char* sectionString) { + SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionString); +} + extern "C" void Save_SaveGlobal(void) { SaveManager::Instance->SaveGlobal(); } diff --git a/soh/soh/SaveManager.h b/soh/soh/SaveManager.h index 3401e5781..93a1fe336 100644 --- a/soh/soh/SaveManager.h +++ b/soh/soh/SaveManager.h @@ -45,7 +45,7 @@ public: using InitFunc = void(*)(bool isDebug); using LoadFunc = void(*)(); - using SaveFunc = void(*)(SaveContext* saveContext); + using SaveFunc = void(*)(SaveContext* saveContext, const std::string& subSection); using PostFunc = void(*)(int version); SaveManager(); @@ -53,6 +53,7 @@ public: void Init(); void InitFile(bool isDebug); void SaveFile(int fileNum); + void SaveSection(int fileNum, const std::string& sectionString); void SaveGlobal(); void LoadFile(int fileNum); bool SaveFile_Exist(int fileNum); @@ -128,7 +129,7 @@ public: void ConvertFromUnversioned(); void CreateDefaultGlobal(); - void SaveFileThreaded(int fileNum, SaveContext* saveContext, const std::string sectionString); + void SaveFileThreaded(int fileNum, SaveContext* saveContext, const std::string& sectionString); void InitMeta(int slotNum); static void InitFileImpl(bool isDebug); @@ -137,13 +138,13 @@ public: static void LoadRandomizerVersion1(); static void LoadRandomizerVersion2(); - static void SaveRandomizer(SaveContext* saveContext); + static void SaveRandomizer(SaveContext* saveContext, const std::string& subString); static void LoadBaseVersion1(); static void LoadBaseVersion2(); static void LoadBaseVersion3(); static void LoadBaseVersion4(); - static void SaveBase(SaveContext* saveContext); + static void SaveBase(SaveContext* saveContext, const std::string& subString); std::vector initFuncs; @@ -172,6 +173,7 @@ typedef void (*Save_SaveFunc)(const SaveContext* saveContext); void Save_Init(void); void Save_InitFile(int isDebug); void Save_SaveFile(void); +void Save_SaveSection(char* sectionString); void Save_SaveGlobal(void); void Save_LoadGlobal(void); void Save_AddLoadFunction(char* name, int version, Save_LoadFunc func);