summaryrefslogtreecommitdiffstats
path: root/src/core/loader
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/loader')
-rw-r--r--src/core/loader/3dsx.cpp350
-rw-r--r--src/core/loader/3dsx.h46
-rw-r--r--src/core/loader/loader.cpp31
-rw-r--r--src/core/loader/loader.h4
-rw-r--r--src/core/loader/ncch.cpp263
-rw-r--r--src/core/loader/ncch.h80
6 files changed, 0 insertions, 774 deletions
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
deleted file mode 100644
index 7b0342cc9..000000000
--- a/src/core/loader/3dsx.cpp
+++ /dev/null
@@ -1,350 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include <vector>
-#include "common/logging/log.h"
-#include "core/file_sys/archive_selfncch.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"
-
-namespace Loader {
-
-/*
- * File layout:
- * - File header
- * - Code, rodata and data relocation table headers
- * - Code segment
- * - Rodata segment
- * - Loadable (non-BSS) part of the data segment
- * - Code relocation table
- * - Rodata relocation table
- * - Data relocation table
- *
- * Memory layout before relocations are applied:
- * [0..codeSegSize) -> code segment
- * [codeSegSize..rodataSegSize) -> rodata segment
- * [rodataSegSize..dataSegSize) -> data segment
- *
- * Memory layout after relocations are applied: well, however the loader sets it up :)
- * The entrypoint is always the start of the code segment.
- * The BSS section must be cleared manually by the application.
- */
-
-enum THREEDSX_Error { ERROR_NONE = 0, ERROR_READ = 1, ERROR_FILE = 2, ERROR_ALLOC = 3 };
-
-static const u32 RELOCBUFSIZE = 512;
-static const unsigned int NUM_SEGMENTS = 3;
-
-// File header
-#pragma pack(1)
-struct THREEDSX_Header {
- u32 magic;
- u16 header_size, reloc_hdr_size;
- u32 format_ver;
- u32 flags;
-
- // Sizes of the code, rodata and data segments +
- // size of the BSS section (uninitialized latter half of the data segment)
- u32 code_seg_size, rodata_seg_size, data_seg_size, bss_size;
- // offset and size of smdh
- u32 smdh_offset, smdh_size;
- // offset to filesystem
- u32 fs_offset;
-};
-
-// Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts.
-struct THREEDSX_RelocHdr {
- // # of absolute relocations (that is, fix address to post-relocation memory layout)
- u32 cross_segment_absolute;
- // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be
- // patched)
- u32 cross_segment_relative;
- // more?
-
- // Relocations are written in this order:
- // - Absolute relocations
- // - Relative relocations
-};
-
-// Relocation entry: from the current pointer, skip X words and patch Y words
-struct THREEDSX_Reloc {
- u16 skip, patch;
-};
-#pragma pack()
-
-struct THREEloadinfo {
- u8* seg_ptrs[3]; // code, rodata & data
- u32 seg_addrs[3];
- u32 seg_sizes[3];
-};
-
-static u32 TranslateAddr(u32 addr, const THREEloadinfo* loadinfo, u32* offsets) {
- if (addr < offsets[0])
- return loadinfo->seg_addrs[0] + addr;
- if (addr < offsets[1])
- return loadinfo->seg_addrs[1] + addr - offsets[0];
- return loadinfo->seg_addrs[2] + addr - offsets[1];
-}
-
-using Kernel::CodeSet;
-using Kernel::SharedPtr;
-
-static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr,
- SharedPtr<CodeSet>* out_codeset) {
- if (!file.IsOpen())
- return ERROR_FILE;
-
- // Reset read pointer in case this file has been read before.
- file.Seek(0, SEEK_SET);
-
- THREEDSX_Header hdr;
- if (file.ReadBytes(&hdr, sizeof(hdr)) != sizeof(hdr))
- return ERROR_READ;
-
- THREEloadinfo loadinfo;
- // loadinfo segments must be a multiple of 0x1000
- loadinfo.seg_sizes[0] = (hdr.code_seg_size + 0xFFF) & ~0xFFF;
- loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) & ~0xFFF;
- loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) & ~0xFFF;
- u32 offsets[2] = {loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1]};
- u32 n_reloc_tables = hdr.reloc_hdr_size / sizeof(u32);
- std::vector<u8> program_image(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] +
- loadinfo.seg_sizes[2]);
-
- loadinfo.seg_addrs[0] = base_addr;
- loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0];
- loadinfo.seg_addrs[2] = loadinfo.seg_addrs[1] + loadinfo.seg_sizes[1];
- loadinfo.seg_ptrs[0] = program_image.data();
- loadinfo.seg_ptrs[1] = loadinfo.seg_ptrs[0] + loadinfo.seg_sizes[0];
- loadinfo.seg_ptrs[2] = loadinfo.seg_ptrs[1] + loadinfo.seg_sizes[1];
-
- // Skip header for future compatibility
- file.Seek(hdr.header_size, SEEK_SET);
-
- // Read the relocation headers
- std::vector<u32> relocs(n_reloc_tables * NUM_SEGMENTS);
- for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) {
- size_t size = n_reloc_tables * sizeof(u32);
- if (file.ReadBytes(&relocs[current_segment * n_reloc_tables], size) != size)
- return ERROR_READ;
- }
-
- // Read the segments
- if (file.ReadBytes(loadinfo.seg_ptrs[0], hdr.code_seg_size) != hdr.code_seg_size)
- return ERROR_READ;
- if (file.ReadBytes(loadinfo.seg_ptrs[1], hdr.rodata_seg_size) != hdr.rodata_seg_size)
- return ERROR_READ;
- if (file.ReadBytes(loadinfo.seg_ptrs[2], hdr.data_seg_size - hdr.bss_size) !=
- hdr.data_seg_size - hdr.bss_size)
- return ERROR_READ;
-
- // BSS clear
- memset((char*)loadinfo.seg_ptrs[2] + hdr.data_seg_size - hdr.bss_size, 0, hdr.bss_size);
-
- // Relocate the segments
- for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) {
- for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables;
- current_segment_reloc_table++) {
- u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table];
- if (current_segment_reloc_table >= 2) {
- // We are not using this table - ignore it because we don't know what it dose
- file.Seek(n_relocs * sizeof(THREEDSX_Reloc), SEEK_CUR);
- continue;
- }
- THREEDSX_Reloc reloc_table[RELOCBUFSIZE];
-
- u32* pos = (u32*)loadinfo.seg_ptrs[current_segment];
- const u32* end_pos = pos + (loadinfo.seg_sizes[current_segment] / 4);
-
- while (n_relocs) {
- u32 remaining = std::min(RELOCBUFSIZE, n_relocs);
- n_relocs -= remaining;
-
- if (file.ReadBytes(reloc_table, remaining * sizeof(THREEDSX_Reloc)) !=
- remaining * sizeof(THREEDSX_Reloc))
- return ERROR_READ;
-
- for (unsigned current_inprogress = 0;
- current_inprogress < remaining && pos < end_pos; current_inprogress++) {
- const auto& table = reloc_table[current_inprogress];
- LOG_TRACE(Loader, "(t=%d,skip=%u,patch=%u)", current_segment_reloc_table,
- static_cast<u32>(table.skip), static_cast<u32>(table.patch));
- pos += table.skip;
- s32 num_patches = table.patch;
- while (0 < num_patches && pos < end_pos) {
- u32 in_addr = base_addr + static_cast<u32>(reinterpret_cast<u8*>(pos) -
- program_image.data());
- u32 orig_data = *pos;
- u32 sub_type = orig_data >> (32 - 4);
- u32 addr = TranslateAddr(orig_data & ~0xF0000000, &loadinfo, offsets);
- LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)", in_addr, addr,
- current_segment_reloc_table, *pos);
- switch (current_segment_reloc_table) {
- case 0: {
- if (sub_type != 0)
- return ERROR_READ;
- *pos = addr;
- break;
- }
- case 1: {
- u32 data = addr - in_addr;
- switch (sub_type) {
- case 0: // 32-bit signed offset
- *pos = data;
- break;
- case 1: // 31-bit signed offset
- *pos = data & ~(1U << 31);
- break;
- default:
- return ERROR_READ;
- }
- break;
- }
- default:
- break; // this should never happen
- }
- pos++;
- num_patches--;
- }
- }
- }
- }
- }
-
- // Create the CodeSet
- SharedPtr<CodeSet> code_set = CodeSet::Create("", 0);
-
- code_set->code.offset = loadinfo.seg_ptrs[0] - program_image.data();
- code_set->code.addr = loadinfo.seg_addrs[0];
- code_set->code.size = loadinfo.seg_sizes[0];
-
- code_set->rodata.offset = loadinfo.seg_ptrs[1] - program_image.data();
- code_set->rodata.addr = loadinfo.seg_addrs[1];
- code_set->rodata.size = loadinfo.seg_sizes[1];
-
- code_set->data.offset = loadinfo.seg_ptrs[2] - program_image.data();
- code_set->data.addr = loadinfo.seg_addrs[2];
- code_set->data.size = loadinfo.seg_sizes[2];
-
- code_set->entrypoint = code_set->code.addr;
- code_set->memory = std::make_shared<std::vector<u8>>(std::move(program_image));
-
- LOG_DEBUG(Loader, "code size: 0x%X", loadinfo.seg_sizes[0]);
- LOG_DEBUG(Loader, "rodata size: 0x%X", loadinfo.seg_sizes[1]);
- LOG_DEBUG(Loader, "data size: 0x%X (including 0x%X of bss)", loadinfo.seg_sizes[2],
- hdr.bss_size);
-
- *out_codeset = code_set;
- return ERROR_NONE;
-}
-
-FileType AppLoader_THREEDSX::IdentifyType(FileUtil::IOFile& file) {
- u32 magic;
- file.Seek(0, SEEK_SET);
- if (1 != file.ReadArray<u32>(&magic, 1))
- return FileType::Error;
-
- if (MakeMagic('3', 'D', 'S', 'X') == magic)
- return FileType::THREEDSX;
-
- return FileType::Error;
-}
-
-ResultStatus AppLoader_THREEDSX::Load(Kernel::SharedPtr<Kernel::Process>& process) {
- if (is_loaded)
- return ResultStatus::ErrorAlreadyLoaded;
-
- if (!file.IsOpen())
- return ResultStatus::Error;
-
- SharedPtr<CodeSet> codeset;
- if (Load3DSXFile(file, Memory::PROCESS_IMAGE_VADDR, &codeset) != ERROR_NONE)
- return ResultStatus::Error;
- codeset->name = filename;
-
- process = Kernel::Process::Create("main");
- process->LoadModule(codeset, codeset->entrypoint);
- process->svc_access_mask.set();
- process->address_mappings = default_address_mappings;
-
- // Attach the default resource limit (APPLICATION) to the process
- process->resource_limit =
- Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
- process->Run(codeset->entrypoint, 48, Kernel::DEFAULT_STACK_SIZE);
-
- Service::FS::RegisterSelfNCCH(*this);
-
- is_loaded = true;
- return ResultStatus::Success;
-}
-
-ResultStatus AppLoader_THREEDSX::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file,
- u64& offset, u64& size) {
- if (!file.IsOpen())
- return ResultStatus::Error;
-
- // Reset read pointer in case this file has been read before.
- file.Seek(0, SEEK_SET);
-
- THREEDSX_Header hdr;
- if (file.ReadBytes(&hdr, sizeof(THREEDSX_Header)) != sizeof(THREEDSX_Header))
- return ResultStatus::Error;
-
- if (hdr.header_size != sizeof(THREEDSX_Header))
- return ResultStatus::Error;
-
- // Check if the 3DSX has a RomFS...
- if (hdr.fs_offset != 0) {
- u32 romfs_offset = hdr.fs_offset;
- u32 romfs_size = static_cast<u32>(file.GetSize()) - hdr.fs_offset;
-
- LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset);
- LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size);
-
- // We reopen the file, to allow its position to be independent from file's
- romfs_file = std::make_shared<FileUtil::IOFile>(filepath, "rb");
- if (!romfs_file->IsOpen())
- return ResultStatus::Error;
-
- offset = romfs_offset;
- size = romfs_size;
-
- return ResultStatus::Success;
- }
- LOG_DEBUG(Loader, "3DSX has no RomFS");
- return ResultStatus::ErrorNotUsed;
-}
-
-ResultStatus AppLoader_THREEDSX::ReadIcon(std::vector<u8>& buffer) {
- if (!file.IsOpen())
- return ResultStatus::Error;
-
- // Reset read pointer in case this file has been read before.
- file.Seek(0, SEEK_SET);
-
- THREEDSX_Header hdr;
- if (file.ReadBytes(&hdr, sizeof(THREEDSX_Header)) != sizeof(THREEDSX_Header))
- return ResultStatus::Error;
-
- if (hdr.header_size != sizeof(THREEDSX_Header))
- return ResultStatus::Error;
-
- // Check if the 3DSX has a SMDH...
- if (hdr.smdh_offset != 0) {
- file.Seek(hdr.smdh_offset, SEEK_SET);
- buffer.resize(hdr.smdh_size);
-
- if (file.ReadBytes(&buffer[0], hdr.smdh_size) != hdr.smdh_size)
- return ResultStatus::Error;
-
- return ResultStatus::Success;
- }
- return ResultStatus::ErrorNotUsed;
-}
-
-} // namespace Loader
diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h
deleted file mode 100644
index 1e59bbb9d..000000000
--- a/src/core/loader/3dsx.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 Dolphin Emulator Project / Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <string>
-#include "common/common_types.h"
-#include "core/loader/loader.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Loader namespace
-
-namespace Loader {
-
-/// Loads an 3DSX file
-class AppLoader_THREEDSX final : public AppLoader {
-public:
- AppLoader_THREEDSX(FileUtil::IOFile&& file, const std::string& filename,
- const std::string& filepath)
- : AppLoader(std::move(file)), filename(std::move(filename)), filepath(filepath) {}
-
- /**
- * Returns the type of the file
- * @param file FileUtil::IOFile open file
- * @return FileType found, or FileType::Error if this loader doesn't know it
- */
- static FileType IdentifyType(FileUtil::IOFile& file);
-
- FileType GetFileType() override {
- return IdentifyType(file);
- }
-
- ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
-
- ResultStatus ReadIcon(std::vector<u8>& buffer) override;
-
- ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
- u64& size) override;
-
-private:
- std::string filename;
- std::string filepath;
-};
-
-} // namespace Loader
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 73318c584..46b2c28d2 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -31,9 +31,7 @@ FileType IdentifyFile(FileUtil::IOFile& file) {
if (FileType::Error != type) \
return type;
- CHECK_TYPE(THREEDSX)
CHECK_TYPE(ELF)
- CHECK_TYPE(NCCH)
CHECK_TYPE(NSO)
CHECK_TYPE(NRO)
@@ -58,33 +56,13 @@ FileType GuessFromExtension(const std::string& extension_) {
if (extension == ".elf" || extension == ".axf")
return FileType::ELF;
- if (extension == ".cci" || extension == ".3ds")
- return FileType::CCI;
-
- if (extension == ".cxi")
- 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;
@@ -106,19 +84,10 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileUtil::IOFile&& file, FileTyp
const std::string& filepath) {
switch (type) {
- // 3DSX file format.
- case FileType::THREEDSX:
- return std::make_unique<AppLoader_THREEDSX>(std::move(file), filename, filepath);
-
// Standard ELF file format.
case FileType::ELF:
return std::make_unique<AppLoader_ELF>(std::move(file), filename);
- // NCCH/NCSD container formats.
- case FileType::CXI:
- case FileType::CCI:
- return std::make_unique<AppLoader_NCCH>(std::move(file), filepath);
-
// NX NSO file format.
case FileType::NSO:
return std::make_unique<AppLoader_NSO>(std::move(file), filepath);
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 311785d05..ac4e7acc2 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -29,11 +29,7 @@ namespace Loader {
enum class FileType {
Error,
Unknown,
- CCI,
- CXI,
- CIA,
ELF,
- THREEDSX, // 3DSX
NSO,
NRO,
};
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
deleted file mode 100644
index e33a37b2e..000000000
--- a/src/core/loader/ncch.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include <cinttypes>
-#include <codecvt>
-#include <cstring>
-#include <locale>
-#include <memory>
-#include "common/logging/log.h"
-#include "common/string_util.h"
-#include "common/swap.h"
-#include "core/core.h"
-#include "core/file_sys/archive_selfncch.h"
-#include "core/file_sys/ncch_container.h"
-#include "core/file_sys/title_metadata.h"
-#include "core/hle/kernel/process.h"
-#include "core/hle/kernel/resource_limit.h"
-#include "core/hle/service/cfg/cfg.h"
-#include "core/hle/service/fs/archive.h"
-#include "core/loader/ncch.h"
-#include "core/loader/smdh.h"
-#include "core/memory.h"
-#include "network/network.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Loader namespace
-
-namespace Loader {
-
-static const u64 UPDATE_MASK = 0x0000000e00000000;
-
-FileType AppLoader_NCCH::IdentifyType(FileUtil::IOFile& file) {
- u32 magic;
- file.Seek(0x100, SEEK_SET);
- if (1 != file.ReadArray<u32>(&magic, 1))
- return FileType::Error;
-
- if (MakeMagic('N', 'C', 'S', 'D') == magic)
- return FileType::CCI;
-
- if (MakeMagic('N', 'C', 'C', 'H') == magic)
- return FileType::CXI;
-
- return FileType::Error;
-}
-
-static std::string GetUpdateNCCHPath(u64_le program_id) {
- u32 high = static_cast<u32>((program_id | UPDATE_MASK) >> 32);
- u32 low = static_cast<u32>((program_id | UPDATE_MASK) & 0xFFFFFFFF);
-
- // TODO(shinyquagsire23): Title database should be doing this path lookup
- std::string content_path = Common::StringFromFormat(
- "%sNintendo 3DS/%s/%s/title/%08x/%08x/content/", FileUtil::GetUserPath(D_SDMC_IDX).c_str(),
- SYSTEM_ID, SDCARD_ID, high, low);
- std::string tmd_path = content_path + "00000000.tmd";
-
- u32 content_id = 0;
- FileSys::TitleMetadata tmd(tmd_path);
- if (tmd.Load() == ResultStatus::Success) {
- content_id = tmd.GetBootContentID();
- }
-
- return Common::StringFromFormat("%s%08x.app", content_path.c_str(), content_id);
-}
-
-std::pair<boost::optional<u32>, ResultStatus> AppLoader_NCCH::LoadKernelSystemMode() {
- if (!is_loaded) {
- ResultStatus res = base_ncch.Load();
- if (res != ResultStatus::Success) {
- return std::make_pair(boost::none, res);
- }
- }
-
- // Set the system mode as the one from the exheader.
- return std::make_pair(overlay_ncch->exheader_header.arm11_system_local_caps.system_mode.Value(),
- ResultStatus::Success);
-}
-
-ResultStatus AppLoader_NCCH::LoadExec(Kernel::SharedPtr<Kernel::Process>& process) {
- using Kernel::CodeSet;
- using Kernel::SharedPtr;
-
- if (!is_loaded)
- return ResultStatus::ErrorNotLoaded;
-
- std::vector<u8> code;
- u64_le program_id;
- if (ResultStatus::Success == ReadCode(code) &&
- ResultStatus::Success == ReadProgramId(program_id)) {
- std::string process_name = Common::StringFromFixedZeroTerminatedBuffer(
- (const char*)overlay_ncch->exheader_header.codeset_info.name, 8);
-
- SharedPtr<CodeSet> codeset = CodeSet::Create(process_name, program_id);
-
- codeset->code.offset = 0;
- codeset->code.addr = overlay_ncch->exheader_header.codeset_info.text.address;
- codeset->code.size =
- overlay_ncch->exheader_header.codeset_info.text.num_max_pages * Memory::PAGE_SIZE;
-
- codeset->rodata.offset = codeset->code.offset + codeset->code.size;
- codeset->rodata.addr = overlay_ncch->exheader_header.codeset_info.ro.address;
- codeset->rodata.size =
- overlay_ncch->exheader_header.codeset_info.ro.num_max_pages * Memory::PAGE_SIZE;
-
- // TODO(yuriks): Not sure if the bss size is added to the page-aligned .data size or just
- // to the regular size. Playing it safe for now.
- u32 bss_page_size = (overlay_ncch->exheader_header.codeset_info.bss_size + 0xFFF) & ~0xFFF;
- code.resize(code.size() + bss_page_size, 0);
-
- codeset->data.offset = codeset->rodata.offset + codeset->rodata.size;
- codeset->data.addr = overlay_ncch->exheader_header.codeset_info.data.address;
- codeset->data.size =
- overlay_ncch->exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE +
- bss_page_size;
-
- codeset->entrypoint = codeset->code.addr;
- codeset->memory = std::make_shared<std::vector<u8>>(std::move(code));
-
- process = Kernel::Process::Create("main");
- process->LoadModule(codeset, codeset->entrypoint);
-
- // Attach a resource limit to the process based on the resource limit category
- process->resource_limit =
- Kernel::ResourceLimit::GetForCategory(static_cast<Kernel::ResourceLimitCategory>(
- overlay_ncch->exheader_header.arm11_system_local_caps.resource_limit_category));
-
- // Set the default CPU core for this process
- process->ideal_processor =
- overlay_ncch->exheader_header.arm11_system_local_caps.ideal_processor;
-
- // Copy data while converting endianness
- std::array<u32, ARRAY_SIZE(overlay_ncch->exheader_header.arm11_kernel_caps.descriptors)>
- kernel_caps;
- std::copy_n(overlay_ncch->exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(),
- begin(kernel_caps));
- process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size());
-
- s32 priority = overlay_ncch->exheader_header.arm11_system_local_caps.priority;
- u32 stack_size = overlay_ncch->exheader_header.codeset_info.stack_size;
- process->Run(codeset->entrypoint, priority, stack_size);
- return ResultStatus::Success;
- }
- return ResultStatus::Error;
-}
-
-void AppLoader_NCCH::ParseRegionLockoutInfo() {
- std::vector<u8> smdh_buffer;
- if (ReadIcon(smdh_buffer) == ResultStatus::Success && smdh_buffer.size() >= sizeof(SMDH)) {
- SMDH smdh;
- memcpy(&smdh, smdh_buffer.data(), sizeof(SMDH));
- u32 region_lockout = smdh.region_lockout;
- constexpr u32 REGION_COUNT = 7;
- for (u32 region = 0; region < REGION_COUNT; ++region) {
- if (region_lockout & 1) {
- Service::CFG::SetPreferredRegionCode(region);
- break;
- }
- region_lockout >>= 1;
- }
- }
-}
-
-ResultStatus AppLoader_NCCH::Load(Kernel::SharedPtr<Kernel::Process>& process) {
- u64_le ncch_program_id;
-
- if (is_loaded)
- return ResultStatus::ErrorAlreadyLoaded;
-
- ResultStatus result = base_ncch.Load();
- if (result != ResultStatus::Success)
- return result;
-
- ReadProgramId(ncch_program_id);
- std::string program_id{Common::StringFromFormat("%016" PRIX64, ncch_program_id)};
-
- LOG_INFO(Loader, "Program ID: %s", program_id.c_str());
-
- update_ncch.OpenFile(GetUpdateNCCHPath(ncch_program_id));
- result = update_ncch.Load();
- if (result == ResultStatus::Success) {
- overlay_ncch = &update_ncch;
- }
-
- Core::Telemetry().AddField(Telemetry::FieldType::Session, "ProgramId", program_id);
-
- if (auto room_member = Network::GetRoomMember().lock()) {
- Network::GameInfo game_info;
- ReadTitle(game_info.name);
- game_info.id = ncch_program_id;
- room_member->SendGameInfo(game_info);
- }
-
- is_loaded = true; // Set state to loaded
-
- result = LoadExec(process); // Load the executable into memory for booting
- if (ResultStatus::Success != result)
- return result;
-
- Service::FS::RegisterSelfNCCH(*this);
-
- ParseRegionLockoutInfo();
-
- return ResultStatus::Success;
-}
-
-ResultStatus AppLoader_NCCH::ReadCode(std::vector<u8>& buffer) {
- return overlay_ncch->LoadSectionExeFS(".code", buffer);
-}
-
-ResultStatus AppLoader_NCCH::ReadIcon(std::vector<u8>& buffer) {
- return overlay_ncch->LoadSectionExeFS("icon", buffer);
-}
-
-ResultStatus AppLoader_NCCH::ReadBanner(std::vector<u8>& buffer) {
- return overlay_ncch->LoadSectionExeFS("banner", buffer);
-}
-
-ResultStatus AppLoader_NCCH::ReadLogo(std::vector<u8>& buffer) {
- return overlay_ncch->LoadSectionExeFS("logo", buffer);
-}
-
-ResultStatus AppLoader_NCCH::ReadProgramId(u64& out_program_id) {
- ResultStatus result = base_ncch.ReadProgramId(out_program_id);
- if (result != ResultStatus::Success)
- return result;
-
- return ResultStatus::Success;
-}
-
-ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
- u64& size) {
- return base_ncch.ReadRomFS(romfs_file, offset, size);
-}
-
-ResultStatus AppLoader_NCCH::ReadUpdateRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file,
- u64& offset, u64& size) {
- ResultStatus result = update_ncch.ReadRomFS(romfs_file, offset, size);
-
- if (result != ResultStatus::Success)
- return base_ncch.ReadRomFS(romfs_file, offset, size);
-}
-
-ResultStatus AppLoader_NCCH::ReadTitle(std::string& title) {
- std::vector<u8> data;
- Loader::SMDH smdh;
- ReadIcon(data);
-
- if (!Loader::IsValidSMDH(data)) {
- return ResultStatus::ErrorInvalidFormat;
- }
-
- memcpy(&smdh, data.data(), sizeof(Loader::SMDH));
-
- const auto& short_title = smdh.GetShortTitle(SMDH::TitleLanguage::English);
- auto title_end = std::find(short_title.begin(), short_title.end(), u'\0');
- title = Common::UTF16ToUTF8(std::u16string{short_title.begin(), title_end});
-
- return ResultStatus::Success;
-}
-
-} // namespace Loader
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h
deleted file mode 100644
index 09230ae33..000000000
--- a/src/core/loader/ncch.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <memory>
-#include "common/common_types.h"
-#include "common/swap.h"
-#include "core/file_sys/ncch_container.h"
-#include "core/loader/loader.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Loader namespace
-
-namespace Loader {
-
-/// Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI)
-class AppLoader_NCCH final : public AppLoader {
-public:
- AppLoader_NCCH(FileUtil::IOFile&& file, const std::string& filepath)
- : AppLoader(std::move(file)), filepath(filepath), base_ncch(filepath),
- overlay_ncch(&base_ncch) {}
-
- /**
- * Returns the type of the file
- * @param file FileUtil::IOFile open file
- * @return FileType found, or FileType::Error if this loader doesn't know it
- */
- static FileType IdentifyType(FileUtil::IOFile& file);
-
- FileType GetFileType() override {
- return IdentifyType(file);
- }
-
- ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
-
- /**
- * Loads the Exheader and returns the system mode for this application.
- * @returns A pair with the optional system mode, and and the status.
- */
- std::pair<boost::optional<u32>, ResultStatus> LoadKernelSystemMode() override;
-
- ResultStatus ReadCode(std::vector<u8>& buffer) override;
-
- ResultStatus ReadIcon(std::vector<u8>& buffer) override;
-
- ResultStatus ReadBanner(std::vector<u8>& buffer) override;
-
- ResultStatus ReadLogo(std::vector<u8>& buffer) override;
-
- ResultStatus ReadProgramId(u64& out_program_id) override;
-
- ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
- u64& size) override;
-
- ResultStatus ReadUpdateRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
- u64& size) override;
-
- ResultStatus ReadTitle(std::string& title) override;
-
-private:
- /**
- * Loads .code section into memory for booting
- * @param process The newly created process
- * @return ResultStatus result of function
- */
- ResultStatus LoadExec(Kernel::SharedPtr<Kernel::Process>& process);
-
- /// Reads the region lockout info in the SMDH and send it to CFG service
- void ParseRegionLockoutInfo();
-
- FileSys::NCCHContainer base_ncch;
- FileSys::NCCHContainer update_ncch;
- FileSys::NCCHContainer* overlay_ncch;
-
- std::string filepath;
-};
-
-} // namespace Loader