summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett Cox <garrettjcox@gmail.com>2024-05-25 09:54:08 -0500
committerGitHub <noreply@github.com>2024-05-25 09:54:08 -0500
commit5cc1798818242395ac5f3b568e8f6b1cc00af382 (patch)
tree37fc80905ac85e546cc93c67a9f28aab9089d251
parente2dc6a3fc70a79bb36de0cdaf1e57485e2d7f042 (diff)
Rework save files organization (#445)
-rw-r--r--.gitignore1
-rw-r--r--mm/2s2h/SaveManager/BinarySaveConverter.cpp16
-rw-r--r--mm/2s2h/SaveManager/Migrations/4.cpp10
-rw-r--r--mm/2s2h/SaveManager/Migrations/5.cpp19
-rw-r--r--mm/2s2h/SaveManager/SaveManager.cpp350
-rw-r--r--mm/2s2h/SaveManager/SaveManager.h1
6 files changed, 272 insertions, 125 deletions
diff --git a/.gitignore b/.gitignore
index 4049f2f1a..95795f438 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@ shipofharkinian.json
*.sav
.envrc
imgui.ini
+saves/*
mm/libultraship/extern/Debug/ImGui.lib
diff --git a/mm/2s2h/SaveManager/BinarySaveConverter.cpp b/mm/2s2h/SaveManager/BinarySaveConverter.cpp
index df2bc910e..e682f409f 100644
--- a/mm/2s2h/SaveManager/BinarySaveConverter.cpp
+++ b/mm/2s2h/SaveManager/BinarySaveConverter.cpp
@@ -696,11 +696,11 @@ bool BinarySaveConverter_HandleFileDropped(std::string filePath) {
reader->Seek(saveOffsets[0] - 0x24, Ship::SeekOffsetType::Start);
BinarySaveConverter_ReadBufferToSave(&saveContext, reader);
nlohmann::json j;
- std::string fileName = "save_" + std::to_string(saveSlot) + ".sav";
+ std::string fileName = SaveManager_GetFileName(saveSlot);
- j["save"] = saveContext.save;
-
- SaveManager_WriteSaveFile(fileName, j);
+ j["newCycleSave"]["save"] = saveContext.save;
+ j["type"] = "2S2H_SAVE";
+ j["version"] = 4;
// Based on where the save was found, determine if the two possible owl save offsets are in the list of save
// offsets. If they are, we can assume that the save is the owl save associated with the other file above
@@ -716,14 +716,12 @@ bool BinarySaveConverter_HandleFileDropped(std::string filePath) {
if (foundOwlSave) {
memset(&saveContext, 0, sizeof(Legacy_SaveContext));
BinarySaveConverter_ReadBufferToSave(&saveContext, reader);
- fileName = "save_" + std::to_string(saveSlot + 4) + ".sav";
- nlohmann::json j2;
-
- j2 = saveContext;
- SaveManager_WriteSaveFile(fileName, j2);
+ j["owlSave"] = saveContext;
}
+ SaveManager_WriteSaveFile(fileName, j);
+
if (gFileSelectState != NULL) {
func_801457CC(&gFileSelectState->state, &gFileSelectState->sramCtx);
if (gFileSelectState->menuMode == FS_MENU_MODE_CONFIG && gFileSelectState->configMode == CM_MAIN_MENU) {
diff --git a/mm/2s2h/SaveManager/Migrations/4.cpp b/mm/2s2h/SaveManager/Migrations/4.cpp
new file mode 100644
index 000000000..39ba4c34f
--- /dev/null
+++ b/mm/2s2h/SaveManager/Migrations/4.cpp
@@ -0,0 +1,10 @@
+#include "2s2h/SaveManager/SaveManager.h"
+#include "z64.h"
+
+// Final legacy migration, prior to merging owl saves into main save file.
+void SaveManager_Migration_4(nlohmann::json& j) {
+ nlohmann::json rootSave;
+ rootSave["newCycleSave"] = j;
+
+ j = rootSave;
+}
diff --git a/mm/2s2h/SaveManager/Migrations/5.cpp b/mm/2s2h/SaveManager/Migrations/5.cpp
new file mode 100644
index 000000000..6fdeb7a1c
--- /dev/null
+++ b/mm/2s2h/SaveManager/Migrations/5.cpp
@@ -0,0 +1,19 @@
+#include "2s2h/SaveManager/SaveManager.h"
+#include "z64.h"
+
+// This is the base migration, binary saves are imported as this version.
+void SaveManager_Migration_5(nlohmann::json& j) {
+ nlohmann::json dpadEquips;
+ for (int i = 0; i < EQUIP_SLOT_D_MAX; i++) {
+ for (int j = 0; j < EQUIP_SLOT_D_MAX; j++) {
+ dpadEquips["dpadItems"][i][j] = ITEM_NONE;
+ dpadEquips["dpadSlots"][i][j] = SLOT_NONE;
+ }
+ }
+
+ // if shipSaveInfo doesn't exist, create it
+ if (!j["save"].contains("shipSaveInfo")) {
+ j["save"]["shipSaveInfo"]["dpadEquips"] = dpadEquips;
+ j["save"]["shipSaveInfo"]["pauseSaveEntrance"] = -1;
+ }
+}
diff --git a/mm/2s2h/SaveManager/SaveManager.cpp b/mm/2s2h/SaveManager/SaveManager.cpp
index 933330d69..691d740b2 100644
--- a/mm/2s2h/SaveManager/SaveManager.cpp
+++ b/mm/2s2h/SaveManager/SaveManager.cpp
@@ -34,7 +34,7 @@ typedef enum FlashSlotFile {
((GET_NEWF(save, 0) == 'Z') && (GET_NEWF(save, 1) == 'E') && (GET_NEWF(save, 2) == 'L') && \
(GET_NEWF(save, 3) == 'D') && (GET_NEWF(save, 4) == 'A') && (GET_NEWF(save, 5) == '3'))
-const std::filesystem::path savesFolderPath(Ship::Context::GetPathRelativeToAppDirectory("Save"));
+const std::filesystem::path savesFolderPath(Ship::Context::GetPathRelativeToAppDirectory("saves"));
// Migrations
// The idea here is that we can read in any version of the save as generic JSON, then apply migrations
@@ -46,28 +46,60 @@ const std::filesystem::path savesFolderPath(Ship::Context::GetPathRelativeToAppD
// - 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 = 3;
+const uint32_t CURRENT_SAVE_VERSION = 5;
void SaveManager_Migration_1(nlohmann::json& j);
void SaveManager_Migration_2(nlohmann::json& j);
void SaveManager_Migration_3(nlohmann::json& j);
+void SaveManager_Migration_4(nlohmann::json& j);
+void SaveManager_Migration_5(nlohmann::json& j);
const std::unordered_map<uint32_t, std::function<void(nlohmann::json&)>> migrations = {
+ // Pre-1.0.0 Migrations, deprecated
{ 0, SaveManager_Migration_1 },
{ 1, SaveManager_Migration_2 },
{ 2, SaveManager_Migration_3 },
+ { 3, SaveManager_Migration_4 },
+ // Base Migration
+ { 4, SaveManager_Migration_5 },
};
-void SaveManager_MigrateSave(nlohmann::json& j) {
+int SaveManager_MigrateSave(nlohmann::json& j) {
int version = j.value("version", 0);
- // BENTODO: what should we do if the version number is greater?
- while (version < CURRENT_SAVE_VERSION) {
- if (migrations.contains(version)) {
- auto migration = migrations.at(version);
- migration(j);
+ if (version > CURRENT_SAVE_VERSION) {
+ SPDLOG_ERROR("Save version is greater than current version");
+ return -1;
+ }
+
+ if (version >= 4 && !j.contains("newCycleSave") && !j.contains("owlSave")) {
+ SPDLOG_ERROR("Save file is missing newCycleSave and owlSave");
+ return -1;
+ }
+
+ try {
+ while (version < CURRENT_SAVE_VERSION) {
+ if (migrations.contains(version)) {
+ auto migration = migrations.at(version);
+ if (version < 4) {
+ migration(j); // Pre-1.0.0 Migrations, deprecated
+ } else {
+ // In the case of copying files, the owl save is copied first, so the new cycle may not exist yet.
+ if (j.contains("newCycleSave")) {
+ migration(j["newCycleSave"]);
+ }
+ // Only migrate the owl save if it exists
+ if (j.contains("owlSave")) {
+ migration(j["owlSave"]);
+ }
+ }
+ }
+ version = j["version"] = version + 1;
}
- version = j["version"] = version + 1;
+ return 0;
+ } catch (...) {
+ SPDLOG_ERROR("Failed to migrate save file");
+ return -1;
}
}
@@ -78,17 +110,21 @@ void SaveManager_WriteSaveFile(std::filesystem::path fileName, nlohmann::json j)
std::filesystem::create_directory(savesFolderPath);
}
- std::ofstream o(filePath);
- o << std::setw(4) << j << std::endl;
- o.close();
+ try {
+ std::ofstream o(filePath);
+ o << std::setw(4) << j << std::endl;
+ o.close();
+ } catch (...) { SPDLOG_ERROR("Failed to write save file"); }
}
void SaveManager_DeleteSaveFile(std::filesystem::path fileName) {
const std::filesystem::path filePath = savesFolderPath / fileName;
- if (std::filesystem::exists(filePath)) {
- std::filesystem::remove(filePath);
- }
+ try {
+ if (std::filesystem::exists(filePath)) {
+ std::filesystem::remove(filePath);
+ }
+ } catch (...) { SPDLOG_ERROR("Failed to delete save file"); }
}
int SaveManager_ReadSaveFile(std::filesystem::path fileName, nlohmann::json& j) {
@@ -98,19 +134,39 @@ int SaveManager_ReadSaveFile(std::filesystem::path fileName, nlohmann::json& j)
return -1;
}
- std::ifstream i(filePath);
- i >> j;
- i.close();
- return 0;
+ try {
+ std::ifstream i(filePath);
+ i >> j;
+ i.close();
+ return 0;
+ } catch (...) {
+ SPDLOG_ERROR("Failed to read save file");
+ return -2;
+ }
+}
+
+void SaveManager_MoveInvalidSaveFile(std::filesystem::path fileName, std::string message) {
+ const std::filesystem::path filePath = savesFolderPath / fileName;
+ const std::filesystem::path backupFilePath =
+ savesFolderPath / (fileName.stem().string() + "_invalid_" + std::to_string(std::time(nullptr)) + ".json");
+
+ try {
+ if (std::filesystem::exists(filePath)) {
+ std::filesystem::rename(filePath, backupFilePath);
+ }
+
+ auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
+ gui->GetGameOverlay()->TextDrawNotification(30.0f, true, message.c_str());
+ } catch (...) { SPDLOG_ERROR("Failed to move invalid save file"); }
}
int SaveManager_GetOpenFileSlot() {
- std::string fileName = "save_0.sav";
+ std::string fileName = "file1.json";
if (!std::filesystem::exists(savesFolderPath / fileName)) {
- return 0;
+ return 1;
}
- fileName = "save_2.sav";
+ fileName = "file2.json";
if (!std::filesystem::exists(savesFolderPath / fileName)) {
return 2;
}
@@ -118,6 +174,50 @@ int SaveManager_GetOpenFileSlot() {
return -1;
}
+FlashSlotFile SaveManager_GetFlashSlotFileFromPages(u32 pageNum, u32 pageCount) {
+ FlashSlotFile flashSlotFile = FLASH_SLOT_FILE_UNAVAILABLE;
+
+ for (u32 i = 0; i < ARRAY_COUNT(gFlashSaveStartPages) - 1; i++) {
+ // Verify that the requested pages align with expected values
+ if (pageNum == (u32)gFlashSaveStartPages[i] &&
+ (pageCount == (u32)gFlashSaveNumPages[i] || pageCount == (u32)gFlashSpecialSaveNumPages[i])) {
+ flashSlotFile = static_cast<FlashSlotFile>(i);
+ break;
+ }
+ }
+
+ return flashSlotFile;
+}
+
+std::string SaveManager_GetFileName(int fileNum, bool isBackup) {
+ return "file" + std::to_string(fileNum) + (isBackup ? "backup" : "") + ".json";
+}
+
+std::string SaveManager_GetFileNameFromFlashSlotFile(FlashSlotFile flashSlotFile) {
+ if (flashSlotFile == FLASH_SLOT_FILE_UNAVAILABLE)
+ return "invalid";
+
+ if (flashSlotFile == FLASH_SLOT_FILE_SRAM_HEADER || flashSlotFile == FLASH_SLOT_FILE_SRAM_HEADER_BACKUP) {
+ return "global.json";
+ }
+
+ bool isBackup =
+ flashSlotFile == FLASH_SLOT_FILE_1_NEW_CYCLE_BACKUP || flashSlotFile == FLASH_SLOT_FILE_2_NEW_CYCLE_BACKUP ||
+ flashSlotFile == FLASH_SLOT_FILE_1_OWL_SAVE_BACKUP || flashSlotFile == FLASH_SLOT_FILE_2_OWL_SAVE_BACKUP;
+
+ int fileNum =
+ (flashSlotFile == FLASH_SLOT_FILE_1_NEW_CYCLE_BACKUP || flashSlotFile == FLASH_SLOT_FILE_1_NEW_CYCLE ||
+ flashSlotFile == FLASH_SLOT_FILE_1_OWL_SAVE_BACKUP || flashSlotFile == FLASH_SLOT_FILE_1_OWL_SAVE)
+ ? 1
+ : 2;
+
+ bool isOwlSave =
+ (flashSlotFile == FLASH_SLOT_FILE_1_OWL_SAVE || flashSlotFile == FLASH_SLOT_FILE_1_OWL_SAVE_BACKUP ||
+ flashSlotFile == FLASH_SLOT_FILE_2_OWL_SAVE || flashSlotFile == FLASH_SLOT_FILE_2_OWL_SAVE_BACKUP);
+
+ return "file" + std::to_string(fileNum) + (isBackup ? "backup" : "") + ".json";
+}
+
bool SaveManager_HandleFileDropped(std::string filePath) {
try {
std::ifstream fileStream(filePath);
@@ -134,13 +234,9 @@ bool SaveManager_HandleFileDropped(std::string filePath) {
nlohmann::json j;
try {
fileStream >> j;
- } catch (nlohmann::json::parse_error& e) {
- SPDLOG_ERROR("Failed to parse JSON: {}", e.what());
- return false;
- }
+ } catch (nlohmann::json::parse_error& e) { return false; }
if (!j.contains("type") || j["type"] != "2S2H_SAVE") {
- SPDLOG_ERROR("Invalid save file type");
return false;
}
@@ -152,7 +248,7 @@ bool SaveManager_HandleFileDropped(std::string filePath) {
return true;
}
- std::string fileName = "save_" + std::to_string(saveSlot) + ".sav";
+ std::string fileName = SaveManager_GetFileName(saveSlot);
SaveManager_WriteSaveFile(fileName, j);
@@ -178,20 +274,24 @@ bool SaveManager_HandleFileDropped(std::string filePath) {
}
extern "C" void SaveManager_SysFlashrom_WriteData(u8* saveBuffer, u32 pageNum, u32 pageCount) {
- FlashSlotFile flashSlotFile = FLASH_SLOT_FILE_UNAVAILABLE;
+ FlashSlotFile flashSlotFile = SaveManager_GetFlashSlotFileFromPages(pageNum, pageCount);
+ std::string fileName = SaveManager_GetFileNameFromFlashSlotFile(flashSlotFile);
+
bool isBackup = false;
- for (u32 i = 0; i < ARRAY_COUNT(gFlashSaveStartPages) - 1; i++) {
- // Verify that the requested pages align with expected values
- if (pageNum == (u32)gFlashSaveStartPages[i] &&
- (pageCount == (u32)gFlashSaveNumPages[i] || pageCount == (u32)gFlashSpecialSaveNumPages[i])) {
- flashSlotFile = static_cast<FlashSlotFile>(i);
- break;
- }
+
+ if (flashSlotFile == FLASH_SLOT_FILE_UNAVAILABLE) {
+ return;
+ }
+
+ if (flashSlotFile == FLASH_SLOT_FILE_SRAM_HEADER || flashSlotFile == FLASH_SLOT_FILE_SRAM_HEADER_BACKUP) {
+ SaveOptions saveOptions;
+ memcpy(&saveOptions, saveBuffer, sizeof(SaveOptions));
+
+ SaveManager_WriteSaveFile(fileName, saveOptions);
+ return;
}
switch (flashSlotFile) {
- case FLASH_SLOT_FILE_UNAVAILABLE:
- return;
case FLASH_SLOT_FILE_1_NEW_CYCLE_BACKUP:
case FLASH_SLOT_FILE_2_NEW_CYCLE_BACKUP:
isBackup = true;
@@ -201,19 +301,32 @@ extern "C" void SaveManager_SysFlashrom_WriteData(u8* saveBuffer, u32 pageNum, u
Save save;
memcpy(&save, saveBuffer, sizeof(Save));
- std::string fileName = "save_" + std::to_string(flashSlotFile) + ".sav";
- if (isBackup)
- fileName += ".bak";
-
if (IS_VALID_FILE(save)) {
nlohmann::json j;
- j["save"] = save;
+ // Read the existing save file to preserve the owl save
+ int result = SaveManager_ReadSaveFile(fileName, j);
+ if (result == -2) {
+ SaveManager_MoveInvalidSaveFile(
+ fileName,
+ "Something went wrong trying to preserve the owl save. Original save file has been backed up.");
+ } else if (result == 0) {
+ result = SaveManager_MigrateSave(j);
+
+ if (result != 0) {
+ SaveManager_MoveInvalidSaveFile(
+ fileName, "Failed to migrate owl save. Original save file has been backed up.");
+ }
+ }
+
+ j["newCycleSave"]["save"] = save;
j["version"] = CURRENT_SAVE_VERSION;
j["type"] = "2S2H_SAVE";
SaveManager_WriteSaveFile(fileName, j);
} else {
+ // If IS_VALID_FILE fails, we should delete the save file, even if there is an owl save in it, because
+ // they just deleted the new cycle save
SaveManager_DeleteSaveFile(fileName);
}
break;
@@ -227,106 +340,111 @@ extern "C" void SaveManager_SysFlashrom_WriteData(u8* saveBuffer, u32 pageNum, u
SaveContext saveContext;
memcpy(&saveContext, saveBuffer, offsetof(SaveContext, fileNum));
- std::string fileName = "save_" + std::to_string(flashSlotFile) + ".sav";
- if (isBackup)
- fileName += ".bak";
+ nlohmann::json j;
+ // Read the existing save file to preserve the new cycle save
+ int result = SaveManager_ReadSaveFile(fileName, j);
+ if (result == -2) {
+ SaveManager_MoveInvalidSaveFile(fileName, "Something went wrong trying to preserve the new cycle save. "
+ "Original save file has been backed up.");
+ } else if (result == 0) {
+ result = SaveManager_MigrateSave(j);
+
+ if (result != 0) {
+ SaveManager_MoveInvalidSaveFile(
+ fileName, "Failed to migrate new cycle save. Original save file has been backed up.");
+ }
+ }
if (IS_VALID_FILE(saveContext.save)) {
- nlohmann::json j = saveContext;
-
+ j["owlSave"] = saveContext;
j["version"] = CURRENT_SAVE_VERSION;
j["type"] = "2S2H_SAVE";
SaveManager_WriteSaveFile(fileName, j);
} else {
- SaveManager_DeleteSaveFile(fileName);
+ // If IS_VALID_FILE fails, and there is still a new cycle save present, we just want to only remove the
+ // owl save and write the new cycle save back
+ if (j.contains("newCycleSave")) {
+ if (j.contains("owlSave")) {
+ j.erase("owlSave");
+ }
+ j["version"] = CURRENT_SAVE_VERSION;
+ j["type"] = "2S2H_SAVE";
+ SaveManager_WriteSaveFile(fileName, j);
+ // If there is no new cycle save, we should just delete the save file
+ } else {
+ SaveManager_DeleteSaveFile(fileName);
+ }
}
break;
}
- case FLASH_SLOT_FILE_SRAM_HEADER_BACKUP:
- case FLASH_SLOT_FILE_SRAM_HEADER: {
- SaveOptions saveOptions;
- memcpy(&saveOptions, saveBuffer, sizeof(SaveOptions));
-
- std::string fileName = "global.sav";
- SaveManager_WriteSaveFile(fileName, saveOptions);
- break;
- }
}
}
extern "C" s32 SaveManager_SysFlashrom_ReadData(void* saveBuffer, u32 pageNum, u32 pageCount) {
- FlashSlotFile flashSlotFile = FLASH_SLOT_FILE_UNAVAILABLE;
- bool isBackup = false;
- for (u32 i = 0; i < ARRAY_COUNT(gFlashSaveStartPages) - 1; i++) {
- // Verify that the requested pages align with expected values
- if (pageNum == (u32)gFlashSaveStartPages[i] &&
- (pageCount == (u32)gFlashSaveNumPages[i] || pageCount == (u32)gFlashSpecialSaveNumPages[i])) {
- flashSlotFile = static_cast<FlashSlotFile>(i);
- break;
- }
+ FlashSlotFile flashSlotFile = SaveManager_GetFlashSlotFileFromPages(pageNum, pageCount);
+ std::string fileName = SaveManager_GetFileNameFromFlashSlotFile(flashSlotFile);
+
+ if (flashSlotFile == FLASH_SLOT_FILE_UNAVAILABLE) {
+ return -1;
}
- switch (flashSlotFile) {
- case FLASH_SLOT_FILE_UNAVAILABLE:
+ if (flashSlotFile == FLASH_SLOT_FILE_SRAM_HEADER || flashSlotFile == FLASH_SLOT_FILE_SRAM_HEADER_BACKUP) {
+ nlohmann::json j;
+ int result = SaveManager_ReadSaveFile(fileName, j);
+ if (result == -2) {
+ SaveManager_MoveInvalidSaveFile(
+ fileName,
+ "Something went wrong trying to read global save file, the original file has been backed up.");
return -1;
- case FLASH_SLOT_FILE_1_NEW_CYCLE_BACKUP:
- case FLASH_SLOT_FILE_2_NEW_CYCLE_BACKUP:
- isBackup = true;
- // fallthrough
- case FLASH_SLOT_FILE_1_NEW_CYCLE:
- case FLASH_SLOT_FILE_2_NEW_CYCLE: {
- std::string fileName = "save_" + std::to_string(flashSlotFile) + ".sav";
- if (isBackup)
- fileName += ".bak";
-
- nlohmann::json j;
- int result = SaveManager_ReadSaveFile(fileName, j);
- if (result != 0)
- return result;
+ } else if (result != 0) {
+ return result;
+ }
- SaveManager_MigrateSave(j);
+ SaveOptions saveOptions = j;
- Save save = j["save"];
+ memcpy(saveBuffer, &saveOptions, sizeof(SaveOptions));
+ return 0;
+ }
- memcpy(saveBuffer, &save, sizeof(Save));
- return result;
- }
- case FLASH_SLOT_FILE_1_OWL_SAVE_BACKUP:
- case FLASH_SLOT_FILE_2_OWL_SAVE_BACKUP:
- isBackup = true;
- // fallthrough
- case FLASH_SLOT_FILE_1_OWL_SAVE:
- case FLASH_SLOT_FILE_2_OWL_SAVE: {
- std::string fileName = "save_" + std::to_string(flashSlotFile) + ".sav";
- if (isBackup)
- fileName += ".bak";
+ bool isOwlSave =
+ (flashSlotFile == FLASH_SLOT_FILE_1_OWL_SAVE || flashSlotFile == FLASH_SLOT_FILE_1_OWL_SAVE_BACKUP ||
+ flashSlotFile == FLASH_SLOT_FILE_2_OWL_SAVE || flashSlotFile == FLASH_SLOT_FILE_2_OWL_SAVE_BACKUP);
- nlohmann::json j;
- int result = SaveManager_ReadSaveFile(fileName, j);
- if (result != 0)
- return result;
+ nlohmann::json j;
+ int result = SaveManager_ReadSaveFile(fileName, j);
+ if (result == -2) {
+ SaveManager_MoveInvalidSaveFile(
+ fileName, "Something went wrong trying to read save file, the original file has been backed up.");
+ return -1;
+ } else if (result != 0) {
+ return result;
+ }
- SaveManager_MigrateSave(j);
+ result = SaveManager_MigrateSave(j);
- SaveContext saveContext = j;
+ if (result != 0) {
+ SaveManager_MoveInvalidSaveFile(fileName, "Failed to migrate save file, the original file has been backed up.");
+ return -1;
+ }
- memcpy(saveBuffer, &saveContext, offsetof(SaveContext, fileNum));
- return result;
+ if (isOwlSave) {
+ if (!j.contains("owlSave")) {
+ return -1;
}
- case FLASH_SLOT_FILE_SRAM_HEADER:
- case FLASH_SLOT_FILE_SRAM_HEADER_BACKUP: {
- std::string fileName = "global.sav";
- nlohmann::json j;
- int result = SaveManager_ReadSaveFile(fileName, j);
- if (result != 0)
- return result;
-
- SaveOptions saveOptions = j;
+ SaveContext saveContext = j["owlSave"];
- memcpy(saveBuffer, &saveOptions, sizeof(SaveOptions));
- return 0;
+ memcpy(saveBuffer, &saveContext, offsetof(SaveContext, fileNum));
+ return 0;
+ } else {
+ if (!j.contains("newCycleSave")) {
+ return -1;
}
+
+ Save save = j["newCycleSave"]["save"];
+
+ memcpy(saveBuffer, &save, sizeof(Save));
+ return 0;
}
}
diff --git a/mm/2s2h/SaveManager/SaveManager.h b/mm/2s2h/SaveManager/SaveManager.h
index 1ac918050..31dcd6735 100644
--- a/mm/2s2h/SaveManager/SaveManager.h
+++ b/mm/2s2h/SaveManager/SaveManager.h
@@ -5,6 +5,7 @@
#include <libultraship/libultraship.h>
#ifdef __cplusplus
+std::string SaveManager_GetFileName(int fileNum, bool isBackup = false);
bool SaveManager_HandleFileDropped(std::string filePath);
bool BinarySaveConverter_HandleFileDropped(std::string filePath);
int SaveManager_GetOpenFileSlot();