file_sys: Add support for the BOSS ext save data archive. (#7231)
This commit is contained in:
		| @@ -41,6 +41,7 @@ class Path { | ||||
| public: | ||||
|     Path() : type(LowPathType::Invalid) {} | ||||
|     Path(const char* path) : type(LowPathType::Char), string(path) {} | ||||
|     Path(std::string path) : type(LowPathType::Char), string(std::move(path)) {} | ||||
|     Path(std::vector<u8> binary_data) : type(LowPathType::Binary), binary(std::move(binary_data)) {} | ||||
|     template <std::size_t size> | ||||
|     Path(const std::array<u8, size>& binary_data) | ||||
|   | ||||
| @@ -216,14 +216,16 @@ Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) { | ||||
| } | ||||
|  | ||||
| ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location, | ||||
|                                                        bool shared) | ||||
|     : shared(shared), mount_point(GetExtDataContainerPath(mount_location, shared)) { | ||||
|                                                        ExtSaveDataType type_) | ||||
|     : type(type_), | ||||
|       mount_point(GetExtDataContainerPath(mount_location, type_ == ExtSaveDataType::Shared)) { | ||||
|     LOG_DEBUG(Service_FS, "Directory {} set as base for ExtSaveData.", mount_point); | ||||
| } | ||||
|  | ||||
| Path ArchiveFactory_ExtSaveData::GetCorrectedPath(const Path& path) { | ||||
|     if (!shared) | ||||
|     if (type != ExtSaveDataType::Shared) { | ||||
|         return path; | ||||
|     } | ||||
|  | ||||
|     static constexpr u32 SharedExtDataHigh = 0x48000; | ||||
|  | ||||
| @@ -242,11 +244,12 @@ Path ArchiveFactory_ExtSaveData::GetCorrectedPath(const Path& path) { | ||||
|  | ||||
| ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(const Path& path, | ||||
|                                                                             u64 program_id) { | ||||
|     std::string fullpath = GetExtSaveDataPath(mount_point, GetCorrectedPath(path)) + "user/"; | ||||
|     const auto directory = type == ExtSaveDataType::Boss ? "boss/" : "user/"; | ||||
|     const auto fullpath = GetExtSaveDataPath(mount_point, GetCorrectedPath(path)) + directory; | ||||
|     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. | ||||
|         if (!shared) { | ||||
|         if (type != ExtSaveDataType::Shared) { | ||||
|             return ERR_NOT_FOUND_INVALID_STATE; | ||||
|         } else { | ||||
|             return ERR_NOT_FORMATTED; | ||||
|   | ||||
| @@ -15,10 +15,16 @@ | ||||
|  | ||||
| namespace FileSys { | ||||
|  | ||||
| enum class ExtSaveDataType { | ||||
|     Normal, ///< Regular non-shared ext save data | ||||
|     Shared, ///< Shared ext save data | ||||
|     Boss,   ///< SpotPass ext save data | ||||
| }; | ||||
|  | ||||
| /// File system interface to the ExtSaveData archive | ||||
| class ArchiveFactory_ExtSaveData final : public ArchiveFactory { | ||||
| public: | ||||
|     ArchiveFactory_ExtSaveData(const std::string& mount_point, bool shared); | ||||
|     ArchiveFactory_ExtSaveData(const std::string& mount_point, ExtSaveDataType type_); | ||||
|  | ||||
|     std::string GetName() const override { | ||||
|         return "ExtSaveData"; | ||||
| @@ -42,8 +48,8 @@ public: | ||||
|     void WriteIcon(const Path& path, std::span<const u8> icon); | ||||
|  | ||||
| private: | ||||
|     bool shared; ///< Whether this archive represents an ExtSaveData archive or a SharedExtSaveData | ||||
|                  /// archive | ||||
|     /// Type of ext save data archive being accessed. | ||||
|     ExtSaveDataType type; | ||||
|  | ||||
|     /** | ||||
|      * This holds the full directory path for this archive, it is only set after a successful call | ||||
| @@ -59,7 +65,7 @@ private: | ||||
|     template <class Archive> | ||||
|     void serialize(Archive& ar, const unsigned int) { | ||||
|         ar& boost::serialization::base_object<ArchiveFactory>(*this); | ||||
|         ar& shared; | ||||
|         ar& type; | ||||
|         ar& mount_point; | ||||
|     } | ||||
|     friend class boost::serialization::access; | ||||
|   | ||||
| @@ -19,7 +19,8 @@ std::vector<Mii::MiiData> LoadMiis() { | ||||
|     std::vector<Mii::MiiData> miis; | ||||
|  | ||||
|     std::string nand_directory{FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)}; | ||||
|     FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, true); | ||||
|     FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, | ||||
|                                                                 FileSys::ExtSaveDataType::Shared); | ||||
|  | ||||
|     auto archive_result = extdata_archive_factory.Open(Service::PTM::ptm_shared_extdata_id, 0); | ||||
|     if (archive_result.Succeeded()) { | ||||
|   | ||||
| @@ -349,14 +349,18 @@ void ArchiveManager::RegisterArchiveTypes() { | ||||
|     RegisterArchiveType(std::move(other_savedata_general_factory), | ||||
|                         ArchiveIdCode::OtherSaveDataGeneral); | ||||
|  | ||||
|     auto extsavedata_factory = | ||||
|         std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false); | ||||
|     auto extsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>( | ||||
|         sdmc_directory, FileSys::ExtSaveDataType::Normal); | ||||
|     RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData); | ||||
|  | ||||
|     auto sharedextsavedata_factory = | ||||
|         std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true); | ||||
|     auto sharedextsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>( | ||||
|         nand_directory, FileSys::ExtSaveDataType::Shared); | ||||
|     RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData); | ||||
|  | ||||
|     auto bossextsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>( | ||||
|         sdmc_directory, FileSys::ExtSaveDataType::Boss); | ||||
|     RegisterArchiveType(std::move(bossextsavedata_factory), ArchiveIdCode::BossExtSaveData); | ||||
|  | ||||
|     // Create the NCCH archive, basically a small variation of the RomFS archive | ||||
|     auto savedatacheck_factory = std::make_unique<FileSys::ArchiveFactory_NCCH>(); | ||||
|     RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::NCCH); | ||||
|   | ||||
| @@ -40,6 +40,7 @@ enum class ArchiveIdCode : u32 { | ||||
|     SystemSaveData = 0x00000008, | ||||
|     SDMC = 0x00000009, | ||||
|     SDMCWriteOnly = 0x0000000A, | ||||
|     BossExtSaveData = 0x12345678, | ||||
|     NCCH = 0x2345678A, | ||||
|     OtherSaveDataGeneral = 0x567890B2, | ||||
|     OtherSaveDataPermitted = 0x567890B4, | ||||
|   | ||||
| @@ -146,7 +146,8 @@ void Module::Interface::GetSystemTime(Kernel::HLERequestContext& ctx) { | ||||
|  | ||||
| static void WriteGameCoinData(GameCoin gamecoin_data) { | ||||
|     const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); | ||||
|     FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, true); | ||||
|     FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, | ||||
|                                                                 FileSys::ExtSaveDataType::Shared); | ||||
|  | ||||
|     FileSys::Path archive_path(ptm_shared_extdata_id); | ||||
|     auto archive_result = extdata_archive_factory.Open(archive_path, 0); | ||||
| @@ -179,7 +180,8 @@ static void WriteGameCoinData(GameCoin gamecoin_data) { | ||||
|  | ||||
| static GameCoin ReadGameCoinData() { | ||||
|     const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); | ||||
|     FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, true); | ||||
|     FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, | ||||
|                                                                 FileSys::ExtSaveDataType::Shared); | ||||
|  | ||||
|     FileSys::Path archive_path(ptm_shared_extdata_id); | ||||
|     auto archive_result = extdata_archive_factory.Open(archive_path, 0); | ||||
| @@ -209,7 +211,8 @@ Module::Module() { | ||||
|     // Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't | ||||
|     // exist | ||||
|     const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); | ||||
|     FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, true); | ||||
|     FileSys::ArchiveFactory_ExtSaveData extdata_archive_factory(nand_directory, | ||||
|                                                                 FileSys::ExtSaveDataType::Shared); | ||||
|     const FileSys::Path archive_path(ptm_shared_extdata_id); | ||||
|     const auto archive_result = extdata_archive_factory.Open(archive_path, 0); | ||||
|     // If the archive didn't exist, write the default game coin file | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Steveice10
					Steveice10