mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Loader: Keep a reference to the file and pass it to the correct AppLoader, instead of loading it multiple times.
This commit is contained in:
		
							parent
							
								
									2d63df90a9
								
							
						
					
					
						commit
						b5237e885d
					
				
					 8 changed files with 130 additions and 190 deletions
				
			
		|  | @ -199,28 +199,15 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) | ||||||
|     return ERROR_NONE; |     return ERROR_NONE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// AppLoader_DSX constructor
 |  | ||||||
| AppLoader_THREEDSX::AppLoader_THREEDSX(const std::string& filename) : filename(filename) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// AppLoader_DSX destructor
 |  | ||||||
| AppLoader_THREEDSX::~AppLoader_THREEDSX() { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ResultStatus AppLoader_THREEDSX::Load() { | ResultStatus AppLoader_THREEDSX::Load() { | ||||||
|     LOG_INFO(Loader, "Loading 3DSX file %s...", filename.c_str()); |  | ||||||
| 
 |  | ||||||
|     if (is_loaded) |     if (is_loaded) | ||||||
|         return ResultStatus::ErrorAlreadyLoaded; |         return ResultStatus::ErrorAlreadyLoaded; | ||||||
| 
 | 
 | ||||||
|     FileUtil::IOFile file(filename, "rb"); |     if (!file->IsOpen()) | ||||||
| 
 |  | ||||||
|     if (file.IsOpen()) { |  | ||||||
|         Load3DSXFile(file, 0x00100000); |  | ||||||
|         Kernel::LoadExec(0x00100000); |  | ||||||
|     } else { |  | ||||||
|         return ResultStatus::Error; |         return ResultStatus::Error; | ||||||
|     } | 
 | ||||||
|  |     Load3DSXFile(*file, 0x00100000); | ||||||
|  |     Kernel::LoadExec(0x00100000); | ||||||
| 
 | 
 | ||||||
|     is_loaded = true; |     is_loaded = true; | ||||||
|     return ResultStatus::Success; |     return ResultStatus::Success; | ||||||
|  |  | ||||||
|  | @ -15,18 +15,13 @@ namespace Loader { | ||||||
| /// Loads an 3DSX file
 | /// Loads an 3DSX file
 | ||||||
| class AppLoader_THREEDSX final : public AppLoader { | class AppLoader_THREEDSX final : public AppLoader { | ||||||
| public: | public: | ||||||
|     AppLoader_THREEDSX(const std::string& filename); |     AppLoader_THREEDSX(std::unique_ptr<FileUtil::IOFile>&& file) : AppLoader(std::move(file)) { } | ||||||
|     ~AppLoader_THREEDSX() override; |  | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Load the bootable file |      * Load the bootable file | ||||||
|      * @return ResultStatus result of function |      * @return ResultStatus result of function | ||||||
|      */ |      */ | ||||||
|     ResultStatus Load() override; |     ResultStatus Load() override; | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     std::string filename; |  | ||||||
|     bool        is_loaded = false; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace Loader
 | } // namespace Loader
 | ||||||
|  |  | ||||||
|  | @ -330,34 +330,20 @@ bool ElfReader::LoadSymbols() { | ||||||
| 
 | 
 | ||||||
| namespace Loader { | namespace Loader { | ||||||
| 
 | 
 | ||||||
| /// AppLoader_ELF constructor
 |  | ||||||
| AppLoader_ELF::AppLoader_ELF(const std::string& filename) { |  | ||||||
|     this->filename = filename; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// AppLoader_NCCH destructor
 |  | ||||||
| AppLoader_ELF::~AppLoader_ELF() { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ResultStatus AppLoader_ELF::Load() { | ResultStatus AppLoader_ELF::Load() { | ||||||
|     LOG_INFO(Loader, "Loading ELF file %s...", filename.c_str()); |  | ||||||
| 
 |  | ||||||
|     if (is_loaded) |     if (is_loaded) | ||||||
|         return ResultStatus::ErrorAlreadyLoaded; |         return ResultStatus::ErrorAlreadyLoaded; | ||||||
| 
 | 
 | ||||||
|     FileUtil::IOFile file(filename, "rb"); |     if (!file->IsOpen()) | ||||||
| 
 |  | ||||||
|     if (file.IsOpen()) { |  | ||||||
|         u32 size = (u32)file.GetSize(); |  | ||||||
|         std::unique_ptr<u8[]> buffer(new u8[size]); |  | ||||||
|         file.ReadBytes(&buffer[0], size); |  | ||||||
| 
 |  | ||||||
|         ElfReader elf_reader(&buffer[0]); |  | ||||||
|         elf_reader.LoadInto(0x00100000); |  | ||||||
|         Kernel::LoadExec(elf_reader.GetEntryPoint()); |  | ||||||
|     } else { |  | ||||||
|         return ResultStatus::Error; |         return ResultStatus::Error; | ||||||
|     } | 
 | ||||||
|  |     u32 size = static_cast<u32>(file->GetSize()); | ||||||
|  |     std::unique_ptr<u8[]> buffer(new u8[size]); | ||||||
|  |     file->ReadBytes(&buffer[0], size); | ||||||
|  | 
 | ||||||
|  |     ElfReader elf_reader(&buffer[0]); | ||||||
|  |     elf_reader.LoadInto(0x00100000); | ||||||
|  |     Kernel::LoadExec(elf_reader.GetEntryPoint()); | ||||||
| 
 | 
 | ||||||
|     is_loaded = true; |     is_loaded = true; | ||||||
|     return ResultStatus::Success; |     return ResultStatus::Success; | ||||||
|  |  | ||||||
|  | @ -15,18 +15,13 @@ namespace Loader { | ||||||
| /// Loads an ELF/AXF file
 | /// Loads an ELF/AXF file
 | ||||||
| class AppLoader_ELF final : public AppLoader { | class AppLoader_ELF final : public AppLoader { | ||||||
| public: | public: | ||||||
|     AppLoader_ELF(const std::string& filename); |     AppLoader_ELF(std::unique_ptr<FileUtil::IOFile>&& file) : AppLoader(std::move(file)) { } | ||||||
|     ~AppLoader_ELF() override; |  | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Load the bootable file |      * Load the bootable file | ||||||
|      * @return ResultStatus result of function |      * @return ResultStatus result of function | ||||||
|      */ |      */ | ||||||
|     ResultStatus Load() override; |     ResultStatus Load() override; | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     std::string filename; |  | ||||||
|     bool        is_loaded = false; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace Loader
 | } // namespace Loader
 | ||||||
|  |  | ||||||
|  | @ -56,20 +56,24 @@ FileType IdentifyFile(const std::string &filename) { | ||||||
| ResultStatus LoadFile(const std::string& filename) { | ResultStatus LoadFile(const std::string& filename) { | ||||||
|     LOG_INFO(Loader, "Loading file %s...", filename.c_str()); |     LOG_INFO(Loader, "Loading file %s...", filename.c_str()); | ||||||
| 
 | 
 | ||||||
|  |     std::unique_ptr<FileUtil::IOFile> file(new FileUtil::IOFile(filename, "rb")); | ||||||
|  |     if (!file->IsOpen()) | ||||||
|  |         return ResultStatus::Error; | ||||||
|  | 
 | ||||||
|     switch (IdentifyFile(filename)) { |     switch (IdentifyFile(filename)) { | ||||||
| 
 | 
 | ||||||
|     //3DSX file format...
 |     //3DSX file format...
 | ||||||
|     case FileType::THREEDSX: |     case FileType::THREEDSX: | ||||||
|         return AppLoader_THREEDSX(filename).Load(); |         return AppLoader_THREEDSX(std::move(file)).Load(); | ||||||
| 
 | 
 | ||||||
|     // Standard ELF file format...
 |     // Standard ELF file format...
 | ||||||
|     case FileType::ELF: |     case FileType::ELF: | ||||||
|         return AppLoader_ELF(filename).Load(); |         return AppLoader_ELF(std::move(file)).Load(); | ||||||
| 
 | 
 | ||||||
|     // NCCH/NCSD container formats...
 |     // NCCH/NCSD container formats...
 | ||||||
|     case FileType::CXI: |     case FileType::CXI: | ||||||
|     case FileType::CCI: { |     case FileType::CCI: { | ||||||
|         AppLoader_NCCH app_loader(filename); |         AppLoader_NCCH app_loader(std::move(file)); | ||||||
| 
 | 
 | ||||||
|         // Load application and RomFS
 |         // Load application and RomFS
 | ||||||
|         if (ResultStatus::Success == app_loader.Load()) { |         if (ResultStatus::Success == app_loader.Load()) { | ||||||
|  | @ -83,16 +87,11 @@ ResultStatus LoadFile(const std::string& filename) { | ||||||
|     // Raw BIN file format...
 |     // Raw BIN file format...
 | ||||||
|     case FileType::BIN: |     case FileType::BIN: | ||||||
|     { |     { | ||||||
|         LOG_INFO(Loader, "Loading BIN file %s...", filename.c_str()); |         size_t size = (size_t)file->GetSize(); | ||||||
| 
 |         if (file->ReadBytes(Memory::GetPointer(Memory::EXEFS_CODE_VADDR), size) != size) | ||||||
|         FileUtil::IOFile file(filename, "rb"); |  | ||||||
| 
 |  | ||||||
|         if (file.IsOpen()) { |  | ||||||
|             file.ReadBytes(Memory::GetPointer(Memory::EXEFS_CODE_VADDR), (size_t)file.GetSize()); |  | ||||||
|             Kernel::LoadExec(Memory::EXEFS_CODE_VADDR); |  | ||||||
|         } else { |  | ||||||
|             return ResultStatus::Error; |             return ResultStatus::Error; | ||||||
|         } | 
 | ||||||
|  |         Kernel::LoadExec(Memory::EXEFS_CODE_VADDR); | ||||||
|         return ResultStatus::Success; |         return ResultStatus::Success; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
| #include "common/common.h" | #include "common/common.h" | ||||||
|  | #include "common/file_util.h" | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // Loader namespace
 | // Loader namespace
 | ||||||
|  | @ -40,7 +41,7 @@ enum class ResultStatus { | ||||||
| /// Interface for loading an application
 | /// Interface for loading an application
 | ||||||
| class AppLoader : NonCopyable { | class AppLoader : NonCopyable { | ||||||
| public: | public: | ||||||
|     AppLoader() { } |     AppLoader(std::unique_ptr<FileUtil::IOFile>&& file) : file(std::move(file)) { } | ||||||
|     virtual ~AppLoader() { } |     virtual ~AppLoader() { } | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|  | @ -93,6 +94,10 @@ public: | ||||||
|     virtual ResultStatus ReadRomFS(std::vector<u8>& buffer) const { |     virtual ResultStatus ReadRomFS(std::vector<u8>& buffer) const { | ||||||
|         return ResultStatus::ErrorNotImplemented; |         return ResultStatus::ErrorNotImplemented; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  | protected: | ||||||
|  |     std::unique_ptr<FileUtil::IOFile> file; | ||||||
|  |     bool                              is_loaded = false; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
|  | @ -4,8 +4,6 @@ | ||||||
| 
 | 
 | ||||||
| #include <memory> | #include <memory> | ||||||
| 
 | 
 | ||||||
| #include "common/file_util.h" |  | ||||||
| 
 |  | ||||||
| #include "core/loader/ncch.h" | #include "core/loader/ncch.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/mem_map.h" | #include "core/mem_map.h" | ||||||
|  | @ -99,15 +97,6 @@ static bool LZSS_Decompress(u8* compressed, u32 compressed_size, u8* decompresse | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // AppLoader_NCCH class
 | // AppLoader_NCCH class
 | ||||||
| 
 | 
 | ||||||
| /// AppLoader_NCCH constructor
 |  | ||||||
| AppLoader_NCCH::AppLoader_NCCH(const std::string& filename) { |  | ||||||
|     this->filename = filename; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// AppLoader_NCCH destructor
 |  | ||||||
| AppLoader_NCCH::~AppLoader_NCCH() { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ResultStatus AppLoader_NCCH::LoadExec() const { | ResultStatus AppLoader_NCCH::LoadExec() const { | ||||||
|     if (!is_loaded) |     if (!is_loaded) | ||||||
|         return ResultStatus::ErrorNotLoaded; |         return ResultStatus::ErrorNotLoaded; | ||||||
|  | @ -123,108 +112,100 @@ ResultStatus AppLoader_NCCH::LoadExec() const { | ||||||
| 
 | 
 | ||||||
| ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector<u8>& buffer) const { | ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector<u8>& buffer) const { | ||||||
|     // Iterate through the ExeFs archive until we find the .code file...
 |     // Iterate through the ExeFs archive until we find the .code file...
 | ||||||
|     FileUtil::IOFile file(filename, "rb"); |     if (!file->IsOpen()) | ||||||
|     if (file.IsOpen()) { |  | ||||||
|         LOG_DEBUG(Loader, "%d sections:", kMaxSections); |  | ||||||
|         for (int i = 0; i < kMaxSections; i++) { |  | ||||||
|             // Load the specified section...
 |  | ||||||
|             if (strcmp((const char*)exefs_header.section[i].name, name) == 0) { |  | ||||||
|                 LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", i, |  | ||||||
|                         exefs_header.section[i].offset, exefs_header.section[i].size, |  | ||||||
|                         exefs_header.section[i].name); |  | ||||||
| 
 |  | ||||||
|                 s64 section_offset = (exefs_header.section[i].offset + exefs_offset + |  | ||||||
|                                      sizeof(ExeFs_Header)+ncch_offset); |  | ||||||
|                 file.Seek(section_offset, 0); |  | ||||||
| 
 |  | ||||||
|                 // Section is compressed...
 |  | ||||||
|                 if (i == 0 && is_compressed) { |  | ||||||
|                     // Read compressed .code section...
 |  | ||||||
|                     std::unique_ptr<u8[]> temp_buffer; |  | ||||||
|                     try { |  | ||||||
|                         temp_buffer.reset(new u8[exefs_header.section[i].size]); |  | ||||||
|                     } catch (std::bad_alloc&) { |  | ||||||
|                         return ResultStatus::ErrorMemoryAllocationFailed; |  | ||||||
|                     } |  | ||||||
|                     file.ReadBytes(&temp_buffer[0], exefs_header.section[i].size); |  | ||||||
| 
 |  | ||||||
|                     // Decompress .code section...
 |  | ||||||
|                     u32 decompressed_size = LZSS_GetDecompressedSize(&temp_buffer[0], |  | ||||||
|                         exefs_header.section[i].size); |  | ||||||
|                     buffer.resize(decompressed_size); |  | ||||||
|                     if (!LZSS_Decompress(&temp_buffer[0], exefs_header.section[i].size, &buffer[0], |  | ||||||
|                         decompressed_size)) { |  | ||||||
|                         return ResultStatus::ErrorInvalidFormat; |  | ||||||
|                     } |  | ||||||
|                     // Section is uncompressed...
 |  | ||||||
|                 } |  | ||||||
|                 else { |  | ||||||
|                     buffer.resize(exefs_header.section[i].size); |  | ||||||
|                     file.ReadBytes(&buffer[0], exefs_header.section[i].size); |  | ||||||
|                 } |  | ||||||
|                 return ResultStatus::Success; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } else { |  | ||||||
|         LOG_ERROR(Loader, "Unable to read file %s!", filename.c_str()); |  | ||||||
|         return ResultStatus::Error; |         return ResultStatus::Error; | ||||||
|  | 
 | ||||||
|  |     LOG_DEBUG(Loader, "%d sections:", kMaxSections); | ||||||
|  |     for (int i = 0; i < kMaxSections; i++) { | ||||||
|  |         // Load the specified section...
 | ||||||
|  |         if (strcmp((const char*)exefs_header.section[i].name, name) == 0) { | ||||||
|  |             LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", i, | ||||||
|  |                     exefs_header.section[i].offset, exefs_header.section[i].size, | ||||||
|  |                     exefs_header.section[i].name); | ||||||
|  | 
 | ||||||
|  |             s64 section_offset = (exefs_header.section[i].offset + exefs_offset + | ||||||
|  |                                  sizeof(ExeFs_Header)+ncch_offset); | ||||||
|  |             file->Seek(section_offset, 0); | ||||||
|  | 
 | ||||||
|  |             // Section is compressed...
 | ||||||
|  |             if (i == 0 && is_compressed) { | ||||||
|  |                 // Read compressed .code section...
 | ||||||
|  |                 std::unique_ptr<u8[]> temp_buffer; | ||||||
|  |                 try { | ||||||
|  |                     temp_buffer.reset(new u8[exefs_header.section[i].size]); | ||||||
|  |                 } catch (std::bad_alloc&) { | ||||||
|  |                     return ResultStatus::ErrorMemoryAllocationFailed; | ||||||
|  |                 } | ||||||
|  |                 file->ReadBytes(&temp_buffer[0], exefs_header.section[i].size); | ||||||
|  | 
 | ||||||
|  |                 // Decompress .code section...
 | ||||||
|  |                 u32 decompressed_size = LZSS_GetDecompressedSize(&temp_buffer[0], | ||||||
|  |                     exefs_header.section[i].size); | ||||||
|  |                 buffer.resize(decompressed_size); | ||||||
|  |                 if (!LZSS_Decompress(&temp_buffer[0], exefs_header.section[i].size, &buffer[0], | ||||||
|  |                     decompressed_size)) { | ||||||
|  |                     return ResultStatus::ErrorInvalidFormat; | ||||||
|  |                 } | ||||||
|  |                 // Section is uncompressed...
 | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 buffer.resize(exefs_header.section[i].size); | ||||||
|  |                 file->ReadBytes(&buffer[0], exefs_header.section[i].size); | ||||||
|  |             } | ||||||
|  |             return ResultStatus::Success; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     return ResultStatus::ErrorNotUsed; |     return ResultStatus::ErrorNotUsed; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultStatus AppLoader_NCCH::Load() { | ResultStatus AppLoader_NCCH::Load() { | ||||||
|     LOG_INFO(Loader, "Loading NCCH file %s...", filename.c_str()); |  | ||||||
| 
 |  | ||||||
|     if (is_loaded) |     if (is_loaded) | ||||||
|         return ResultStatus::ErrorAlreadyLoaded; |         return ResultStatus::ErrorAlreadyLoaded; | ||||||
| 
 | 
 | ||||||
|     FileUtil::IOFile file(filename, "rb"); |     if (!file->IsOpen()) | ||||||
|     if (file.IsOpen()) { |         return ResultStatus::Error; | ||||||
|         file.ReadBytes(&ncch_header, sizeof(NCCH_Header)); |  | ||||||
| 
 | 
 | ||||||
|         // Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)...
 |     file->ReadBytes(&ncch_header, sizeof(NCCH_Header)); | ||||||
|         if (0 == memcmp(&ncch_header.magic, "NCSD", 4)) { |  | ||||||
|             LOG_WARNING(Loader, "Only loading the first (bootable) NCCH within the NCSD file!"); |  | ||||||
|             ncch_offset = 0x4000; |  | ||||||
|             file.Seek(ncch_offset, 0); |  | ||||||
|             file.ReadBytes(&ncch_header, sizeof(NCCH_Header)); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         // Verify we are loading the correct file type...
 |     // Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)...
 | ||||||
|         if (0 != memcmp(&ncch_header.magic, "NCCH", 4)) |     if (0 == memcmp(&ncch_header.magic, "NCSD", 4)) { | ||||||
|             return ResultStatus::ErrorInvalidFormat; |         LOG_WARNING(Loader, "Only loading the first (bootable) NCCH within the NCSD file!"); | ||||||
| 
 |         ncch_offset = 0x4000; | ||||||
|         // Read ExHeader...
 |         file->Seek(ncch_offset, 0); | ||||||
| 
 |         file->ReadBytes(&ncch_header, sizeof(NCCH_Header)); | ||||||
|         file.ReadBytes(&exheader_header, sizeof(ExHeader_Header)); |  | ||||||
| 
 |  | ||||||
|         is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1; |  | ||||||
|         entry_point = exheader_header.codeset_info.text.address; |  | ||||||
| 
 |  | ||||||
|         LOG_INFO(Loader, "Name:            %s", exheader_header.codeset_info.name); |  | ||||||
|         LOG_DEBUG(Loader, "Code compressed: %s", is_compressed ? "yes" : "no"); |  | ||||||
|         LOG_DEBUG(Loader, "Entry point:     0x%08X", entry_point); |  | ||||||
| 
 |  | ||||||
|         // Read ExeFS...
 |  | ||||||
| 
 |  | ||||||
|         exefs_offset = ncch_header.exefs_offset * kBlockSize; |  | ||||||
|         u32 exefs_size = ncch_header.exefs_size * kBlockSize; |  | ||||||
| 
 |  | ||||||
|         LOG_DEBUG(Loader, "ExeFS offset:    0x%08X", exefs_offset); |  | ||||||
|         LOG_DEBUG(Loader, "ExeFS size:      0x%08X", exefs_size); |  | ||||||
| 
 |  | ||||||
|         file.Seek(exefs_offset + ncch_offset, 0); |  | ||||||
|         file.ReadBytes(&exefs_header, sizeof(ExeFs_Header)); |  | ||||||
| 
 |  | ||||||
|         LoadExec(); // Load the executable into memory for booting
 |  | ||||||
| 
 |  | ||||||
|         is_loaded = true; // Set state to loaded
 |  | ||||||
| 
 |  | ||||||
|         return ResultStatus::Success; |  | ||||||
|     } else { |  | ||||||
|         LOG_ERROR(Loader, "Unable to read file %s!", filename.c_str()); |  | ||||||
|     } |     } | ||||||
|     return ResultStatus::Error; | 
 | ||||||
|  |     // Verify we are loading the correct file type...
 | ||||||
|  |     if (0 != memcmp(&ncch_header.magic, "NCCH", 4)) | ||||||
|  |         return ResultStatus::ErrorInvalidFormat; | ||||||
|  | 
 | ||||||
|  |     // Read ExHeader...
 | ||||||
|  | 
 | ||||||
|  |     file->ReadBytes(&exheader_header, sizeof(ExHeader_Header)); | ||||||
|  | 
 | ||||||
|  |     is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1; | ||||||
|  |     entry_point = exheader_header.codeset_info.text.address; | ||||||
|  | 
 | ||||||
|  |     LOG_INFO(Loader, "Name:            %s", exheader_header.codeset_info.name); | ||||||
|  |     LOG_DEBUG(Loader, "Code compressed: %s", is_compressed ? "yes" : "no"); | ||||||
|  |     LOG_DEBUG(Loader, "Entry point:     0x%08X", entry_point); | ||||||
|  | 
 | ||||||
|  |     // Read ExeFS...
 | ||||||
|  | 
 | ||||||
|  |     exefs_offset = ncch_header.exefs_offset * kBlockSize; | ||||||
|  |     u32 exefs_size = ncch_header.exefs_size * kBlockSize; | ||||||
|  | 
 | ||||||
|  |     LOG_DEBUG(Loader, "ExeFS offset:    0x%08X", exefs_offset); | ||||||
|  |     LOG_DEBUG(Loader, "ExeFS size:      0x%08X", exefs_size); | ||||||
|  | 
 | ||||||
|  |     file->Seek(exefs_offset + ncch_offset, 0); | ||||||
|  |     file->ReadBytes(&exefs_header, sizeof(ExeFs_Header)); | ||||||
|  | 
 | ||||||
|  |     LoadExec(); // Load the executable into memory for booting
 | ||||||
|  | 
 | ||||||
|  |     is_loaded = true; // Set state to loaded
 | ||||||
|  | 
 | ||||||
|  |     return ResultStatus::Success; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultStatus AppLoader_NCCH::ReadCode(std::vector<u8>& buffer) const { | ResultStatus AppLoader_NCCH::ReadCode(std::vector<u8>& buffer) const { | ||||||
|  | @ -244,29 +225,26 @@ ResultStatus AppLoader_NCCH::ReadLogo(std::vector<u8>& buffer) const { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultStatus AppLoader_NCCH::ReadRomFS(std::vector<u8>& buffer) const { | ResultStatus AppLoader_NCCH::ReadRomFS(std::vector<u8>& buffer) const { | ||||||
|     FileUtil::IOFile file(filename, "rb"); |     if (!file->IsOpen()) | ||||||
|     if (file.IsOpen()) { |         return ResultStatus::Error; | ||||||
|         // Check if the NCCH has a RomFS...
 |  | ||||||
|         if (ncch_header.romfs_offset != 0 && ncch_header.romfs_size != 0) { |  | ||||||
|             u32 romfs_offset = ncch_offset + (ncch_header.romfs_offset * kBlockSize) + 0x1000; |  | ||||||
|             u32 romfs_size = (ncch_header.romfs_size * kBlockSize) - 0x1000; |  | ||||||
| 
 | 
 | ||||||
|             LOG_DEBUG(Loader, "RomFS offset:    0x%08X", romfs_offset); |     // Check if the NCCH has a RomFS...
 | ||||||
|             LOG_DEBUG(Loader, "RomFS size:      0x%08X", romfs_size); |     if (ncch_header.romfs_offset != 0 && ncch_header.romfs_size != 0) { | ||||||
|  |         u32 romfs_offset = ncch_offset + (ncch_header.romfs_offset * kBlockSize) + 0x1000; | ||||||
|  |         u32 romfs_size = (ncch_header.romfs_size * kBlockSize) - 0x1000; | ||||||
| 
 | 
 | ||||||
|             buffer.resize(romfs_size); |         LOG_DEBUG(Loader, "RomFS offset:    0x%08X", romfs_offset); | ||||||
|  |         LOG_DEBUG(Loader, "RomFS size:      0x%08X", romfs_size); | ||||||
| 
 | 
 | ||||||
|             file.Seek(romfs_offset, 0); |         buffer.resize(romfs_size); | ||||||
|             file.ReadBytes(&buffer[0], romfs_size); |  | ||||||
| 
 | 
 | ||||||
|             return ResultStatus::Success; |         file->Seek(romfs_offset, 0); | ||||||
|         } |         file->ReadBytes(&buffer[0], romfs_size); | ||||||
|         LOG_DEBUG(Loader, "NCCH has no RomFS"); | 
 | ||||||
|         return ResultStatus::ErrorNotUsed; |         return ResultStatus::Success; | ||||||
|     } else { |  | ||||||
|         LOG_ERROR(Loader, "Unable to read file %s!", filename.c_str()); |  | ||||||
|     } |     } | ||||||
|     return ResultStatus::Error; |     LOG_DEBUG(Loader, "NCCH has no RomFS"); | ||||||
|  |     return ResultStatus::ErrorNotUsed; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| u64 AppLoader_NCCH::GetProgramId() const { | u64 AppLoader_NCCH::GetProgramId() const { | ||||||
|  |  | ||||||
|  | @ -5,7 +5,6 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "common/common.h" | #include "common/common.h" | ||||||
| #include "common/file_util.h" |  | ||||||
| 
 | 
 | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| 
 | 
 | ||||||
|  | @ -147,8 +146,7 @@ namespace Loader { | ||||||
| /// Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI)
 | /// Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI)
 | ||||||
| class AppLoader_NCCH final : public AppLoader { | class AppLoader_NCCH final : public AppLoader { | ||||||
| public: | public: | ||||||
|     AppLoader_NCCH(const std::string& filename); |     AppLoader_NCCH(std::unique_ptr<FileUtil::IOFile>&& file) : AppLoader(std::move(file)) { } | ||||||
|     ~AppLoader_NCCH() override; |  | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Load the application |      * Load the application | ||||||
|  | @ -213,9 +211,6 @@ private: | ||||||
|      */ |      */ | ||||||
|     ResultStatus LoadExec() const; |     ResultStatus LoadExec() const; | ||||||
| 
 | 
 | ||||||
|     std::string     filename; |  | ||||||
| 
 |  | ||||||
|     bool            is_loaded = false; |  | ||||||
|     bool            is_compressed = false; |     bool            is_compressed = false; | ||||||
| 
 | 
 | ||||||
|     u32             entry_point = 0; |     u32             entry_point = 0; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue