File size: 4,154 Bytes
034d0a2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | // Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#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";
}
/**
* Get a loader for a file with a specific type
* @param file The file to load
* @param type The type of the file
* @param filename the file name (without path)
* @param filepath the file full path (with name)
* @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type
*/
static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileUtil::IOFile&& file,
FileType type, const std::string& filename,
const std::string& filepath) {
switch (type) {
// 3DSX file format.
case FileType::THREEDSX:
return std::make_unique<AppLoader_THREEDSX>(system, std::move(file), filename, filepath);
// Standard ELF file format.
case FileType::ELF:
return std::make_unique<AppLoader_ELF>(system, std::move(file), filename);
// NCCH/NCSD container formats.
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);
}
} // namespace Loader
|