file_sys: Add support for the BOSS ext save data archive. (#7231)
This commit is contained in:
parent
ea9f522c0c
commit
875f5eaad5
7 changed files with 36 additions and 17 deletions
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue