Merge pull request #4229 from zhaowenlan1779/open-folder
citra_qt, core: game list "Open XXX Location" improvements
This commit is contained in:
commit
87e16c80ac
11 changed files with 153 additions and 20 deletions
|
@ -176,6 +176,13 @@ std::string GetExtDataContainerPath(const std::string& mount_point, bool shared)
|
|||
return fmt::format("{}Nintendo 3DS/{}/{}/extdata/", mount_point, SYSTEM_ID, SDCARD_ID);
|
||||
}
|
||||
|
||||
std::string GetExtDataPathFromId(const std::string& mount_point, u64 extdata_id) {
|
||||
u32 high = static_cast<u32>(extdata_id >> 32);
|
||||
u32 low = static_cast<u32>(extdata_id & 0xFFFFFFFF);
|
||||
|
||||
return fmt::format("{}{:08x}/{:08x}/", GetExtDataContainerPath(mount_point, false), high, low);
|
||||
}
|
||||
|
||||
Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) {
|
||||
ExtSaveDataArchivePath path;
|
||||
path.media_type = media_type;
|
||||
|
|
|
@ -64,6 +64,15 @@ private:
|
|||
*/
|
||||
std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path);
|
||||
|
||||
/**
|
||||
* Constructs a path to the concrete ExtData archive in the host filesystem based on the
|
||||
* extdata ID and base mount point.
|
||||
* @param mount_point The base mount point of the ExtSaveData archives.
|
||||
* @param extdata_id The id of the ExtSaveData
|
||||
* @returns The complete path to the specified extdata archive in the host filesystem
|
||||
*/
|
||||
std::string GetExtDataPathFromId(const std::string& mount_point, u64 extdata_id);
|
||||
|
||||
/**
|
||||
* Constructs a path to the base folder to hold concrete ExtSaveData archives in the host file
|
||||
* system.
|
||||
|
|
|
@ -576,6 +576,41 @@ Loader::ResultStatus NCCHContainer::ReadProgramId(u64_le& program_id) {
|
|||
return Loader::ResultStatus::Success;
|
||||
}
|
||||
|
||||
Loader::ResultStatus NCCHContainer::ReadExtdataId(u64& extdata_id) {
|
||||
Loader::ResultStatus result = Load();
|
||||
if (result != Loader::ResultStatus::Success)
|
||||
return result;
|
||||
|
||||
if (!has_exheader)
|
||||
return Loader::ResultStatus::ErrorNotUsed;
|
||||
|
||||
if (exheader_header.arm11_system_local_caps.storage_info.other_attributes >> 1) {
|
||||
// Using extended save data access
|
||||
// There would be multiple possible extdata IDs in this case. The best we can do for now is
|
||||
// guessing that the first one would be the main save.
|
||||
const std::array<u64, 6> extdata_ids{{
|
||||
exheader_header.arm11_system_local_caps.storage_info.extdata_id0.Value(),
|
||||
exheader_header.arm11_system_local_caps.storage_info.extdata_id1.Value(),
|
||||
exheader_header.arm11_system_local_caps.storage_info.extdata_id2.Value(),
|
||||
exheader_header.arm11_system_local_caps.storage_info.extdata_id3.Value(),
|
||||
exheader_header.arm11_system_local_caps.storage_info.extdata_id4.Value(),
|
||||
exheader_header.arm11_system_local_caps.storage_info.extdata_id5.Value(),
|
||||
}};
|
||||
for (u64 id : extdata_ids) {
|
||||
if (id) {
|
||||
// Found a non-zero ID, use it
|
||||
extdata_id = id;
|
||||
return Loader::ResultStatus::Success;
|
||||
}
|
||||
}
|
||||
|
||||
return Loader::ResultStatus::ErrorNotUsed;
|
||||
}
|
||||
|
||||
extdata_id = exheader_header.arm11_system_local_caps.storage_info.ext_save_data_id;
|
||||
return Loader::ResultStatus::Success;
|
||||
}
|
||||
|
||||
bool NCCHContainer::HasExeFS() {
|
||||
Loader::ResultStatus result = Load();
|
||||
if (result != Loader::ResultStatus::Success)
|
||||
|
|
|
@ -125,9 +125,23 @@ struct ExHeader_SystemInfo {
|
|||
};
|
||||
|
||||
struct ExHeader_StorageInfo {
|
||||
u8 ext_save_data_id[8];
|
||||
union {
|
||||
u64_le ext_save_data_id;
|
||||
// When using extended savedata access
|
||||
// Prefer the ID specified in the most significant bits
|
||||
BitField<40, 20, u64_le> extdata_id3;
|
||||
BitField<20, 20, u64_le> extdata_id4;
|
||||
BitField<0, 20, u64_le> extdata_id5;
|
||||
};
|
||||
u8 system_save_data_id[8];
|
||||
u8 reserved[8];
|
||||
union {
|
||||
u64_le storage_accessible_unique_ids;
|
||||
// When using extended savedata access
|
||||
// Prefer the ID specified in the most significant bits
|
||||
BitField<40, 20, u64_le> extdata_id0;
|
||||
BitField<20, 20, u64_le> extdata_id1;
|
||||
BitField<0, 20, u64_le> extdata_id2;
|
||||
};
|
||||
u8 access_info[7];
|
||||
u8 other_attributes;
|
||||
};
|
||||
|
@ -251,6 +265,12 @@ public:
|
|||
*/
|
||||
Loader::ResultStatus ReadProgramId(u64_le& program_id);
|
||||
|
||||
/**
|
||||
* Get the Extdata ID of the NCCH container
|
||||
* @return ResultStatus result of function
|
||||
*/
|
||||
Loader::ResultStatus ReadExtdataId(u64& extdata_id);
|
||||
|
||||
/**
|
||||
* Checks whether the NCCH container contains an ExeFS
|
||||
* @return bool check result
|
||||
|
|
|
@ -157,6 +157,15 @@ public:
|
|||
return ResultStatus::ErrorNotImplemented;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extdata id for the application
|
||||
* @param out_extdata_id Reference to store extdata id into
|
||||
* @return ResultStatus result of function
|
||||
*/
|
||||
virtual ResultStatus ReadExtdataId(u64& out_extdata_id) {
|
||||
return ResultStatus::ErrorNotImplemented;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the RomFS of the application
|
||||
* Since the RomFS can be huge, we return a file reference instead of copying to a buffer
|
||||
|
|
|
@ -216,6 +216,14 @@ ResultStatus AppLoader_NCCH::ReadProgramId(u64& out_program_id) {
|
|||
return ResultStatus::Success;
|
||||
}
|
||||
|
||||
ResultStatus AppLoader_NCCH::ReadExtdataId(u64& out_extdata_id) {
|
||||
ResultStatus result = base_ncch.ReadExtdataId(out_extdata_id);
|
||||
if (result != ResultStatus::Success)
|
||||
return result;
|
||||
|
||||
return ResultStatus::Success;
|
||||
}
|
||||
|
||||
ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileSys::RomFSReader>& romfs_file) {
|
||||
return base_ncch.ReadRomFS(romfs_file);
|
||||
}
|
||||
|
|
|
@ -51,6 +51,8 @@ public:
|
|||
|
||||
ResultStatus ReadProgramId(u64& out_program_id) override;
|
||||
|
||||
ResultStatus ReadExtdataId(u64& out_extdata_id) override;
|
||||
|
||||
ResultStatus ReadRomFS(std::shared_ptr<FileSys::RomFSReader>& romfs_file) override;
|
||||
|
||||
ResultStatus ReadUpdateRomFS(std::shared_ptr<FileSys::RomFSReader>& romfs_file) override;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue