savedata_factory: Detect future save data paths
Enable compatibility for new account/device save paths planned on a future implementation.
This commit is contained in:
		| @@ -5,6 +5,7 @@ | |||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "common/uuid.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/file_sys/savedata_factory.h" | #include "core/file_sys/savedata_factory.h" | ||||||
| #include "core/file_sys/vfs.h" | #include "core/file_sys/vfs.h" | ||||||
| @@ -59,6 +60,36 @@ bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataA | |||||||
|             attr.title_id == 0 && attr.save_id == 0); |             attr.title_id == 0 && attr.save_id == 0); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u64 title_id, | ||||||
|  |                                   u128 user_id) { | ||||||
|  |     // Only detect nand user saves. | ||||||
|  |     const auto space_id_path = [space_id]() -> std::string_view { | ||||||
|  |         switch (space_id) { | ||||||
|  |         case SaveDataSpaceId::NandUser: | ||||||
|  |             return "/user/save"; | ||||||
|  |         default: | ||||||
|  |             return ""; | ||||||
|  |         } | ||||||
|  |     }(); | ||||||
|  |  | ||||||
|  |     if (space_id_path.empty()) { | ||||||
|  |         return ""; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     Common::UUID uuid; | ||||||
|  |     std::memcpy(uuid.uuid.data(), user_id.data(), sizeof(Common::UUID)); | ||||||
|  |  | ||||||
|  |     // Only detect account/device saves from the future location. | ||||||
|  |     switch (type) { | ||||||
|  |     case SaveDataType::SaveData: | ||||||
|  |         return fmt::format("{}/account/{}/{:016X}/1", space_id_path, uuid.RawString(), title_id); | ||||||
|  |     case SaveDataType::DeviceSaveData: | ||||||
|  |         return fmt::format("{}/device/{:016X}/1", space_id_path, title_id); | ||||||
|  |     default: | ||||||
|  |         return ""; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| } // Anonymous namespace | } // Anonymous namespace | ||||||
|  |  | ||||||
| std::string SaveDataAttribute::DebugInfo() const { | std::string SaveDataAttribute::DebugInfo() const { | ||||||
| @@ -82,7 +113,7 @@ ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space, | |||||||
|     PrintSaveDataAttributeWarnings(meta); |     PrintSaveDataAttributeWarnings(meta); | ||||||
|  |  | ||||||
|     const auto save_directory = |     const auto save_directory = | ||||||
|         GetFullPath(system, space, meta.type, meta.title_id, meta.user_id, meta.save_id); |         GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); | ||||||
|  |  | ||||||
|     auto out = dir->CreateDirectoryRelative(save_directory); |     auto out = dir->CreateDirectoryRelative(save_directory); | ||||||
|  |  | ||||||
| @@ -99,7 +130,7 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, | |||||||
|                                             const SaveDataAttribute& meta) const { |                                             const SaveDataAttribute& meta) const { | ||||||
|  |  | ||||||
|     const auto save_directory = |     const auto save_directory = | ||||||
|         GetFullPath(system, space, meta.type, meta.title_id, meta.user_id, meta.save_id); |         GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); | ||||||
|  |  | ||||||
|     auto out = dir->GetDirectoryRelative(save_directory); |     auto out = dir->GetDirectoryRelative(save_directory); | ||||||
|  |  | ||||||
| @@ -134,9 +165,9 @@ std::string SaveDataFactory::GetSaveDataSpaceIdPath(SaveDataSpaceId space) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| std::string SaveDataFactory::GetFullPath(Core::System& system, SaveDataSpaceId space, | std::string SaveDataFactory::GetFullPath(Core::System& system, VirtualDir dir, | ||||||
|                                          SaveDataType type, u64 title_id, u128 user_id, |                                          SaveDataSpaceId space, SaveDataType type, u64 title_id, | ||||||
|                                          u64 save_id) { |                                          u128 user_id, u64 save_id) { | ||||||
|     // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should |     // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should | ||||||
|     // be interpreted as the title id of the current process. |     // be interpreted as the title id of the current process. | ||||||
|     if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) { |     if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) { | ||||||
| @@ -145,6 +176,17 @@ std::string SaveDataFactory::GetFullPath(Core::System& system, SaveDataSpaceId s | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // For compat with a future impl. | ||||||
|  |     if (std::string future_path = | ||||||
|  |             GetFutureSaveDataPath(space, type, title_id & ~(0xFFULL), user_id); | ||||||
|  |         !future_path.empty()) { | ||||||
|  |         // Check if this location exists, and prefer it over the old. | ||||||
|  |         if (const auto future_dir = dir->GetDirectoryRelative(future_path); future_dir != nullptr) { | ||||||
|  |             LOG_INFO(Service_FS, "Using save at new location: {}", future_path); | ||||||
|  |             return future_path; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     std::string out = GetSaveDataSpaceIdPath(space); |     std::string out = GetSaveDataSpaceIdPath(space); | ||||||
|  |  | ||||||
|     switch (type) { |     switch (type) { | ||||||
| @@ -167,7 +209,8 @@ std::string SaveDataFactory::GetFullPath(Core::System& system, SaveDataSpaceId s | |||||||
|  |  | ||||||
| SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id, | SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id, | ||||||
|                                                u128 user_id) const { |                                                u128 user_id) const { | ||||||
|     const auto path = GetFullPath(system, SaveDataSpaceId::NandUser, type, title_id, user_id, 0); |     const auto path = | ||||||
|  |         GetFullPath(system, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0); | ||||||
|     const auto relative_dir = GetOrCreateDirectoryRelative(dir, path); |     const auto relative_dir = GetOrCreateDirectoryRelative(dir, path); | ||||||
|  |  | ||||||
|     const auto size_file = relative_dir->GetFile(SAVE_DATA_SIZE_FILENAME); |     const auto size_file = relative_dir->GetFile(SAVE_DATA_SIZE_FILENAME); | ||||||
| @@ -185,7 +228,8 @@ SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id, | |||||||
|  |  | ||||||
| void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id, | void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id, | ||||||
|                                         SaveDataSize new_value) const { |                                         SaveDataSize new_value) const { | ||||||
|     const auto path = GetFullPath(system, SaveDataSpaceId::NandUser, type, title_id, user_id, 0); |     const auto path = | ||||||
|  |         GetFullPath(system, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0); | ||||||
|     const auto relative_dir = GetOrCreateDirectoryRelative(dir, path); |     const auto relative_dir = GetOrCreateDirectoryRelative(dir, path); | ||||||
|  |  | ||||||
|     const auto size_file = relative_dir->CreateFile(SAVE_DATA_SIZE_FILENAME); |     const auto size_file = relative_dir->CreateFile(SAVE_DATA_SIZE_FILENAME); | ||||||
|   | |||||||
| @@ -95,8 +95,8 @@ public: | |||||||
|     VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; |     VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; | ||||||
|  |  | ||||||
|     static std::string GetSaveDataSpaceIdPath(SaveDataSpaceId space); |     static std::string GetSaveDataSpaceIdPath(SaveDataSpaceId space); | ||||||
|     static std::string GetFullPath(Core::System& system, SaveDataSpaceId space, SaveDataType type, |     static std::string GetFullPath(Core::System& system, VirtualDir dir, SaveDataSpaceId space, | ||||||
|                                    u64 title_id, u128 user_id, u64 save_id); |                                    SaveDataType type, u64 title_id, u128 user_id, u64 save_id); | ||||||
|  |  | ||||||
|     SaveDataSize ReadSaveDataSize(SaveDataType type, u64 title_id, u128 user_id) const; |     SaveDataSize ReadSaveDataSize(SaveDataType type, u64 title_id, u128 user_id) const; | ||||||
|     void WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id, |     void WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id, | ||||||
|   | |||||||
| @@ -1895,6 +1895,8 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target | |||||||
|     case GameListOpenTarget::SaveData: { |     case GameListOpenTarget::SaveData: { | ||||||
|         open_target = tr("Save Data"); |         open_target = tr("Save Data"); | ||||||
|         const auto nand_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir); |         const auto nand_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir); | ||||||
|  |         auto vfs_nand_dir = | ||||||
|  |             vfs->OpenDirectory(Common::FS::PathToUTF8String(nand_dir), FileSys::Mode::Read); | ||||||
|  |  | ||||||
|         if (has_user_save) { |         if (has_user_save) { | ||||||
|             // User save data |             // User save data | ||||||
| @@ -1921,15 +1923,15 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target | |||||||
|             ASSERT(user_id); |             ASSERT(user_id); | ||||||
|  |  | ||||||
|             const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath( |             const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath( | ||||||
|                 *system, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, |                 *system, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser, | ||||||
|                 program_id, user_id->AsU128(), 0); |                 FileSys::SaveDataType::SaveData, program_id, user_id->AsU128(), 0); | ||||||
|  |  | ||||||
|             path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path); |             path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path); | ||||||
|         } else { |         } else { | ||||||
|             // Device save data |             // Device save data | ||||||
|             const auto device_save_data_path = FileSys::SaveDataFactory::GetFullPath( |             const auto device_save_data_path = FileSys::SaveDataFactory::GetFullPath( | ||||||
|                 *system, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, |                 *system, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser, | ||||||
|                 program_id, {}, 0); |                 FileSys::SaveDataType::SaveData, program_id, {}, 0); | ||||||
|  |  | ||||||
|             path = Common::FS::ConcatPathSafe(nand_dir, device_save_data_path); |             path = Common::FS::ConcatPathSafe(nand_dir, device_save_data_path); | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user