From 37cb18358b2002526f6674f8986635e21a6733a9 Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 9 Dec 2017 00:16:51 -0500 Subject: [PATCH] HLE/FS: Always use 0x48000 as the high dword when opening the SharedExtData archive The FS module overrides whatever value was in the saveid high dword with 0x48000 when trying to open the archive. This fixes the problem where the Home Menu would create a few SharedExtData archives with 0x48000 as the saveid high, but then try to open them with 0 as the high value and fail. --- src/core/file_sys/archive_extsavedata.cpp | 37 ++++++++++++++++++++--- src/core/file_sys/archive_extsavedata.h | 3 ++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp index e401be507..9cab0d0f7 100644 --- a/src/core/file_sys/archive_extsavedata.cpp +++ b/src/core/file_sys/archive_extsavedata.cpp @@ -131,6 +131,14 @@ public: } }; +struct ExtSaveDataArchivePath { + u32_le media_type; + u32_le save_low; + u32_le save_high; +}; + +static_assert(sizeof(ExtSaveDataArchivePath) == 12, "Incorrect path size"); + std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path) { std::vector vec_data = path.AsBinary(); const u32* data = reinterpret_cast(vec_data.data()); @@ -183,8 +191,27 @@ bool ArchiveFactory_ExtSaveData::Initialize() { return true; } +Path ArchiveFactory_ExtSaveData::GetCorrectedPath(const Path& path) { + if (!shared) + return path; + + static constexpr u32 SharedExtDataHigh = 0x48000; + + ExtSaveDataArchivePath new_path; + std::memcpy(&new_path, path.AsBinary().data(), sizeof(new_path)); + + // The FS module overwrites the high value of the saveid when dealing with the SharedExtSaveData + // archive. + new_path.save_high = SharedExtDataHigh; + + std::vector binary_data(sizeof(new_path)); + std::memcpy(binary_data.data(), &new_path, binary_data.size()); + + return {binary_data}; +} + ResultVal> ArchiveFactory_ExtSaveData::Open(const Path& path) { - std::string fullpath = GetExtSaveDataPath(mount_point, path) + "user/"; + std::string fullpath = GetExtSaveDataPath(mount_point, GetCorrectedPath(path)) + "user/"; if (!FileUtil::Exists(fullpath)) { // TODO(Subv): Verify the archive behavior of SharedExtSaveData compared to ExtSaveData. // ExtSaveData seems to return FS_NotFound (120) when the archive doesn't exist. @@ -200,14 +227,16 @@ ResultVal> ArchiveFactory_ExtSaveData::Open(cons ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { + auto corrected_path = GetCorrectedPath(path); + // These folders are always created with the ExtSaveData - std::string user_path = GetExtSaveDataPath(mount_point, path) + "user/"; - std::string boss_path = GetExtSaveDataPath(mount_point, path) + "boss/"; + std::string user_path = GetExtSaveDataPath(mount_point, corrected_path) + "user/"; + std::string boss_path = GetExtSaveDataPath(mount_point, corrected_path) + "boss/"; FileUtil::CreateFullPath(user_path); FileUtil::CreateFullPath(boss_path); // Write the format metadata - std::string metadata_path = GetExtSaveDataPath(mount_point, path) + "metadata"; + std::string metadata_path = GetExtSaveDataPath(mount_point, corrected_path) + "metadata"; FileUtil::IOFile file(metadata_path, "wb"); if (!file.IsOpen()) { diff --git a/src/core/file_sys/archive_extsavedata.h b/src/core/file_sys/archive_extsavedata.h index f705ade1c..19814b5a0 100644 --- a/src/core/file_sys/archive_extsavedata.h +++ b/src/core/file_sys/archive_extsavedata.h @@ -56,6 +56,9 @@ private: * See GetExtSaveDataPath for the code that extracts this data from an archive path. */ std::string mount_point; + + /// Returns a path with the correct SaveIdHigh value for Shared extdata paths. + Path GetCorrectedPath(const Path& path); }; /**