فهرست منبع

Loader: Keep a reference to the file and pass it to the correct AppLoader, instead of loading it multiple times.

Emmanuel Gil Peyrot 11 سال پیش
والد
کامیت
b5237e885d
8فایلهای تغییر یافته به همراه116 افزوده شده و 176 حذف شده
  1. 4 17
      src/core/loader/3dsx.cpp
  2. 1 6
      src/core/loader/3dsx.h
  3. 8 22
      src/core/loader/elf.cpp
  4. 1 6
      src/core/loader/elf.h
  5. 11 12
      src/core/loader/loader.cpp
  6. 6 1
      src/core/loader/loader.h
  7. 84 106
      src/core/loader/ncch.cpp
  8. 1 6
      src/core/loader/ncch.h

+ 4 - 17
src/core/loader/3dsx.cpp

@@ -199,28 +199,15 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr)
     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() {
-    LOG_INFO(Loader, "Loading 3DSX file %s...", filename.c_str());
-
     if (is_loaded)
         return ResultStatus::ErrorAlreadyLoaded;
 
-    FileUtil::IOFile file(filename, "rb");
-
-    if (file.IsOpen()) {
-        Load3DSXFile(file, 0x00100000);
-        Kernel::LoadExec(0x00100000);
-    } else {
+    if (!file->IsOpen())
         return ResultStatus::Error;
-    }
+
+    Load3DSXFile(*file, 0x00100000);
+    Kernel::LoadExec(0x00100000);
 
     is_loaded = true;
     return ResultStatus::Success;

+ 1 - 6
src/core/loader/3dsx.h

@@ -15,18 +15,13 @@ namespace Loader {
 /// Loads an 3DSX file
 class AppLoader_THREEDSX final : public AppLoader {
 public:
-    AppLoader_THREEDSX(const std::string& filename);
-    ~AppLoader_THREEDSX() override;
+    AppLoader_THREEDSX(std::unique_ptr<FileUtil::IOFile>&& file) : AppLoader(std::move(file)) { }
 
     /**
      * Load the bootable file
      * @return ResultStatus result of function
      */
     ResultStatus Load() override;
-
-private:
-    std::string filename;
-    bool        is_loaded = false;
 };
 
 } // namespace Loader

+ 8 - 22
src/core/loader/elf.cpp

@@ -330,34 +330,20 @@ bool ElfReader::LoadSymbols() {
 
 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() {
-    LOG_INFO(Loader, "Loading ELF file %s...", filename.c_str());
-
     if (is_loaded)
         return ResultStatus::ErrorAlreadyLoaded;
 
-    FileUtil::IOFile file(filename, "rb");
+    if (!file->IsOpen())
+        return ResultStatus::Error;
 
-    if (file.IsOpen()) {
-        u32 size = (u32)file.GetSize();
-        std::unique_ptr<u8[]> buffer(new u8[size]);
-        file.ReadBytes(&buffer[0], size);
+    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());
-    } else {
-        return ResultStatus::Error;
-    }
+    ElfReader elf_reader(&buffer[0]);
+    elf_reader.LoadInto(0x00100000);
+    Kernel::LoadExec(elf_reader.GetEntryPoint());
 
     is_loaded = true;
     return ResultStatus::Success;

+ 1 - 6
src/core/loader/elf.h

@@ -15,18 +15,13 @@ namespace Loader {
 /// Loads an ELF/AXF file
 class AppLoader_ELF final : public AppLoader {
 public:
-    AppLoader_ELF(const std::string& filename);
-    ~AppLoader_ELF() override;
+    AppLoader_ELF(std::unique_ptr<FileUtil::IOFile>&& file) : AppLoader(std::move(file)) { }
 
     /**
      * Load the bootable file
      * @return ResultStatus result of function
      */
     ResultStatus Load() override;
-
-private:
-    std::string filename;
-    bool        is_loaded = false;
 };
 
 } // namespace Loader

+ 11 - 12
src/core/loader/loader.cpp

@@ -56,20 +56,24 @@ FileType IdentifyFile(const std::string &filename) {
 ResultStatus LoadFile(const std::string& filename) {
     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)) {
 
     //3DSX file format...
     case FileType::THREEDSX:
-        return AppLoader_THREEDSX(filename).Load();
+        return AppLoader_THREEDSX(std::move(file)).Load();
 
     // Standard ELF file format...
     case FileType::ELF:
-        return AppLoader_ELF(filename).Load();
+        return AppLoader_ELF(std::move(file)).Load();
 
     // NCCH/NCSD container formats...
     case FileType::CXI:
     case FileType::CCI: {
-        AppLoader_NCCH app_loader(filename);
+        AppLoader_NCCH app_loader(std::move(file));
 
         // Load application and RomFS
         if (ResultStatus::Success == app_loader.Load()) {
@@ -83,16 +87,11 @@ ResultStatus LoadFile(const std::string& filename) {
     // Raw BIN file format...
     case FileType::BIN:
     {
-        LOG_INFO(Loader, "Loading BIN file %s...", filename.c_str());
-
-        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 {
+        size_t size = (size_t)file->GetSize();
+        if (file->ReadBytes(Memory::GetPointer(Memory::EXEFS_CODE_VADDR), size) != size)
             return ResultStatus::Error;
-        }
+
+        Kernel::LoadExec(Memory::EXEFS_CODE_VADDR);
         return ResultStatus::Success;
     }
 

+ 6 - 1
src/core/loader/loader.h

@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "common/common.h"
+#include "common/file_util.h"
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Loader namespace
@@ -40,7 +41,7 @@ enum class ResultStatus {
 /// Interface for loading an application
 class AppLoader : NonCopyable {
 public:
-    AppLoader() { }
+    AppLoader(std::unique_ptr<FileUtil::IOFile>&& file) : file(std::move(file)) { }
     virtual ~AppLoader() { }
 
     /**
@@ -93,6 +94,10 @@ public:
     virtual ResultStatus ReadRomFS(std::vector<u8>& buffer) const {
         return ResultStatus::ErrorNotImplemented;
     }
+
+protected:
+    std::unique_ptr<FileUtil::IOFile> file;
+    bool                              is_loaded = false;
 };
 
 /**

+ 84 - 106
src/core/loader/ncch.cpp

@@ -4,8 +4,6 @@
 
 #include <memory>
 
-#include "common/file_util.h"
-
 #include "core/loader/ncch.h"
 #include "core/hle/kernel/kernel.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 constructor
-AppLoader_NCCH::AppLoader_NCCH(const std::string& filename) {
-    this->filename = filename;
-}
-
-/// AppLoader_NCCH destructor
-AppLoader_NCCH::~AppLoader_NCCH() {
-}
-
 ResultStatus AppLoader_NCCH::LoadExec() const {
     if (!is_loaded)
         return ResultStatus::ErrorNotLoaded;
@@ -123,108 +112,100 @@ ResultStatus AppLoader_NCCH::LoadExec() const {
 
 ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector<u8>& buffer) const {
     // Iterate through the ExeFs archive until we find the .code file...
-    FileUtil::IOFile file(filename, "rb");
-    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...
+    if (!file->IsOpen())
+        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;
                 }
-                else {
-                    buffer.resize(exefs_header.section[i].size);
-                    file.ReadBytes(&buffer[0], exefs_header.section[i].size);
+                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;
                 }
-                return ResultStatus::Success;
+                // 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::ErrorNotUsed;
 }
 
 ResultStatus AppLoader_NCCH::Load() {
-    LOG_INFO(Loader, "Loading NCCH file %s...", filename.c_str());
-
     if (is_loaded)
         return ResultStatus::ErrorAlreadyLoaded;
 
-    FileUtil::IOFile file(filename, "rb");
-    if (file.IsOpen()) {
-        file.ReadBytes(&ncch_header, sizeof(NCCH_Header));
+    if (!file->IsOpen())
+        return ResultStatus::Error;
 
-        // Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)...
-        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));
-        }
+    file->ReadBytes(&ncch_header, sizeof(NCCH_Header));
 
-        // Verify we are loading the correct file type...
-        if (0 != memcmp(&ncch_header.magic, "NCCH", 4))
-            return ResultStatus::ErrorInvalidFormat;
+    // Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)...
+    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));
+    }
 
-        // Read ExHeader...
+    // Verify we are loading the correct file type...
+    if (0 != memcmp(&ncch_header.magic, "NCCH", 4))
+        return ResultStatus::ErrorInvalidFormat;
 
-        file.ReadBytes(&exheader_header, sizeof(ExHeader_Header));
+    // Read ExHeader...
 
-        is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1;
-        entry_point = exheader_header.codeset_info.text.address;
+    file->ReadBytes(&exheader_header, sizeof(ExHeader_Header));
 
-        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);
+    is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1;
+    entry_point = exheader_header.codeset_info.text.address;
 
-        // Read ExeFS...
+    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);
 
-        exefs_offset = ncch_header.exefs_offset * kBlockSize;
-        u32 exefs_size = ncch_header.exefs_size * kBlockSize;
+    // Read ExeFS...
 
-        LOG_DEBUG(Loader, "ExeFS offset:    0x%08X", exefs_offset);
-        LOG_DEBUG(Loader, "ExeFS size:      0x%08X", exefs_size);
+    exefs_offset = ncch_header.exefs_offset * kBlockSize;
+    u32 exefs_size = ncch_header.exefs_size * kBlockSize;
 
-        file.Seek(exefs_offset + ncch_offset, 0);
-        file.ReadBytes(&exefs_header, sizeof(ExeFs_Header));
+    LOG_DEBUG(Loader, "ExeFS offset:    0x%08X", exefs_offset);
+    LOG_DEBUG(Loader, "ExeFS size:      0x%08X", exefs_size);
 
-        LoadExec(); // Load the executable into memory for booting
+    file->Seek(exefs_offset + ncch_offset, 0);
+    file->ReadBytes(&exefs_header, sizeof(ExeFs_Header));
 
-        is_loaded = true; // Set state to loaded
+    LoadExec(); // Load the executable into memory for booting
 
-        return ResultStatus::Success;
-    } else {
-        LOG_ERROR(Loader, "Unable to read file %s!", filename.c_str());
-    }
-    return ResultStatus::Error;
+    is_loaded = true; // Set state to loaded
+
+    return ResultStatus::Success;
 }
 
 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 {
-    FileUtil::IOFile file(filename, "rb");
-    if (file.IsOpen()) {
-        // 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;
+    if (!file->IsOpen())
+        return ResultStatus::Error;
 
-            LOG_DEBUG(Loader, "RomFS offset:    0x%08X", romfs_offset);
-            LOG_DEBUG(Loader, "RomFS size:      0x%08X", romfs_size);
+    // 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;
 
-            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);
-            file.ReadBytes(&buffer[0], romfs_size);
+        buffer.resize(romfs_size);
 
-            return ResultStatus::Success;
-        }
-        LOG_DEBUG(Loader, "NCCH has no RomFS");
-        return ResultStatus::ErrorNotUsed;
-    } else {
-        LOG_ERROR(Loader, "Unable to read file %s!", filename.c_str());
+        file->Seek(romfs_offset, 0);
+        file->ReadBytes(&buffer[0], romfs_size);
+
+        return ResultStatus::Success;
     }
-    return ResultStatus::Error;
+    LOG_DEBUG(Loader, "NCCH has no RomFS");
+    return ResultStatus::ErrorNotUsed;
 }
 
 u64 AppLoader_NCCH::GetProgramId() const {

+ 1 - 6
src/core/loader/ncch.h

@@ -5,7 +5,6 @@
 #pragma once
 
 #include "common/common.h"
-#include "common/file_util.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)
 class AppLoader_NCCH final : public AppLoader {
 public:
-    AppLoader_NCCH(const std::string& filename);
-    ~AppLoader_NCCH() override;
+    AppLoader_NCCH(std::unique_ptr<FileUtil::IOFile>&& file) : AppLoader(std::move(file)) { }
 
     /**
      * Load the application
@@ -213,9 +211,6 @@ private:
      */
     ResultStatus LoadExec() const;
 
-    std::string     filename;
-
-    bool            is_loaded = false;
     bool            is_compressed = false;
 
     u32             entry_point = 0;