summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMalkierian <malkierian@gmail.com>2023-11-14 18:46:50 -0700
committerGitHub <noreply@github.com>2023-11-14 20:46:50 -0500
commitafe032ea215215273a38b810d5c7be0705aaa460 (patch)
tree99582d31474930bdb50496aa559f250a6c19f518
parentfb45b66903b2c7449a4673a331c2117a94ce02cb (diff)
[Feature/fix] Save to temp file first (#3376)
* Add temp file flow to `SaveManager::SaveFileThreaded`. Add "Save finish" info log message. * Fix WiiU/Switch
-rw-r--r--soh/soh/SaveManager.cpp84
-rw-r--r--soh/soh/SaveManager.h1
2 files changed, 57 insertions, 28 deletions
diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp
index 2d1f6e68b..e61cf9223 100644
--- a/soh/soh/SaveManager.cpp
+++ b/soh/soh/SaveManager.cpp
@@ -47,6 +47,11 @@ std::filesystem::path SaveManager::GetFileName(int fileNum) {
return sSavePath / ("file" + std::to_string(fileNum + 1) + ".sav");
}
+std::filesystem::path SaveManager::GetFileTempName(int fileNum) {
+ const std::filesystem::path sSavePath(LUS::Context::GetPathRelativeToAppDirectory("Save"));
+ return sSavePath / ("file" + std::to_string(fileNum + 1) + ".temp");
+}
+
SaveManager::SaveManager() {
coreSectionIDsByName["base"] = SECTION_ID_BASE;
coreSectionIDsByName["randomizer"] = SECTION_ID_RANDOMIZER;
@@ -874,6 +879,32 @@ void SaveManager::InitFileMaxed() {
gSaveContext.sceneFlags[5].swch = 0x40000000;
}
+#if defined(__WIIU__) || defined(__SWITCH__)
+// std::filesystem::copy_file doesn't work properly with the Wii U's toolchain atm
+int copy_file(const char* src, const char* dst) {
+ alignas(0x40) uint8_t buf[4096];
+ FILE* r = fopen(src, "r");
+ if (!r) {
+ return -1;
+ }
+ FILE* w = fopen(dst, "w");
+ if (!w) {
+ return -2;
+ }
+
+ size_t res;
+ while ((res = fread(buf, 1, sizeof(buf), r)) > 0) {
+ if (fwrite(buf, 1, res, w) != res) {
+ break;
+ }
+ }
+
+ fclose(r);
+ fclose(w);
+ return res >= 0 ? 0 : res;
+}
+#endif
+
// Threaded SaveFile takes copy of gSaveContext for local unmodified storage
void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext, int sectionID) {
@@ -915,19 +946,42 @@ void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext, int se
svi.func(saveContext, sectionID, false);
}
+ std::filesystem::path fileName = GetFileName(fileNum);
+ std::filesystem::path tempFile = GetFileTempName(fileNum);
+
+ if (std::filesystem::exists(tempFile)) {
+ std::filesystem::remove(tempFile);
+ }
+
#if defined(__SWITCH__) || defined(__WIIU__)
- FILE* w = fopen(GetFileName(fileNum).c_str(), "w");
+ FILE* w = fopen(tempFile.c_str(), "w");
std::string json_string = saveBlock.dump(4);
fwrite(json_string.c_str(), sizeof(char), json_string.length(), w);
fclose(w);
#else
- std::ofstream output(GetFileName(fileNum));
+ std::ofstream output(tempFile);
output << std::setw(4) << saveBlock << std::endl;
+ output.close();
#endif
+ if (std::filesystem::exists(fileName)) {
+ std::filesystem::remove(fileName);
+ }
+
+#if defined(__SWITCH__) || defined(__WIIU__)
+ copy_file(tempFile.c_str(), fileName.c_str());
+#else
+ std::filesystem::copy_file(tempFile, fileName);
+#endif
+
+ if (std::filesystem::exists(tempFile)) {
+ std::filesystem::remove(tempFile);
+ }
+
delete saveContext;
InitMeta(fileNum);
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSaveFile>(fileNum);
+ SPDLOG_INFO("Save File Finish - fileNum: {}", fileNum);
}
// SaveSection creates a copy of gSaveContext to prevent mid-save data modification, and passes its reference to SaveFileThreaded
@@ -2110,32 +2164,6 @@ void SaveManager::LoadStruct(const std::string& name, LoadStructFunc func) {
}
}
-#if defined(__WIIU__) || defined(__SWITCH__)
-// std::filesystem::copy_file doesn't work properly with the Wii U's toolchain atm
-int copy_file(const char* src, const char* dst) {
- alignas(0x40) uint8_t buf[4096];
- FILE* r = fopen(src, "r");
- if (!r) {
- return -1;
- }
- FILE* w = fopen(dst, "w");
- if (!w) {
- return -2;
- }
-
- size_t res;
- while ((res = fread(buf, 1, sizeof(buf), r)) > 0) {
- if (fwrite(buf, 1, res, w) != res) {
- break;
- }
- }
-
- fclose(r);
- fclose(w);
- return res >= 0 ? 0 : res;
-}
-#endif
-
void SaveManager::CopyZeldaFile(int from, int to) {
assert(std::filesystem::exists(GetFileName(from)));
DeleteZeldaFile(to);
diff --git a/soh/soh/SaveManager.h b/soh/soh/SaveManager.h
index 892aec923..310ecda7d 100644
--- a/soh/soh/SaveManager.h
+++ b/soh/soh/SaveManager.h
@@ -142,6 +142,7 @@ class SaveManager {
private:
std::filesystem::path GetFileName(int fileNum);
+ std::filesystem::path GetFileTempName(int fileNum);
nlohmann::json saveBlock;
void ConvertFromUnversioned();