mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-26 03:12:18 -05:00
Modified sectional saving to utilize an integer ID for calling specific sections to cut down on string copying. Utilizes enum values for non-mod sections to allow for cross-project use of those IDs, and sets up AddSaveFunction
to add mod sections after that using max value enum.
This commit is contained in:
parent
4bc0d7d60d
commit
50fbe5d00c
@ -61,6 +61,15 @@ typedef struct {
|
|||||||
u8 isRoom;
|
u8 isRoom;
|
||||||
} SceneTimestamp;
|
} SceneTimestamp;
|
||||||
|
|
||||||
|
typedef enum { // Pre-existing IDs for save sections in base code
|
||||||
|
SECTION_ID_BASE,
|
||||||
|
SECTION_ID_RANDOMIZER,
|
||||||
|
SECTION_ID_STATS,
|
||||||
|
SECTION_ID_ENTRANCES,
|
||||||
|
SECTION_ID_SCENES,
|
||||||
|
SECTION_ID_MAX
|
||||||
|
} SaveFuncIDs;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* */ char buildVersion[50];
|
/* */ char buildVersion[50];
|
||||||
/* */ s16 buildVersionMajor;
|
/* */ s16 buildVersionMajor;
|
||||||
|
@ -231,8 +231,8 @@ void LoadStatsVersion1() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveStats(SaveContext* saveContext, const std::string& subSection) {
|
void SaveStats(SaveContext* saveContext, int sectionID) {
|
||||||
if (subSection == "all") {
|
if (sectionID == SECTION_ID_BASE) {
|
||||||
std::string buildVersion;
|
std::string buildVersion;
|
||||||
SaveManager::Instance->LoadData("buildVersion", buildVersion);
|
SaveManager::Instance->LoadData("buildVersion", buildVersion);
|
||||||
strncpy(gSaveContext.sohStats.buildVersion, buildVersion.c_str(), ARRAY_COUNT(gSaveContext.sohStats.buildVersion) - 1);
|
strncpy(gSaveContext.sohStats.buildVersion, buildVersion.c_str(), ARRAY_COUNT(gSaveContext.sohStats.buildVersion) - 1);
|
||||||
@ -268,12 +268,12 @@ void SaveStats(SaveContext* saveContext, const std::string& subSection) {
|
|||||||
SaveManager::Instance->LoadData("", gSaveContext.sohStats.locationsSkipped[i]);
|
SaveManager::Instance->LoadData("", gSaveContext.sohStats.locationsSkipped[i]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (subSection == "entrances" || subSection == "all") {
|
if (sectionID == SECTION_ID_ENTRANCES || sectionID == SECTION_ID_BASE) {
|
||||||
SaveManager::Instance->SaveArray("entrancesDiscovered", ARRAY_COUNT(saveContext->sohStats.entrancesDiscovered), [&](size_t i) {
|
SaveManager::Instance->SaveArray("entrancesDiscovered", ARRAY_COUNT(saveContext->sohStats.entrancesDiscovered), [&](size_t i) {
|
||||||
SaveManager::Instance->SaveData("", saveContext->sohStats.entrancesDiscovered[i]);
|
SaveManager::Instance->SaveData("", saveContext->sohStats.entrancesDiscovered[i]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (subSection == "scenes" || subSection == "all") {
|
if (sectionID == SECTION_ID_SCENES || sectionID == SECTION_ID_BASE) {
|
||||||
SaveManager::Instance->SaveArray("scenesDiscovered", ARRAY_COUNT(saveContext->sohStats.scenesDiscovered), [&](size_t i) {
|
SaveManager::Instance->SaveArray("scenesDiscovered", ARRAY_COUNT(saveContext->sohStats.scenesDiscovered), [&](size_t i) {
|
||||||
SaveManager::Instance->SaveData("", saveContext->sohStats.scenesDiscovered[i]);
|
SaveManager::Instance->SaveData("", saveContext->sohStats.scenesDiscovered[i]);
|
||||||
});
|
});
|
||||||
@ -821,7 +821,10 @@ extern "C" void InitStatTracker() {
|
|||||||
SetupDisplayNames();
|
SetupDisplayNames();
|
||||||
SetupDisplayColors();
|
SetupDisplayColors();
|
||||||
SaveManager::Instance->AddLoadFunction("sohStats", 1, LoadStatsVersion1);
|
SaveManager::Instance->AddLoadFunction("sohStats", 1, LoadStatsVersion1);
|
||||||
SaveManager::Instance->AddSaveFunction("sohStats", 1, SaveStats);
|
// Add main section save, no parent
|
||||||
|
SaveManager::Instance->AddSaveFunction("sohStats", 1, SaveStats, true, SECTION_PARENT_NONE);
|
||||||
|
// Add subsections, parent of "sohStats". Not sure how to do this without the redundant references to "SaveStats"
|
||||||
|
SaveManager::Instance->AddSaveFunction("entrances", 1, SaveStats, false, SECTION_ID_STATS);
|
||||||
|
SaveManager::Instance->AddSaveFunction("scenes", 1, SaveStats, false, SECTION_ID_STATS);
|
||||||
SaveManager::Instance->AddInitFunction(InitStats);
|
SaveManager::Instance->AddInitFunction(InitStats);
|
||||||
SaveManager::Instance->RegisterGameSaveSection("sohStats");
|
|
||||||
}
|
}
|
@ -769,7 +769,8 @@ void Entrance_SetSceneDiscovered(u8 sceneNum) {
|
|||||||
u32 sceneBit = 1 << (sceneNum - (idx * bitsPerIndex));
|
u32 sceneBit = 1 << (sceneNum - (idx * bitsPerIndex));
|
||||||
gSaveContext.sohStats.scenesDiscovered[idx] |= sceneBit;
|
gSaveContext.sohStats.scenesDiscovered[idx] |= sceneBit;
|
||||||
}
|
}
|
||||||
Save_SaveSection("sohStats.scenes");
|
// Save scenesDiscovered
|
||||||
|
Save_SaveSection(SECTION_ID_SCENES);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 Entrance_GetIsEntranceDiscovered(u16 entranceIndex) {
|
u8 Entrance_GetIsEntranceDiscovered(u16 entranceIndex) {
|
||||||
@ -802,5 +803,6 @@ void Entrance_SetEntranceDiscovered(u16 entranceIndex) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Save_SaveSection("sohStats.entrances");
|
// Save entrancesDiscovered
|
||||||
|
Save_SaveSection(SECTION_ID_ENTRANCES);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
extern "C" SaveContext gSaveContext;
|
extern "C" SaveContext gSaveContext;
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
void SaveManager::WriteSaveFile(const std::filesystem::path& savePath, const uintptr_t addr, void* dramAddr,
|
void SaveManager::WriteSaveFile(const std::filesystem::path& savePath, const uintptr_t addr, void* dramAddr,
|
||||||
const size_t size) {
|
const size_t size) {
|
||||||
@ -46,17 +47,20 @@ std::filesystem::path SaveManager::GetFileName(int fileNum) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SaveManager::SaveManager() {
|
SaveManager::SaveManager() {
|
||||||
|
coreSectionIDsByName["base"] = SECTION_ID_BASE;
|
||||||
|
coreSectionIDsByName["randomizer"] = SECTION_ID_RANDOMIZER;
|
||||||
|
coreSectionIDsByName["sohStats"] = SECTION_ID_STATS;
|
||||||
|
coreSectionIDsByName["entrances"] = SECTION_ID_ENTRANCES;
|
||||||
|
coreSectionIDsByName["scenes"] = SECTION_ID_SCENES;
|
||||||
AddLoadFunction("base", 1, LoadBaseVersion1);
|
AddLoadFunction("base", 1, LoadBaseVersion1);
|
||||||
AddLoadFunction("base", 2, LoadBaseVersion2);
|
AddLoadFunction("base", 2, LoadBaseVersion2);
|
||||||
AddLoadFunction("base", 3, LoadBaseVersion3);
|
AddLoadFunction("base", 3, LoadBaseVersion3);
|
||||||
AddLoadFunction("base", 4, LoadBaseVersion4);
|
AddLoadFunction("base", 4, LoadBaseVersion4);
|
||||||
AddSaveFunction("base", 4, SaveBase);
|
AddSaveFunction("base", 4, SaveBase, true, SECTION_PARENT_NONE);
|
||||||
RegisterGameSaveSection("base");
|
|
||||||
|
|
||||||
AddLoadFunction("randomizer", 1, LoadRandomizerVersion1);
|
AddLoadFunction("randomizer", 1, LoadRandomizerVersion1);
|
||||||
AddLoadFunction("randomizer", 2, LoadRandomizerVersion2);
|
AddLoadFunction("randomizer", 2, LoadRandomizerVersion2);
|
||||||
AddSaveFunction("randomizer", 2, SaveRandomizer);
|
AddSaveFunction("randomizer", 2, SaveRandomizer, true, SECTION_PARENT_NONE);
|
||||||
RegisterGameSaveSection("randomizer");
|
|
||||||
|
|
||||||
AddInitFunction(InitFileImpl);
|
AddInitFunction(InitFileImpl);
|
||||||
|
|
||||||
@ -86,20 +90,6 @@ SaveManager::SaveManager() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GameSaveSection functions affect the list of sections that save their data when a game save is triggered
|
|
||||||
void SaveManager::RegisterGameSaveSection(std::string section) {
|
|
||||||
if (std::find(gameSaveRegistry.begin(), gameSaveRegistry.end(), section) == gameSaveRegistry.end()) {
|
|
||||||
gameSaveRegistry.push_back(section);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SaveManager::UnregisterAutosaveSection(std::string section) {
|
|
||||||
auto find = std::find(gameSaveRegistry.begin(), gameSaveRegistry.end(), section);
|
|
||||||
if (find != gameSaveRegistry.end()) {
|
|
||||||
gameSaveRegistry.erase(find);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SaveManager::LoadRandomizerVersion1() {
|
void SaveManager::LoadRandomizerVersion1() {
|
||||||
for (int i = 0; i < ARRAY_COUNT(gSaveContext.itemLocations); i++) {
|
for (int i = 0; i < ARRAY_COUNT(gSaveContext.itemLocations); i++) {
|
||||||
SaveManager::Instance->LoadStruct("get" + std::to_string(i), [&]() {
|
SaveManager::Instance->LoadStruct("get" + std::to_string(i), [&]() {
|
||||||
@ -278,7 +268,7 @@ void SaveManager::LoadRandomizerVersion2() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveManager::SaveRandomizer(SaveContext* saveContext, const std::string& subString) {
|
void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID) {
|
||||||
|
|
||||||
if(!saveContext->n64ddFlag) return;
|
if(!saveContext->n64ddFlag) return;
|
||||||
|
|
||||||
@ -700,40 +690,42 @@ void SaveManager::InitFileDebug() {
|
|||||||
gSaveContext.sceneFlags[5].swch = 0x40000000;
|
gSaveContext.sceneFlags[5].swch = 0x40000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Threaded SaveFile takes copy of gSaveContext for local unmodified storage
|
void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext, int sectionID) {
|
||||||
void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext, const std::string& sectionString) {
|
// Needed for first time save, hasn't changed in forever anyway
|
||||||
saveBlock["version"] = 1;
|
saveBlock["version"] = 1;
|
||||||
size_t period = sectionString.find(".");
|
if (sectionID == SECTION_ID_BASE) {
|
||||||
std::string section = sectionString;
|
for (auto& sectionHandlerPair : sectionSaveHandlers) {
|
||||||
std::string subsection = "";
|
auto& saveFuncInfo = sectionHandlerPair.second;
|
||||||
if (period != std::string::npos) {
|
// Don't call SaveFuncs for sections that aren't tied to game save
|
||||||
subsection = sectionString.substr(period + 1, std::string::npos);
|
if (!saveFuncInfo.saveWithBase) {
|
||||||
section = sectionString.substr(0, sectionString.length() - (subsection.length() + 1));
|
continue;
|
||||||
}
|
|
||||||
if (sectionString == "all") {
|
|
||||||
for (auto& sectionHandler : sectionSaveHandlers) {
|
|
||||||
if (std::find(gameSaveRegistry.begin(), gameSaveRegistry.end(), sectionHandler.first) != gameSaveRegistry.end()) {
|
|
||||||
nlohmann::json& sectionBlock = saveBlock["sections"][sectionHandler.first];
|
|
||||||
sectionBlock["version"] = sectionHandler.second.first;
|
|
||||||
// If any save file is loaded for medatata, or a spoiler log is loaded (not sure which at this point), there is still data in the "randomizer" section
|
|
||||||
// This clears the randomizer data block if and only if the section being called is "randomizer" and n64ddFlag is false.
|
|
||||||
if (sectionHandler.first == "randomizer" && !gSaveContext.n64ddFlag) {
|
|
||||||
sectionBlock["data"] = nlohmann::json::object();
|
|
||||||
}
|
|
||||||
|
|
||||||
currentJsonContext = §ionBlock["data"];
|
|
||||||
sectionHandler.second.second(saveContext, "all");
|
|
||||||
}
|
}
|
||||||
|
nlohmann::json& sectionBlock = saveBlock["sections"][saveFuncInfo.name];
|
||||||
|
sectionBlock["version"] = sectionHandlerPair.second.version;
|
||||||
|
// If any save file is loaded for medatata, or a spoiler log is loaded (not sure which at this point), there is still data in the "randomizer" section
|
||||||
|
// This clears the randomizer data block if and only if the section being called is "randomizer" and n64ddFlag is false.
|
||||||
|
if (sectionHandlerPair.second.name == "randomizer" && !gSaveContext.n64ddFlag) {
|
||||||
|
sectionBlock["data"] = nlohmann::json::object();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentJsonContext = §ionBlock["data"];
|
||||||
|
sectionHandlerPair.second.func(saveContext, sectionID);
|
||||||
}
|
}
|
||||||
} 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, subsection);
|
|
||||||
} else {
|
} else {
|
||||||
// save function for specified section does not exist. should this error?
|
SaveFuncInfo svi = sectionSaveHandlers.find(sectionID)->second;
|
||||||
return;
|
auto& sectionName = svi.name;
|
||||||
|
auto sectionVersion = svi.version;
|
||||||
|
// If section has a parentSection, it is a subsection. Load parentSection version and set sectionBlock to parent string
|
||||||
|
if (svi.parentSection != -1 && svi.parentSection < sectionIndex) {
|
||||||
|
auto parentSvi = sectionSaveHandlers.find(svi.parentSection)->second;
|
||||||
|
sectionName = parentSvi.name;
|
||||||
|
sectionVersion = parentSvi.version;
|
||||||
|
}
|
||||||
|
nlohmann::json& sectionBlock = saveBlock["sections"][sectionName];
|
||||||
|
sectionBlock["version"] = sectionVersion;
|
||||||
|
currentJsonContext = §ionBlock["data"];
|
||||||
|
svi.func(saveContext, sectionID);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__SWITCH__) || defined(__WIIU__)
|
#if defined(__SWITCH__) || defined(__WIIU__)
|
||||||
@ -751,18 +743,24 @@ void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext, const
|
|||||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSaveFile>(fileNum);
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSaveFile>(fileNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveManager::SaveSection(int fileNum, const std::string& sectionString) {
|
// SaveSection creates a copy of gSaveContext to prevent mid-save data modification, and passes its reference to SaveFileThreaded
|
||||||
|
void SaveManager::SaveSection(int fileNum, int sectionID) {
|
||||||
if (fileNum == 0xFF) {
|
if (fileNum == 0xFF) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Can't think of any time the promise would be needed, so use push_task instead of submit
|
// Don't save a nonexistent section
|
||||||
|
if (sectionID >= sectionIndex) {
|
||||||
|
SPDLOG_ERROR("SaveSection: Section ID not registered.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto saveContext = new SaveContext;
|
auto saveContext = new SaveContext;
|
||||||
memcpy(saveContext, &gSaveContext, sizeof(gSaveContext));
|
memcpy(saveContext, &gSaveContext, sizeof(gSaveContext));
|
||||||
smThreadPool->push_task_back(&SaveManager::SaveFileThreaded, this, fileNum, saveContext, sectionString);
|
// Can't think of any time the promise would be needed, so use push_task instead of submit
|
||||||
|
smThreadPool->push_task_back(&SaveManager::SaveFileThreaded, this, fileNum, saveContext, sectionID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveManager::SaveFile(int fileNum) {
|
void SaveManager::SaveFile(int fileNum) {
|
||||||
SaveSection(fileNum, "all");
|
SaveSection(fileNum, SECTION_ID_BASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveManager::SaveGlobal() {
|
void SaveManager::SaveGlobal() {
|
||||||
@ -860,14 +858,21 @@ void SaveManager::AddLoadFunction(const std::string& name, int version, LoadFunc
|
|||||||
sectionLoadHandlers[name][version] = func;
|
sectionLoadHandlers[name][version] = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveManager::AddSaveFunction(const std::string& name, int version, SaveFunc func) {
|
void SaveManager::AddSaveFunction(const std::string& name, int version, SaveFunc func, bool saveWithBase, int parentSection = -1) {
|
||||||
if (sectionSaveHandlers.contains(name)) {
|
if (sectionRegistry.contains(name)) {
|
||||||
SPDLOG_ERROR("Adding save function for section that already has one: " + name);
|
SPDLOG_ERROR("Adding save function for section that already has one: " + name);
|
||||||
assert(false);
|
assert(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
int index = sectionIndex;
|
||||||
sectionSaveHandlers[name] = std::make_pair(version, func);
|
if (coreSectionIDsByName.contains(name)) {
|
||||||
|
index = coreSectionIDsByName.find(name)->second;
|
||||||
|
} else {
|
||||||
|
sectionIndex++;
|
||||||
|
}
|
||||||
|
SaveFuncInfo sfi = { name, version, func, saveWithBase, parentSection };
|
||||||
|
sectionSaveHandlers.emplace(index, sfi);
|
||||||
|
sectionRegistry.emplace(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveManager::AddPostFunction(const std::string& name, PostFunc func) {
|
void SaveManager::AddPostFunction(const std::string& name, PostFunc func) {
|
||||||
@ -1623,7 +1628,7 @@ void SaveManager::LoadBaseVersion4() {
|
|||||||
SaveManager::Instance->LoadData("dogParams", gSaveContext.dogParams);
|
SaveManager::Instance->LoadData("dogParams", gSaveContext.dogParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveManager::SaveBase(SaveContext* saveContext, const std::string& subString) {
|
void SaveManager::SaveBase(SaveContext* saveContext, int sectionID) {
|
||||||
SaveManager::Instance->SaveData("entranceIndex", saveContext->entranceIndex);
|
SaveManager::Instance->SaveData("entranceIndex", saveContext->entranceIndex);
|
||||||
SaveManager::Instance->SaveData("linkAge", saveContext->linkAge);
|
SaveManager::Instance->SaveData("linkAge", saveContext->linkAge);
|
||||||
SaveManager::Instance->SaveData("cutsceneIndex", saveContext->cutsceneIndex);
|
SaveManager::Instance->SaveData("cutsceneIndex", saveContext->cutsceneIndex);
|
||||||
@ -2290,8 +2295,8 @@ extern "C" void Save_SaveFile(void) {
|
|||||||
SaveManager::Instance->SaveFile(gSaveContext.fileNum);
|
SaveManager::Instance->SaveFile(gSaveContext.fileNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void Save_SaveSection(char* sectionString) {
|
extern "C" void Save_SaveSection(int sectionID) {
|
||||||
SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionString);
|
SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionID);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void Save_SaveGlobal(void) {
|
extern "C" void Save_SaveGlobal(void) {
|
||||||
@ -2307,8 +2312,8 @@ extern "C" void Save_AddLoadFunction(char* name, int version, SaveManager::LoadF
|
|||||||
SaveManager::Instance->AddLoadFunction(name, version, func);
|
SaveManager::Instance->AddLoadFunction(name, version, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void Save_AddSaveFunction(char* name, int version, SaveManager::SaveFunc func) {
|
extern "C" void Save_AddSaveFunction(char* name, int version, SaveManager::SaveFunc func, bool saveWithBase, int parentSection = SECTION_PARENT_NONE) {
|
||||||
SaveManager::Instance->AddSaveFunction(name, version, func);
|
SaveManager::Instance->AddSaveFunction(name, version, func, saveWithBase, parentSection);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" SaveFileMetaInfo* Save_GetSaveMetaInfo(int fileNum) {
|
extern "C" SaveFileMetaInfo* Save_GetSaveMetaInfo(int fileNum) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <libultraship/libultra/gbi.h>
|
#include <libultraship/libultra/gbi.h>
|
||||||
|
|
||||||
|
#define SECTION_PARENT_NONE -1
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 valid;
|
u8 valid;
|
||||||
u16 deaths;
|
u16 deaths;
|
||||||
@ -27,6 +28,7 @@ typedef struct {
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include "thread-pool/BS_thread_pool.hpp"
|
#include "thread-pool/BS_thread_pool.hpp"
|
||||||
|
|
||||||
@ -38,6 +40,7 @@ extern "C" {
|
|||||||
|
|
||||||
class SaveManager {
|
class SaveManager {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static SaveManager* Instance;
|
static SaveManager* Instance;
|
||||||
|
|
||||||
static void WriteSaveFile(const std::filesystem::path& savePath, uintptr_t addr, void* dramAddr, size_t size);
|
static void WriteSaveFile(const std::filesystem::path& savePath, uintptr_t addr, void* dramAddr, size_t size);
|
||||||
@ -45,15 +48,23 @@ public:
|
|||||||
|
|
||||||
using InitFunc = void(*)(bool isDebug);
|
using InitFunc = void(*)(bool isDebug);
|
||||||
using LoadFunc = void(*)();
|
using LoadFunc = void(*)();
|
||||||
using SaveFunc = void(*)(SaveContext* saveContext, const std::string& subSection);
|
using SaveFunc = void(*)(SaveContext* saveContext, int sectionID);
|
||||||
using PostFunc = void(*)(int version);
|
using PostFunc = void (*)(int version);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
std::string name;
|
||||||
|
int version;
|
||||||
|
SaveManager::SaveFunc func;
|
||||||
|
bool saveWithBase;
|
||||||
|
int parentSection;
|
||||||
|
} SaveFuncInfo;
|
||||||
|
|
||||||
SaveManager();
|
SaveManager();
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void InitFile(bool isDebug);
|
void InitFile(bool isDebug);
|
||||||
void SaveFile(int fileNum);
|
void SaveFile(int fileNum);
|
||||||
void SaveSection(int fileNum, const std::string& sectionString);
|
void SaveSection(int fileNum, int sectionID);
|
||||||
void SaveGlobal();
|
void SaveGlobal();
|
||||||
void LoadFile(int fileNum);
|
void LoadFile(int fileNum);
|
||||||
bool SaveFile_Exist(int fileNum);
|
bool SaveFile_Exist(int fileNum);
|
||||||
@ -66,7 +77,7 @@ public:
|
|||||||
void AddLoadFunction(const std::string& name, int version, LoadFunc func);
|
void AddLoadFunction(const std::string& name, int version, LoadFunc func);
|
||||||
|
|
||||||
// Adds a function that is called when saving. This should only be called once for each function, the version is filled in automatically.
|
// Adds a function that is called when saving. This should only be called once for each function, the version is filled in automatically.
|
||||||
void AddSaveFunction(const std::string& name, int version, SaveFunc func);
|
void AddSaveFunction(const std::string& name, int version, SaveFunc func, bool saveWithBase, int parentSection);
|
||||||
|
|
||||||
// Adds a function to be called after loading is complete. This is to handle any cleanup required from loading old versions.
|
// Adds a function to be called after loading is complete. This is to handle any cleanup required from loading old versions.
|
||||||
void AddPostFunction(const std::string& name, PostFunc func);
|
void AddPostFunction(const std::string& name, PostFunc func);
|
||||||
@ -119,9 +130,6 @@ public:
|
|||||||
static const int MaxFiles = 3;
|
static const int MaxFiles = 3;
|
||||||
std::array<SaveFileMetaInfo, MaxFiles> fileMetaInfo;
|
std::array<SaveFileMetaInfo, MaxFiles> fileMetaInfo;
|
||||||
|
|
||||||
void RegisterGameSaveSection(std::string section);
|
|
||||||
void UnregisterAutosaveSection(std::string section);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::filesystem::path GetFileName(int fileNum);
|
std::filesystem::path GetFileName(int fileNum);
|
||||||
nlohmann::json saveBlock;
|
nlohmann::json saveBlock;
|
||||||
@ -129,7 +137,7 @@ public:
|
|||||||
void ConvertFromUnversioned();
|
void ConvertFromUnversioned();
|
||||||
void CreateDefaultGlobal();
|
void CreateDefaultGlobal();
|
||||||
|
|
||||||
void SaveFileThreaded(int fileNum, SaveContext* saveContext, const std::string& sectionString);
|
void SaveFileThreaded(int fileNum, SaveContext* saveContext, int sectionID);
|
||||||
|
|
||||||
void InitMeta(int slotNum);
|
void InitMeta(int slotNum);
|
||||||
static void InitFileImpl(bool isDebug);
|
static void InitFileImpl(bool isDebug);
|
||||||
@ -138,23 +146,23 @@ public:
|
|||||||
|
|
||||||
static void LoadRandomizerVersion1();
|
static void LoadRandomizerVersion1();
|
||||||
static void LoadRandomizerVersion2();
|
static void LoadRandomizerVersion2();
|
||||||
static void SaveRandomizer(SaveContext* saveContext, const std::string& subString);
|
static void SaveRandomizer(SaveContext* saveContext, int sectionID);
|
||||||
|
|
||||||
static void LoadBaseVersion1();
|
static void LoadBaseVersion1();
|
||||||
static void LoadBaseVersion2();
|
static void LoadBaseVersion2();
|
||||||
static void LoadBaseVersion3();
|
static void LoadBaseVersion3();
|
||||||
static void LoadBaseVersion4();
|
static void LoadBaseVersion4();
|
||||||
static void SaveBase(SaveContext* saveContext, const std::string& subString);
|
static void SaveBase(SaveContext* saveContext, int sectionID);
|
||||||
|
|
||||||
std::vector<InitFunc> initFuncs;
|
std::vector<InitFunc> initFuncs;
|
||||||
|
|
||||||
using SectionLoadHandler = std::map<int, LoadFunc>;
|
using SectionLoadHandler = std::map<int, LoadFunc>;
|
||||||
std::map<std::string, SectionLoadHandler> sectionLoadHandlers;
|
std::map<std::string, SectionLoadHandler> sectionLoadHandlers;
|
||||||
|
|
||||||
using SectionSaveHandler = std::pair<int, SaveFunc>;
|
int sectionIndex = SECTION_ID_MAX;
|
||||||
std::map<std::string, SectionSaveHandler> sectionSaveHandlers;
|
std::map<std::string, int> coreSectionIDsByName;
|
||||||
// tracks sections to save during game saves
|
std::map<int, SaveFuncInfo> sectionSaveHandlers;
|
||||||
std::vector<std::string> gameSaveRegistry;
|
std::set<std::string> sectionRegistry;
|
||||||
|
|
||||||
std::map<std::string, PostFunc> postHandlers;
|
std::map<std::string, PostFunc> postHandlers;
|
||||||
|
|
||||||
@ -168,16 +176,16 @@ public:
|
|||||||
// TODO feature parity to the C++ interface. We need Save_AddInitFunction and Save_AddPostFunction at least
|
// TODO feature parity to the C++ interface. We need Save_AddInitFunction and Save_AddPostFunction at least
|
||||||
|
|
||||||
typedef void (*Save_LoadFunc)(void);
|
typedef void (*Save_LoadFunc)(void);
|
||||||
typedef void (*Save_SaveFunc)(const SaveContext* saveContext);
|
typedef void (*Save_SaveFunc)(const SaveContext* saveContext, int sectionID);
|
||||||
|
|
||||||
void Save_Init(void);
|
void Save_Init(void);
|
||||||
void Save_InitFile(int isDebug);
|
void Save_InitFile(int isDebug);
|
||||||
void Save_SaveFile(void);
|
void Save_SaveFile(void);
|
||||||
void Save_SaveSection(char* sectionString);
|
void Save_SaveSection(int sectionID);
|
||||||
void Save_SaveGlobal(void);
|
void Save_SaveGlobal(void);
|
||||||
void Save_LoadGlobal(void);
|
void Save_LoadGlobal(void);
|
||||||
void Save_AddLoadFunction(char* name, int version, Save_LoadFunc func);
|
void Save_AddLoadFunction(char* name, int version, Save_LoadFunc func);
|
||||||
void Save_AddSaveFunction(char* name, int version, Save_SaveFunc func);
|
void Save_AddSaveFunction(char* name, int version, Save_SaveFunc func, bool saveWithBase, int parentSection);
|
||||||
SaveFileMetaInfo* Save_GetSaveMetaInfo(int fileNum);
|
SaveFileMetaInfo* Save_GetSaveMetaInfo(int fileNum);
|
||||||
void Save_CopyFile(int from, int to);
|
void Save_CopyFile(int from, int to);
|
||||||
void Save_DeleteFile(int fileNum);
|
void Save_DeleteFile(int fileNum);
|
||||||
|
Loading…
Reference in New Issue
Block a user