| | |
| | |
| | |
| |
|
| | #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); |
| | } |
| |
|
| | } |
| |
|