Просмотр исходного кода

Loader, Frontends: Refactor loader creation and game loading

This allows frontends to keep a single loader and use it multiple times
e.g. for code loading and SMDH parsing.
Emmanuel Gil Peyrot 10 лет назад
Родитель
Сommit
8fc9c03126

+ 7 - 1
src/citra/citra.cpp

@@ -114,7 +114,13 @@ int main(int argc, char **argv) {
     System::Init(emu_window.get());
     SCOPE_EXIT({ System::Shutdown(); });
 
-    Loader::ResultStatus load_result = Loader::LoadFile(boot_filename);
+    std::unique_ptr<Loader::AppLoader> loader = Loader::GetFileLoader(boot_filename);
+    if (!loader) {
+        LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", boot_filename.c_str());
+        return -1;
+    }
+
+    Loader::ResultStatus load_result = loader->Load();
     if (Loader::ResultStatus::Success != load_result) {
         LOG_CRITICAL(Frontend, "Failed to load ROM (Error %i)!", load_result);
         return -1;

+ 9 - 1
src/citra_qt/main.cpp

@@ -272,7 +272,15 @@ bool GMainWindow::InitializeSystem() {
 }
 
 bool GMainWindow::LoadROM(const std::string& filename) {
-    Loader::ResultStatus result = Loader::LoadFile(filename);
+    std::unique_ptr<Loader::AppLoader> app_loader = Loader::GetFileLoader(filename);
+    if (!app_loader) {
+        LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filename.c_str());
+        QMessageBox::critical(this, tr("Error while loading ROM!"),
+                              tr("The ROM format is not supported."));
+        return false;
+    }
+
+    Loader::ResultStatus result = app_loader->Load();
     if (Loader::ResultStatus::Success != result) {
         LOG_CRITICAL(Frontend, "Failed to load ROM!");
         System::Shutdown();

+ 3 - 0
src/core/loader/3dsx.cpp

@@ -10,6 +10,7 @@
 #include "core/file_sys/archive_romfs.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/resource_limit.h"
+#include "core/hle/service/fs/archive.h"
 #include "core/loader/3dsx.h"
 #include "core/memory.h"
 
@@ -263,6 +264,8 @@ ResultStatus AppLoader_THREEDSX::Load() {
 
     Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE);
 
+    Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this), Service::FS::ArchiveIdCode::RomFS);
+
     is_loaded = true;
     return ResultStatus::Success;
 }

+ 7 - 43
src/core/loader/loader.cpp

@@ -8,9 +8,7 @@
 #include "common/logging/log.h"
 #include "common/string_util.h"
 
-#include "core/file_sys/archive_romfs.h"
 #include "core/hle/kernel/process.h"
-#include "core/hle/service/fs/archive.h"
 #include "core/loader/3dsx.h"
 #include "core/loader/elf.h"
 #include "core/loader/ncch.h"
@@ -67,6 +65,9 @@ FileType GuessFromExtension(const std::string& extension_) {
     if (extension == ".3dsx")
         return FileType::THREEDSX;
 
+    if (extension == ".cia")
+        return FileType::CIA;
+
     return FileType::Unknown;
 }
 
@@ -108,15 +109,15 @@ std::unique_ptr<AppLoader> GetLoader(FileUtil::IOFile&& file, FileType type,
         return std::make_unique<AppLoader_NCCH>(std::move(file), filepath);
 
     default:
-        return std::unique_ptr<AppLoader>();
+        return nullptr;
     }
 }
 
-ResultStatus LoadFile(const std::string& filename) {
+std::unique_ptr<AppLoader> GetFileLoader(const std::string& filename) {
     FileUtil::IOFile file(filename, "rb");
     if (!file.IsOpen()) {
         LOG_ERROR(Loader, "Failed to load file %s", filename.c_str());
-        return ResultStatus::Error;
+        return nullptr;
     }
 
     std::string filename_filename, filename_extension;
@@ -133,44 +134,7 @@ ResultStatus LoadFile(const std::string& filename) {
 
     LOG_INFO(Loader, "Loading file %s as %s...", filename.c_str(), GetFileTypeString(type));
 
-    std::unique_ptr<AppLoader> app_loader = GetLoader(std::move(file), type, filename_filename, filename);
-
-    switch (type) {
-
-    // 3DSX file format...
-    // or NCCH/NCSD container formats...
-    case FileType::THREEDSX:
-    case FileType::CXI:
-    case FileType::CCI:
-    {
-        // Load application and RomFS
-        ResultStatus result = app_loader->Load();
-        if (ResultStatus::Success == result) {
-            Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*app_loader), Service::FS::ArchiveIdCode::RomFS);
-            return ResultStatus::Success;
-        }
-        return result;
-    }
-
-    // Standard ELF file format...
-    case FileType::ELF:
-        return app_loader->Load();
-
-    // CIA file format...
-    case FileType::CIA:
-        return ResultStatus::ErrorNotImplemented;
-
-    // Error occurred durring IdentifyFile...
-    case FileType::Error:
-
-    // IdentifyFile could know identify file type...
-    case FileType::Unknown:
-    {
-        LOG_CRITICAL(Loader, "File %s is of unknown type.", filename.c_str());
-        return ResultStatus::ErrorInvalidFormat;
-    }
-    }
-    return ResultStatus::Error;
+    return GetLoader(std::move(file), type, filename_filename, filename);
 }
 
 } // namespace Loader

+ 3 - 3
src/core/loader/loader.h

@@ -207,10 +207,10 @@ extern const std::initializer_list<Kernel::AddressMapping> default_address_mappi
 std::unique_ptr<AppLoader> GetLoader(FileUtil::IOFile&& file, FileType type, const std::string& filename, const std::string& filepath);
 
 /**
- * Identifies and loads a bootable file
+ * Identifies a bootable file and return a suitable loader
  * @param filename String filename of bootable file
- * @return ResultStatus result of function
+ * @return best loader for this file
  */
-ResultStatus LoadFile(const std::string& filename);
+std::unique_ptr<AppLoader> GetFileLoader(const std::string& filename);
 
 } // namespace

+ 8 - 1
src/core/loader/ncch.cpp

@@ -10,8 +10,10 @@
 #include "common/string_util.h"
 #include "common/swap.h"
 
+#include "core/file_sys/archive_romfs.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/resource_limit.h"
+#include "core/hle/service/fs/archive.h"
 #include "core/loader/ncch.h"
 #include "core/memory.h"
 
@@ -303,7 +305,12 @@ ResultStatus AppLoader_NCCH::Load() {
 
     is_loaded = true; // Set state to loaded
 
-    return LoadExec(); // Load the executable into memory for booting
+    result = LoadExec(); // Load the executable into memory for booting
+    if (ResultStatus::Success != result)
+        return result;
+
+    Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this), Service::FS::ArchiveIdCode::RomFS);
+    return ResultStatus::Success;
 }
 
 ResultStatus AppLoader_NCCH::ReadCode(std::vector<u8>& buffer) {