mirror of
https://github.com/PabloMK7/citra.git
synced 2025-09-10 21:00:06 +00:00
[WIP] NCCHContainer: support for partitions if container is NCSD (#5345)
* GetProgramLaunchInfo: improve to for 3ds files * NCSD: allow to load other partitions * fix typo * Update src/core/hle/service/fs/fs_user.cpp Co-authored-by: Valentin Vanelslande <vvanelslandedev@gmail.com> * Update src/core/hle/service/fs/fs_user.cpp Co-authored-by: Valentin Vanelslande <vvanelslandedev@gmail.com> Co-authored-by: Marshall Mohror <mohror64@gmail.com> Co-authored-by: Valentin Vanelslande <vvanelslandedev@gmail.com>
This commit is contained in:
parent
897e473da4
commit
1722701c07
10 changed files with 226 additions and 34 deletions
|
@ -90,7 +90,7 @@ ResultVal<std::unique_ptr<FileBackend>> NCCHArchive::OpenFile(const Path& path,
|
|||
|
||||
std::string file_path =
|
||||
Service::AM::GetTitleContentPath(media_type, title_id, openfile_path.content_index);
|
||||
auto ncch_container = NCCHContainer(file_path);
|
||||
auto ncch_container = NCCHContainer(file_path, 0, openfile_path.content_index);
|
||||
|
||||
Loader::ResultStatus result;
|
||||
std::unique_ptr<FileBackend> file;
|
||||
|
|
|
@ -114,14 +114,16 @@ static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decom
|
|||
return true;
|
||||
}
|
||||
|
||||
NCCHContainer::NCCHContainer(const std::string& filepath, u32 ncch_offset)
|
||||
: ncch_offset(ncch_offset), filepath(filepath) {
|
||||
NCCHContainer::NCCHContainer(const std::string& filepath, u32 ncch_offset, u32 partition)
|
||||
: ncch_offset(ncch_offset), partition(partition), filepath(filepath) {
|
||||
file = FileUtil::IOFile(filepath, "rb");
|
||||
}
|
||||
|
||||
Loader::ResultStatus NCCHContainer::OpenFile(const std::string& filepath, u32 ncch_offset) {
|
||||
Loader::ResultStatus NCCHContainer::OpenFile(const std::string& filepath, u32 ncch_offset,
|
||||
u32 partition) {
|
||||
this->filepath = filepath;
|
||||
this->ncch_offset = ncch_offset;
|
||||
this->partition = partition;
|
||||
file = FileUtil::IOFile(filepath, "rb");
|
||||
|
||||
if (!file.IsOpen()) {
|
||||
|
@ -150,8 +152,13 @@ Loader::ResultStatus NCCHContainer::LoadHeader() {
|
|||
|
||||
// Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)...
|
||||
if (Loader::MakeMagic('N', 'C', 'S', 'D') == ncch_header.magic) {
|
||||
LOG_DEBUG(Service_FS, "Only loading the first (bootable) NCCH within the NCSD file!");
|
||||
ncch_offset += 0x4000;
|
||||
NCSD_Header ncsd_header;
|
||||
file.Seek(ncch_offset, SEEK_SET);
|
||||
file.ReadBytes(&ncsd_header, sizeof(NCSD_Header));
|
||||
ASSERT(Loader::MakeMagic('N', 'C', 'S', 'D') == ncsd_header.magic);
|
||||
ASSERT(partition < 8);
|
||||
ncch_offset = ncsd_header.partitions[partition].offset * kBlockSize;
|
||||
LOG_ERROR(Service_FS, "{}", ncch_offset);
|
||||
file.Seek(ncch_offset, SEEK_SET);
|
||||
file.ReadBytes(&ncch_header, sizeof(NCCH_Header));
|
||||
}
|
||||
|
@ -178,8 +185,12 @@ Loader::ResultStatus NCCHContainer::Load() {
|
|||
|
||||
// Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)...
|
||||
if (Loader::MakeMagic('N', 'C', 'S', 'D') == ncch_header.magic) {
|
||||
LOG_DEBUG(Service_FS, "Only loading the first (bootable) NCCH within the NCSD file!");
|
||||
ncch_offset += 0x4000;
|
||||
NCSD_Header ncsd_header;
|
||||
file.Seek(ncch_offset, SEEK_SET);
|
||||
file.ReadBytes(&ncsd_header, sizeof(NCSD_Header));
|
||||
ASSERT(Loader::MakeMagic('N', 'C', 'S', 'D') == ncsd_header.magic);
|
||||
ASSERT(partition < 8);
|
||||
ncch_offset = ncsd_header.partitions[partition].offset * kBlockSize;
|
||||
file.Seek(ncch_offset, SEEK_SET);
|
||||
file.ReadBytes(&ncch_header, sizeof(NCCH_Header));
|
||||
}
|
||||
|
|
|
@ -15,6 +15,31 @@
|
|||
#include "core/core.h"
|
||||
#include "core/file_sys/romfs_reader.h"
|
||||
|
||||
enum NCSDContentIndex { Main = 0, Manual = 1, DLP = 2, New3DSUpdate = 6, Update = 7 };
|
||||
|
||||
struct NCSD_Partitions {
|
||||
u32 offset;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct NCSD_Header {
|
||||
u8 signature[0x100];
|
||||
u32_le magic;
|
||||
u32_le media_size;
|
||||
u8 media_id[8];
|
||||
u8 partition_fs_type[8];
|
||||
u8 partition_crypt_type[8];
|
||||
NCSD_Partitions partitions[8];
|
||||
u8 extended_header_hash[0x20];
|
||||
u32_le additional_header_size;
|
||||
u32_le sector_zero_offset;
|
||||
u8 partition_flags[8];
|
||||
u8 partition_id_table[0x40];
|
||||
u8 reserved[0x30];
|
||||
};
|
||||
|
||||
static_assert(sizeof(NCSD_Header) == 0x200, "NCCH header structure size is wrong");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// NCCH header (Note: "NCCH" appears to be a publicly unknown acronym)
|
||||
|
||||
|
@ -209,10 +234,11 @@ namespace FileSys {
|
|||
*/
|
||||
class NCCHContainer {
|
||||
public:
|
||||
NCCHContainer(const std::string& filepath, u32 ncch_offset = 0);
|
||||
NCCHContainer(const std::string& filepath, u32 ncch_offset = 0, u32 partition = 0);
|
||||
NCCHContainer() {}
|
||||
|
||||
Loader::ResultStatus OpenFile(const std::string& filepath, u32 ncch_offset = 0);
|
||||
Loader::ResultStatus OpenFile(const std::string& filepath, u32 ncch_offset = 0,
|
||||
u32 partition = 0);
|
||||
|
||||
/**
|
||||
* Ensure NCCH header is loaded and ready for reading sections
|
||||
|
@ -339,6 +365,7 @@ private:
|
|||
|
||||
u32 ncch_offset = 0; // Offset to NCCH header, can be 0 for NCCHs or non-zero for CIAs/NCSDs
|
||||
u32 exefs_offset = 0;
|
||||
u32 partition = 0;
|
||||
|
||||
std::string filepath;
|
||||
FileUtil::IOFile file;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue