Implement save file redirection fallback.

This commit is contained in:
Skyth 2024-12-30 23:31:27 +03:00
parent cb7b8a0d2d
commit 34f8315c01
5 changed files with 41 additions and 13 deletions

View file

@ -308,7 +308,7 @@ SWA_API uint32_t XamContentCreateEx(uint32_t dwUserIndex, const char* szRootName
if (pContentData->dwContentType == XCONTENTTYPE_SAVEDATA) if (pContentData->dwContentType == XCONTENTTYPE_SAVEDATA)
{ {
std::u8string savePathU8 = GetSavePath().u8string(); std::u8string savePathU8 = GetSavePath(true).u8string();
root = (const char *)(savePathU8.c_str()); root = (const char *)(savePathU8.c_str());
} }
else if (pContentData->dwContentType == XCONTENTTYPE_DLC) else if (pContentData->dwContentType == XCONTENTTYPE_DLC)

View file

@ -54,13 +54,26 @@ void KiSystemStartup()
XamRegisterContent(gameContent, GAME_INSTALL_DIRECTORY "/game"); XamRegisterContent(gameContent, GAME_INSTALL_DIRECTORY "/game");
XamRegisterContent(updateContent, GAME_INSTALL_DIRECTORY "/update"); XamRegisterContent(updateContent, GAME_INSTALL_DIRECTORY "/update");
const auto savePath = GetSavePath(); const auto saveFilePath = GetSaveFilePath(true);
const auto saveName = "SYS-DATA"; bool saveFileExists = std::filesystem::exists(saveFilePath);
if (std::filesystem::exists(savePath / saveName)) if (!saveFileExists)
{ {
std::u8string savePathU8 = savePath.u8string(); // Copy base save data to modded save as fallback.
XamRegisterContent(XamMakeContent(XCONTENTTYPE_SAVEDATA, saveName), (const char *)(savePathU8.c_str())); std::error_code ec;
std::filesystem::create_directories(saveFilePath.parent_path(), ec);
if (!ec)
{
std::filesystem::copy_file(GetSaveFilePath(false), saveFilePath, ec);
saveFileExists = !ec;
}
}
if (saveFileExists)
{
std::u8string savePathU8 = saveFilePath.parent_path().u8string();
XamRegisterContent(XamMakeContent(XCONTENTTYPE_SAVEDATA, "SYS-DATA"), (const char*)(savePathU8.c_str()));
} }
// Mount game // Mount game

View file

@ -104,10 +104,15 @@ bool AchievementData::VerifyChecksum()
void AchievementData::Load() void AchievementData::Load()
{ {
auto dataPath = GetDataPath(); auto dataPath = GetDataPath(true);
if (!std::filesystem::exists(dataPath))
{
// Try loading base achievement data as fallback.
dataPath = GetDataPath(false);
if (!std::filesystem::exists(dataPath)) if (!std::filesystem::exists(dataPath))
return; return;
}
std::ifstream file(dataPath, std::ios::binary); std::ifstream file(dataPath, std::ios::binary);
@ -160,7 +165,7 @@ void AchievementData::Load()
void AchievementData::Save() void AchievementData::Save()
{ {
std::ofstream file(GetDataPath(), std::ios::binary); std::ofstream file(GetDataPath(true), std::ios::binary);
if (!file) if (!file)
{ {

View file

@ -45,9 +45,9 @@ public:
static inline Data Data{ ACH_SIGNATURE, ACH_VERSION }; static inline Data Data{ ACH_SIGNATURE, ACH_VERSION };
static std::filesystem::path GetDataPath() static std::filesystem::path GetDataPath(bool checkForMods)
{ {
return GetSavePath() / "ACH-DATA"; return GetSavePath(checkForMods) / "ACH-DATA";
} }
static time_t GetTimestamp(uint16_t id); static time_t GetTimestamp(uint16_t id);

View file

@ -50,10 +50,20 @@ inline std::filesystem::path GetUserPath()
return userPath; return userPath;
} }
inline std::filesystem::path GetSavePath() inline std::filesystem::path GetSavePath(bool checkForMods)
{ {
if (!ModLoader::s_saveFilePath.empty()) if (checkForMods && !ModLoader::s_saveFilePath.empty())
return ModLoader::s_saveFilePath.parent_path(); return ModLoader::s_saveFilePath.parent_path();
else else
return GetUserPath() / "save"; return GetUserPath() / "save";
} }
// Returned file name may not necessarily be
// equal to SYS-DATA as mods can assign anything.
inline std::filesystem::path GetSaveFilePath(bool checkForMods)
{
if (checkForMods && !ModLoader::s_saveFilePath.empty())
return ModLoader::s_saveFilePath;
else
return GetSavePath(false) / "SYS-DATA";
}