| |
| |
| |
|
|
| #include <memory> |
| #include <string> |
| #include "common/logging/log.h" |
| #include "common/string_util.h" |
| #include "core/core.h" |
| #include "core/hle/kernel/process.h" |
| #include "core/loader/3dsx.h" |
| #include "core/loader/elf.h" |
| #include "core/loader/ncch.h" |
|
|
| namespace Loader { |
|
|
| FileType IdentifyFile(FileUtil::IOFile& file) { |
| FileType type; |
|
|
| #define CHECK_TYPE(loader) \ |
| type = AppLoader_##loader::IdentifyType(file); \ |
| if (FileType::Error != type) \ |
| return type; |
|
|
| CHECK_TYPE(THREEDSX) |
| CHECK_TYPE(ELF) |
| CHECK_TYPE(NCCH) |
|
|
| #undef CHECK_TYPE |
|
|
| return FileType::Unknown; |
| } |
|
|
| FileType IdentifyFile(const std::string& file_name) { |
| FileUtil::IOFile file(file_name, "rb"); |
| if (!file.IsOpen()) { |
| LOG_ERROR(Loader, "Failed to load file {}", file_name); |
| return FileType::Unknown; |
| } |
|
|
| return IdentifyFile(file); |
| } |
|
|
| FileType GuessFromExtension(const std::string& extension_) { |
| std::string extension = Common::ToLower(extension_); |
|
|
| if (extension == ".elf" || extension == ".axf") |
| return FileType::ELF; |
|
|
| if (extension == ".cci" || extension == ".3ds") |
| return FileType::CCI; |
|
|
| if (extension == ".cxi" || extension == ".app") |
| return FileType::CXI; |
|
|
| if (extension == ".3dsx") |
| return FileType::THREEDSX; |
|
|
| if (extension == ".cia") |
| return FileType::CIA; |
|
|
| return FileType::Unknown; |
| } |
|
|
| const char* GetFileTypeString(FileType type) { |
| switch (type) { |
| case FileType::CCI: |
| return "NCSD"; |
| case FileType::CXI: |
| return "NCCH"; |
| case FileType::CIA: |
| return "CIA"; |
| case FileType::ELF: |
| return "ELF"; |
| case FileType::THREEDSX: |
| return "3DSX"; |
| case FileType::Error: |
| case FileType::Unknown: |
| break; |
| } |
|
|
| return "unknown"; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileUtil::IOFile&& file, |
| FileType type, const std::string& filename, |
| const std::string& filepath) { |
| switch (type) { |
|
|
| |
| case FileType::THREEDSX: |
| return std::make_unique<AppLoader_THREEDSX>(system, std::move(file), filename, filepath); |
|
|
| |
| case FileType::ELF: |
| return std::make_unique<AppLoader_ELF>(system, std::move(file), filename); |
|
|
| |
| case FileType::CXI: |
| case FileType::CCI: |
| return std::make_unique<AppLoader_NCCH>(system, std::move(file), filepath); |
|
|
| default: |
| return nullptr; |
| } |
| } |
|
|
| std::unique_ptr<AppLoader> GetLoader(const std::string& filename) { |
| FileUtil::IOFile file(filename, "rb"); |
| if (!file.IsOpen()) { |
| LOG_ERROR(Loader, "Failed to load file {}", filename); |
| return nullptr; |
| } |
|
|
| std::string filename_filename, filename_extension; |
| Common::SplitPath(filename, nullptr, &filename_filename, &filename_extension); |
|
|
| FileType type = IdentifyFile(file); |
| FileType filename_type = GuessFromExtension(filename_extension); |
|
|
| if (type != filename_type) { |
| LOG_WARNING(Loader, "File {} has a different type than its extension.", filename); |
| if (FileType::Unknown == type) |
| type = filename_type; |
| } |
|
|
| LOG_DEBUG(Loader, "Loading file {} as {}...", filename, GetFileTypeString(type)); |
|
|
| auto& system = Core::System::GetInstance(); |
| return GetFileLoader(system, std::move(file), type, filename_filename, filename); |
| } |
|
|
| } |
|
|