aboutsummaryrefslogtreecommitdiff
path: root/src/core/loader
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/loader')
-rw-r--r--src/core/loader/3dsx.cpp34
-rw-r--r--src/core/loader/ncch.cpp24
-rw-r--r--src/core/loader/ncch.h5
3 files changed, 52 insertions, 11 deletions
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
index 1c10740a0..09266e8b0 100644
--- a/src/core/loader/3dsx.cpp
+++ b/src/core/loader/3dsx.cpp
@@ -177,18 +177,34 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr,
pos += table.skip;
s32 num_patches = table.patch;
while (0 < num_patches && pos < end_pos) {
- u32 in_addr =
- static_cast<u32>(reinterpret_cast<u8*>(pos) - program_image.data());
- u32 addr = TranslateAddr(*pos, &loadinfo, offsets);
- LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)",
- base_addr + in_addr, addr, current_segment_reloc_table, *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:
- *pos = (addr);
+ case 0: {
+ if (sub_type != 0)
+ return ERROR_READ;
+ *pos = addr;
break;
- case 1:
- *pos = static_cast<u32>(addr - in_addr);
+ }
+ 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
}
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index 6f2164428..5df33f6d2 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -11,8 +11,10 @@
#include "core/file_sys/archive_romfs.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"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -286,7 +288,7 @@ ResultStatus AppLoader_NCCH::LoadExeFS() {
LOG_DEBUG(Loader, "Thread priority: 0x%X", priority);
LOG_DEBUG(Loader, "Resource limit category: %d", resource_limit_category);
LOG_DEBUG(Loader, "System Mode: %d",
- exheader_header.arm11_system_local_caps.system_mode);
+ static_cast<int>(exheader_header.arm11_system_local_caps.system_mode));
if (exheader_header.arm11_system_local_caps.program_id != ncch_header.program_id) {
LOG_ERROR(Loader, "ExHeader Program ID mismatch: the ROM is probably encrypted.");
@@ -309,6 +311,23 @@ ResultStatus AppLoader_NCCH::LoadExeFS() {
return ResultStatus::Success;
}
+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() {
if (is_loaded)
return ResultStatus::ErrorAlreadyLoaded;
@@ -325,6 +344,9 @@ ResultStatus AppLoader_NCCH::Load() {
Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this),
Service::FS::ArchiveIdCode::RomFS);
+
+ ParseRegionLockoutInfo();
+
return ResultStatus::Success;
}
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h
index 6afc171a5..4ef95b5c6 100644
--- a/src/core/loader/ncch.h
+++ b/src/core/loader/ncch.h
@@ -181,7 +181,7 @@ public:
* Loads the Exheader and returns the system mode for this application.
* @return Optional with the kernel system mode
*/
- boost::optional<u32> LoadKernelSystemMode();
+ boost::optional<u32> LoadKernelSystemMode() override;
ResultStatus ReadCode(std::vector<u8>& buffer) override;
@@ -229,6 +229,9 @@ private:
*/
ResultStatus LoadExeFS();
+ /// Reads the region lockout info in the SMDH and send it to CFG service
+ void ParseRegionLockoutInfo();
+
bool is_exefs_loaded = false;
bool is_compressed = false;