summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
m---------externals/dynarmic0
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp24
-rw-r--r--src/core/arm/unicorn/arm_unicorn.cpp3
-rw-r--r--src/core/file_sys/program_metadata.cpp114
-rw-r--r--src/core/file_sys/program_metadata.h154
-rw-r--r--src/core/hle/kernel/svc.cpp12
-rw-r--r--src/core/hle/service/am/am.cpp41
-rw-r--r--src/core/hle/service/am/am.h8
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp9
-rw-r--r--src/core/hle/service/aoc/aoc_u.h1
-rw-r--r--src/core/hle/service/audio/audren_u.cpp4
-rw-r--r--src/core/hle/service/nifm/nifm.cpp32
-rw-r--r--src/core/hle/service/sockets/bsd_u.cpp10
-rw-r--r--src/core/hle/service/sockets/bsd_u.h1
-rw-r--r--src/core/hle/service/time/time_s.cpp4
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp23
-rw-r--r--src/core/loader/deconstructed_rom_directory.h2
-rw-r--r--src/core/loader/nso.cpp6
-rw-r--r--src/core/loader/nso.h2
-rw-r--r--src/core/memory.cpp11
21 files changed, 443 insertions, 20 deletions
diff --git a/externals/dynarmic b/externals/dynarmic
Subproject e585e1d49ed65c31edd567510e00508d42decb1 Subproject 6b4c6b06a94290690d2132adfa45a8087958c2c
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index ec011787e..1bc536075 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -12,6 +12,8 @@ add_library(core STATIC
12 file_sys/filesystem.h 12 file_sys/filesystem.h
13 file_sys/path_parser.cpp 13 file_sys/path_parser.cpp
14 file_sys/path_parser.h 14 file_sys/path_parser.h
15 file_sys/program_metadata.cpp
16 file_sys/program_metadata.h
15 file_sys/romfs_factory.cpp 17 file_sys/romfs_factory.cpp
16 file_sys/romfs_factory.h 18 file_sys/romfs_factory.h
17 file_sys/romfs_filesystem.cpp 19 file_sys/romfs_filesystem.cpp
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index 283d20831..e7f6bf8c2 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -6,6 +6,7 @@
6#include <memory> 6#include <memory>
7#include <dynarmic/A64/a64.h> 7#include <dynarmic/A64/a64.h>
8#include <dynarmic/A64/config.h> 8#include <dynarmic/A64/config.h>
9#include "common/logging/log.h"
9#include "core/arm/dynarmic/arm_dynarmic.h" 10#include "core/arm/dynarmic/arm_dynarmic.h"
10#include "core/core_timing.h" 11#include "core/core_timing.h"
11#include "core/hle/kernel/memory.h" 12#include "core/hle/kernel/memory.h"
@@ -53,6 +54,9 @@ public:
53 } 54 }
54 55
55 void InterpreterFallback(u64 pc, size_t num_instructions) override { 56 void InterpreterFallback(u64 pc, size_t num_instructions) override {
57 LOG_INFO(Core_ARM, "Unicorn fallback @ 0x%" PRIx64 " for %zu instructions (instr = %08x)",
58 pc, num_instructions, MemoryReadCode(pc));
59
56 ARM_Interface::ThreadContext ctx; 60 ARM_Interface::ThreadContext ctx;
57 parent.SaveContext(ctx); 61 parent.SaveContext(ctx);
58 parent.inner_unicorn.LoadContext(ctx); 62 parent.inner_unicorn.LoadContext(ctx);
@@ -63,8 +67,17 @@ public:
63 } 67 }
64 68
65 void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override { 69 void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override {
66 ASSERT_MSG(false, "ExceptionRaised(exception = %zu, pc = %" PRIx64 ")", 70 switch (exception) {
67 static_cast<size_t>(exception), pc); 71 case Dynarmic::A64::Exception::WaitForInterrupt:
72 case Dynarmic::A64::Exception::WaitForEvent:
73 case Dynarmic::A64::Exception::SendEvent:
74 case Dynarmic::A64::Exception::SendEventLocal:
75 case Dynarmic::A64::Exception::Yield:
76 return;
77 default:
78 ASSERT_MSG(false, "ExceptionRaised(exception = %zu, pc = %" PRIx64 ")",
79 static_cast<size_t>(exception), pc);
80 }
68 } 81 }
69 82
70 void CallSVC(u32 swi) override { 83 void CallSVC(u32 swi) override {
@@ -81,11 +94,15 @@ public:
81 u64 GetTicksRemaining() override { 94 u64 GetTicksRemaining() override {
82 return ticks_remaining; 95 return ticks_remaining;
83 } 96 }
97 u64 GetCNTPCT() override {
98 return CoreTiming::GetTicks();
99 }
84 100
85 ARM_Dynarmic& parent; 101 ARM_Dynarmic& parent;
86 size_t ticks_remaining = 0; 102 size_t ticks_remaining = 0;
87 size_t num_interpreted_instructions = 0; 103 size_t num_interpreted_instructions = 0;
88 u64 tpidrro_el0 = 0; 104 u64 tpidrro_el0 = 0;
105 u64 tpidr_el0 = 0;
89}; 106};
90 107
91std::unique_ptr<Dynarmic::A64::Jit> MakeJit(const std::unique_ptr<ARM_Dynarmic_Callbacks>& cb) { 108std::unique_ptr<Dynarmic::A64::Jit> MakeJit(const std::unique_ptr<ARM_Dynarmic_Callbacks>& cb) {
@@ -94,10 +111,13 @@ std::unique_ptr<Dynarmic::A64::Jit> MakeJit(const std::unique_ptr<ARM_Dynarmic_C
94 Dynarmic::A64::UserConfig config; 111 Dynarmic::A64::UserConfig config;
95 config.callbacks = cb.get(); 112 config.callbacks = cb.get();
96 config.tpidrro_el0 = &cb->tpidrro_el0; 113 config.tpidrro_el0 = &cb->tpidrro_el0;
114 config.tpidr_el0 = &cb->tpidr_el0;
97 config.dczid_el0 = 4; 115 config.dczid_el0 = 4;
116 config.ctr_el0 = 0x8444c004;
98 config.page_table = reinterpret_cast<void**>(page_table); 117 config.page_table = reinterpret_cast<void**>(page_table);
99 config.page_table_address_space_bits = Memory::ADDRESS_SPACE_BITS; 118 config.page_table_address_space_bits = Memory::ADDRESS_SPACE_BITS;
100 config.silently_mirror_page_table = false; 119 config.silently_mirror_page_table = false;
120
101 return std::make_unique<Dynarmic::A64::Jit>(config); 121 return std::make_unique<Dynarmic::A64::Jit>(config);
102} 122}
103 123
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp
index fd64eab39..5d2956bfd 100644
--- a/src/core/arm/unicorn/arm_unicorn.cpp
+++ b/src/core/arm/unicorn/arm_unicorn.cpp
@@ -52,7 +52,8 @@ static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int si
52 void* user_data) { 52 void* user_data) {
53 ARM_Interface::ThreadContext ctx{}; 53 ARM_Interface::ThreadContext ctx{};
54 Core::CPU().SaveContext(ctx); 54 Core::CPU().SaveContext(ctx);
55 ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x%llx", addr); 55 ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x%llx, pc=0x%llx, lr=0x%llx", addr,
56 ctx.pc, ctx.cpu_registers[30]);
56 return {}; 57 return {};
57} 58}
58 59
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp
new file mode 100644
index 000000000..a6dcebcc3
--- /dev/null
+++ b/src/core/file_sys/program_metadata.cpp
@@ -0,0 +1,114 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cinttypes>
6#include "common/file_util.h"
7#include "common/logging/log.h"
8#include "core/file_sys/program_metadata.h"
9#include "core/loader/loader.h"
10
11namespace FileSys {
12
13Loader::ResultStatus ProgramMetadata::Load(const std::string& file_path) {
14 FileUtil::IOFile file(file_path, "rb");
15 if (!file.IsOpen())
16 return Loader::ResultStatus::Error;
17
18 std::vector<u8> file_data(file.GetSize());
19
20 if (!file.ReadBytes(file_data.data(), file_data.size()))
21 return Loader::ResultStatus::Error;
22
23 Loader::ResultStatus result = Load(file_data);
24 if (result != Loader::ResultStatus::Success)
25 LOG_ERROR(Service_FS, "Failed to load NPDM from file %s!", file_path.c_str());
26
27 return result;
28}
29
30Loader::ResultStatus ProgramMetadata::Load(const std::vector<u8> file_data, size_t offset) {
31 size_t total_size = static_cast<size_t>(file_data.size() - offset);
32 if (total_size < sizeof(Header))
33 return Loader::ResultStatus::Error;
34
35 size_t header_offset = offset;
36 memcpy(&npdm_header, &file_data[offset], sizeof(Header));
37
38 size_t aci_offset = header_offset + npdm_header.aci_offset;
39 size_t acid_offset = header_offset + npdm_header.acid_offset;
40 memcpy(&aci_header, &file_data[aci_offset], sizeof(AciHeader));
41 memcpy(&acid_header, &file_data[acid_offset], sizeof(AcidHeader));
42
43 size_t fac_offset = acid_offset + acid_header.fac_offset;
44 size_t fah_offset = aci_offset + aci_header.fah_offset;
45 memcpy(&acid_file_access, &file_data[fac_offset], sizeof(FileAccessControl));
46 memcpy(&aci_file_access, &file_data[fah_offset], sizeof(FileAccessHeader));
47
48 return Loader::ResultStatus::Success;
49}
50
51bool ProgramMetadata::Is64BitProgram() const {
52 return npdm_header.has_64_bit_instructions;
53}
54
55ProgramAddressSpaceType ProgramMetadata::GetAddressSpaceType() const {
56 return npdm_header.address_space_type;
57}
58
59u8 ProgramMetadata::GetMainThreadPriority() const {
60 return npdm_header.main_thread_priority;
61}
62
63u8 ProgramMetadata::GetMainThreadCore() const {
64 return npdm_header.main_thread_cpu;
65}
66
67u32 ProgramMetadata::GetMainThreadStackSize() const {
68 return npdm_header.main_stack_size;
69}
70
71u64 ProgramMetadata::GetTitleID() const {
72 return aci_header.title_id;
73}
74
75u64 ProgramMetadata::GetFilesystemPermissions() const {
76 return aci_file_access.permissions;
77}
78
79void ProgramMetadata::Print() const {
80 LOG_DEBUG(Service_FS, "Magic: %.4s", npdm_header.magic.data());
81 LOG_DEBUG(Service_FS, "Main thread priority: 0x%02x", npdm_header.main_thread_priority);
82 LOG_DEBUG(Service_FS, "Main thread core: %u", npdm_header.main_thread_cpu);
83 LOG_DEBUG(Service_FS, "Main thread stack size: 0x%x bytes", npdm_header.main_stack_size);
84 LOG_DEBUG(Service_FS, "Process category: %u", npdm_header.process_category);
85 LOG_DEBUG(Service_FS, "Flags: %02x", npdm_header.flags);
86 LOG_DEBUG(Service_FS, " > 64-bit instructions: %s",
87 npdm_header.has_64_bit_instructions ? "YES" : "NO");
88
89 auto address_space = "Unknown";
90 switch (npdm_header.address_space_type) {
91 case ProgramAddressSpaceType::Is64Bit:
92 address_space = "64-bit";
93 break;
94 case ProgramAddressSpaceType::Is32Bit:
95 address_space = "32-bit";
96 break;
97 }
98
99 LOG_DEBUG(Service_FS, " > Address space: %s\n", address_space);
100
101 // Begin ACID printing (potential perms, signed)
102 LOG_DEBUG(Service_FS, "Magic: %.4s", acid_header.magic.data());
103 LOG_DEBUG(Service_FS, "Flags: %02x", acid_header.flags);
104 LOG_DEBUG(Service_FS, " > Is Retail: %s", acid_header.is_retail ? "YES" : "NO");
105 LOG_DEBUG(Service_FS, "Title ID Min: %016" PRIX64, acid_header.title_id_min);
106 LOG_DEBUG(Service_FS, "Title ID Max: %016" PRIX64, acid_header.title_id_max);
107 LOG_DEBUG(Service_FS, "Filesystem Access: %016" PRIX64 "\n", acid_file_access.permissions);
108
109 // Begin ACI0 printing (actual perms, unsigned)
110 LOG_DEBUG(Service_FS, "Magic: %.4s", aci_header.magic.data());
111 LOG_DEBUG(Service_FS, "Title ID: %016" PRIX64, aci_header.title_id);
112 LOG_DEBUG(Service_FS, "Filesystem Access: %016" PRIX64 "\n", aci_file_access.permissions);
113}
114} // namespace FileSys
diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h
new file mode 100644
index 000000000..b80a08485
--- /dev/null
+++ b/src/core/file_sys/program_metadata.h
@@ -0,0 +1,154 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <string>
9#include <vector>
10#include "common/bit_field.h"
11#include "common/common_types.h"
12#include "common/swap.h"
13
14namespace Loader {
15enum class ResultStatus;
16}
17
18namespace FileSys {
19
20enum class ProgramAddressSpaceType : u8 {
21 Is64Bit = 1,
22 Is32Bit = 2,
23};
24
25enum class ProgramFilePermission : u64 {
26 MountContent = 1ULL << 0,
27 SaveDataBackup = 1ULL << 5,
28 SdCard = 1ULL << 21,
29 Calibration = 1ULL << 34,
30 Bit62 = 1ULL << 62,
31 Everything = 1ULL << 63,
32};
33
34/**
35 * Helper which implements an interface to parse Program Description Metadata (NPDM)
36 * Data can either be loaded from a file path or with data and an offset into it.
37 */
38class ProgramMetadata {
39public:
40 Loader::ResultStatus Load(const std::string& file_path);
41 Loader::ResultStatus Load(const std::vector<u8> file_data, size_t offset = 0);
42
43 bool Is64BitProgram() const;
44 ProgramAddressSpaceType GetAddressSpaceType() const;
45 u8 GetMainThreadPriority() const;
46 u8 GetMainThreadCore() const;
47 u32 GetMainThreadStackSize() const;
48 u64 GetTitleID() const;
49 u64 GetFilesystemPermissions() const;
50
51 void Print() const;
52
53private:
54 struct Header {
55 std::array<char, 4> magic;
56 std::array<u8, 8> reserved;
57 union {
58 u8 flags;
59
60 BitField<0, 1, u8> has_64_bit_instructions;
61 BitField<1, 3, ProgramAddressSpaceType> address_space_type;
62 BitField<4, 4, u8> reserved_2;
63 };
64 u8 reserved_3;
65 u8 main_thread_priority;
66 u8 main_thread_cpu;
67 std::array<u8, 8> reserved_4;
68 u32_le process_category;
69 u32_le main_stack_size;
70 std::array<u8, 0x10> application_name;
71 std::array<u8, 0x40> reserved_5;
72 u32_le aci_offset;
73 u32_le aci_size;
74 u32_le acid_offset;
75 u32_le acid_size;
76 };
77
78 static_assert(sizeof(Header) == 0x80, "NPDM header structure size is wrong");
79
80 struct AcidHeader {
81 std::array<u8, 0x100> signature;
82 std::array<u8, 0x100> nca_modulus;
83 std::array<char, 4> magic;
84 u32_le nca_size;
85 std::array<u8, 0x4> reserved;
86 union {
87 u32 flags;
88
89 BitField<0, 1, u32> is_retail;
90 BitField<1, 31, u32> flags_unk;
91 };
92 u64_le title_id_min;
93 u64_le title_id_max;
94 u32_le fac_offset;
95 u32_le fac_size;
96 u32_le sac_offset;
97 u32_le sac_size;
98 u32_le kac_offset;
99 u32_le kac_size;
100 INSERT_PADDING_BYTES(0x8);
101 };
102
103 static_assert(sizeof(AcidHeader) == 0x240, "ACID header structure size is wrong");
104
105 struct AciHeader {
106 std::array<char, 4> magic;
107 std::array<u8, 0xC> reserved;
108 u64_le title_id;
109 INSERT_PADDING_BYTES(0x8);
110 u32_le fah_offset;
111 u32_le fah_size;
112 u32_le sac_offset;
113 u32_le sac_size;
114 u32_le kac_offset;
115 u32_le kac_size;
116 INSERT_PADDING_BYTES(0x8);
117 };
118
119 static_assert(sizeof(AciHeader) == 0x40, "ACI0 header structure size is wrong");
120
121#pragma pack(push, 1)
122
123 struct FileAccessControl {
124 u8 version;
125 INSERT_PADDING_BYTES(3);
126 u64_le permissions;
127 std::array<u8, 0x20> unknown;
128 };
129
130 static_assert(sizeof(FileAccessControl) == 0x2C, "FS access control structure size is wrong");
131
132 struct FileAccessHeader {
133 u8 version;
134 INSERT_PADDING_BYTES(3);
135 u64_le permissions;
136 u32_le unk_offset;
137 u32_le unk_size;
138 u32_le unk_offset_2;
139 u32_le unk_size_2;
140 };
141
142 static_assert(sizeof(FileAccessHeader) == 0x1C, "FS access header structure size is wrong");
143
144#pragma pack(pop)
145
146 Header npdm_header;
147 AciHeader aci_header;
148 AcidHeader acid_header;
149
150 FileAccessControl acid_file_access;
151 FileAccessHeader aci_file_access;
152};
153
154} // namespace FileSys
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 4141c0ec2..1ab8cbd88 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -772,6 +772,16 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
772 return RESULT_SUCCESS; 772 return RESULT_SUCCESS;
773} 773}
774 774
775static ResultCode ClearEvent(Handle handle) {
776 LOG_TRACE(Kernel_SVC, "called, event=0xX", handle);
777
778 SharedPtr<Event> evt = g_handle_table.Get<Event>(handle);
779 if (evt == nullptr)
780 return ERR_INVALID_HANDLE;
781 evt->Clear();
782 return RESULT_SUCCESS;
783}
784
775namespace { 785namespace {
776struct FunctionDef { 786struct FunctionDef {
777 using Func = void(); 787 using Func = void();
@@ -801,7 +811,7 @@ static const FunctionDef SVC_Table[] = {
801 {0x0F, SvcWrap<SetThreadCoreMask>, "SetThreadCoreMask"}, 811 {0x0F, SvcWrap<SetThreadCoreMask>, "SetThreadCoreMask"},
802 {0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"}, 812 {0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"},
803 {0x11, nullptr, "SignalEvent"}, 813 {0x11, nullptr, "SignalEvent"},
804 {0x12, nullptr, "ClearEvent"}, 814 {0x12, SvcWrap<ClearEvent>, "ClearEvent"},
805 {0x13, SvcWrap<MapSharedMemory>, "MapSharedMemory"}, 815 {0x13, SvcWrap<MapSharedMemory>, "MapSharedMemory"},
806 {0x14, SvcWrap<UnmapSharedMemory>, "UnmapSharedMemory"}, 816 {0x14, SvcWrap<UnmapSharedMemory>, "UnmapSharedMemory"},
807 {0x15, SvcWrap<CreateTransferMemory>, "CreateTransferMemory"}, 817 {0x15, SvcWrap<CreateTransferMemory>, "CreateTransferMemory"},
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 03305814f..d3a674cf6 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -34,7 +34,38 @@ void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx)
34 rb.Push(RESULT_SUCCESS); 34 rb.Push(RESULT_SUCCESS);
35} 35}
36 36
37IAudioController::IAudioController() : ServiceFramework("IAudioController") {} 37IAudioController::IAudioController() : ServiceFramework("IAudioController") {
38 static const FunctionInfo functions[] = {
39 {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"},
40 {1, &IAudioController::GetMainAppletExpectedMasterVolume,
41 "GetMainAppletExpectedMasterVolume"},
42 {2, &IAudioController::GetLibraryAppletExpectedMasterVolume,
43 "GetLibraryAppletExpectedMasterVolume"},
44 {3, nullptr, "ChangeMainAppletMasterVolume"},
45 {4, nullptr, "SetTransparentVolumeRate"},
46 };
47 RegisterHandlers(functions);
48}
49
50void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
51 LOG_WARNING(Service_AM, "(STUBBED) called");
52 IPC::ResponseBuilder rb{ctx, 2};
53 rb.Push(RESULT_SUCCESS);
54}
55
56void IAudioController::GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
57 LOG_WARNING(Service_AM, "(STUBBED) called");
58 IPC::ResponseBuilder rb{ctx, 3};
59 rb.Push(RESULT_SUCCESS);
60 rb.Push(volume);
61}
62
63void IAudioController::GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
64 LOG_WARNING(Service_AM, "(STUBBED) called");
65 IPC::ResponseBuilder rb{ctx, 3};
66 rb.Push(RESULT_SUCCESS);
67 rb.Push(volume);
68}
38 69
39IDisplayController::IDisplayController() : ServiceFramework("IDisplayController") {} 70IDisplayController::IDisplayController() : ServiceFramework("IDisplayController") {}
40 71
@@ -46,6 +77,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
46 {1, &ISelfController::LockExit, "LockExit"}, 77 {1, &ISelfController::LockExit, "LockExit"},
47 {2, &ISelfController::UnlockExit, "UnlockExit"}, 78 {2, &ISelfController::UnlockExit, "UnlockExit"},
48 {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"}, 79 {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"},
80 {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"},
49 {11, &ISelfController::SetOperationModeChangedNotification, 81 {11, &ISelfController::SetOperationModeChangedNotification,
50 "SetOperationModeChangedNotification"}, 82 "SetOperationModeChangedNotification"},
51 {12, &ISelfController::SetPerformanceModeChangedNotification, 83 {12, &ISelfController::SetPerformanceModeChangedNotification,
@@ -98,6 +130,13 @@ void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestCo
98 LOG_WARNING(Service_AM, "(STUBBED) called flag=%u", static_cast<u32>(flag)); 130 LOG_WARNING(Service_AM, "(STUBBED) called flag=%u", static_cast<u32>(flag));
99} 131}
100 132
133void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
134 IPC::ResponseBuilder rb{ctx, 2};
135 rb.Push(RESULT_SUCCESS);
136
137 LOG_WARNING(Service_AM, "(STUBBED) called");
138}
139
101void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) { 140void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
102 IPC::RequestParser rp{ctx}; 141 IPC::RequestParser rp{ctx};
103 142
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 793ac6555..27dbd8c95 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -36,6 +36,13 @@ private:
36class IAudioController final : public ServiceFramework<IAudioController> { 36class IAudioController final : public ServiceFramework<IAudioController> {
37public: 37public:
38 IAudioController(); 38 IAudioController();
39
40private:
41 void SetExpectedMasterVolume(Kernel::HLERequestContext& ctx);
42 void GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx);
43 void GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx);
44
45 u32 volume{100};
39}; 46};
40 47
41class IDisplayController final : public ServiceFramework<IDisplayController> { 48class IDisplayController final : public ServiceFramework<IDisplayController> {
@@ -62,6 +69,7 @@ private:
62 void UnlockExit(Kernel::HLERequestContext& ctx); 69 void UnlockExit(Kernel::HLERequestContext& ctx);
63 void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx); 70 void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx);
64 void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); 71 void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx);
72 void SetScreenShotPermission(Kernel::HLERequestContext& ctx);
65 73
66 std::shared_ptr<NVFlinger::NVFlinger> nvflinger; 74 std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
67 Kernel::SharedPtr<Kernel::Event> launchable_event; 75 Kernel::SharedPtr<Kernel::Event> launchable_event;
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 430b2a7ad..8b55d2fcb 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -13,7 +13,7 @@ AOC_U::AOC_U() : ServiceFramework("aoc:u") {
13 static const FunctionInfo functions[] = { 13 static const FunctionInfo functions[] = {
14 {0, nullptr, "CountAddOnContentByApplicationId"}, 14 {0, nullptr, "CountAddOnContentByApplicationId"},
15 {1, nullptr, "ListAddOnContentByApplicationId"}, 15 {1, nullptr, "ListAddOnContentByApplicationId"},
16 {2, nullptr, "CountAddOnContent"}, 16 {2, &AOC_U::CountAddOnContent, "CountAddOnContent"},
17 {3, &AOC_U::ListAddOnContent, "ListAddOnContent"}, 17 {3, &AOC_U::ListAddOnContent, "ListAddOnContent"},
18 {4, nullptr, "GetAddOnContentBaseIdByApplicationId"}, 18 {4, nullptr, "GetAddOnContentBaseIdByApplicationId"},
19 {5, nullptr, "GetAddOnContentBaseId"}, 19 {5, nullptr, "GetAddOnContentBaseId"},
@@ -23,6 +23,13 @@ AOC_U::AOC_U() : ServiceFramework("aoc:u") {
23 RegisterHandlers(functions); 23 RegisterHandlers(functions);
24} 24}
25 25
26void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) {
27 IPC::ResponseBuilder rb{ctx, 4};
28 rb.Push(RESULT_SUCCESS);
29 rb.Push<u64>(0);
30 LOG_WARNING(Service_AOC, "(STUBBED) called");
31}
32
26void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) { 33void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) {
27 IPC::ResponseBuilder rb{ctx, 4}; 34 IPC::ResponseBuilder rb{ctx, 4};
28 rb.Push(RESULT_SUCCESS); 35 rb.Push(RESULT_SUCCESS);
diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h
index 4d6720a9d..6e0ba15a5 100644
--- a/src/core/hle/service/aoc/aoc_u.h
+++ b/src/core/hle/service/aoc/aoc_u.h
@@ -15,6 +15,7 @@ public:
15 ~AOC_U() = default; 15 ~AOC_U() = default;
16 16
17private: 17private:
18 void CountAddOnContent(Kernel::HLERequestContext& ctx);
18 void ListAddOnContent(Kernel::HLERequestContext& ctx); 19 void ListAddOnContent(Kernel::HLERequestContext& ctx);
19}; 20};
20 21
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 4efc789ac..dda135d18 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -178,10 +178,10 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
178} 178}
179 179
180void AudRenU::GetAudioRenderersProcessMasterVolume(Kernel::HLERequestContext& ctx) { 180void AudRenU::GetAudioRenderersProcessMasterVolume(Kernel::HLERequestContext& ctx) {
181 IPC::ResponseBuilder rb{ctx, 2}; 181 IPC::ResponseBuilder rb{ctx, 3};
182 182
183 rb.Push(RESULT_SUCCESS); 183 rb.Push(RESULT_SUCCESS);
184 184 rb.Push<u32>(100);
185 LOG_WARNING(Service_Audio, "(STUBBED) called"); 185 LOG_WARNING(Service_Audio, "(STUBBED) called");
186} 186}
187 187
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index 290a2ee74..e6f05eae5 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/ipc_helpers.h" 5#include "core/hle/ipc_helpers.h"
6#include "core/hle/kernel/event.h"
6#include "core/hle/service/nifm/nifm.h" 7#include "core/hle/service/nifm/nifm.h"
7#include "core/hle/service/nifm/nifm_a.h" 8#include "core/hle/service/nifm/nifm_a.h"
8#include "core/hle/service/nifm/nifm_s.h" 9#include "core/hle/service/nifm/nifm_s.h"
@@ -28,9 +29,9 @@ class IRequest final : public ServiceFramework<IRequest> {
28public: 29public:
29 explicit IRequest() : ServiceFramework("IRequest") { 30 explicit IRequest() : ServiceFramework("IRequest") {
30 static const FunctionInfo functions[] = { 31 static const FunctionInfo functions[] = {
31 {0, nullptr, "GetRequestState"}, 32 {0, &IRequest::GetRequestState, "GetRequestState"},
32 {1, nullptr, "GetResult"}, 33 {1, &IRequest::GetResult, "GetResult"},
33 {2, nullptr, "GetSystemEventReadableHandles"}, 34 {2, &IRequest::GetSystemEventReadableHandles, "GetSystemEventReadableHandles"},
34 {3, nullptr, "Cancel"}, 35 {3, nullptr, "Cancel"},
35 {4, nullptr, "Submit"}, 36 {4, nullptr, "Submit"},
36 {5, nullptr, "SetRequirement"}, 37 {5, nullptr, "SetRequirement"},
@@ -55,7 +56,32 @@ public:
55 {25, nullptr, "UnregisterSocketDescriptor"}, 56 {25, nullptr, "UnregisterSocketDescriptor"},
56 }; 57 };
57 RegisterHandlers(functions); 58 RegisterHandlers(functions);
59
60 event1 = Kernel::Event::Create(Kernel::ResetType::OneShot, "IRequest:Event1");
61 event2 = Kernel::Event::Create(Kernel::ResetType::OneShot, "IRequest:Event2");
62 }
63
64private:
65 void GetRequestState(Kernel::HLERequestContext& ctx) {
66 LOG_WARNING(Service_NIFM, "(STUBBED) called");
67 IPC::ResponseBuilder rb{ctx, 3};
68 rb.Push(RESULT_SUCCESS);
69 rb.Push<u32>(0);
58 } 70 }
71 void GetResult(Kernel::HLERequestContext& ctx) {
72 LOG_WARNING(Service_NIFM, "(STUBBED) called");
73 IPC::ResponseBuilder rb{ctx, 3};
74 rb.Push(RESULT_SUCCESS);
75 rb.Push<u32>(0);
76 }
77 void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) {
78 LOG_WARNING(Service_NIFM, "(STUBBED) called");
79 IPC::ResponseBuilder rb{ctx, 2, 2};
80 rb.Push(RESULT_SUCCESS);
81 rb.PushCopyObjects(event1, event2);
82 }
83
84 Kernel::SharedPtr<Kernel::Event> event1, event2;
59}; 85};
60 86
61class INetworkProfile final : public ServiceFramework<INetworkProfile> { 87class INetworkProfile final : public ServiceFramework<INetworkProfile> {
diff --git a/src/core/hle/service/sockets/bsd_u.cpp b/src/core/hle/service/sockets/bsd_u.cpp
index 629ffb040..2ca1000ca 100644
--- a/src/core/hle/service/sockets/bsd_u.cpp
+++ b/src/core/hle/service/sockets/bsd_u.cpp
@@ -17,6 +17,15 @@ void BSD_U::RegisterClient(Kernel::HLERequestContext& ctx) {
17 rb.Push<u32>(0); // bsd errno 17 rb.Push<u32>(0); // bsd errno
18} 18}
19 19
20void BSD_U::StartMonitoring(Kernel::HLERequestContext& ctx) {
21 LOG_WARNING(Service, "(STUBBED) called");
22
23 IPC::ResponseBuilder rb{ctx, 3};
24
25 rb.Push(RESULT_SUCCESS);
26 rb.Push<u32>(0); // bsd errno
27}
28
20void BSD_U::Socket(Kernel::HLERequestContext& ctx) { 29void BSD_U::Socket(Kernel::HLERequestContext& ctx) {
21 IPC::RequestParser rp{ctx}; 30 IPC::RequestParser rp{ctx};
22 31
@@ -67,6 +76,7 @@ void BSD_U::Close(Kernel::HLERequestContext& ctx) {
67 76
68BSD_U::BSD_U() : ServiceFramework("bsd:u") { 77BSD_U::BSD_U() : ServiceFramework("bsd:u") {
69 static const FunctionInfo functions[] = {{0, &BSD_U::RegisterClient, "RegisterClient"}, 78 static const FunctionInfo functions[] = {{0, &BSD_U::RegisterClient, "RegisterClient"},
79 {1, &BSD_U::StartMonitoring, "StartMonitoring"},
70 {2, &BSD_U::Socket, "Socket"}, 80 {2, &BSD_U::Socket, "Socket"},
71 {11, &BSD_U::SendTo, "SendTo"}, 81 {11, &BSD_U::SendTo, "SendTo"},
72 {14, &BSD_U::Connect, "Connect"}, 82 {14, &BSD_U::Connect, "Connect"},
diff --git a/src/core/hle/service/sockets/bsd_u.h b/src/core/hle/service/sockets/bsd_u.h
index fde08a22b..4e1252e9d 100644
--- a/src/core/hle/service/sockets/bsd_u.h
+++ b/src/core/hle/service/sockets/bsd_u.h
@@ -17,6 +17,7 @@ public:
17 17
18private: 18private:
19 void RegisterClient(Kernel::HLERequestContext& ctx); 19 void RegisterClient(Kernel::HLERequestContext& ctx);
20 void StartMonitoring(Kernel::HLERequestContext& ctx);
20 void Socket(Kernel::HLERequestContext& ctx); 21 void Socket(Kernel::HLERequestContext& ctx);
21 void Connect(Kernel::HLERequestContext& ctx); 22 void Connect(Kernel::HLERequestContext& ctx);
22 void SendTo(Kernel::HLERequestContext& ctx); 23 void SendTo(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/time/time_s.cpp b/src/core/hle/service/time/time_s.cpp
index 1634d3300..b172b2bd6 100644
--- a/src/core/hle/service/time/time_s.cpp
+++ b/src/core/hle/service/time/time_s.cpp
@@ -10,6 +10,10 @@ namespace Time {
10TIME_S::TIME_S(std::shared_ptr<Module> time) : Module::Interface(std::move(time), "time:s") { 10TIME_S::TIME_S(std::shared_ptr<Module> time) : Module::Interface(std::move(time), "time:s") {
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {0, &TIME_S::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, 12 {0, &TIME_S::GetStandardUserSystemClock, "GetStandardUserSystemClock"},
13 {1, &TIME_S::GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
14 {2, &TIME_S::GetStandardSteadyClock, "GetStandardSteadyClock"},
15 {3, &TIME_S::GetTimeZoneService, "GetTimeZoneService"},
16 {4, &TIME_S::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
13 }; 17 };
14 RegisterHandlers(functions); 18 RegisterHandlers(functions);
15} 19}
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 661803b5f..864cf25cd 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -53,6 +53,7 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileUti
53FileType AppLoader_DeconstructedRomDirectory::IdentifyType(FileUtil::IOFile& file, 53FileType AppLoader_DeconstructedRomDirectory::IdentifyType(FileUtil::IOFile& file,
54 const std::string& filepath) { 54 const std::string& filepath) {
55 bool is_main_found{}; 55 bool is_main_found{};
56 bool is_npdm_found{};
56 bool is_rtld_found{}; 57 bool is_rtld_found{};
57 bool is_sdk_found{}; 58 bool is_sdk_found{};
58 59
@@ -67,6 +68,9 @@ FileType AppLoader_DeconstructedRomDirectory::IdentifyType(FileUtil::IOFile& fil
67 // Verify filename 68 // Verify filename
68 if (Common::ToLower(virtual_name) == "main") { 69 if (Common::ToLower(virtual_name) == "main") {
69 is_main_found = true; 70 is_main_found = true;
71 } else if (Common::ToLower(virtual_name) == "main.npdm") {
72 is_npdm_found = true;
73 return true;
70 } else if (Common::ToLower(virtual_name) == "rtld") { 74 } else if (Common::ToLower(virtual_name) == "rtld") {
71 is_rtld_found = true; 75 is_rtld_found = true;
72 } else if (Common::ToLower(virtual_name) == "sdk") { 76 } else if (Common::ToLower(virtual_name) == "sdk") {
@@ -83,14 +87,14 @@ FileType AppLoader_DeconstructedRomDirectory::IdentifyType(FileUtil::IOFile& fil
83 } 87 }
84 88
85 // We are done if we've found and verified all required NSOs 89 // We are done if we've found and verified all required NSOs
86 return !(is_main_found && is_rtld_found && is_sdk_found); 90 return !(is_main_found && is_npdm_found && is_rtld_found && is_sdk_found);
87 }; 91 };
88 92
89 // Search the directory recursively, looking for the required modules 93 // Search the directory recursively, looking for the required modules
90 const std::string directory = filepath.substr(0, filepath.find_last_of("/\\")) + DIR_SEP; 94 const std::string directory = filepath.substr(0, filepath.find_last_of("/\\")) + DIR_SEP;
91 FileUtil::ForeachDirectoryEntry(nullptr, directory, callback); 95 FileUtil::ForeachDirectoryEntry(nullptr, directory, callback);
92 96
93 if (is_main_found && is_rtld_found && is_sdk_found) { 97 if (is_main_found && is_npdm_found && is_rtld_found && is_sdk_found) {
94 return FileType::DeconstructedRomDirectory; 98 return FileType::DeconstructedRomDirectory;
95 } 99 }
96 100
@@ -108,14 +112,22 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
108 112
109 process = Kernel::Process::Create("main"); 113 process = Kernel::Process::Create("main");
110 114
115 const std::string directory = filepath.substr(0, filepath.find_last_of("/\\")) + DIR_SEP;
116 const std::string npdm_path = directory + DIR_SEP + "main.npdm";
117
118 ResultStatus result = metadata.Load(npdm_path);
119 if (result != ResultStatus::Success) {
120 return result;
121 }
122 metadata.Print();
123
111 // Load NSO modules 124 // Load NSO modules
112 VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR}; 125 VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR};
113 const std::string directory = filepath.substr(0, filepath.find_last_of("/\\")) + DIR_SEP;
114 for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3", 126 for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
115 "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) { 127 "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) {
116 const std::string path = directory + DIR_SEP + module; 128 const std::string path = directory + DIR_SEP + module;
117 const VAddr load_addr = next_load_addr; 129 const VAddr load_addr = next_load_addr;
118 next_load_addr = AppLoader_NSO::LoadModule(path, load_addr); 130 next_load_addr = AppLoader_NSO::LoadModule(path, load_addr, metadata.GetTitleID());
119 if (next_load_addr) { 131 if (next_load_addr) {
120 LOG_DEBUG(Loader, "loaded module %s @ 0x%" PRIx64, module, load_addr); 132 LOG_DEBUG(Loader, "loaded module %s @ 0x%" PRIx64, module, load_addr);
121 } else { 133 } else {
@@ -127,7 +139,8 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
127 process->address_mappings = default_address_mappings; 139 process->address_mappings = default_address_mappings;
128 process->resource_limit = 140 process->resource_limit =
129 Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); 141 Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
130 process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Kernel::DEFAULT_STACK_SIZE); 142 process->Run(Memory::PROCESS_IMAGE_VADDR, metadata.GetMainThreadPriority(),
143 metadata.GetMainThreadStackSize());
131 144
132 // Find the RomFS by searching for a ".romfs" file in this directory 145 // Find the RomFS by searching for a ".romfs" file in this directory
133 filepath_romfs = FindRomFS(directory); 146 filepath_romfs = FindRomFS(directory);
diff --git a/src/core/loader/deconstructed_rom_directory.h b/src/core/loader/deconstructed_rom_directory.h
index 536a2dab7..23295d911 100644
--- a/src/core/loader/deconstructed_rom_directory.h
+++ b/src/core/loader/deconstructed_rom_directory.h
@@ -6,6 +6,7 @@
6 6
7#include <string> 7#include <string>
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "core/file_sys/program_metadata.h"
9#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
10#include "core/loader/loader.h" 11#include "core/loader/loader.h"
11 12
@@ -41,6 +42,7 @@ public:
41private: 42private:
42 std::string filepath_romfs; 43 std::string filepath_romfs;
43 std::string filepath; 44 std::string filepath;
45 FileSys::ProgramMetadata metadata;
44}; 46};
45 47
46} // namespace Loader 48} // namespace Loader
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 407025da0..7f8d24dd6 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -92,7 +92,7 @@ static constexpr u32 PageAlignSize(u32 size) {
92 return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; 92 return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK;
93} 93}
94 94
95VAddr AppLoader_NSO::LoadModule(const std::string& path, VAddr load_base) { 95VAddr AppLoader_NSO::LoadModule(const std::string& path, VAddr load_base, u64 tid) {
96 FileUtil::IOFile file(path, "rb"); 96 FileUtil::IOFile file(path, "rb");
97 if (!file.IsOpen()) { 97 if (!file.IsOpen()) {
98 return {}; 98 return {};
@@ -109,7 +109,7 @@ VAddr AppLoader_NSO::LoadModule(const std::string& path, VAddr load_base) {
109 } 109 }
110 110
111 // Build program image 111 // Build program image
112 Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create("", 0); 112 Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create("", tid);
113 std::vector<u8> program_image; 113 std::vector<u8> program_image;
114 for (int i = 0; i < nso_header.segments.size(); ++i) { 114 for (int i = 0; i < nso_header.segments.size(); ++i) {
115 std::vector<u8> data = 115 std::vector<u8> data =
@@ -158,7 +158,7 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
158 process = Kernel::Process::Create("main"); 158 process = Kernel::Process::Create("main");
159 159
160 // Load module 160 // Load module
161 LoadModule(filepath, Memory::PROCESS_IMAGE_VADDR); 161 LoadModule(filepath, Memory::PROCESS_IMAGE_VADDR, 0);
162 LOG_DEBUG(Loader, "loaded module %s @ 0x%" PRIx64, filepath.c_str(), 162 LOG_DEBUG(Loader, "loaded module %s @ 0x%" PRIx64, filepath.c_str(),
163 Memory::PROCESS_IMAGE_VADDR); 163 Memory::PROCESS_IMAGE_VADDR);
164 164
diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h
index 1ae30a824..14eb1d87e 100644
--- a/src/core/loader/nso.h
+++ b/src/core/loader/nso.h
@@ -29,7 +29,7 @@ public:
29 return IdentifyType(file, filepath); 29 return IdentifyType(file, filepath);
30 } 30 }
31 31
32 static VAddr LoadModule(const std::string& path, VAddr load_base); 32 static VAddr LoadModule(const std::string& path, VAddr load_base, u64 tid);
33 33
34 ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override; 34 ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
35 35
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index cc1ed16b6..ce62666d7 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -118,6 +118,11 @@ boost::optional<T> ReadSpecial(VAddr addr);
118 118
119template <typename T> 119template <typename T>
120T Read(const VAddr vaddr) { 120T Read(const VAddr vaddr) {
121 if ((vaddr >> PAGE_BITS) >= PAGE_TABLE_NUM_ENTRIES) {
122 LOG_ERROR(HW_Memory, "Read%lu after page table @ 0x%016" PRIX64, sizeof(T) * 8, vaddr);
123 return 0;
124 }
125
121 const PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; 126 const PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
122 switch (type) { 127 switch (type) {
123 case PageType::Unmapped: 128 case PageType::Unmapped:
@@ -146,6 +151,12 @@ bool WriteSpecial(VAddr addr, const T data);
146 151
147template <typename T> 152template <typename T>
148void Write(const VAddr vaddr, const T data) { 153void Write(const VAddr vaddr, const T data) {
154 if ((vaddr >> PAGE_BITS) >= PAGE_TABLE_NUM_ENTRIES) {
155 LOG_ERROR(HW_Memory, "Write%lu after page table 0x%08X @ 0x%016" PRIX64, sizeof(data) * 8,
156 (u32)data, vaddr);
157 return;
158 }
159
149 const PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; 160 const PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
150 switch (type) { 161 switch (type) {
151 case PageType::Unmapped: 162 case PageType::Unmapped: