From 8fc9c0312660aa8b74a1251f02dfedc84da5b96b Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 17 May 2016 23:06:33 +0100 Subject: [PATCH] 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. --- src/citra/citra.cpp | 8 +++++- src/citra_qt/main.cpp | 10 +++++++- src/core/loader/3dsx.cpp | 3 +++ src/core/loader/loader.cpp | 50 ++++++-------------------------------- src/core/loader/loader.h | 6 ++--- src/core/loader/ncch.cpp | 9 ++++++- 6 files changed, 37 insertions(+), 49 deletions(-) diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp index b4501eb2e..aa3bf94ca 100644 --- a/src/citra/citra.cpp +++ b/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 = 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; diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index a85c94a4b..9d47014aa 100644 --- a/src/citra_qt/main.cpp +++ b/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 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(); diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index 98e7ab48f..a16411e14 100644 --- a/src/core/loader/3dsx.cpp +++ b/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(*this), Service::FS::ArchiveIdCode::RomFS); + is_loaded = true; return ResultStatus::Success; } diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index af3f62248..c82688026 100644 --- a/src/core/loader/loader.cpp +++ b/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 GetLoader(FileUtil::IOFile&& file, FileType type, return std::make_unique(std::move(file), filepath); default: - return std::unique_ptr(); + return nullptr; } } -ResultStatus LoadFile(const std::string& filename) { +std::unique_ptr 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 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(*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 diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 9d3e9ed3b..4a4bd7c77 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -207,10 +207,10 @@ extern const std::initializer_list default_address_mappi std::unique_ptr 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 GetFileLoader(const std::string& filename); } // namespace diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 7391bdb26..fca091ff9 100644 --- a/src/core/loader/ncch.cpp +++ b/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(*this), Service::FS::ArchiveIdCode::RomFS); + return ResultStatus::Success; } ResultStatus AppLoader_NCCH::ReadCode(std::vector& buffer) {