file_sys: Add support for the BOSS ext save data archive. (#7231)

This commit is contained in:
Steveice10 2023-12-03 14:02:23 -08:00 committed by GitHub
parent ea9f522c0c
commit 875f5eaad5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 36 additions and 17 deletions

View file

@ -41,6 +41,7 @@ class Path {
public: public:
Path() : type(LowPathType::Invalid) {} Path() : type(LowPathType::Invalid) {}
Path(const char* path) : type(LowPathType::Char), string(path) {} 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)) {} Path(std::vector<u8> binary_data) : type(LowPathType::Binary), binary(std::move(binary_data)) {}
template <std::size_t size> template <std::size_t size>
Path(const std::array<u8, size>& binary_data) Path(const std::array<u8, size>& binary_data)

View file

@ -216,14 +216,16 @@ Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) {
} }
ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location, ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location,
bool shared) ExtSaveDataType type_)
: shared(shared), mount_point(GetExtDataContainerPath(mount_location, shared)) { : type(type_),
mount_point(GetExtDataContainerPath(mount_location, type_ == ExtSaveDataType::Shared)) {
LOG_DEBUG(Service_FS, "Directory {} set as base for ExtSaveData.", mount_point); LOG_DEBUG(Service_FS, "Directory {} set as base for ExtSaveData.", mount_point);
} }
Path ArchiveFactory_ExtSaveData::GetCorrectedPath(const Path& path) { Path ArchiveFactory_ExtSaveData::GetCorrectedPath(const Path& path) {
if (!shared) if (type != ExtSaveDataType::Shared) {
return path; return path;
}
static constexpr u32 SharedExtDataHigh = 0x48000; 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, ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(const Path& path,
u64 program_id) { 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)) { if (!FileUtil::Exists(fullpath)) {
// TODO(Subv): Verify the archive behavior of SharedExtSaveData compared to ExtSaveData. // TODO(Subv): Verify the archive behavior of SharedExtSaveData compared to ExtSaveData.
// ExtSaveData seems to return FS_NotFound (120) when the archive doesn't exist. // 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; return ERR_NOT_FOUND_INVALID_STATE;
} else { } else {
return ERR_NOT_FORMATTED; return ERR_NOT_FORMATTED;

View file

@ -15,10 +15,16 @@
namespace FileSys { 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 /// File system interface to the ExtSaveData archive
class ArchiveFactory_ExtSaveData final : public ArchiveFactory { class ArchiveFactory_ExtSaveData final : public ArchiveFactory {
public: public:
ArchiveFactory_ExtSaveData(const std::string& mount_point, bool shared); ArchiveFactory_ExtSaveData(const std::string& mount_point, ExtSaveDataType type_);
std::string GetName() const override { std::string GetName() const override {
return "ExtSaveData"; return "ExtSaveData";
@ -42,8 +48,8 @@ public:
void WriteIcon(const Path& path, std::span<const u8> icon); void WriteIcon(const Path& path, std::span<const u8> icon);
private: private:
bool shared; ///< Whether this archive represents an ExtSaveData archive or a SharedExtSaveData /// Type of ext save data archive being accessed.
/// archive ExtSaveDataType type;
/** /**
* This holds the full directory path for this archive, it is only set after a successful call * 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> template <class Archive>
void serialize(Archive& ar, const unsigned int) { void serialize(Archive& ar, const unsigned int) {
ar& boost::serialization::base_object<ArchiveFactory>(*this); ar& boost::serialization::base_object<ArchiveFactory>(*this);
ar& shared; ar& type;
ar& mount_point; ar& mount_point;
} }
friend class boost::serialization::access; friend class boost::serialization::access;

View file

@ -19,7 +19,8 @@ std::vector<Mii::MiiData> LoadMiis() {
std::vector<Mii::MiiData> miis; std::vector<Mii::MiiData> miis;
std::string nand_directory{FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)}; 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); auto archive_result = extdata_archive_factory.Open(Service::PTM::ptm_shared_extdata_id, 0);
if (archive_result.Succeeded()) { if (archive_result.Succeeded()) {

View file

@ -349,14 +349,18 @@ void ArchiveManager::RegisterArchiveTypes() {
RegisterArchiveType(std::move(other_savedata_general_factory), RegisterArchiveType(std::move(other_savedata_general_factory),
ArchiveIdCode::OtherSaveDataGeneral); ArchiveIdCode::OtherSaveDataGeneral);
auto extsavedata_factory = auto extsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(
std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false); sdmc_directory, FileSys::ExtSaveDataType::Normal);
RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData); RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData);
auto sharedextsavedata_factory = auto sharedextsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(
std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true); nand_directory, FileSys::ExtSaveDataType::Shared);
RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData); 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 // Create the NCCH archive, basically a small variation of the RomFS archive
auto savedatacheck_factory = std::make_unique<FileSys::ArchiveFactory_NCCH>(); auto savedatacheck_factory = std::make_unique<FileSys::ArchiveFactory_NCCH>();
RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::NCCH); RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::NCCH);

View file

@ -40,6 +40,7 @@ enum class ArchiveIdCode : u32 {
SystemSaveData = 0x00000008, SystemSaveData = 0x00000008,
SDMC = 0x00000009, SDMC = 0x00000009,
SDMCWriteOnly = 0x0000000A, SDMCWriteOnly = 0x0000000A,
BossExtSaveData = 0x12345678,
NCCH = 0x2345678A, NCCH = 0x2345678A,
OtherSaveDataGeneral = 0x567890B2, OtherSaveDataGeneral = 0x567890B2,
OtherSaveDataPermitted = 0x567890B4, OtherSaveDataPermitted = 0x567890B4,

View file

@ -146,7 +146,8 @@ void Module::Interface::GetSystemTime(Kernel::HLERequestContext& ctx) {
static void WriteGameCoinData(GameCoin gamecoin_data) { static void WriteGameCoinData(GameCoin gamecoin_data) {
const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); 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); FileSys::Path archive_path(ptm_shared_extdata_id);
auto archive_result = extdata_archive_factory.Open(archive_path, 0); auto archive_result = extdata_archive_factory.Open(archive_path, 0);
@ -179,7 +180,8 @@ static void WriteGameCoinData(GameCoin gamecoin_data) {
static GameCoin ReadGameCoinData() { static GameCoin ReadGameCoinData() {
const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); 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); FileSys::Path archive_path(ptm_shared_extdata_id);
auto archive_result = extdata_archive_factory.Open(archive_path, 0); 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 // Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't
// exist // exist
const std::string& nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); 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 FileSys::Path archive_path(ptm_shared_extdata_id);
const auto archive_result = extdata_archive_factory.Open(archive_path, 0); const auto archive_result = extdata_archive_factory.Open(archive_path, 0);
// If the archive didn't exist, write the default game coin file // If the archive didn't exist, write the default game coin file