mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +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