summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt10
-rw-r--r--src/core/arm/arm_interface.h14
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp23
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.h6
-rw-r--r--src/core/arm/unicorn/arm_unicorn.h2
-rw-r--r--src/core/core.cpp83
-rw-r--r--src/core/core.h29
-rw-r--r--src/core/cpu_core_manager.cpp6
-rw-r--r--src/core/cpu_core_manager.h7
-rw-r--r--src/core/frontend/applets/error.cpp34
-rw-r--r--src/core/frontend/applets/error.h37
-rw-r--r--src/core/frontend/applets/general_frontend.cpp27
-rw-r--r--src/core/frontend/applets/general_frontend.h28
-rw-r--r--src/core/hle/kernel/kernel.cpp10
-rw-r--r--src/core/hle/kernel/process.cpp25
-rw-r--r--src/core/hle/kernel/process.h7
-rw-r--r--src/core/hle/kernel/svc.cpp170
-rw-r--r--src/core/hle/kernel/svc_wrap.h7
-rw-r--r--src/core/hle/kernel/thread.cpp14
-rw-r--r--src/core/hle/kernel/thread.h58
-rw-r--r--src/core/hle/kernel/vm_manager.cpp80
-rw-r--r--src/core/hle/kernel/vm_manager.h49
-rw-r--r--src/core/hle/kernel/wait_object.cpp31
-rw-r--r--src/core/hle/kernel/wait_object.h2
-rw-r--r--src/core/hle/service/acc/acc.cpp4
-rw-r--r--src/core/hle/service/acc/acc_su.cpp6
-rw-r--r--src/core/hle/service/acc/acc_u0.cpp8
-rw-r--r--src/core/hle/service/acc/acc_u1.cpp6
-rw-r--r--src/core/hle/service/am/am.cpp43
-rw-r--r--src/core/hle/service/am/applet_ae.cpp8
-rw-r--r--src/core/hle/service/am/applets/applets.cpp82
-rw-r--r--src/core/hle/service/am/applets/applets.h55
-rw-r--r--src/core/hle/service/am/applets/error.cpp182
-rw-r--r--src/core/hle/service/am/applets/error.h47
-rw-r--r--src/core/hle/service/am/applets/general_backend.cpp (renamed from src/core/hle/service/am/applets/stub_applet.cpp)56
-rw-r--r--src/core/hle/service/am/applets/general_backend.h48
-rw-r--r--src/core/hle/service/am/applets/profile_select.cpp6
-rw-r--r--src/core/hle/service/am/applets/profile_select.h4
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.cpp7
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.h4
-rw-r--r--src/core/hle/service/am/applets/stub_applet.h24
-rw-r--r--src/core/hle/service/am/applets/web_browser.cpp4
-rw-r--r--src/core/hle/service/am/applets/web_browser.h4
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp4
-rw-r--r--src/core/hle/service/apm/interface.cpp2
-rw-r--r--src/core/hle/service/audio/audctl.cpp30
-rw-r--r--src/core/hle/service/audio/audctl.h4
-rw-r--r--src/core/hle/service/audio/audin_u.cpp1
-rw-r--r--src/core/hle/service/audio/audout_u.cpp5
-rw-r--r--src/core/hle/service/btdrv/btdrv.cpp3
-rw-r--r--src/core/hle/service/caps/caps.cpp89
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp7
-rw-r--r--src/core/hle/service/friend/friend.cpp5
-rw-r--r--src/core/hle/service/hid/hid.cpp15
-rw-r--r--src/core/hle/service/ldn/ldn.cpp54
-rw-r--r--src/core/hle/service/ldr/ldr.cpp1
-rw-r--r--src/core/hle/service/nifm/nifm.cpp4
-rw-r--r--src/core/hle/service/npns/npns.cpp3
-rw-r--r--src/core/hle/service/pctl/module.cpp7
-rw-r--r--src/core/hle/service/pm/pm.cpp21
-rw-r--r--src/core/hle/service/set/set.cpp4
-rw-r--r--src/core/hle/service/set/set_cal.cpp2
-rw-r--r--src/core/hle/service/set/set_sys.cpp27
-rw-r--r--src/core/hle/service/sockets/bsd.cpp5
-rw-r--r--src/core/hle/service/ssl/ssl.cpp2
-rw-r--r--src/core/hle/service/time/interface.cpp10
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp40
-rw-r--r--src/core/loader/deconstructed_rom_directory.h2
-rw-r--r--src/core/loader/elf.cpp15
-rw-r--r--src/core/loader/elf.h2
-rw-r--r--src/core/loader/loader.h8
-rw-r--r--src/core/loader/nax.cpp30
-rw-r--r--src/core/loader/nax.h2
-rw-r--r--src/core/loader/nca.cpp26
-rw-r--r--src/core/loader/nca.h2
-rw-r--r--src/core/loader/nro.cpp14
-rw-r--r--src/core/loader/nro.h2
-rw-r--r--src/core/loader/nso.cpp11
-rw-r--r--src/core/loader/nso.h2
-rw-r--r--src/core/loader/nsp.cpp38
-rw-r--r--src/core/loader/nsp.h2
-rw-r--r--src/core/loader/xci.cpp28
-rw-r--r--src/core/loader/xci.h2
-rw-r--r--src/core/memory.cpp16
-rw-r--r--src/core/memory.h5
-rw-r--r--src/core/settings.cpp1
-rw-r--r--src/core/settings.h1
87 files changed, 1499 insertions, 412 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index c59107102..2ace866ee 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -88,6 +88,10 @@ add_library(core STATIC
88 file_sys/vfs_vector.h 88 file_sys/vfs_vector.h
89 file_sys/xts_archive.cpp 89 file_sys/xts_archive.cpp
90 file_sys/xts_archive.h 90 file_sys/xts_archive.h
91 frontend/applets/error.cpp
92 frontend/applets/error.h
93 frontend/applets/general_frontend.cpp
94 frontend/applets/general_frontend.h
91 frontend/applets/profile_select.cpp 95 frontend/applets/profile_select.cpp
92 frontend/applets/profile_select.h 96 frontend/applets/profile_select.h
93 frontend/applets/software_keyboard.cpp 97 frontend/applets/software_keyboard.cpp
@@ -177,12 +181,14 @@ add_library(core STATIC
177 hle/service/am/applet_oe.h 181 hle/service/am/applet_oe.h
178 hle/service/am/applets/applets.cpp 182 hle/service/am/applets/applets.cpp
179 hle/service/am/applets/applets.h 183 hle/service/am/applets/applets.h
184 hle/service/am/applets/error.cpp
185 hle/service/am/applets/error.h
186 hle/service/am/applets/general_backend.cpp
187 hle/service/am/applets/general_backend.h
180 hle/service/am/applets/profile_select.cpp 188 hle/service/am/applets/profile_select.cpp
181 hle/service/am/applets/profile_select.h 189 hle/service/am/applets/profile_select.h
182 hle/service/am/applets/software_keyboard.cpp 190 hle/service/am/applets/software_keyboard.cpp
183 hle/service/am/applets/software_keyboard.h 191 hle/service/am/applets/software_keyboard.h
184 hle/service/am/applets/stub_applet.cpp
185 hle/service/am/applets/stub_applet.h
186 hle/service/am/applets/web_browser.cpp 192 hle/service/am/applets/web_browser.cpp
187 hle/service/am/applets/web_browser.h 193 hle/service/am/applets/web_browser.h
188 hle/service/am/idle.cpp 194 hle/service/am/idle.cpp
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 4dfd41b43..978b1518f 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -7,6 +7,10 @@
7#include <array> 7#include <array>
8#include "common/common_types.h" 8#include "common/common_types.h"
9 9
10namespace Common {
11struct PageTable;
12}
13
10namespace Kernel { 14namespace Kernel {
11enum class VMAPermission : u8; 15enum class VMAPermission : u8;
12} 16}
@@ -49,8 +53,14 @@ public:
49 /// Clear all instruction cache 53 /// Clear all instruction cache
50 virtual void ClearInstructionCache() = 0; 54 virtual void ClearInstructionCache() = 0;
51 55
52 /// Notify CPU emulation that page tables have changed 56 /// Notifies CPU emulation that the current page table has changed.
53 virtual void PageTableChanged() = 0; 57 ///
58 /// @param new_page_table The new page table.
59 /// @param new_address_space_size_in_bits The new usable size of the address space in bits.
60 /// This can be either 32, 36, or 39 on official software.
61 ///
62 virtual void PageTableChanged(Common::PageTable& new_page_table,
63 std::size_t new_address_space_size_in_bits) = 0;
54 64
55 /** 65 /**
56 * Set the Program Counter to an address 66 * Set the Program Counter to an address
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index dc96e35d5..44307fa19 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -14,7 +14,6 @@
14#include "core/core_timing.h" 14#include "core/core_timing.h"
15#include "core/core_timing_util.h" 15#include "core/core_timing_util.h"
16#include "core/gdbstub/gdbstub.h" 16#include "core/gdbstub/gdbstub.h"
17#include "core/hle/kernel/kernel.h"
18#include "core/hle/kernel/process.h" 17#include "core/hle/kernel/process.h"
19#include "core/hle/kernel/svc.h" 18#include "core/hle/kernel/svc.h"
20#include "core/hle/kernel/vm_manager.h" 19#include "core/hle/kernel/vm_manager.h"
@@ -129,18 +128,16 @@ public:
129 u64 tpidr_el0 = 0; 128 u64 tpidr_el0 = 0;
130}; 129};
131 130
132std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() const { 131std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& page_table,
133 auto* current_process = system.Kernel().CurrentProcess(); 132 std::size_t address_space_bits) const {
134 auto** const page_table = current_process->VMManager().page_table.pointers.data();
135
136 Dynarmic::A64::UserConfig config; 133 Dynarmic::A64::UserConfig config;
137 134
138 // Callbacks 135 // Callbacks
139 config.callbacks = cb.get(); 136 config.callbacks = cb.get();
140 137
141 // Memory 138 // Memory
142 config.page_table = reinterpret_cast<void**>(page_table); 139 config.page_table = reinterpret_cast<void**>(page_table.pointers.data());
143 config.page_table_address_space_bits = current_process->VMManager().GetAddressSpaceWidth(); 140 config.page_table_address_space_bits = address_space_bits;
144 config.silently_mirror_page_table = false; 141 config.silently_mirror_page_table = false;
145 142
146 // Multi-process state 143 // Multi-process state
@@ -176,12 +173,7 @@ ARM_Dynarmic::ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor,
176 std::size_t core_index) 173 std::size_t core_index)
177 : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), inner_unicorn{system}, 174 : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), inner_unicorn{system},
178 core_index{core_index}, system{system}, 175 core_index{core_index}, system{system},
179 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} { 176 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
180 ThreadContext ctx{};
181 inner_unicorn.SaveContext(ctx);
182 PageTableChanged();
183 LoadContext(ctx);
184}
185 177
186ARM_Dynarmic::~ARM_Dynarmic() = default; 178ARM_Dynarmic::~ARM_Dynarmic() = default;
187 179
@@ -276,8 +268,9 @@ void ARM_Dynarmic::ClearExclusiveState() {
276 jit->ClearExclusiveState(); 268 jit->ClearExclusiveState();
277} 269}
278 270
279void ARM_Dynarmic::PageTableChanged() { 271void ARM_Dynarmic::PageTableChanged(Common::PageTable& page_table,
280 jit = MakeJit(); 272 std::size_t new_address_space_size_in_bits) {
273 jit = MakeJit(page_table, new_address_space_size_in_bits);
281} 274}
282 275
283DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(std::size_t core_count) : monitor(core_count) {} 276DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(std::size_t core_count) : monitor(core_count) {}
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h
index c1db254e8..b701e97a3 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.h
+++ b/src/core/arm/dynarmic/arm_dynarmic.h
@@ -48,10 +48,12 @@ public:
48 void ClearExclusiveState() override; 48 void ClearExclusiveState() override;
49 49
50 void ClearInstructionCache() override; 50 void ClearInstructionCache() override;
51 void PageTableChanged() override; 51 void PageTableChanged(Common::PageTable& new_page_table,
52 std::size_t new_address_space_size_in_bits) override;
52 53
53private: 54private:
54 std::unique_ptr<Dynarmic::A64::Jit> MakeJit() const; 55 std::unique_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable& page_table,
56 std::size_t address_space_bits) const;
55 57
56 friend class ARM_Dynarmic_Callbacks; 58 friend class ARM_Dynarmic_Callbacks;
57 std::unique_ptr<ARM_Dynarmic_Callbacks> cb; 59 std::unique_ptr<ARM_Dynarmic_Callbacks> cb;
diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h
index 209fc16ad..34e974b4d 100644
--- a/src/core/arm/unicorn/arm_unicorn.h
+++ b/src/core/arm/unicorn/arm_unicorn.h
@@ -41,7 +41,7 @@ public:
41 void Run() override; 41 void Run() override;
42 void Step() override; 42 void Step() override;
43 void ClearInstructionCache() override; 43 void ClearInstructionCache() override;
44 void PageTableChanged() override{}; 44 void PageTableChanged(Common::PageTable&, std::size_t) override {}
45 void RecordBreak(GDBStub::BreakpointAddress bkpt); 45 void RecordBreak(GDBStub::BreakpointAddress bkpt);
46 46
47private: 47private:
diff --git a/src/core/core.cpp b/src/core/core.cpp
index bc9e887b6..7106151bd 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -3,9 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array> 5#include <array>
6#include <map>
7#include <memory> 6#include <memory>
8#include <thread>
9#include <utility> 7#include <utility>
10 8
11#include "common/file_util.h" 9#include "common/file_util.h"
@@ -20,13 +18,18 @@
20#include "core/file_sys/registered_cache.h" 18#include "core/file_sys/registered_cache.h"
21#include "core/file_sys/vfs_concat.h" 19#include "core/file_sys/vfs_concat.h"
22#include "core/file_sys/vfs_real.h" 20#include "core/file_sys/vfs_real.h"
21#include "core/frontend/applets/error.h"
22#include "core/frontend/applets/general_frontend.h"
23#include "core/frontend/applets/profile_select.h"
24#include "core/frontend/applets/software_keyboard.h"
25#include "core/frontend/applets/web_browser.h"
23#include "core/gdbstub/gdbstub.h" 26#include "core/gdbstub/gdbstub.h"
24#include "core/hle/kernel/client_port.h" 27#include "core/hle/kernel/client_port.h"
25#include "core/hle/kernel/kernel.h" 28#include "core/hle/kernel/kernel.h"
26#include "core/hle/kernel/process.h" 29#include "core/hle/kernel/process.h"
27#include "core/hle/kernel/scheduler.h" 30#include "core/hle/kernel/scheduler.h"
28#include "core/hle/kernel/thread.h" 31#include "core/hle/kernel/thread.h"
29#include "core/hle/service/am/applets/software_keyboard.h" 32#include "core/hle/service/am/applets/applets.h"
30#include "core/hle/service/service.h" 33#include "core/hle/service/service.h"
31#include "core/hle/service/sm/sm.h" 34#include "core/hle/service/sm/sm.h"
32#include "core/loader/loader.h" 35#include "core/loader/loader.h"
@@ -38,8 +41,6 @@
38#include "frontend/applets/software_keyboard.h" 41#include "frontend/applets/software_keyboard.h"
39#include "frontend/applets/web_browser.h" 42#include "frontend/applets/web_browser.h"
40#include "video_core/debug_utils/debug_utils.h" 43#include "video_core/debug_utils/debug_utils.h"
41#include "video_core/gpu_asynch.h"
42#include "video_core/gpu_synch.h"
43#include "video_core/renderer_base.h" 44#include "video_core/renderer_base.h"
44#include "video_core/video_core.h" 45#include "video_core/video_core.h"
45 46
@@ -81,7 +82,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
81 return vfs->OpenFile(path, FileSys::Mode::Read); 82 return vfs->OpenFile(path, FileSys::Mode::Read);
82} 83}
83struct System::Impl { 84struct System::Impl {
84 explicit Impl(System& system) : kernel{system} {} 85 explicit Impl(System& system) : kernel{system}, cpu_core_manager{system} {}
85 86
86 Cpu& CurrentCpuCore() { 87 Cpu& CurrentCpuCore() {
87 return cpu_core_manager.GetCurrentCore(); 88 return cpu_core_manager.GetCurrentCore();
@@ -99,6 +100,7 @@ struct System::Impl {
99 LOG_DEBUG(HW_Memory, "initialized OK"); 100 LOG_DEBUG(HW_Memory, "initialized OK");
100 101
101 core_timing.Initialize(); 102 core_timing.Initialize();
103 cpu_core_manager.Initialize();
102 kernel.Initialize(); 104 kernel.Initialize();
103 105
104 const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( 106 const auto current_time = std::chrono::duration_cast<std::chrono::seconds>(
@@ -113,15 +115,7 @@ struct System::Impl {
113 content_provider = std::make_unique<FileSys::ContentProviderUnion>(); 115 content_provider = std::make_unique<FileSys::ContentProviderUnion>();
114 116
115 /// Create default implementations of applets if one is not provided. 117 /// Create default implementations of applets if one is not provided.
116 if (profile_selector == nullptr) 118 applet_manager.SetDefaultAppletsIfMissing();
117 profile_selector = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
118 if (software_keyboard == nullptr)
119 software_keyboard = std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
120 if (web_browser == nullptr)
121 web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
122
123 auto main_process = Kernel::Process::Create(system, "main");
124 kernel.MakeCurrentProcess(main_process.get());
125 119
126 telemetry_session = std::make_unique<Core::TelemetrySession>(); 120 telemetry_session = std::make_unique<Core::TelemetrySession>();
127 service_manager = std::make_shared<Service::SM::ServiceManager>(); 121 service_manager = std::make_shared<Service::SM::ServiceManager>();
@@ -134,15 +128,9 @@ struct System::Impl {
134 return ResultStatus::ErrorVideoCore; 128 return ResultStatus::ErrorVideoCore;
135 } 129 }
136 130
137 is_powered_on = true; 131 gpu_core = VideoCore::CreateGPU(system);
138 132
139 if (Settings::values.use_asynchronous_gpu_emulation) { 133 is_powered_on = true;
140 gpu_core = std::make_unique<VideoCommon::GPUAsynch>(system, *renderer);
141 } else {
142 gpu_core = std::make_unique<VideoCommon::GPUSynch>(system, *renderer);
143 }
144
145 cpu_core_manager.Initialize(system);
146 134
147 LOG_DEBUG(Core, "Initialized OK"); 135 LOG_DEBUG(Core, "Initialized OK");
148 136
@@ -179,7 +167,8 @@ struct System::Impl {
179 return init_result; 167 return init_result;
180 } 168 }
181 169
182 const Loader::ResultStatus load_result{app_loader->Load(*kernel.CurrentProcess())}; 170 auto main_process = Kernel::Process::Create(system, "main");
171 const auto [load_result, load_parameters] = app_loader->Load(*main_process);
183 if (load_result != Loader::ResultStatus::Success) { 172 if (load_result != Loader::ResultStatus::Success) {
184 LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result)); 173 LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result));
185 Shutdown(); 174 Shutdown();
@@ -187,6 +176,16 @@ struct System::Impl {
187 return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) + 176 return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) +
188 static_cast<u32>(load_result)); 177 static_cast<u32>(load_result));
189 } 178 }
179 kernel.MakeCurrentProcess(main_process.get());
180
181 // Main process has been loaded and been made current.
182 // Begin GPU and CPU execution.
183 gpu_core->Start();
184 cpu_core_manager.StartThreads();
185
186 // All threads are started, begin main process execution, now that we're in the clear.
187 main_process->Run(load_parameters->main_thread_priority,
188 load_parameters->main_thread_stack_size);
190 189
191 status = ResultStatus::Success; 190 status = ResultStatus::Success;
192 return status; 191 return status;
@@ -224,9 +223,7 @@ struct System::Impl {
224 app_loader.reset(); 223 app_loader.reset();
225 224
226 // Clear all applets 225 // Clear all applets
227 profile_selector.reset(); 226 applet_manager.ClearAll();
228 software_keyboard.reset();
229 web_browser.reset();
230 227
231 LOG_DEBUG(Core, "Shutdown OK"); 228 LOG_DEBUG(Core, "Shutdown OK");
232 } 229 }
@@ -265,9 +262,7 @@ struct System::Impl {
265 std::unique_ptr<FileSys::CheatEngine> cheat_engine; 262 std::unique_ptr<FileSys::CheatEngine> cheat_engine;
266 263
267 /// Frontend applets 264 /// Frontend applets
268 std::unique_ptr<Core::Frontend::ProfileSelectApplet> profile_selector; 265 Service::AM::Applets::AppletManager applet_manager;
269 std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard;
270 std::unique_ptr<Core::Frontend::WebBrowserApplet> web_browser;
271 266
272 /// Service manager 267 /// Service manager
273 std::shared_ptr<Service::SM::ServiceManager> service_manager; 268 std::shared_ptr<Service::SM::ServiceManager> service_manager;
@@ -477,20 +472,20 @@ std::shared_ptr<FileSys::VfsFilesystem> System::GetFilesystem() const {
477 return impl->virtual_filesystem; 472 return impl->virtual_filesystem;
478} 473}
479 474
480void System::SetProfileSelector(std::unique_ptr<Frontend::ProfileSelectApplet> applet) { 475void System::SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set) {
481 impl->profile_selector = std::move(applet); 476 impl->applet_manager.SetAppletFrontendSet(std::move(set));
482} 477}
483 478
484const Frontend::ProfileSelectApplet& System::GetProfileSelector() const { 479void System::SetDefaultAppletFrontendSet() {
485 return *impl->profile_selector; 480 impl->applet_manager.SetDefaultAppletFrontendSet();
486} 481}
487 482
488void System::SetSoftwareKeyboard(std::unique_ptr<Frontend::SoftwareKeyboardApplet> applet) { 483Service::AM::Applets::AppletManager& System::GetAppletManager() {
489 impl->software_keyboard = std::move(applet); 484 return impl->applet_manager;
490} 485}
491 486
492const Frontend::SoftwareKeyboardApplet& System::GetSoftwareKeyboard() const { 487const Service::AM::Applets::AppletManager& System::GetAppletManager() const {
493 return *impl->software_keyboard; 488 return impl->applet_manager;
494} 489}
495 490
496void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) { 491void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) {
@@ -514,18 +509,6 @@ void System::ClearContentProvider(FileSys::ContentProviderUnionSlot slot) {
514 impl->content_provider->ClearSlot(slot); 509 impl->content_provider->ClearSlot(slot);
515} 510}
516 511
517void System::SetWebBrowser(std::unique_ptr<Frontend::WebBrowserApplet> applet) {
518 impl->web_browser = std::move(applet);
519}
520
521Frontend::WebBrowserApplet& System::GetWebBrowser() {
522 return *impl->web_browser;
523}
524
525const Frontend::WebBrowserApplet& System::GetWebBrowser() const {
526 return *impl->web_browser;
527}
528
529System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { 512System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
530 return impl->Init(*this, emu_window); 513 return impl->Init(*this, emu_window);
531} 514}
diff --git a/src/core/core.h b/src/core/core.h
index 82b2e087e..a9a756a4c 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -14,9 +14,6 @@
14 14
15namespace Core::Frontend { 15namespace Core::Frontend {
16class EmuWindow; 16class EmuWindow;
17class ProfileSelectApplet;
18class SoftwareKeyboardApplet;
19class WebBrowserApplet;
20} // namespace Core::Frontend 17} // namespace Core::Frontend
21 18
22namespace FileSys { 19namespace FileSys {
@@ -38,9 +35,18 @@ class AppLoader;
38enum class ResultStatus : u16; 35enum class ResultStatus : u16;
39} // namespace Loader 36} // namespace Loader
40 37
41namespace Service::SM { 38namespace Service {
39
40namespace AM::Applets {
41struct AppletFrontendSet;
42class AppletManager;
43} // namespace AM::Applets
44
45namespace SM {
42class ServiceManager; 46class ServiceManager;
43} // namespace Service::SM 47} // namespace SM
48
49} // namespace Service
44 50
45namespace Tegra { 51namespace Tegra {
46class DebugContext; 52class DebugContext;
@@ -260,18 +266,13 @@ public:
260 void RegisterCheatList(const std::vector<FileSys::CheatList>& list, const std::string& build_id, 266 void RegisterCheatList(const std::vector<FileSys::CheatList>& list, const std::string& build_id,
261 VAddr code_region_start, VAddr code_region_end); 267 VAddr code_region_start, VAddr code_region_end);
262 268
263 void SetProfileSelector(std::unique_ptr<Frontend::ProfileSelectApplet> applet); 269 void SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set);
264
265 const Frontend::ProfileSelectApplet& GetProfileSelector() const;
266
267 void SetSoftwareKeyboard(std::unique_ptr<Frontend::SoftwareKeyboardApplet> applet);
268 270
269 const Frontend::SoftwareKeyboardApplet& GetSoftwareKeyboard() const; 271 void SetDefaultAppletFrontendSet();
270 272
271 void SetWebBrowser(std::unique_ptr<Frontend::WebBrowserApplet> applet); 273 Service::AM::Applets::AppletManager& GetAppletManager();
272 274
273 Frontend::WebBrowserApplet& GetWebBrowser(); 275 const Service::AM::Applets::AppletManager& GetAppletManager() const;
274 const Frontend::WebBrowserApplet& GetWebBrowser() const;
275 276
276 void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider); 277 void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider);
277 278
diff --git a/src/core/cpu_core_manager.cpp b/src/core/cpu_core_manager.cpp
index 93bc5619c..8fcb4eeb1 100644
--- a/src/core/cpu_core_manager.cpp
+++ b/src/core/cpu_core_manager.cpp
@@ -19,17 +19,19 @@ void RunCpuCore(const System& system, Cpu& cpu_state) {
19} 19}
20} // Anonymous namespace 20} // Anonymous namespace
21 21
22CpuCoreManager::CpuCoreManager() = default; 22CpuCoreManager::CpuCoreManager(System& system) : system{system} {}
23CpuCoreManager::~CpuCoreManager() = default; 23CpuCoreManager::~CpuCoreManager() = default;
24 24
25void CpuCoreManager::Initialize(System& system) { 25void CpuCoreManager::Initialize() {
26 barrier = std::make_unique<CpuBarrier>(); 26 barrier = std::make_unique<CpuBarrier>();
27 exclusive_monitor = Cpu::MakeExclusiveMonitor(cores.size()); 27 exclusive_monitor = Cpu::MakeExclusiveMonitor(cores.size());
28 28
29 for (std::size_t index = 0; index < cores.size(); ++index) { 29 for (std::size_t index = 0; index < cores.size(); ++index) {
30 cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index); 30 cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index);
31 } 31 }
32}
32 33
34void CpuCoreManager::StartThreads() {
33 // Create threads for CPU cores 1-3, and build thread_to_cpu map 35 // Create threads for CPU cores 1-3, and build thread_to_cpu map
34 // CPU core 0 is run on the main thread 36 // CPU core 0 is run on the main thread
35 thread_to_cpu[std::this_thread::get_id()] = cores[0].get(); 37 thread_to_cpu[std::this_thread::get_id()] = cores[0].get();
diff --git a/src/core/cpu_core_manager.h b/src/core/cpu_core_manager.h
index a4d70ec56..2cbbf8216 100644
--- a/src/core/cpu_core_manager.h
+++ b/src/core/cpu_core_manager.h
@@ -18,7 +18,7 @@ class System;
18 18
19class CpuCoreManager { 19class CpuCoreManager {
20public: 20public:
21 CpuCoreManager(); 21 explicit CpuCoreManager(System& system);
22 CpuCoreManager(const CpuCoreManager&) = delete; 22 CpuCoreManager(const CpuCoreManager&) = delete;
23 CpuCoreManager(CpuCoreManager&&) = delete; 23 CpuCoreManager(CpuCoreManager&&) = delete;
24 24
@@ -27,7 +27,8 @@ public:
27 CpuCoreManager& operator=(const CpuCoreManager&) = delete; 27 CpuCoreManager& operator=(const CpuCoreManager&) = delete;
28 CpuCoreManager& operator=(CpuCoreManager&&) = delete; 28 CpuCoreManager& operator=(CpuCoreManager&&) = delete;
29 29
30 void Initialize(System& system); 30 void Initialize();
31 void StartThreads();
31 void Shutdown(); 32 void Shutdown();
32 33
33 Cpu& GetCore(std::size_t index); 34 Cpu& GetCore(std::size_t index);
@@ -54,6 +55,8 @@ private:
54 55
55 /// Map of guest threads to CPU cores 56 /// Map of guest threads to CPU cores
56 std::map<std::thread::id, Cpu*> thread_to_cpu; 57 std::map<std::thread::id, Cpu*> thread_to_cpu;
58
59 System& system;
57}; 60};
58 61
59} // namespace Core 62} // namespace Core
diff --git a/src/core/frontend/applets/error.cpp b/src/core/frontend/applets/error.cpp
new file mode 100644
index 000000000..4002a9211
--- /dev/null
+++ b/src/core/frontend/applets/error.cpp
@@ -0,0 +1,34 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/frontend/applets/error.h"
6
7namespace Core::Frontend {
8
9ErrorApplet::~ErrorApplet() = default;
10
11void DefaultErrorApplet::ShowError(ResultCode error, std::function<void()> finished) const {
12 LOG_CRITICAL(Service_Fatal, "Application requested error display: {:04}-{:04} (raw={:08X})",
13 static_cast<u32>(error.module.Value()), error.description.Value(), error.raw);
14}
15
16void DefaultErrorApplet::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
17 std::function<void()> finished) const {
18 LOG_CRITICAL(
19 Service_Fatal,
20 "Application requested error display: {:04X}-{:04X} (raw={:08X}) with timestamp={:016X}",
21 static_cast<u32>(error.module.Value()), error.description.Value(), error.raw, time.count());
22}
23
24void DefaultErrorApplet::ShowCustomErrorText(ResultCode error, std::string main_text,
25 std::string detail_text,
26 std::function<void()> finished) const {
27 LOG_CRITICAL(Service_Fatal,
28 "Application requested custom error with error_code={:04X}-{:04X} (raw={:08X})",
29 static_cast<u32>(error.module.Value()), error.description.Value(), error.raw);
30 LOG_CRITICAL(Service_Fatal, " Main Text: {}", main_text);
31 LOG_CRITICAL(Service_Fatal, " Detail Text: {}", detail_text);
32}
33
34} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/error.h b/src/core/frontend/applets/error.h
new file mode 100644
index 000000000..699df940d
--- /dev/null
+++ b/src/core/frontend/applets/error.h
@@ -0,0 +1,37 @@
1// Copyright 2019 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 <chrono>
8#include <functional>
9
10#include "core/hle/result.h"
11
12namespace Core::Frontend {
13
14class ErrorApplet {
15public:
16 virtual ~ErrorApplet();
17
18 virtual void ShowError(ResultCode error, std::function<void()> finished) const = 0;
19
20 virtual void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
21 std::function<void()> finished) const = 0;
22
23 virtual void ShowCustomErrorText(ResultCode error, std::string dialog_text,
24 std::string fullscreen_text,
25 std::function<void()> finished) const = 0;
26};
27
28class DefaultErrorApplet final : public ErrorApplet {
29public:
30 void ShowError(ResultCode error, std::function<void()> finished) const override;
31 void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
32 std::function<void()> finished) const override;
33 void ShowCustomErrorText(ResultCode error, std::string main_text, std::string detail_text,
34 std::function<void()> finished) const override;
35};
36
37} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/general_frontend.cpp b/src/core/frontend/applets/general_frontend.cpp
new file mode 100644
index 000000000..b974f2289
--- /dev/null
+++ b/src/core/frontend/applets/general_frontend.cpp
@@ -0,0 +1,27 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/logging/log.h"
6#include "core/frontend/applets/general_frontend.h"
7
8namespace Core::Frontend {
9
10PhotoViewerApplet::~PhotoViewerApplet() = default;
11
12DefaultPhotoViewerApplet::~DefaultPhotoViewerApplet() {}
13
14void DefaultPhotoViewerApplet::ShowPhotosForApplication(u64 title_id,
15 std::function<void()> finished) const {
16 LOG_INFO(Service_AM,
17 "Application requested frontend to display stored photos for title_id={:016X}",
18 title_id);
19 finished();
20}
21
22void DefaultPhotoViewerApplet::ShowAllPhotos(std::function<void()> finished) const {
23 LOG_INFO(Service_AM, "Application requested frontend to display all stored photos.");
24 finished();
25}
26
27} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/general_frontend.h b/src/core/frontend/applets/general_frontend.h
new file mode 100644
index 000000000..d4506c999
--- /dev/null
+++ b/src/core/frontend/applets/general_frontend.h
@@ -0,0 +1,28 @@
1// Copyright 2019 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 <functional>
8#include "common/common_types.h"
9
10namespace Core::Frontend {
11
12class PhotoViewerApplet {
13public:
14 virtual ~PhotoViewerApplet();
15
16 virtual void ShowPhotosForApplication(u64 title_id, std::function<void()> finished) const = 0;
17 virtual void ShowAllPhotos(std::function<void()> finished) const = 0;
18};
19
20class DefaultPhotoViewerApplet final : public PhotoViewerApplet {
21public:
22 ~DefaultPhotoViewerApplet() override;
23
24 void ShowPhotosForApplication(u64 title_id, std::function<void()> finished) const override;
25 void ShowAllPhotos(std::function<void()> finished) const override;
26};
27
28} // namespace Core::Frontend
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 4d58e7c69..757e5f21f 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -46,8 +46,7 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_
46 46
47 bool resume = true; 47 bool resume = true;
48 48
49 if (thread->GetStatus() == ThreadStatus::WaitSynchAny || 49 if (thread->GetStatus() == ThreadStatus::WaitSynch ||
50 thread->GetStatus() == ThreadStatus::WaitSynchAll ||
51 thread->GetStatus() == ThreadStatus::WaitHLEEvent) { 50 thread->GetStatus() == ThreadStatus::WaitHLEEvent) {
52 // Remove the thread from each of its waiting objects' waitlists 51 // Remove the thread from each of its waiting objects' waitlists
53 for (const auto& object : thread->GetWaitObjects()) { 52 for (const auto& object : thread->GetWaitObjects()) {
@@ -182,7 +181,12 @@ void KernelCore::AppendNewProcess(SharedPtr<Process> process) {
182 181
183void KernelCore::MakeCurrentProcess(Process* process) { 182void KernelCore::MakeCurrentProcess(Process* process) {
184 impl->current_process = process; 183 impl->current_process = process;
185 Memory::SetCurrentPageTable(&process->VMManager().page_table); 184
185 if (process == nullptr) {
186 return;
187 }
188
189 Memory::SetCurrentPageTable(*process);
186} 190}
187 191
188Process* KernelCore::CurrentProcess() { 192Process* KernelCore::CurrentProcess() {
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 4e94048da..20d01fc88 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -28,21 +28,20 @@ namespace {
28 * 28 *
29 * @param owner_process The parent process for the main thread 29 * @param owner_process The parent process for the main thread
30 * @param kernel The kernel instance to create the main thread under. 30 * @param kernel The kernel instance to create the main thread under.
31 * @param entry_point The address at which the thread should start execution
32 * @param priority The priority to give the main thread 31 * @param priority The priority to give the main thread
33 */ 32 */
34void SetupMainThread(Process& owner_process, KernelCore& kernel, VAddr entry_point, u32 priority) { 33void SetupMainThread(Process& owner_process, KernelCore& kernel, u32 priority) {
35 // Initialize new "main" thread 34 const auto& vm_manager = owner_process.VMManager();
36 const VAddr stack_top = owner_process.VMManager().GetTLSIORegionEndAddress(); 35 const VAddr entry_point = vm_manager.GetCodeRegionBaseAddress();
36 const VAddr stack_top = vm_manager.GetTLSIORegionEndAddress();
37 auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0, 37 auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0,
38 owner_process.GetIdealCore(), stack_top, owner_process); 38 owner_process.GetIdealCore(), stack_top, owner_process);
39 39
40 SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); 40 SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
41 41
42 // Register 1 must be a handle to the main thread 42 // Register 1 must be a handle to the main thread
43 const Handle guest_handle = owner_process.GetHandleTable().Create(thread).Unwrap(); 43 const Handle thread_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
44 thread->SetGuestHandle(guest_handle); 44 thread->GetContext().cpu_registers[1] = thread_handle;
45 thread->GetContext().cpu_registers[1] = guest_handle;
46 45
47 // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires 46 // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
48 thread->ResumeFromWait(); 47 thread->ResumeFromWait();
@@ -106,8 +105,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
106 is_64bit_process = metadata.Is64BitProgram(); 105 is_64bit_process = metadata.Is64BitProgram();
107 106
108 vm_manager.Reset(metadata.GetAddressSpaceType()); 107 vm_manager.Reset(metadata.GetAddressSpaceType());
109 // Ensure that the potentially resized page table is seen by CPU backends.
110 Memory::SetCurrentPageTable(&vm_manager.page_table);
111 108
112 const auto& caps = metadata.GetKernelCapabilities(); 109 const auto& caps = metadata.GetKernelCapabilities();
113 const auto capability_init_result = 110 const auto capability_init_result =
@@ -119,7 +116,7 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
119 return handle_table.SetSize(capabilities.GetHandleTableSize()); 116 return handle_table.SetSize(capabilities.GetHandleTableSize());
120} 117}
121 118
122void Process::Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size) { 119void Process::Run(s32 main_thread_priority, u64 stack_size) {
123 // The kernel always ensures that the given stack size is page aligned. 120 // The kernel always ensures that the given stack size is page aligned.
124 main_thread_stack_size = Common::AlignUp(stack_size, Memory::PAGE_SIZE); 121 main_thread_stack_size = Common::AlignUp(stack_size, Memory::PAGE_SIZE);
125 122
@@ -135,7 +132,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size) {
135 vm_manager.LogLayout(); 132 vm_manager.LogLayout();
136 ChangeStatus(ProcessStatus::Running); 133 ChangeStatus(ProcessStatus::Running);
137 134
138 SetupMainThread(*this, kernel, entry_point, main_thread_priority); 135 SetupMainThread(*this, kernel, main_thread_priority);
139} 136}
140 137
141void Process::PrepareForTermination() { 138void Process::PrepareForTermination() {
@@ -150,8 +147,7 @@ void Process::PrepareForTermination() {
150 continue; 147 continue;
151 148
152 // TODO(Subv): When are the other running/ready threads terminated? 149 // TODO(Subv): When are the other running/ready threads terminated?
153 ASSERT_MSG(thread->GetStatus() == ThreadStatus::WaitSynchAny || 150 ASSERT_MSG(thread->GetStatus() == ThreadStatus::WaitSynch,
154 thread->GetStatus() == ThreadStatus::WaitSynchAll,
155 "Exiting processes with non-waiting threads is currently unimplemented"); 151 "Exiting processes with non-waiting threads is currently unimplemented");
156 152
157 thread->Stop(); 153 thread->Stop();
@@ -242,9 +238,6 @@ void Process::LoadModule(CodeSet module_, VAddr base_addr) {
242 MapSegment(module_.DataSegment(), VMAPermission::ReadWrite, MemoryState::CodeData); 238 MapSegment(module_.DataSegment(), VMAPermission::ReadWrite, MemoryState::CodeData);
243 239
244 code_memory_size += module_.memory.size(); 240 code_memory_size += module_.memory.size();
245
246 // Clear instruction cache in CPU JIT
247 system.InvalidateCpuInstructionCaches();
248} 241}
249 242
250Process::Process(Core::System& system) 243Process::Process(Core::System& system)
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index dda52f4c0..bf3b7eef3 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -225,9 +225,12 @@ public:
225 ResultCode LoadFromMetadata(const FileSys::ProgramMetadata& metadata); 225 ResultCode LoadFromMetadata(const FileSys::ProgramMetadata& metadata);
226 226
227 /** 227 /**
228 * Applies address space changes and launches the process main thread. 228 * Starts the main application thread for this process.
229 *
230 * @param main_thread_priority The priority for the main thread.
231 * @param stack_size The stack size for the main thread in bytes.
229 */ 232 */
230 void Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size); 233 void Run(s32 main_thread_priority, u64 stack_size);
231 234
232 /** 235 /**
233 * Prepares a process for termination by stopping all of its threads 236 * Prepares a process for termination by stopping all of its threads
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index e5d4d6b55..2dcf174c5 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -424,7 +424,7 @@ static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle han
424/// Default thread wakeup callback for WaitSynchronization 424/// Default thread wakeup callback for WaitSynchronization
425static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread, 425static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread,
426 SharedPtr<WaitObject> object, std::size_t index) { 426 SharedPtr<WaitObject> object, std::size_t index) {
427 ASSERT(thread->GetStatus() == ThreadStatus::WaitSynchAny); 427 ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch);
428 428
429 if (reason == ThreadWakeupReason::Timeout) { 429 if (reason == ThreadWakeupReason::Timeout) {
430 thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); 430 thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
@@ -502,7 +502,7 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr
502 } 502 }
503 503
504 thread->SetWaitObjects(std::move(objects)); 504 thread->SetWaitObjects(std::move(objects));
505 thread->SetStatus(ThreadStatus::WaitSynchAny); 505 thread->SetStatus(ThreadStatus::WaitSynch);
506 506
507 // Create an event to wake the thread up after the specified nanosecond delay has passed 507 // Create an event to wake the thread up after the specified nanosecond delay has passed
508 thread->WakeAfterDelay(nano_seconds); 508 thread->WakeAfterDelay(nano_seconds);
@@ -518,16 +518,14 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand
518 LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle); 518 LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
519 519
520 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 520 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
521 const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle); 521 SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
522 if (!thread) { 522 if (!thread) {
523 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}", 523 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
524 thread_handle); 524 thread_handle);
525 return ERR_INVALID_HANDLE; 525 return ERR_INVALID_HANDLE;
526 } 526 }
527 527
528 ASSERT(thread->GetStatus() == ThreadStatus::WaitSynchAny); 528 thread->CancelWait();
529 thread->SetWaitSynchronizationResult(ERR_SYNCHRONIZATION_CANCELED);
530 thread->ResumeFromWait();
531 return RESULT_SUCCESS; 529 return RESULT_SUCCESS;
532} 530}
533 531
@@ -1189,6 +1187,142 @@ static ResultCode QueryMemory(Core::System& system, VAddr memory_info_address,
1189 query_address); 1187 query_address);
1190} 1188}
1191 1189
1190static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
1191 u64 src_address, u64 size) {
1192 LOG_DEBUG(Kernel_SVC,
1193 "called. process_handle=0x{:08X}, dst_address=0x{:016X}, "
1194 "src_address=0x{:016X}, size=0x{:016X}",
1195 process_handle, dst_address, src_address, size);
1196
1197 if (!Common::Is4KBAligned(src_address)) {
1198 LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
1199 src_address);
1200 return ERR_INVALID_ADDRESS;
1201 }
1202
1203 if (!Common::Is4KBAligned(dst_address)) {
1204 LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
1205 dst_address);
1206 return ERR_INVALID_ADDRESS;
1207 }
1208
1209 if (size == 0 || !Common::Is4KBAligned(size)) {
1210 LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X})", size);
1211 return ERR_INVALID_SIZE;
1212 }
1213
1214 if (!IsValidAddressRange(dst_address, size)) {
1215 LOG_ERROR(Kernel_SVC,
1216 "Destination address range overflows the address space (dst_address=0x{:016X}, "
1217 "size=0x{:016X}).",
1218 dst_address, size);
1219 return ERR_INVALID_ADDRESS_STATE;
1220 }
1221
1222 if (!IsValidAddressRange(src_address, size)) {
1223 LOG_ERROR(Kernel_SVC,
1224 "Source address range overflows the address space (src_address=0x{:016X}, "
1225 "size=0x{:016X}).",
1226 src_address, size);
1227 return ERR_INVALID_ADDRESS_STATE;
1228 }
1229
1230 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1231 auto process = handle_table.Get<Process>(process_handle);
1232 if (!process) {
1233 LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
1234 process_handle);
1235 return ERR_INVALID_HANDLE;
1236 }
1237
1238 auto& vm_manager = process->VMManager();
1239 if (!vm_manager.IsWithinAddressSpace(src_address, size)) {
1240 LOG_ERROR(Kernel_SVC,
1241 "Source address range is not within the address space (src_address=0x{:016X}, "
1242 "size=0x{:016X}).",
1243 src_address, size);
1244 return ERR_INVALID_ADDRESS_STATE;
1245 }
1246
1247 if (!vm_manager.IsWithinASLRRegion(dst_address, size)) {
1248 LOG_ERROR(Kernel_SVC,
1249 "Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
1250 "size=0x{:016X}).",
1251 dst_address, size);
1252 return ERR_INVALID_MEMORY_RANGE;
1253 }
1254
1255 return vm_manager.MapCodeMemory(dst_address, src_address, size);
1256}
1257
1258ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
1259 u64 src_address, u64 size) {
1260 LOG_DEBUG(Kernel_SVC,
1261 "called. process_handle=0x{:08X}, dst_address=0x{:016X}, src_address=0x{:016X}, "
1262 "size=0x{:016X}",
1263 process_handle, dst_address, src_address, size);
1264
1265 if (!Common::Is4KBAligned(dst_address)) {
1266 LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
1267 dst_address);
1268 return ERR_INVALID_ADDRESS;
1269 }
1270
1271 if (!Common::Is4KBAligned(src_address)) {
1272 LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
1273 src_address);
1274 return ERR_INVALID_ADDRESS;
1275 }
1276
1277 if (size == 0 || Common::Is4KBAligned(size)) {
1278 LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X}).", size);
1279 return ERR_INVALID_SIZE;
1280 }
1281
1282 if (!IsValidAddressRange(dst_address, size)) {
1283 LOG_ERROR(Kernel_SVC,
1284 "Destination address range overflows the address space (dst_address=0x{:016X}, "
1285 "size=0x{:016X}).",
1286 dst_address, size);
1287 return ERR_INVALID_ADDRESS_STATE;
1288 }
1289
1290 if (!IsValidAddressRange(src_address, size)) {
1291 LOG_ERROR(Kernel_SVC,
1292 "Source address range overflows the address space (src_address=0x{:016X}, "
1293 "size=0x{:016X}).",
1294 src_address, size);
1295 return ERR_INVALID_ADDRESS_STATE;
1296 }
1297
1298 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1299 auto process = handle_table.Get<Process>(process_handle);
1300 if (!process) {
1301 LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
1302 process_handle);
1303 return ERR_INVALID_HANDLE;
1304 }
1305
1306 auto& vm_manager = process->VMManager();
1307 if (!vm_manager.IsWithinAddressSpace(src_address, size)) {
1308 LOG_ERROR(Kernel_SVC,
1309 "Source address range is not within the address space (src_address=0x{:016X}, "
1310 "size=0x{:016X}).",
1311 src_address, size);
1312 return ERR_INVALID_ADDRESS_STATE;
1313 }
1314
1315 if (!vm_manager.IsWithinASLRRegion(dst_address, size)) {
1316 LOG_ERROR(Kernel_SVC,
1317 "Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
1318 "size=0x{:016X}).",
1319 dst_address, size);
1320 return ERR_INVALID_MEMORY_RANGE;
1321 }
1322
1323 return vm_manager.UnmapCodeMemory(dst_address, src_address, size);
1324}
1325
1192/// Exits the current process 1326/// Exits the current process
1193static void ExitProcess(Core::System& system) { 1327static void ExitProcess(Core::System& system) {
1194 auto* current_process = system.Kernel().CurrentProcess(); 1328 auto* current_process = system.Kernel().CurrentProcess();
@@ -1244,20 +1378,22 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
1244 return ERR_INVALID_THREAD_PRIORITY; 1378 return ERR_INVALID_THREAD_PRIORITY;
1245 } 1379 }
1246 1380
1247 const std::string name = fmt::format("thread-{:X}", entry_point);
1248 auto& kernel = system.Kernel(); 1381 auto& kernel = system.Kernel();
1249 CASCADE_RESULT(SharedPtr<Thread> thread, 1382 CASCADE_RESULT(SharedPtr<Thread> thread,
1250 Thread::Create(kernel, name, entry_point, priority, arg, processor_id, stack_top, 1383 Thread::Create(kernel, "", entry_point, priority, arg, processor_id, stack_top,
1251 *current_process)); 1384 *current_process));
1252 1385
1253 const auto new_guest_handle = current_process->GetHandleTable().Create(thread); 1386 const auto new_thread_handle = current_process->GetHandleTable().Create(thread);
1254 if (new_guest_handle.Failed()) { 1387 if (new_thread_handle.Failed()) {
1255 LOG_ERROR(Kernel_SVC, "Failed to create handle with error=0x{:X}", 1388 LOG_ERROR(Kernel_SVC, "Failed to create handle with error=0x{:X}",
1256 new_guest_handle.Code().raw); 1389 new_thread_handle.Code().raw);
1257 return new_guest_handle.Code(); 1390 return new_thread_handle.Code();
1258 } 1391 }
1259 thread->SetGuestHandle(*new_guest_handle); 1392 *out_handle = *new_thread_handle;
1260 *out_handle = *new_guest_handle; 1393
1394 // Set the thread name for debugging purposes.
1395 thread->SetName(
1396 fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle));
1261 1397
1262 system.CpuCore(thread->GetProcessorID()).PrepareReschedule(); 1398 system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
1263 1399
@@ -2152,7 +2288,7 @@ static const FunctionDef SVC_Table[] = {
2152 {0x33, SvcWrap<GetThreadContext>, "GetThreadContext"}, 2288 {0x33, SvcWrap<GetThreadContext>, "GetThreadContext"},
2153 {0x34, SvcWrap<WaitForAddress>, "WaitForAddress"}, 2289 {0x34, SvcWrap<WaitForAddress>, "WaitForAddress"},
2154 {0x35, SvcWrap<SignalToAddress>, "SignalToAddress"}, 2290 {0x35, SvcWrap<SignalToAddress>, "SignalToAddress"},
2155 {0x36, nullptr, "Unknown"}, 2291 {0x36, nullptr, "SynchronizePreemptionState"},
2156 {0x37, nullptr, "Unknown"}, 2292 {0x37, nullptr, "Unknown"},
2157 {0x38, nullptr, "Unknown"}, 2293 {0x38, nullptr, "Unknown"},
2158 {0x39, nullptr, "Unknown"}, 2294 {0x39, nullptr, "Unknown"},
@@ -2217,8 +2353,8 @@ static const FunctionDef SVC_Table[] = {
2217 {0x74, nullptr, "MapProcessMemory"}, 2353 {0x74, nullptr, "MapProcessMemory"},
2218 {0x75, nullptr, "UnmapProcessMemory"}, 2354 {0x75, nullptr, "UnmapProcessMemory"},
2219 {0x76, SvcWrap<QueryProcessMemory>, "QueryProcessMemory"}, 2355 {0x76, SvcWrap<QueryProcessMemory>, "QueryProcessMemory"},
2220 {0x77, nullptr, "MapProcessCodeMemory"}, 2356 {0x77, SvcWrap<MapProcessCodeMemory>, "MapProcessCodeMemory"},
2221 {0x78, nullptr, "UnmapProcessCodeMemory"}, 2357 {0x78, SvcWrap<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"},
2222 {0x79, nullptr, "CreateProcess"}, 2358 {0x79, nullptr, "CreateProcess"},
2223 {0x7A, nullptr, "StartProcess"}, 2359 {0x7A, nullptr, "StartProcess"},
2224 {0x7B, nullptr, "TerminateProcess"}, 2360 {0x7B, nullptr, "TerminateProcess"},
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index b3690b5f3..865473c6f 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -44,6 +44,13 @@ void SvcWrap(Core::System& system) {
44 func(system, static_cast<u32>(Param(system, 0)), static_cast<u32>(Param(system, 1))).raw); 44 func(system, static_cast<u32>(Param(system, 0)), static_cast<u32>(Param(system, 1))).raw);
45} 45}
46 46
47template <ResultCode func(Core::System&, u32, u64, u64, u64)>
48void SvcWrap(Core::System& system) {
49 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
50 Param(system, 2), Param(system, 3))
51 .raw);
52}
53
47template <ResultCode func(Core::System&, u32*)> 54template <ResultCode func(Core::System&, u32*)>
48void SvcWrap(Core::System& system) { 55void SvcWrap(Core::System& system) {
49 u32 param = 0; 56 u32 param = 0;
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 1b891f632..2abf9efca 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -101,8 +101,7 @@ void Thread::ResumeFromWait() {
101 ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects"); 101 ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects");
102 102
103 switch (status) { 103 switch (status) {
104 case ThreadStatus::WaitSynchAll: 104 case ThreadStatus::WaitSynch:
105 case ThreadStatus::WaitSynchAny:
106 case ThreadStatus::WaitHLEEvent: 105 case ThreadStatus::WaitHLEEvent:
107 case ThreadStatus::WaitSleep: 106 case ThreadStatus::WaitSleep:
108 case ThreadStatus::WaitIPC: 107 case ThreadStatus::WaitIPC:
@@ -142,6 +141,12 @@ void Thread::ResumeFromWait() {
142 ChangeScheduler(); 141 ChangeScheduler();
143} 142}
144 143
144void Thread::CancelWait() {
145 ASSERT(GetStatus() == ThreadStatus::WaitSynch);
146 SetWaitSynchronizationResult(ERR_SYNCHRONIZATION_CANCELED);
147 ResumeFromWait();
148}
149
145/** 150/**
146 * Resets a thread context, making it ready to be scheduled and run by the CPU 151 * Resets a thread context, making it ready to be scheduled and run by the CPU
147 * @param context Thread context to reset 152 * @param context Thread context to reset
@@ -220,11 +225,6 @@ void Thread::SetPriority(u32 priority) {
220 UpdatePriority(); 225 UpdatePriority();
221} 226}
222 227
223void Thread::BoostPriority(u32 priority) {
224 scheduler->SetThreadPriority(this, priority);
225 current_priority = priority;
226}
227
228void Thread::SetWaitSynchronizationResult(ResultCode result) { 228void Thread::SetWaitSynchronizationResult(ResultCode result) {
229 context.cpu_registers[0] = result.raw; 229 context.cpu_registers[0] = result.raw;
230} 230}
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 83c83e45a..f07332f02 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -49,8 +49,7 @@ enum class ThreadStatus {
49 WaitHLEEvent, ///< Waiting for hle event to finish 49 WaitHLEEvent, ///< Waiting for hle event to finish
50 WaitSleep, ///< Waiting due to a SleepThread SVC 50 WaitSleep, ///< Waiting due to a SleepThread SVC
51 WaitIPC, ///< Waiting for the reply from an IPC request 51 WaitIPC, ///< Waiting for the reply from an IPC request
52 WaitSynchAny, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false 52 WaitSynch, ///< Waiting due to WaitSynchronization
53 WaitSynchAll, ///< Waiting due to WaitSynchronizationN with wait_all = true
54 WaitMutex, ///< Waiting due to an ArbitrateLock svc 53 WaitMutex, ///< Waiting due to an ArbitrateLock svc
55 WaitCondVar, ///< Waiting due to an WaitProcessWideKey svc 54 WaitCondVar, ///< Waiting due to an WaitProcessWideKey svc
56 WaitArb, ///< Waiting due to a SignalToAddress/WaitForAddress svc 55 WaitArb, ///< Waiting due to a SignalToAddress/WaitForAddress svc
@@ -102,6 +101,11 @@ public:
102 std::string GetName() const override { 101 std::string GetName() const override {
103 return name; 102 return name;
104 } 103 }
104
105 void SetName(std::string new_name) {
106 name = std::move(new_name);
107 }
108
105 std::string GetTypeName() const override { 109 std::string GetTypeName() const override {
106 return "Thread"; 110 return "Thread";
107 } 111 }
@@ -136,12 +140,6 @@ public:
136 */ 140 */
137 void SetPriority(u32 priority); 141 void SetPriority(u32 priority);
138 142
139 /**
140 * Temporarily boosts the thread's priority until the next time it is scheduled
141 * @param priority The new priority
142 */
143 void BoostPriority(u32 priority);
144
145 /// Adds a thread to the list of threads that are waiting for a lock held by this thread. 143 /// Adds a thread to the list of threads that are waiting for a lock held by this thread.
146 void AddMutexWaiter(SharedPtr<Thread> thread); 144 void AddMutexWaiter(SharedPtr<Thread> thread);
147 145
@@ -170,11 +168,17 @@ public:
170 return tls_memory; 168 return tls_memory;
171 } 169 }
172 170
173 /** 171 /// Resumes a thread from waiting
174 * Resumes a thread from waiting
175 */
176 void ResumeFromWait(); 172 void ResumeFromWait();
177 173
174 /// Cancels a waiting operation that this thread may or may not be within.
175 ///
176 /// When the thread is within a waiting state, this will set the thread's
177 /// waiting result to signal a canceled wait. The function will then resume
178 /// this thread.
179 ///
180 void CancelWait();
181
178 /** 182 /**
179 * Schedules an event to wake up the specified thread after the specified delay 183 * Schedules an event to wake up the specified thread after the specified delay
180 * @param nanoseconds The time this thread will be allowed to sleep for 184 * @param nanoseconds The time this thread will be allowed to sleep for
@@ -185,24 +189,27 @@ public:
185 void CancelWakeupTimer(); 189 void CancelWakeupTimer();
186 190
187 /** 191 /**
188 * Sets the result after the thread awakens (from either WaitSynchronization SVC) 192 * Sets the result after the thread awakens (from svcWaitSynchronization)
189 * @param result Value to set to the returned result 193 * @param result Value to set to the returned result
190 */ 194 */
191 void SetWaitSynchronizationResult(ResultCode result); 195 void SetWaitSynchronizationResult(ResultCode result);
192 196
193 /** 197 /**
194 * Sets the output parameter value after the thread awakens (from WaitSynchronizationN SVC only) 198 * Sets the output parameter value after the thread awakens (from svcWaitSynchronization)
195 * @param output Value to set to the output parameter 199 * @param output Value to set to the output parameter
196 */ 200 */
197 void SetWaitSynchronizationOutput(s32 output); 201 void SetWaitSynchronizationOutput(s32 output);
198 202
199 /** 203 /**
200 * Retrieves the index that this particular object occupies in the list of objects 204 * Retrieves the index that this particular object occupies in the list of objects
201 * that the thread passed to WaitSynchronizationN, starting the search from the last element. 205 * that the thread passed to WaitSynchronization, starting the search from the last element.
202 * It is used to set the output value of WaitSynchronizationN when the thread is awakened. 206 *
207 * It is used to set the output index of WaitSynchronization when the thread is awakened.
208 *
203 * When a thread wakes up due to an object signal, the kernel will use the index of the last 209 * When a thread wakes up due to an object signal, the kernel will use the index of the last
204 * matching object in the wait objects list in case of having multiple instances of the same 210 * matching object in the wait objects list in case of having multiple instances of the same
205 * object in the list. 211 * object in the list.
212 *
206 * @param object Object to query the index of. 213 * @param object Object to query the index of.
207 */ 214 */
208 s32 GetWaitObjectIndex(const WaitObject* object) const; 215 s32 GetWaitObjectIndex(const WaitObject* object) const;
@@ -239,13 +246,9 @@ public:
239 */ 246 */
240 VAddr GetCommandBufferAddress() const; 247 VAddr GetCommandBufferAddress() const;
241 248
242 /** 249 /// Returns whether this thread is waiting on objects from a WaitSynchronization call.
243 * Returns whether this thread is waiting for all the objects in 250 bool IsSleepingOnWait() const {
244 * its wait list to become ready, as a result of a WaitSynchronizationN call 251 return status == ThreadStatus::WaitSynch;
245 * with wait_all = true.
246 */
247 bool IsSleepingOnWaitAll() const {
248 return status == ThreadStatus::WaitSynchAll;
249 } 252 }
250 253
251 ThreadContext& GetContext() { 254 ThreadContext& GetContext() {
@@ -345,10 +348,6 @@ public:
345 arb_wait_address = address; 348 arb_wait_address = address;
346 } 349 }
347 350
348 void SetGuestHandle(Handle handle) {
349 guest_handle = handle;
350 }
351
352 bool HasWakeupCallback() const { 351 bool HasWakeupCallback() const {
353 return wakeup_callback != nullptr; 352 return wakeup_callback != nullptr;
354 } 353 }
@@ -423,7 +422,7 @@ private:
423 Process* owner_process; 422 Process* owner_process;
424 423
425 /// Objects that the thread is waiting on, in the same order as they were 424 /// Objects that the thread is waiting on, in the same order as they were
426 /// passed to WaitSynchronization1/N. 425 /// passed to WaitSynchronization.
427 ThreadWaitObjects wait_objects; 426 ThreadWaitObjects wait_objects;
428 427
429 /// List of threads that are waiting for a mutex that is held by this thread. 428 /// List of threads that are waiting for a mutex that is held by this thread.
@@ -442,14 +441,11 @@ private:
442 /// If waiting for an AddressArbiter, this is the address being waited on. 441 /// If waiting for an AddressArbiter, this is the address being waited on.
443 VAddr arb_wait_address{0}; 442 VAddr arb_wait_address{0};
444 443
445 /// Handle used by guest emulated application to access this thread
446 Handle guest_handle = 0;
447
448 /// Handle used as userdata to reference this object when inserting into the CoreTiming queue. 444 /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
449 Handle callback_handle = 0; 445 Handle callback_handle = 0;
450 446
451 /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread 447 /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
452 /// was waiting via WaitSynchronizationN then the object will be the last object that became 448 /// was waiting via WaitSynchronization then the object will be the last object that became
453 /// available. In case of a timeout, the object will be nullptr. 449 /// available. In case of a timeout, the object will be nullptr.
454 WakeupCallback wakeup_callback; 450 WakeupCallback wakeup_callback;
455 451
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index ec0a480ce..f0c0c12fc 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -302,6 +302,86 @@ ResultVal<VAddr> VMManager::SetHeapSize(u64 size) {
302 return MakeResult<VAddr>(heap_region_base); 302 return MakeResult<VAddr>(heap_region_base);
303} 303}
304 304
305ResultCode VMManager::MapCodeMemory(VAddr dst_address, VAddr src_address, u64 size) {
306 constexpr auto ignore_attribute = MemoryAttribute::LockedForIPC | MemoryAttribute::DeviceMapped;
307 const auto src_check_result = CheckRangeState(
308 src_address, size, MemoryState::All, MemoryState::Heap, VMAPermission::All,
309 VMAPermission::ReadWrite, MemoryAttribute::Mask, MemoryAttribute::None, ignore_attribute);
310
311 if (src_check_result.Failed()) {
312 return src_check_result.Code();
313 }
314
315 const auto mirror_result =
316 MirrorMemory(dst_address, src_address, size, MemoryState::ModuleCode);
317 if (mirror_result.IsError()) {
318 return mirror_result;
319 }
320
321 // Ensure we lock the source memory region.
322 const auto src_vma_result = CarveVMARange(src_address, size);
323 if (src_vma_result.Failed()) {
324 return src_vma_result.Code();
325 }
326 auto src_vma_iter = *src_vma_result;
327 src_vma_iter->second.attribute = MemoryAttribute::Locked;
328 Reprotect(src_vma_iter, VMAPermission::Read);
329
330 // The destination memory region is fine as is, however we need to make it read-only.
331 return ReprotectRange(dst_address, size, VMAPermission::Read);
332}
333
334ResultCode VMManager::UnmapCodeMemory(VAddr dst_address, VAddr src_address, u64 size) {
335 constexpr auto ignore_attribute = MemoryAttribute::LockedForIPC | MemoryAttribute::DeviceMapped;
336 const auto src_check_result = CheckRangeState(
337 src_address, size, MemoryState::All, MemoryState::Heap, VMAPermission::None,
338 VMAPermission::None, MemoryAttribute::Mask, MemoryAttribute::Locked, ignore_attribute);
339
340 if (src_check_result.Failed()) {
341 return src_check_result.Code();
342 }
343
344 // Yes, the kernel only checks the first page of the region.
345 const auto dst_check_result =
346 CheckRangeState(dst_address, Memory::PAGE_SIZE, MemoryState::FlagModule,
347 MemoryState::FlagModule, VMAPermission::None, VMAPermission::None,
348 MemoryAttribute::Mask, MemoryAttribute::None, ignore_attribute);
349
350 if (dst_check_result.Failed()) {
351 return dst_check_result.Code();
352 }
353
354 const auto dst_memory_state = std::get<MemoryState>(*dst_check_result);
355 const auto dst_contiguous_check_result = CheckRangeState(
356 dst_address, size, MemoryState::All, dst_memory_state, VMAPermission::None,
357 VMAPermission::None, MemoryAttribute::Mask, MemoryAttribute::None, ignore_attribute);
358
359 if (dst_contiguous_check_result.Failed()) {
360 return dst_contiguous_check_result.Code();
361 }
362
363 const auto unmap_result = UnmapRange(dst_address, size);
364 if (unmap_result.IsError()) {
365 return unmap_result;
366 }
367
368 // With the mirrored portion unmapped, restore the original region's traits.
369 const auto src_vma_result = CarveVMARange(src_address, size);
370 if (src_vma_result.Failed()) {
371 return src_vma_result.Code();
372 }
373 auto src_vma_iter = *src_vma_result;
374 src_vma_iter->second.state = MemoryState::Heap;
375 src_vma_iter->second.attribute = MemoryAttribute::None;
376 Reprotect(src_vma_iter, VMAPermission::ReadWrite);
377
378 if (dst_memory_state == MemoryState::ModuleCode) {
379 Core::System::GetInstance().InvalidateCpuInstructionCaches();
380 }
381
382 return unmap_result;
383}
384
305MemoryInfo VMManager::QueryMemory(VAddr address) const { 385MemoryInfo VMManager::QueryMemory(VAddr address) const {
306 const auto vma = FindVMA(address); 386 const auto vma = FindVMA(address);
307 MemoryInfo memory_info{}; 387 MemoryInfo memory_info{};
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 6f484b7bf..288eb9450 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -43,6 +43,9 @@ enum class VMAPermission : u8 {
43 ReadExecute = Read | Execute, 43 ReadExecute = Read | Execute,
44 WriteExecute = Write | Execute, 44 WriteExecute = Write | Execute,
45 ReadWriteExecute = Read | Write | Execute, 45 ReadWriteExecute = Read | Write | Execute,
46
47 // Used as a wildcard when checking permissions across memory ranges
48 All = 0xFF,
46}; 49};
47 50
48constexpr VMAPermission operator|(VMAPermission lhs, VMAPermission rhs) { 51constexpr VMAPermission operator|(VMAPermission lhs, VMAPermission rhs) {
@@ -152,6 +155,9 @@ enum class MemoryState : u32 {
152 FlagUncached = 1U << 24, 155 FlagUncached = 1U << 24,
153 FlagCodeMemory = 1U << 25, 156 FlagCodeMemory = 1U << 25,
154 157
158 // Wildcard used in range checking to indicate all states.
159 All = 0xFFFFFFFF,
160
155 // Convenience flag sets to reduce repetition 161 // Convenience flag sets to reduce repetition
156 IPCFlags = FlagIPC0 | FlagIPC3 | FlagIPC1, 162 IPCFlags = FlagIPC0 | FlagIPC3 | FlagIPC1,
157 163
@@ -415,6 +421,49 @@ public:
415 /// 421 ///
416 ResultVal<VAddr> SetHeapSize(u64 size); 422 ResultVal<VAddr> SetHeapSize(u64 size);
417 423
424 /// Maps a region of memory as code memory.
425 ///
426 /// @param dst_address The base address of the region to create the aliasing memory region.
427 /// @param src_address The base address of the region to be aliased.
428 /// @param size The total amount of memory to map in bytes.
429 ///
430 /// @pre Both memory regions lie within the actual addressable address space.
431 ///
432 /// @post After this function finishes execution, assuming success, then the address range
433 /// [dst_address, dst_address+size) will alias the memory region,
434 /// [src_address, src_address+size).
435 /// <p>
436 /// What this also entails is as follows:
437 /// 1. The aliased region gains the Locked memory attribute.
438 /// 2. The aliased region becomes read-only.
439 /// 3. The aliasing region becomes read-only.
440 /// 4. The aliasing region is created with a memory state of MemoryState::CodeModule.
441 ///
442 ResultCode MapCodeMemory(VAddr dst_address, VAddr src_address, u64 size);
443
444 /// Unmaps a region of memory designated as code module memory.
445 ///
446 /// @param dst_address The base address of the memory region aliasing the source memory region.
447 /// @param src_address The base address of the memory region being aliased.
448 /// @param size The size of the memory region to unmap in bytes.
449 ///
450 /// @pre Both memory ranges lie within the actual addressable address space.
451 ///
452 /// @pre The memory region being unmapped has been previously been mapped
453 /// by a call to MapCodeMemory.
454 ///
455 /// @post After execution of the function, if successful. the aliasing memory region
456 /// will be unmapped and the aliased region will have various traits about it
457 /// restored to what they were prior to the original mapping call preceding
458 /// this function call.
459 /// <p>
460 /// What this also entails is as follows:
461 /// 1. The state of the memory region will now indicate a general heap region.
462 /// 2. All memory attributes for the memory region are cleared.
463 /// 3. Memory permissions for the region are restored to user read/write.
464 ///
465 ResultCode UnmapCodeMemory(VAddr dst_address, VAddr src_address, u64 size);
466
418 /// Queries the memory manager for information about the given address. 467 /// Queries the memory manager for information about the given address.
419 /// 468 ///
420 /// @param address The address to query the memory manager about for information. 469 /// @param address The address to query the memory manager about for information.
diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp
index 90580ed93..0e96ba872 100644
--- a/src/core/hle/kernel/wait_object.cpp
+++ b/src/core/hle/kernel/wait_object.cpp
@@ -30,7 +30,7 @@ void WaitObject::RemoveWaitingThread(Thread* thread) {
30 waiting_threads.erase(itr); 30 waiting_threads.erase(itr);
31} 31}
32 32
33SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() { 33SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() const {
34 Thread* candidate = nullptr; 34 Thread* candidate = nullptr;
35 u32 candidate_priority = THREADPRIO_LOWEST + 1; 35 u32 candidate_priority = THREADPRIO_LOWEST + 1;
36 36
@@ -38,8 +38,7 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
38 const ThreadStatus thread_status = thread->GetStatus(); 38 const ThreadStatus thread_status = thread->GetStatus();
39 39
40 // The list of waiting threads must not contain threads that are not waiting to be awakened. 40 // The list of waiting threads must not contain threads that are not waiting to be awakened.
41 ASSERT_MSG(thread_status == ThreadStatus::WaitSynchAny || 41 ASSERT_MSG(thread_status == ThreadStatus::WaitSynch ||
42 thread_status == ThreadStatus::WaitSynchAll ||
43 thread_status == ThreadStatus::WaitHLEEvent, 42 thread_status == ThreadStatus::WaitHLEEvent,
44 "Inconsistent thread statuses in waiting_threads"); 43 "Inconsistent thread statuses in waiting_threads");
45 44
@@ -49,10 +48,10 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
49 if (ShouldWait(thread.get())) 48 if (ShouldWait(thread.get()))
50 continue; 49 continue;
51 50
52 // A thread is ready to run if it's either in ThreadStatus::WaitSynchAny or 51 // A thread is ready to run if it's either in ThreadStatus::WaitSynch
53 // in ThreadStatus::WaitSynchAll and the rest of the objects it is waiting on are ready. 52 // and the rest of the objects it is waiting on are ready.
54 bool ready_to_run = true; 53 bool ready_to_run = true;
55 if (thread_status == ThreadStatus::WaitSynchAll) { 54 if (thread_status == ThreadStatus::WaitSynch) {
56 ready_to_run = thread->AllWaitObjectsReady(); 55 ready_to_run = thread->AllWaitObjectsReady();
57 } 56 }
58 57
@@ -68,33 +67,35 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
68void WaitObject::WakeupWaitingThread(SharedPtr<Thread> thread) { 67void WaitObject::WakeupWaitingThread(SharedPtr<Thread> thread) {
69 ASSERT(!ShouldWait(thread.get())); 68 ASSERT(!ShouldWait(thread.get()));
70 69
71 if (!thread) 70 if (!thread) {
72 return; 71 return;
72 }
73 73
74 if (!thread->IsSleepingOnWaitAll()) { 74 if (thread->IsSleepingOnWait()) {
75 Acquire(thread.get());
76 } else {
77 for (const auto& object : thread->GetWaitObjects()) { 75 for (const auto& object : thread->GetWaitObjects()) {
78 ASSERT(!object->ShouldWait(thread.get())); 76 ASSERT(!object->ShouldWait(thread.get()));
79 object->Acquire(thread.get()); 77 object->Acquire(thread.get());
80 } 78 }
79 } else {
80 Acquire(thread.get());
81 } 81 }
82 82
83 const std::size_t index = thread->GetWaitObjectIndex(this); 83 const std::size_t index = thread->GetWaitObjectIndex(this);
84 84
85 for (const auto& object : thread->GetWaitObjects()) 85 for (const auto& object : thread->GetWaitObjects()) {
86 object->RemoveWaitingThread(thread.get()); 86 object->RemoveWaitingThread(thread.get());
87 }
87 thread->ClearWaitObjects(); 88 thread->ClearWaitObjects();
88 89
89 thread->CancelWakeupTimer(); 90 thread->CancelWakeupTimer();
90 91
91 bool resume = true; 92 bool resume = true;
92 93 if (thread->HasWakeupCallback()) {
93 if (thread->HasWakeupCallback())
94 resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Signal, thread, this, index); 94 resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Signal, thread, this, index);
95 95 }
96 if (resume) 96 if (resume) {
97 thread->ResumeFromWait(); 97 thread->ResumeFromWait();
98 }
98} 99}
99 100
100void WaitObject::WakeupAllWaitingThreads() { 101void WaitObject::WakeupAllWaitingThreads() {
diff --git a/src/core/hle/kernel/wait_object.h b/src/core/hle/kernel/wait_object.h
index 04464a51a..3271a30a7 100644
--- a/src/core/hle/kernel/wait_object.h
+++ b/src/core/hle/kernel/wait_object.h
@@ -54,7 +54,7 @@ public:
54 void WakeupWaitingThread(SharedPtr<Thread> thread); 54 void WakeupWaitingThread(SharedPtr<Thread> thread);
55 55
56 /// Obtains the highest priority thread that is ready to run from this object's waiting list. 56 /// Obtains the highest priority thread that is ready to run from this object's waiting list.
57 SharedPtr<Thread> GetHighestPriorityReadyThread(); 57 SharedPtr<Thread> GetHighestPriorityReadyThread() const;
58 58
59 /// Get a const reference to the waiting threads list for debug use 59 /// Get a const reference to the waiting threads list for debug use
60 const std::vector<SharedPtr<Thread>>& GetWaitingThreads() const; 60 const std::vector<SharedPtr<Thread>>& GetWaitingThreads() const;
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 1f8ed265e..ba7d7acbd 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -137,6 +137,7 @@ private:
137class IManagerForApplication final : public ServiceFramework<IManagerForApplication> { 137class IManagerForApplication final : public ServiceFramework<IManagerForApplication> {
138public: 138public:
139 IManagerForApplication() : ServiceFramework("IManagerForApplication") { 139 IManagerForApplication() : ServiceFramework("IManagerForApplication") {
140 // clang-format off
140 static const FunctionInfo functions[] = { 141 static const FunctionInfo functions[] = {
141 {0, &IManagerForApplication::CheckAvailability, "CheckAvailability"}, 142 {0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
142 {1, &IManagerForApplication::GetAccountId, "GetAccountId"}, 143 {1, &IManagerForApplication::GetAccountId, "GetAccountId"},
@@ -145,7 +146,10 @@ public:
145 {130, nullptr, "GetNintendoAccountUserResourceCacheForApplication"}, 146 {130, nullptr, "GetNintendoAccountUserResourceCacheForApplication"},
146 {150, nullptr, "CreateAuthorizationRequest"}, 147 {150, nullptr, "CreateAuthorizationRequest"},
147 {160, nullptr, "StoreOpenContext"}, 148 {160, nullptr, "StoreOpenContext"},
149 {170, nullptr, "LoadNetworkServiceLicenseKindAsync"},
148 }; 150 };
151 // clang-format on
152
149 RegisterHandlers(functions); 153 RegisterHandlers(functions);
150 } 154 }
151 155
diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp
index 5e2030355..d66233cad 100644
--- a/src/core/hle/service/acc/acc_su.cpp
+++ b/src/core/hle/service/acc/acc_su.cpp
@@ -8,6 +8,7 @@ namespace Service::Account {
8 8
9ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager) 9ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager)
10 : Module::Interface(std::move(module), std::move(profile_manager), "acc:su") { 10 : Module::Interface(std::move(module), std::move(profile_manager), "acc:su") {
11 // clang-format off
11 static const FunctionInfo functions[] = { 12 static const FunctionInfo functions[] = {
12 {0, &ACC_SU::GetUserCount, "GetUserCount"}, 13 {0, &ACC_SU::GetUserCount, "GetUserCount"},
13 {1, &ACC_SU::GetUserExistence, "GetUserExistence"}, 14 {1, &ACC_SU::GetUserExistence, "GetUserExistence"},
@@ -19,6 +20,7 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
19 {50, &ACC_SU::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, 20 {50, &ACC_SU::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
20 {51, &ACC_SU::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, 21 {51, &ACC_SU::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
21 {60, nullptr, "ListOpenContextStoredUsers"}, 22 {60, nullptr, "ListOpenContextStoredUsers"},
23 {99, nullptr, "DebugActivateOpenContextRetention"},
22 {100, nullptr, "GetUserRegistrationNotifier"}, 24 {100, nullptr, "GetUserRegistrationNotifier"},
23 {101, nullptr, "GetUserStateChangeNotifier"}, 25 {101, nullptr, "GetUserStateChangeNotifier"},
24 {102, nullptr, "GetBaasAccountManagerForSystemService"}, 26 {102, nullptr, "GetBaasAccountManagerForSystemService"},
@@ -29,6 +31,8 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
29 {111, nullptr, "ClearSaveDataThumbnail"}, 31 {111, nullptr, "ClearSaveDataThumbnail"},
30 {112, nullptr, "LoadSaveDataThumbnail"}, 32 {112, nullptr, "LoadSaveDataThumbnail"},
31 {113, nullptr, "GetSaveDataThumbnailExistence"}, 33 {113, nullptr, "GetSaveDataThumbnailExistence"},
34 {130, nullptr, "ActivateOpenContextRetention"},
35 {140, nullptr, "ListQualifiedUsers"},
32 {190, nullptr, "GetUserLastOpenedApplication"}, 36 {190, nullptr, "GetUserLastOpenedApplication"},
33 {191, nullptr, "ActivateOpenContextHolder"}, 37 {191, nullptr, "ActivateOpenContextHolder"},
34 {200, nullptr, "BeginUserRegistration"}, 38 {200, nullptr, "BeginUserRegistration"},
@@ -48,6 +52,8 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
48 {998, nullptr, "DebugSetUserStateClose"}, 52 {998, nullptr, "DebugSetUserStateClose"},
49 {999, nullptr, "DebugSetUserStateOpen"}, 53 {999, nullptr, "DebugSetUserStateOpen"},
50 }; 54 };
55 // clang-format on
56
51 RegisterHandlers(functions); 57 RegisterHandlers(functions);
52} 58}
53 59
diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp
index a4d705b45..182f7c7e5 100644
--- a/src/core/hle/service/acc/acc_u0.cpp
+++ b/src/core/hle/service/acc/acc_u0.cpp
@@ -8,6 +8,7 @@ namespace Service::Account {
8 8
9ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager) 9ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager)
10 : Module::Interface(std::move(module), std::move(profile_manager), "acc:u0") { 10 : Module::Interface(std::move(module), std::move(profile_manager), "acc:u0") {
11 // clang-format off
11 static const FunctionInfo functions[] = { 12 static const FunctionInfo functions[] = {
12 {0, &ACC_U0::GetUserCount, "GetUserCount"}, 13 {0, &ACC_U0::GetUserCount, "GetUserCount"},
13 {1, &ACC_U0::GetUserExistence, "GetUserExistence"}, 14 {1, &ACC_U0::GetUserExistence, "GetUserExistence"},
@@ -19,6 +20,7 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
19 {50, &ACC_U0::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, 20 {50, &ACC_U0::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
20 {51, &ACC_U0::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, 21 {51, &ACC_U0::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
21 {60, nullptr, "ListOpenContextStoredUsers"}, 22 {60, nullptr, "ListOpenContextStoredUsers"},
23 {99, nullptr, "DebugActivateOpenContextRetention"},
22 {100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"}, 24 {100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"},
23 {101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"}, 25 {101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"},
24 {102, nullptr, "AuthenticateApplicationAsync"}, 26 {102, nullptr, "AuthenticateApplicationAsync"},
@@ -27,7 +29,13 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
27 {111, nullptr, "ClearSaveDataThumbnail"}, 29 {111, nullptr, "ClearSaveDataThumbnail"},
28 {120, nullptr, "CreateGuestLoginRequest"}, 30 {120, nullptr, "CreateGuestLoginRequest"},
29 {130, nullptr, "LoadOpenContext"}, 31 {130, nullptr, "LoadOpenContext"},
32 {131, nullptr, "ListOpenContextStoredUsers"},
33 {140, nullptr, "InitializeApplicationInfo"},
34 {141, nullptr, "ListQualifiedUsers"},
35 {150, nullptr, "IsUserAccountSwitchLocked"},
30 }; 36 };
37 // clang-format on
38
31 RegisterHandlers(functions); 39 RegisterHandlers(functions);
32} 40}
33 41
diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp
index 8fffc93b5..2dd17d935 100644
--- a/src/core/hle/service/acc/acc_u1.cpp
+++ b/src/core/hle/service/acc/acc_u1.cpp
@@ -8,6 +8,7 @@ namespace Service::Account {
8 8
9ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager) 9ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager)
10 : Module::Interface(std::move(module), std::move(profile_manager), "acc:u1") { 10 : Module::Interface(std::move(module), std::move(profile_manager), "acc:u1") {
11 // clang-format off
11 static const FunctionInfo functions[] = { 12 static const FunctionInfo functions[] = {
12 {0, &ACC_U1::GetUserCount, "GetUserCount"}, 13 {0, &ACC_U1::GetUserCount, "GetUserCount"},
13 {1, &ACC_U1::GetUserExistence, "GetUserExistence"}, 14 {1, &ACC_U1::GetUserExistence, "GetUserExistence"},
@@ -19,6 +20,7 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
19 {50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, 20 {50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
20 {51, &ACC_U1::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, 21 {51, &ACC_U1::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
21 {60, nullptr, "ListOpenContextStoredUsers"}, 22 {60, nullptr, "ListOpenContextStoredUsers"},
23 {99, nullptr, "DebugActivateOpenContextRetention"},
22 {100, nullptr, "GetUserRegistrationNotifier"}, 24 {100, nullptr, "GetUserRegistrationNotifier"},
23 {101, nullptr, "GetUserStateChangeNotifier"}, 25 {101, nullptr, "GetUserStateChangeNotifier"},
24 {102, nullptr, "GetBaasAccountManagerForSystemService"}, 26 {102, nullptr, "GetBaasAccountManagerForSystemService"},
@@ -29,12 +31,16 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
29 {111, nullptr, "ClearSaveDataThumbnail"}, 31 {111, nullptr, "ClearSaveDataThumbnail"},
30 {112, nullptr, "LoadSaveDataThumbnail"}, 32 {112, nullptr, "LoadSaveDataThumbnail"},
31 {113, nullptr, "GetSaveDataThumbnailExistence"}, 33 {113, nullptr, "GetSaveDataThumbnailExistence"},
34 {130, nullptr, "ActivateOpenContextRetention"},
35 {140, nullptr, "ListQualifiedUsers"},
32 {190, nullptr, "GetUserLastOpenedApplication"}, 36 {190, nullptr, "GetUserLastOpenedApplication"},
33 {191, nullptr, "ActivateOpenContextHolder"}, 37 {191, nullptr, "ActivateOpenContextHolder"},
34 {997, nullptr, "DebugInvalidateTokenCacheForUser"}, 38 {997, nullptr, "DebugInvalidateTokenCacheForUser"},
35 {998, nullptr, "DebugSetUserStateClose"}, 39 {998, nullptr, "DebugSetUserStateClose"},
36 {999, nullptr, "DebugSetUserStateOpen"}, 40 {999, nullptr, "DebugSetUserStateOpen"},
37 }; 41 };
42 // clang-format on
43
38 RegisterHandlers(functions); 44 RegisterHandlers(functions);
39} 45}
40 46
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 85271d418..26a665bfd 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -22,7 +22,6 @@
22#include "core/hle/service/am/applets/applets.h" 22#include "core/hle/service/am/applets/applets.h"
23#include "core/hle/service/am/applets/profile_select.h" 23#include "core/hle/service/am/applets/profile_select.h"
24#include "core/hle/service/am/applets/software_keyboard.h" 24#include "core/hle/service/am/applets/software_keyboard.h"
25#include "core/hle/service/am/applets/stub_applet.h"
26#include "core/hle/service/am/applets/web_browser.h" 25#include "core/hle/service/am/applets/web_browser.h"
27#include "core/hle/service/am/idle.h" 26#include "core/hle/service/am/idle.h"
28#include "core/hle/service/am/omm.h" 27#include "core/hle/service/am/omm.h"
@@ -42,12 +41,6 @@ constexpr ResultCode ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 0x2};
42constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 0x3}; 41constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 0x3};
43constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7}; 42constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7};
44 43
45enum class AppletId : u32 {
46 ProfileSelect = 0x10,
47 SoftwareKeyboard = 0x11,
48 LibAppletOff = 0x17,
49};
50
51constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA; 44constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA;
52 45
53struct LaunchParameters { 46struct LaunchParameters {
@@ -224,6 +217,7 @@ IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} {
224 {20, nullptr, "InvalidateTransitionLayer"}, 217 {20, nullptr, "InvalidateTransitionLayer"},
225 {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, 218 {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
226 {40, nullptr, "GetAppletResourceUsageInfo"}, 219 {40, nullptr, "GetAppletResourceUsageInfo"},
220 {41, nullptr, "SetCpuBoostModeForApplet"},
227 }; 221 };
228 // clang-format on 222 // clang-format on
229 223
@@ -256,6 +250,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
256 {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, 250 {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
257 {41, nullptr, "IsSystemBufferSharingEnabled"}, 251 {41, nullptr, "IsSystemBufferSharingEnabled"},
258 {42, nullptr, "GetSystemSharedLayerHandle"}, 252 {42, nullptr, "GetSystemSharedLayerHandle"},
253 {43, nullptr, "GetSystemSharedBufferHandle"},
259 {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"}, 254 {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
260 {51, nullptr, "ApproveToDisplay"}, 255 {51, nullptr, "ApproveToDisplay"},
261 {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"}, 256 {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
@@ -269,9 +264,11 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
269 {68, nullptr, "SetAutoSleepDisabled"}, 264 {68, nullptr, "SetAutoSleepDisabled"},
270 {69, nullptr, "IsAutoSleepDisabled"}, 265 {69, nullptr, "IsAutoSleepDisabled"},
271 {70, nullptr, "ReportMultimediaError"}, 266 {70, nullptr, "ReportMultimediaError"},
267 {71, nullptr, "GetCurrentIlluminanceEx"},
272 {80, nullptr, "SetWirelessPriorityMode"}, 268 {80, nullptr, "SetWirelessPriorityMode"},
273 {90, nullptr, "GetAccumulatedSuspendedTickValue"}, 269 {90, nullptr, "GetAccumulatedSuspendedTickValue"},
274 {91, nullptr, "GetAccumulatedSuspendedTickChangedEvent"}, 270 {91, nullptr, "GetAccumulatedSuspendedTickChangedEvent"},
271 {100, nullptr, "SetAlbumImageTakenNotificationEnabled"},
275 {1000, nullptr, "GetDebugStorageChannel"}, 272 {1000, nullptr, "GetDebugStorageChannel"},
276 }; 273 };
277 // clang-format on 274 // clang-format on
@@ -516,11 +513,20 @@ ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_q
516 {50, nullptr, "IsVrModeEnabled"}, 513 {50, nullptr, "IsVrModeEnabled"},
517 {51, nullptr, "SetVrModeEnabled"}, 514 {51, nullptr, "SetVrModeEnabled"},
518 {52, nullptr, "SwitchLcdBacklight"}, 515 {52, nullptr, "SwitchLcdBacklight"},
516 {53, nullptr, "BeginVrModeEx"},
517 {54, nullptr, "EndVrModeEx"},
519 {55, nullptr, "IsInControllerFirmwareUpdateSection"}, 518 {55, nullptr, "IsInControllerFirmwareUpdateSection"},
520 {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"}, 519 {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
521 {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"}, 520 {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
522 {62, nullptr, "GetHdcpAuthenticationState"}, 521 {62, nullptr, "GetHdcpAuthenticationState"},
523 {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"}, 522 {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
523 {64, nullptr, "SetTvPowerStateMatchingMode"},
524 {65, nullptr, "GetApplicationIdByContentActionName"},
525 {66, nullptr, "SetCpuBoostMode"},
526 {80, nullptr, "PerformSystemButtonPressingIfInFocus"},
527 {90, nullptr, "SetPerformanceConfigurationChangedNotification"},
528 {91, nullptr, "GetCurrentPerformanceConfiguration"},
529 {200, nullptr, "GetOperationModeSystemInfo"},
524 }; 530 };
525 // clang-format on 531 // clang-format on
526 532
@@ -873,30 +879,16 @@ ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryApple
873 879
874ILibraryAppletCreator::~ILibraryAppletCreator() = default; 880ILibraryAppletCreator::~ILibraryAppletCreator() = default;
875 881
876static std::shared_ptr<Applets::Applet> GetAppletFromId(AppletId id) {
877 switch (id) {
878 case AppletId::ProfileSelect:
879 return std::make_shared<Applets::ProfileSelect>();
880 case AppletId::SoftwareKeyboard:
881 return std::make_shared<Applets::SoftwareKeyboard>();
882 case AppletId::LibAppletOff:
883 return std::make_shared<Applets::WebBrowser>();
884 default:
885 LOG_ERROR(Service_AM, "Unimplemented AppletId [{:08X}]! -- Falling back to stub!",
886 static_cast<u32>(id));
887 return std::make_shared<Applets::StubApplet>();
888 }
889}
890
891void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) { 882void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
892 IPC::RequestParser rp{ctx}; 883 IPC::RequestParser rp{ctx};
893 const auto applet_id = rp.PopRaw<AppletId>(); 884 const auto applet_id = rp.PopRaw<Applets::AppletId>();
894 const auto applet_mode = rp.PopRaw<u32>(); 885 const auto applet_mode = rp.PopRaw<u32>();
895 886
896 LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", 887 LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}",
897 static_cast<u32>(applet_id), applet_mode); 888 static_cast<u32>(applet_id), applet_mode);
898 889
899 const auto applet = GetAppletFromId(applet_id); 890 const auto& applet_manager{Core::System::GetInstance().GetAppletManager()};
891 const auto applet = applet_manager.GetApplet(applet_id);
900 892
901 if (applet == nullptr) { 893 if (applet == nullptr) {
902 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id)); 894 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id));
@@ -960,6 +952,8 @@ IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationF
960 {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"}, 952 {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
961 {12, nullptr, "CreateApplicationAndRequestToStart"}, 953 {12, nullptr, "CreateApplicationAndRequestToStart"},
962 {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"}, 954 {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"},
955 {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
956 {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
963 {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"}, 957 {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
964 {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"}, 958 {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
965 {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, 959 {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
@@ -1233,6 +1227,7 @@ IGlobalStateController::IGlobalStateController() : ServiceFramework("IGlobalStat
1233 {2, nullptr, "StartSleepSequence"}, 1227 {2, nullptr, "StartSleepSequence"},
1234 {3, nullptr, "StartShutdownSequence"}, 1228 {3, nullptr, "StartShutdownSequence"},
1235 {4, nullptr, "StartRebootSequence"}, 1229 {4, nullptr, "StartRebootSequence"},
1230 {9, nullptr, "IsAutoPowerDownRequested"},
1236 {10, nullptr, "LoadAndApplyIdlePolicySettings"}, 1231 {10, nullptr, "LoadAndApplyIdlePolicySettings"},
1237 {11, nullptr, "NotifyCecSettingsChanged"}, 1232 {11, nullptr, "NotifyCecSettingsChanged"},
1238 {12, nullptr, "SetDefaultHomeButtonLongPressTime"}, 1233 {12, nullptr, "SetDefaultHomeButtonLongPressTime"},
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp
index b888f861d..488add8e7 100644
--- a/src/core/hle/service/am/applet_ae.cpp
+++ b/src/core/hle/service/am/applet_ae.cpp
@@ -16,6 +16,7 @@ public:
16 std::shared_ptr<AppletMessageQueue> msg_queue) 16 std::shared_ptr<AppletMessageQueue> msg_queue)
17 : ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)), 17 : ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)),
18 msg_queue(std::move(msg_queue)) { 18 msg_queue(std::move(msg_queue)) {
19 // clang-format off
19 static const FunctionInfo functions[] = { 20 static const FunctionInfo functions[] = {
20 {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, 21 {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
21 {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"}, 22 {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"},
@@ -25,8 +26,11 @@ public:
25 {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"}, 26 {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
26 {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, 27 {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
27 {20, &ILibraryAppletProxy::GetApplicationFunctions, "GetApplicationFunctions"}, 28 {20, &ILibraryAppletProxy::GetApplicationFunctions, "GetApplicationFunctions"},
29 {21, nullptr, "GetAppletCommonFunctions"},
28 {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, 30 {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
29 }; 31 };
32 // clang-format on
33
30 RegisterHandlers(functions); 34 RegisterHandlers(functions);
31 } 35 }
32 36
@@ -113,6 +117,7 @@ public:
113 std::shared_ptr<AppletMessageQueue> msg_queue) 117 std::shared_ptr<AppletMessageQueue> msg_queue)
114 : ServiceFramework("ISystemAppletProxy"), nvflinger(std::move(nvflinger)), 118 : ServiceFramework("ISystemAppletProxy"), nvflinger(std::move(nvflinger)),
115 msg_queue(std::move(msg_queue)) { 119 msg_queue(std::move(msg_queue)) {
120 // clang-format off
116 static const FunctionInfo functions[] = { 121 static const FunctionInfo functions[] = {
117 {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, 122 {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
118 {1, &ISystemAppletProxy::GetSelfController, "GetSelfController"}, 123 {1, &ISystemAppletProxy::GetSelfController, "GetSelfController"},
@@ -124,8 +129,11 @@ public:
124 {20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"}, 129 {20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
125 {21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"}, 130 {21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
126 {22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"}, 131 {22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"},
132 {23, nullptr, "GetAppletCommonFunctions"},
127 {1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, 133 {1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
128 }; 134 };
135 // clang-format on
136
129 RegisterHandlers(functions); 137 RegisterHandlers(functions);
130 } 138 }
131 139
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index a6064c63f..7f70b10df 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -5,11 +5,21 @@
5#include <cstring> 5#include <cstring>
6#include "common/assert.h" 6#include "common/assert.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/frontend/applets/error.h"
9#include "core/frontend/applets/general_frontend.h"
10#include "core/frontend/applets/profile_select.h"
11#include "core/frontend/applets/software_keyboard.h"
12#include "core/frontend/applets/web_browser.h"
8#include "core/hle/kernel/readable_event.h" 13#include "core/hle/kernel/readable_event.h"
9#include "core/hle/kernel/server_session.h" 14#include "core/hle/kernel/server_session.h"
10#include "core/hle/kernel/writable_event.h" 15#include "core/hle/kernel/writable_event.h"
11#include "core/hle/service/am/am.h" 16#include "core/hle/service/am/am.h"
12#include "core/hle/service/am/applets/applets.h" 17#include "core/hle/service/am/applets/applets.h"
18#include "core/hle/service/am/applets/error.h"
19#include "core/hle/service/am/applets/general_backend.h"
20#include "core/hle/service/am/applets/profile_select.h"
21#include "core/hle/service/am/applets/software_keyboard.h"
22#include "core/hle/service/am/applets/web_browser.h"
13 23
14namespace Service::AM::Applets { 24namespace Service::AM::Applets {
15 25
@@ -111,4 +121,76 @@ void Applet::Initialize() {
111 initialized = true; 121 initialized = true;
112} 122}
113 123
124AppletManager::AppletManager() = default;
125
126AppletManager::~AppletManager() = default;
127
128void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) {
129 if (set.error != nullptr)
130 frontend.error = std::move(set.error);
131 if (set.photo_viewer != nullptr)
132 frontend.photo_viewer = std::move(set.photo_viewer);
133 if (set.profile_select != nullptr)
134 frontend.profile_select = std::move(set.profile_select);
135 if (set.software_keyboard != nullptr)
136 frontend.software_keyboard = std::move(set.software_keyboard);
137 if (set.web_browser != nullptr)
138 frontend.web_browser = std::move(set.web_browser);
139}
140
141void AppletManager::SetDefaultAppletFrontendSet() {
142 frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
143 frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
144 frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
145 frontend.software_keyboard = std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
146 frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
147}
148
149void AppletManager::SetDefaultAppletsIfMissing() {
150 if (frontend.error == nullptr) {
151 frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
152 }
153
154 if (frontend.photo_viewer == nullptr) {
155 frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
156 }
157
158 if (frontend.profile_select == nullptr) {
159 frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
160 }
161
162 if (frontend.software_keyboard == nullptr) {
163 frontend.software_keyboard =
164 std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
165 }
166
167 if (frontend.web_browser == nullptr) {
168 frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
169 }
170}
171
172void AppletManager::ClearAll() {
173 frontend = {};
174}
175
176std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const {
177 switch (id) {
178 case AppletId::Error:
179 return std::make_shared<Error>(*frontend.error);
180 case AppletId::ProfileSelect:
181 return std::make_shared<ProfileSelect>(*frontend.profile_select);
182 case AppletId::SoftwareKeyboard:
183 return std::make_shared<SoftwareKeyboard>(*frontend.software_keyboard);
184 case AppletId::PhotoViewer:
185 return std::make_shared<PhotoViewer>(*frontend.photo_viewer);
186 case AppletId::LibAppletOff:
187 return std::make_shared<WebBrowser>(*frontend.web_browser);
188 default:
189 UNIMPLEMENTED_MSG(
190 "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.",
191 static_cast<u8>(id));
192 return std::make_shared<StubApplet>();
193 }
194}
195
114} // namespace Service::AM::Applets 196} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index 37424c379..7f932672c 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -12,12 +12,43 @@
12 12
13union ResultCode; 13union ResultCode;
14 14
15namespace Core::Frontend {
16class ErrorApplet;
17class PhotoViewerApplet;
18class ProfileSelectApplet;
19class SoftwareKeyboardApplet;
20class WebBrowserApplet;
21} // namespace Core::Frontend
22
15namespace Service::AM { 23namespace Service::AM {
16 24
17class IStorage; 25class IStorage;
18 26
19namespace Applets { 27namespace Applets {
20 28
29enum class AppletId : u32 {
30 OverlayDisplay = 0x02,
31 QLaunch = 0x03,
32 Starter = 0x04,
33 Auth = 0x0A,
34 Cabinet = 0x0B,
35 Controller = 0x0C,
36 DataErase = 0x0D,
37 Error = 0x0E,
38 NetConnect = 0x0F,
39 ProfileSelect = 0x10,
40 SoftwareKeyboard = 0x11,
41 MiiEdit = 0x12,
42 LibAppletWeb = 0x13,
43 LibAppletShop = 0x14,
44 PhotoViewer = 0x15,
45 Settings = 0x16,
46 LibAppletOff = 0x17,
47 LibAppletWhitelisted = 0x18,
48 LibAppletAuth = 0x19,
49 MyPage = 0x1A,
50};
51
21class AppletDataBroker final { 52class AppletDataBroker final {
22public: 53public:
23 AppletDataBroker(); 54 AppletDataBroker();
@@ -105,5 +136,29 @@ protected:
105 bool initialized = false; 136 bool initialized = false;
106}; 137};
107 138
139struct AppletFrontendSet {
140 std::unique_ptr<Core::Frontend::ErrorApplet> error;
141 std::unique_ptr<Core::Frontend::PhotoViewerApplet> photo_viewer;
142 std::unique_ptr<Core::Frontend::ProfileSelectApplet> profile_select;
143 std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard;
144 std::unique_ptr<Core::Frontend::WebBrowserApplet> web_browser;
145};
146
147class AppletManager {
148public:
149 AppletManager();
150 ~AppletManager();
151
152 void SetAppletFrontendSet(AppletFrontendSet set);
153 void SetDefaultAppletFrontendSet();
154 void SetDefaultAppletsIfMissing();
155 void ClearAll();
156
157 std::shared_ptr<Applet> GetApplet(AppletId id) const;
158
159private:
160 AppletFrontendSet frontend;
161};
162
108} // namespace Applets 163} // namespace Applets
109} // namespace Service::AM 164} // namespace Service::AM
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp
new file mode 100644
index 000000000..04774bedc
--- /dev/null
+++ b/src/core/hle/service/am/applets/error.cpp
@@ -0,0 +1,182 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <array>
6#include <cstring>
7#include "common/assert.h"
8#include "common/logging/log.h"
9#include "common/string_util.h"
10#include "core/core.h"
11#include "core/frontend/applets/error.h"
12#include "core/hle/service/am/am.h"
13#include "core/hle/service/am/applets/error.h"
14
15namespace Service::AM::Applets {
16
17#pragma pack(push, 4)
18struct ShowError {
19 u8 mode;
20 bool jump;
21 INSERT_PADDING_BYTES(4);
22 bool use_64bit_error_code;
23 INSERT_PADDING_BYTES(1);
24 u64 error_code_64;
25 u32 error_code_32;
26};
27static_assert(sizeof(ShowError) == 0x14, "ShowError has incorrect size.");
28#pragma pack(pop)
29
30struct ShowErrorRecord {
31 u8 mode;
32 bool jump;
33 INSERT_PADDING_BYTES(6);
34 u64 error_code_64;
35 u64 posix_time;
36};
37static_assert(sizeof(ShowErrorRecord) == 0x18, "ShowErrorRecord has incorrect size.");
38
39struct SystemErrorArg {
40 u8 mode;
41 bool jump;
42 INSERT_PADDING_BYTES(6);
43 u64 error_code_64;
44 std::array<char, 8> language_code;
45 std::array<char, 0x800> main_text;
46 std::array<char, 0x800> detail_text;
47};
48static_assert(sizeof(SystemErrorArg) == 0x1018, "SystemErrorArg has incorrect size.");
49
50struct ApplicationErrorArg {
51 u8 mode;
52 bool jump;
53 INSERT_PADDING_BYTES(6);
54 u32 error_code;
55 std::array<char, 8> language_code;
56 std::array<char, 0x800> main_text;
57 std::array<char, 0x800> detail_text;
58};
59static_assert(sizeof(ApplicationErrorArg) == 0x1014, "ApplicationErrorArg has incorrect size.");
60
61union Error::ErrorArguments {
62 ShowError error;
63 ShowErrorRecord error_record;
64 SystemErrorArg system_error;
65 ApplicationErrorArg application_error;
66};
67
68namespace {
69template <typename T>
70void CopyArgumentData(const std::vector<u8>& data, T& variable) {
71 ASSERT(data.size() >= sizeof(T));
72 std::memcpy(&variable, data.data(), sizeof(T));
73}
74
75ResultCode Decode64BitError(u64 error) {
76 const auto description = (error >> 32) & 0x1FFF;
77 auto module = error & 0x3FF;
78 if (module >= 2000)
79 module -= 2000;
80 module &= 0x1FF;
81 return {static_cast<ErrorModule>(module), static_cast<u32>(description)};
82}
83
84} // Anonymous namespace
85
86Error::Error(const Core::Frontend::ErrorApplet& frontend) : frontend(frontend) {}
87
88Error::~Error() = default;
89
90void Error::Initialize() {
91 Applet::Initialize();
92 args = std::make_unique<ErrorArguments>();
93 complete = false;
94
95 const auto storage = broker.PopNormalDataToApplet();
96 ASSERT(storage != nullptr);
97 const auto data = storage->GetData();
98
99 ASSERT(!data.empty());
100 std::memcpy(&mode, data.data(), sizeof(ErrorAppletMode));
101
102 switch (mode) {
103 case ErrorAppletMode::ShowError:
104 CopyArgumentData(data, args->error);
105 if (args->error.use_64bit_error_code) {
106 error_code = Decode64BitError(args->error.error_code_64);
107 } else {
108 error_code = ResultCode(args->error.error_code_32);
109 }
110 break;
111 case ErrorAppletMode::ShowSystemError:
112 CopyArgumentData(data, args->system_error);
113 error_code = ResultCode(Decode64BitError(args->system_error.error_code_64));
114 break;
115 case ErrorAppletMode::ShowApplicationError:
116 CopyArgumentData(data, args->application_error);
117 error_code = ResultCode(args->application_error.error_code);
118 break;
119 case ErrorAppletMode::ShowErrorRecord:
120 CopyArgumentData(data, args->error_record);
121 error_code = Decode64BitError(args->error_record.error_code_64);
122 break;
123 default:
124 UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", static_cast<u8>(mode));
125 }
126}
127
128bool Error::TransactionComplete() const {
129 return complete;
130}
131
132ResultCode Error::GetStatus() const {
133 return RESULT_SUCCESS;
134}
135
136void Error::ExecuteInteractive() {
137 UNREACHABLE_MSG("Unexpected interactive applet data!");
138}
139
140void Error::Execute() {
141 if (complete) {
142 return;
143 }
144
145 const auto callback = [this] { DisplayCompleted(); };
146
147 switch (mode) {
148 case ErrorAppletMode::ShowError:
149 frontend.ShowError(error_code, callback);
150 break;
151 case ErrorAppletMode::ShowSystemError:
152 case ErrorAppletMode::ShowApplicationError: {
153 const auto system = mode == ErrorAppletMode::ShowSystemError;
154 const auto& main_text =
155 system ? args->system_error.main_text : args->application_error.main_text;
156 const auto& detail_text =
157 system ? args->system_error.detail_text : args->application_error.detail_text;
158
159 frontend.ShowCustomErrorText(
160 error_code,
161 Common::StringFromFixedZeroTerminatedBuffer(main_text.data(), main_text.size()),
162 Common::StringFromFixedZeroTerminatedBuffer(detail_text.data(), detail_text.size()),
163 callback);
164 break;
165 }
166 case ErrorAppletMode::ShowErrorRecord:
167 frontend.ShowErrorWithTimestamp(
168 error_code, std::chrono::seconds{args->error_record.posix_time}, callback);
169 break;
170 default:
171 UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", static_cast<u8>(mode));
172 DisplayCompleted();
173 }
174}
175
176void Error::DisplayCompleted() {
177 complete = true;
178 broker.PushNormalDataFromApplet(IStorage{{}});
179 broker.SignalStateChanged();
180}
181
182} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/error.h b/src/core/hle/service/am/applets/error.h
new file mode 100644
index 000000000..a3590d181
--- /dev/null
+++ b/src/core/hle/service/am/applets/error.h
@@ -0,0 +1,47 @@
1// Copyright 2019 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 "core/hle/result.h"
8#include "core/hle/service/am/applets/applets.h"
9
10namespace Service::AM::Applets {
11
12enum class ErrorAppletMode : u8 {
13 ShowError = 0,
14 ShowSystemError = 1,
15 ShowApplicationError = 2,
16 ShowEula = 3,
17 ShowErrorPctl = 4,
18 ShowErrorRecord = 5,
19 ShowUpdateEula = 8,
20};
21
22class Error final : public Applet {
23public:
24 explicit Error(const Core::Frontend::ErrorApplet& frontend);
25 ~Error() override;
26
27 void Initialize() override;
28
29 bool TransactionComplete() const override;
30 ResultCode GetStatus() const override;
31 void ExecuteInteractive() override;
32 void Execute() override;
33
34 void DisplayCompleted();
35
36private:
37 union ErrorArguments;
38
39 const Core::Frontend::ErrorApplet& frontend;
40 ResultCode error_code = RESULT_SUCCESS;
41 ErrorAppletMode mode = ErrorAppletMode::ShowError;
42 std::unique_ptr<ErrorArguments> args;
43
44 bool complete = false;
45};
46
47} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/stub_applet.cpp b/src/core/hle/service/am/applets/general_backend.cpp
index ed166b87d..c591b9ac2 100644
--- a/src/core/hle/service/am/applets/stub_applet.cpp
+++ b/src/core/hle/service/am/applets/general_backend.cpp
@@ -4,11 +4,15 @@
4 4
5#include <string> 5#include <string>
6 6
7#include "common/assert.h"
7#include "common/hex_util.h" 8#include "common/hex_util.h"
8#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "core/core.h"
11#include "core/frontend/applets/general_frontend.h"
12#include "core/hle/kernel/process.h"
9#include "core/hle/result.h" 13#include "core/hle/result.h"
10#include "core/hle/service/am/am.h" 14#include "core/hle/service/am/am.h"
11#include "core/hle/service/am/applets/stub_applet.h" 15#include "core/hle/service/am/applets/general_backend.h"
12 16
13namespace Service::AM::Applets { 17namespace Service::AM::Applets {
14 18
@@ -30,6 +34,55 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string prefix) {
30 } 34 }
31} 35}
32 36
37PhotoViewer::PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend) : frontend(frontend) {}
38
39PhotoViewer::~PhotoViewer() = default;
40
41void PhotoViewer::Initialize() {
42 Applet::Initialize();
43 complete = false;
44
45 const auto storage = broker.PopNormalDataToApplet();
46 ASSERT(storage != nullptr);
47 const auto data = storage->GetData();
48 ASSERT(!data.empty());
49 mode = static_cast<PhotoViewerAppletMode>(data[0]);
50}
51
52bool PhotoViewer::TransactionComplete() const {
53 return complete;
54}
55
56ResultCode PhotoViewer::GetStatus() const {
57 return RESULT_SUCCESS;
58}
59
60void PhotoViewer::ExecuteInteractive() {
61 UNREACHABLE_MSG("Unexpected interactive applet data.");
62}
63
64void PhotoViewer::Execute() {
65 if (complete)
66 return;
67
68 const auto callback = [this] { ViewFinished(); };
69 switch (mode) {
70 case PhotoViewerAppletMode::CurrentApp:
71 frontend.ShowPhotosForApplication(Core::CurrentProcess()->GetTitleID(), callback);
72 break;
73 case PhotoViewerAppletMode::AllApps:
74 frontend.ShowAllPhotos(callback);
75 break;
76 default:
77 UNIMPLEMENTED_MSG("Unimplemented PhotoViewer applet mode={:02X}!", static_cast<u8>(mode));
78 }
79}
80
81void PhotoViewer::ViewFinished() {
82 broker.PushNormalDataFromApplet(IStorage{{}});
83 broker.SignalStateChanged();
84}
85
33StubApplet::StubApplet() = default; 86StubApplet::StubApplet() = default;
34 87
35StubApplet::~StubApplet() = default; 88StubApplet::~StubApplet() = default;
@@ -67,4 +120,5 @@ void StubApplet::Execute() {
67 broker.PushInteractiveDataFromApplet(IStorage{std::vector<u8>(0x1000)}); 120 broker.PushInteractiveDataFromApplet(IStorage{std::vector<u8>(0x1000)});
68 broker.SignalStateChanged(); 121 broker.SignalStateChanged();
69} 122}
123
70} // namespace Service::AM::Applets 124} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/general_backend.h b/src/core/hle/service/am/applets/general_backend.h
new file mode 100644
index 000000000..2dd255d7c
--- /dev/null
+++ b/src/core/hle/service/am/applets/general_backend.h
@@ -0,0 +1,48 @@
1// Copyright 2019 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 "core/hle/service/am/applets/applets.h"
8
9namespace Service::AM::Applets {
10
11enum class PhotoViewerAppletMode : u8 {
12 CurrentApp = 0,
13 AllApps = 1,
14};
15
16class PhotoViewer final : public Applet {
17public:
18 explicit PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend);
19 ~PhotoViewer() override;
20
21 void Initialize() override;
22 bool TransactionComplete() const override;
23 ResultCode GetStatus() const override;
24 void ExecuteInteractive() override;
25 void Execute() override;
26
27 void ViewFinished();
28
29private:
30 const Core::Frontend::PhotoViewerApplet& frontend;
31 bool complete = false;
32 PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp;
33};
34
35class StubApplet final : public Applet {
36public:
37 StubApplet();
38 ~StubApplet() override;
39
40 void Initialize() override;
41
42 bool TransactionComplete() const override;
43 ResultCode GetStatus() const override;
44 void ExecuteInteractive() override;
45 void Execute() override;
46};
47
48} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp
index 14e2a1fee..d113bd2eb 100644
--- a/src/core/hle/service/am/applets/profile_select.cpp
+++ b/src/core/hle/service/am/applets/profile_select.cpp
@@ -15,7 +15,9 @@ namespace Service::AM::Applets {
15 15
16constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1}; 16constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1};
17 17
18ProfileSelect::ProfileSelect() = default; 18ProfileSelect::ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend)
19 : frontend(frontend) {}
20
19ProfileSelect::~ProfileSelect() = default; 21ProfileSelect::~ProfileSelect() = default;
20 22
21void ProfileSelect::Initialize() { 23void ProfileSelect::Initialize() {
@@ -51,8 +53,6 @@ void ProfileSelect::Execute() {
51 return; 53 return;
52 } 54 }
53 55
54 const auto& frontend{Core::System::GetInstance().GetProfileSelector()};
55
56 frontend.SelectProfile([this](std::optional<Account::UUID> uuid) { SelectionComplete(uuid); }); 56 frontend.SelectProfile([this](std::optional<Account::UUID> uuid) { SelectionComplete(uuid); });
57} 57}
58 58
diff --git a/src/core/hle/service/am/applets/profile_select.h b/src/core/hle/service/am/applets/profile_select.h
index 787485f22..a2ac6cf50 100644
--- a/src/core/hle/service/am/applets/profile_select.h
+++ b/src/core/hle/service/am/applets/profile_select.h
@@ -28,7 +28,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco
28 28
29class ProfileSelect final : public Applet { 29class ProfileSelect final : public Applet {
30public: 30public:
31 ProfileSelect(); 31 explicit ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend);
32 ~ProfileSelect() override; 32 ~ProfileSelect() override;
33 33
34 void Initialize() override; 34 void Initialize() override;
@@ -41,6 +41,8 @@ public:
41 void SelectionComplete(std::optional<Account::UUID> uuid); 41 void SelectionComplete(std::optional<Account::UUID> uuid);
42 42
43private: 43private:
44 const Core::Frontend::ProfileSelectApplet& frontend;
45
44 UserSelectionConfig config; 46 UserSelectionConfig config;
45 bool complete = false; 47 bool complete = false;
46 ResultCode status = RESULT_SUCCESS; 48 ResultCode status = RESULT_SUCCESS;
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp
index 8c5bd6059..e197990f7 100644
--- a/src/core/hle/service/am/applets/software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/software_keyboard.cpp
@@ -39,7 +39,8 @@ static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters(
39 return params; 39 return params;
40} 40}
41 41
42SoftwareKeyboard::SoftwareKeyboard() = default; 42SoftwareKeyboard::SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend)
43 : frontend(frontend) {}
43 44
44SoftwareKeyboard::~SoftwareKeyboard() = default; 45SoftwareKeyboard::~SoftwareKeyboard() = default;
45 46
@@ -90,8 +91,6 @@ void SoftwareKeyboard::ExecuteInteractive() {
90 if (status == INTERACTIVE_STATUS_OK) { 91 if (status == INTERACTIVE_STATUS_OK) {
91 complete = true; 92 complete = true;
92 } else { 93 } else {
93 const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()};
94
95 std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string; 94 std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string;
96 std::memcpy(string.data(), data.data() + 4, string.size() * 2); 95 std::memcpy(string.data(), data.data() + 4, string.size() * 2);
97 frontend.SendTextCheckDialog( 96 frontend.SendTextCheckDialog(
@@ -106,8 +105,6 @@ void SoftwareKeyboard::Execute() {
106 return; 105 return;
107 } 106 }
108 107
109 const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()};
110
111 const auto parameters = ConvertToFrontendParameters(config, initial_text); 108 const auto parameters = ConvertToFrontendParameters(config, initial_text);
112 109
113 frontend.RequestText([this](std::optional<std::u16string> text) { WriteText(text); }, 110 frontend.RequestText([this](std::optional<std::u16string> text) { WriteText(text); },
diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h
index b93a30d28..0fbc43e51 100644
--- a/src/core/hle/service/am/applets/software_keyboard.h
+++ b/src/core/hle/service/am/applets/software_keyboard.h
@@ -55,7 +55,7 @@ static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect siz
55 55
56class SoftwareKeyboard final : public Applet { 56class SoftwareKeyboard final : public Applet {
57public: 57public:
58 SoftwareKeyboard(); 58 explicit SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend);
59 ~SoftwareKeyboard() override; 59 ~SoftwareKeyboard() override;
60 60
61 void Initialize() override; 61 void Initialize() override;
@@ -68,6 +68,8 @@ public:
68 void WriteText(std::optional<std::u16string> text); 68 void WriteText(std::optional<std::u16string> text);
69 69
70private: 70private:
71 const Core::Frontend::SoftwareKeyboardApplet& frontend;
72
71 KeyboardConfig config; 73 KeyboardConfig config;
72 std::u16string initial_text; 74 std::u16string initial_text;
73 bool complete = false; 75 bool complete = false;
diff --git a/src/core/hle/service/am/applets/stub_applet.h b/src/core/hle/service/am/applets/stub_applet.h
deleted file mode 100644
index 7d8dc968d..000000000
--- a/src/core/hle/service/am/applets/stub_applet.h
+++ /dev/null
@@ -1,24 +0,0 @@
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 "core/hle/service/am/applets/applets.h"
8
9namespace Service::AM::Applets {
10
11class StubApplet final : public Applet {
12public:
13 StubApplet();
14 ~StubApplet() override;
15
16 void Initialize() override;
17
18 bool TransactionComplete() const override;
19 ResultCode GetStatus() const override;
20 void ExecuteInteractive() override;
21 void Execute() override;
22};
23
24} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp
index 7e17df98a..7878f5136 100644
--- a/src/core/hle/service/am/applets/web_browser.cpp
+++ b/src/core/hle/service/am/applets/web_browser.cpp
@@ -95,7 +95,7 @@ static FileSys::VirtualFile GetManualRomFS() {
95 return nullptr; 95 return nullptr;
96} 96}
97 97
98WebBrowser::WebBrowser() = default; 98WebBrowser::WebBrowser(Core::Frontend::WebBrowserApplet& frontend) : frontend(frontend) {}
99 99
100WebBrowser::~WebBrowser() = default; 100WebBrowser::~WebBrowser() = default;
101 101
@@ -152,8 +152,6 @@ void WebBrowser::Execute() {
152 return; 152 return;
153 } 153 }
154 154
155 auto& frontend{Core::System::GetInstance().GetWebBrowser()};
156
157 frontend.OpenPage(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); }); 155 frontend.OpenPage(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); });
158} 156}
159 157
diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h
index b9e228fac..7e0f34c7d 100644
--- a/src/core/hle/service/am/applets/web_browser.h
+++ b/src/core/hle/service/am/applets/web_browser.h
@@ -12,7 +12,7 @@ namespace Service::AM::Applets {
12 12
13class WebBrowser final : public Applet { 13class WebBrowser final : public Applet {
14public: 14public:
15 WebBrowser(); 15 WebBrowser(Core::Frontend::WebBrowserApplet& frontend);
16 ~WebBrowser() override; 16 ~WebBrowser() override;
17 17
18 void Initialize() override; 18 void Initialize() override;
@@ -32,6 +32,8 @@ public:
32 void Finalize(); 32 void Finalize();
33 33
34private: 34private:
35 Core::Frontend::WebBrowserApplet& frontend;
36
35 bool complete = false; 37 bool complete = false;
36 bool unpacked = false; 38 bool unpacked = false;
37 ResultCode status = RESULT_SUCCESS; 39 ResultCode status = RESULT_SUCCESS;
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 2d768d9fc..51d8c26b4 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -50,6 +50,7 @@ static std::vector<u64> AccumulateAOCTitleIDs() {
50} 50}
51 51
52AOC_U::AOC_U() : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs()) { 52AOC_U::AOC_U() : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs()) {
53 // clang-format off
53 static const FunctionInfo functions[] = { 54 static const FunctionInfo functions[] = {
54 {0, nullptr, "CountAddOnContentByApplicationId"}, 55 {0, nullptr, "CountAddOnContentByApplicationId"},
55 {1, nullptr, "ListAddOnContentByApplicationId"}, 56 {1, nullptr, "ListAddOnContentByApplicationId"},
@@ -60,7 +61,10 @@ AOC_U::AOC_U() : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs
60 {6, nullptr, "PrepareAddOnContentByApplicationId"}, 61 {6, nullptr, "PrepareAddOnContentByApplicationId"},
61 {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"}, 62 {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"},
62 {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"}, 63 {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"},
64 {100, nullptr, "CreateEcPurchasedEventManager"},
63 }; 65 };
66 // clang-format on
67
64 RegisterHandlers(functions); 68 RegisterHandlers(functions);
65 69
66 auto& kernel = Core::System::GetInstance().Kernel(); 70 auto& kernel = Core::System::GetInstance().Kernel();
diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/interface.cpp
index fcacbab72..d058c0245 100644
--- a/src/core/hle/service/apm/interface.cpp
+++ b/src/core/hle/service/apm/interface.cpp
@@ -87,6 +87,8 @@ APM_Sys::APM_Sys() : ServiceFramework{"apm:sys"} {
87 {3, nullptr, "GetLastThrottlingState"}, 87 {3, nullptr, "GetLastThrottlingState"},
88 {4, nullptr, "ClearLastThrottlingState"}, 88 {4, nullptr, "ClearLastThrottlingState"},
89 {5, nullptr, "LoadAndApplySettings"}, 89 {5, nullptr, "LoadAndApplySettings"},
90 {6, nullptr, "SetCpuBoostMode"},
91 {7, nullptr, "GetCurrentPerformanceConfiguration"},
90 }; 92 };
91 // clang-format on 93 // clang-format on
92 94
diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp
index b6b71f966..f43e512e9 100644
--- a/src/core/hle/service/audio/audctl.cpp
+++ b/src/core/hle/service/audio/audctl.cpp
@@ -2,6 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h"
6#include "core/hle/ipc_helpers.h"
5#include "core/hle/service/audio/audctl.h" 7#include "core/hle/service/audio/audctl.h"
6 8
7namespace Service::Audio { 9namespace Service::Audio {
@@ -11,8 +13,8 @@ AudCtl::AudCtl() : ServiceFramework{"audctl"} {
11 static const FunctionInfo functions[] = { 13 static const FunctionInfo functions[] = {
12 {0, nullptr, "GetTargetVolume"}, 14 {0, nullptr, "GetTargetVolume"},
13 {1, nullptr, "SetTargetVolume"}, 15 {1, nullptr, "SetTargetVolume"},
14 {2, nullptr, "GetTargetVolumeMin"}, 16 {2, &AudCtl::GetTargetVolumeMin, "GetTargetVolumeMin"},
15 {3, nullptr, "GetTargetVolumeMax"}, 17 {3, &AudCtl::GetTargetVolumeMax, "GetTargetVolumeMax"},
16 {4, nullptr, "IsTargetMute"}, 18 {4, nullptr, "IsTargetMute"},
17 {5, nullptr, "SetTargetMute"}, 19 {5, nullptr, "SetTargetMute"},
18 {6, nullptr, "IsTargetConnected"}, 20 {6, nullptr, "IsTargetConnected"},
@@ -44,4 +46,28 @@ AudCtl::AudCtl() : ServiceFramework{"audctl"} {
44 46
45AudCtl::~AudCtl() = default; 47AudCtl::~AudCtl() = default;
46 48
49void AudCtl::GetTargetVolumeMin(Kernel::HLERequestContext& ctx) {
50 LOG_DEBUG(Audio, "called.");
51
52 // This service function is currently hardcoded on the
53 // actual console to this value (as of 6.0.0).
54 constexpr s32 target_min_volume = 0;
55
56 IPC::ResponseBuilder rb{ctx, 3};
57 rb.Push(RESULT_SUCCESS);
58 rb.Push(target_min_volume);
59}
60
61void AudCtl::GetTargetVolumeMax(Kernel::HLERequestContext& ctx) {
62 LOG_DEBUG(Audio, "called.");
63
64 // This service function is currently hardcoded on the
65 // actual console to this value (as of 6.0.0).
66 constexpr s32 target_max_volume = 15;
67
68 IPC::ResponseBuilder rb{ctx, 3};
69 rb.Push(RESULT_SUCCESS);
70 rb.Push(target_max_volume);
71}
72
47} // namespace Service::Audio 73} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audctl.h b/src/core/hle/service/audio/audctl.h
index 9d2d9e83b..c7fafc02e 100644
--- a/src/core/hle/service/audio/audctl.h
+++ b/src/core/hle/service/audio/audctl.h
@@ -12,6 +12,10 @@ class AudCtl final : public ServiceFramework<AudCtl> {
12public: 12public:
13 explicit AudCtl(); 13 explicit AudCtl();
14 ~AudCtl() override; 14 ~AudCtl() override;
15
16private:
17 void GetTargetVolumeMin(Kernel::HLERequestContext& ctx);
18 void GetTargetVolumeMax(Kernel::HLERequestContext& ctx);
15}; 19};
16 20
17} // namespace Service::Audio 21} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
index e5daefdde..d7f1d348d 100644
--- a/src/core/hle/service/audio/audin_u.cpp
+++ b/src/core/hle/service/audio/audin_u.cpp
@@ -25,6 +25,7 @@ public:
25 {11, nullptr, "GetAudioInBufferCount"}, 25 {11, nullptr, "GetAudioInBufferCount"},
26 {12, nullptr, "SetAudioInDeviceGain"}, 26 {12, nullptr, "SetAudioInDeviceGain"},
27 {13, nullptr, "GetAudioInDeviceGain"}, 27 {13, nullptr, "GetAudioInDeviceGain"},
28 {14, nullptr, "FlushAudioInBuffers"},
28 }; 29 };
29 // clang-format on 30 // clang-format on
30 31
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 39acb7b23..12875fb42 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -44,7 +44,7 @@ public:
44 std::string&& unique_name) 44 std::string&& unique_name)
45 : ServiceFramework("IAudioOut"), audio_core(audio_core), 45 : ServiceFramework("IAudioOut"), audio_core(audio_core),
46 device_name(std::move(device_name)), audio_params(audio_params) { 46 device_name(std::move(device_name)), audio_params(audio_params) {
47 47 // clang-format off
48 static const FunctionInfo functions[] = { 48 static const FunctionInfo functions[] = {
49 {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, 49 {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
50 {1, &IAudioOut::StartAudioOut, "StartAudioOut"}, 50 {1, &IAudioOut::StartAudioOut, "StartAudioOut"},
@@ -58,7 +58,10 @@ public:
58 {9, &IAudioOut::GetAudioOutBufferCount, "GetAudioOutBufferCount"}, 58 {9, &IAudioOut::GetAudioOutBufferCount, "GetAudioOutBufferCount"},
59 {10, nullptr, "GetAudioOutPlayedSampleCount"}, 59 {10, nullptr, "GetAudioOutPlayedSampleCount"},
60 {11, nullptr, "FlushAudioOutBuffers"}, 60 {11, nullptr, "FlushAudioOutBuffers"},
61 {12, nullptr, "SetAudioOutVolume"},
62 {13, nullptr, "GetAudioOutVolume"},
61 }; 63 };
64 // clang-format on
62 RegisterHandlers(functions); 65 RegisterHandlers(functions);
63 66
64 // This is the event handle used to check if the audio buffer was released 67 // This is the event handle used to check if the audio buffer was released
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp
index 59ef603e1..974ff8e1a 100644
--- a/src/core/hle/service/btdrv/btdrv.cpp
+++ b/src/core/hle/service/btdrv/btdrv.cpp
@@ -154,7 +154,8 @@ public:
154 {96, nullptr, "GetLeHidEventInfo"}, 154 {96, nullptr, "GetLeHidEventInfo"},
155 {97, nullptr, "RegisterBleHidEvent"}, 155 {97, nullptr, "RegisterBleHidEvent"},
156 {98, nullptr, "SetLeScanParameter"}, 156 {98, nullptr, "SetLeScanParameter"},
157 {256, nullptr, "GetIsManufacturingMode"} 157 {256, nullptr, "GetIsManufacturingMode"},
158 {257, nullptr, "EmulateBluetoothCrash"},
158 }; 159 };
159 // clang-format on 160 // clang-format on
160 161
diff --git a/src/core/hle/service/caps/caps.cpp b/src/core/hle/service/caps/caps.cpp
index ae7b0720b..907f464ab 100644
--- a/src/core/hle/service/caps/caps.cpp
+++ b/src/core/hle/service/caps/caps.cpp
@@ -15,32 +15,41 @@ public:
15 explicit CAPS_A() : ServiceFramework{"caps:a"} { 15 explicit CAPS_A() : ServiceFramework{"caps:a"} {
16 // clang-format off 16 // clang-format off
17 static const FunctionInfo functions[] = { 17 static const FunctionInfo functions[] = {
18 {0, nullptr, "Unknown1"}, 18 {0, nullptr, "GetAlbumFileCount"},
19 {1, nullptr, "Unknown2"}, 19 {1, nullptr, "GetAlbumFileList"},
20 {2, nullptr, "Unknown3"}, 20 {2, nullptr, "LoadAlbumFile"},
21 {3, nullptr, "Unknown4"}, 21 {3, nullptr, "DeleteAlbumFile"},
22 {4, nullptr, "Unknown5"}, 22 {4, nullptr, "StorageCopyAlbumFile"},
23 {5, nullptr, "Unknown6"}, 23 {5, nullptr, "IsAlbumMounted"},
24 {6, nullptr, "Unknown7"}, 24 {6, nullptr, "GetAlbumUsage"},
25 {7, nullptr, "Unknown8"}, 25 {7, nullptr, "GetAlbumFileSize"},
26 {8, nullptr, "Unknown9"}, 26 {8, nullptr, "LoadAlbumFileThumbnail"},
27 {9, nullptr, "Unknown10"}, 27 {9, nullptr, "LoadAlbumScreenShotImage"},
28 {10, nullptr, "Unknown11"}, 28 {10, nullptr, "LoadAlbumScreenShotThumbnailImage"},
29 {11, nullptr, "Unknown12"}, 29 {11, nullptr, "GetAlbumEntryFromApplicationAlbumEntry"},
30 {12, nullptr, "Unknown13"}, 30 {12, nullptr, "Unknown12"},
31 {13, nullptr, "Unknown14"}, 31 {13, nullptr, "Unknown13"},
32 {14, nullptr, "Unknown15"}, 32 {14, nullptr, "Unknown14"},
33 {301, nullptr, "Unknown16"}, 33 {15, nullptr, "Unknown15"},
34 {401, nullptr, "Unknown17"}, 34 {16, nullptr, "Unknown16"},
35 {501, nullptr, "Unknown18"}, 35 {17, nullptr, "Unknown17"},
36 {1001, nullptr, "Unknown19"}, 36 {18, nullptr, "Unknown18"},
37 {1002, nullptr, "Unknown20"}, 37 {202, nullptr, "SaveEditedScreenShot"},
38 {8001, nullptr, "Unknown21"}, 38 {301, nullptr, "GetLastThumbnail"},
39 {8002, nullptr, "Unknown22"}, 39 {401, nullptr, "GetAutoSavingStorage"},
40 {8011, nullptr, "Unknown23"}, 40 {501, nullptr, "GetRequiredStorageSpaceSizeToCopyAll"},
41 {8012, nullptr, "Unknown24"}, 41 {1001, nullptr, "Unknown1001"},
42 {8021, nullptr, "Unknown25"}, 42 {1002, nullptr, "Unknown1002"},
43 {10011, nullptr, "Unknown26"}, 43 {1003, nullptr, "Unknown1003"},
44 {8001, nullptr, "ForceAlbumUnmounted"},
45 {8002, nullptr, "ResetAlbumMountStatus"},
46 {8011, nullptr, "RefreshAlbumCache"},
47 {8012, nullptr, "GetAlbumCache"},
48 {8013, nullptr, "Unknown8013"},
49 {8021, nullptr, "GetAlbumEntryFromApplicationAlbumEntryAruid"},
50 {10011, nullptr, "SetInternalErrorConversionEnabled"},
51 {50000, nullptr, "Unknown50000"},
52 {60002, nullptr, "Unknown60002"},
44 }; 53 };
45 // clang-format on 54 // clang-format on
46 55
@@ -53,16 +62,17 @@ public:
53 explicit CAPS_C() : ServiceFramework{"caps:c"} { 62 explicit CAPS_C() : ServiceFramework{"caps:c"} {
54 // clang-format off 63 // clang-format off
55 static const FunctionInfo functions[] = { 64 static const FunctionInfo functions[] = {
56 {2001, nullptr, "Unknown1"}, 65 {33, nullptr, "Unknown33"},
57 {2002, nullptr, "Unknown2"}, 66 {2001, nullptr, "Unknown2001"},
58 {2011, nullptr, "Unknown3"}, 67 {2002, nullptr, "Unknown2002"},
59 {2012, nullptr, "Unknown4"}, 68 {2011, nullptr, "Unknown2011"},
60 {2013, nullptr, "Unknown5"}, 69 {2012, nullptr, "Unknown2012"},
61 {2014, nullptr, "Unknown6"}, 70 {2013, nullptr, "Unknown2013"},
62 {2101, nullptr, "Unknown7"}, 71 {2014, nullptr, "Unknown2014"},
63 {2102, nullptr, "Unknown8"}, 72 {2101, nullptr, "Unknown2101"},
64 {2201, nullptr, "Unknown9"}, 73 {2102, nullptr, "Unknown2102"},
65 {2301, nullptr, "Unknown10"}, 74 {2201, nullptr, "Unknown2201"},
75 {2301, nullptr, "Unknown2301"},
66 }; 76 };
67 // clang-format on 77 // clang-format on
68 78
@@ -127,11 +137,18 @@ public:
127 explicit CAPS_U() : ServiceFramework{"caps:u"} { 137 explicit CAPS_U() : ServiceFramework{"caps:u"} {
128 // clang-format off 138 // clang-format off
129 static const FunctionInfo functions[] = { 139 static const FunctionInfo functions[] = {
140 {32, nullptr, "SetShimLibraryVersion"},
130 {102, nullptr, "GetAlbumFileListByAruid"}, 141 {102, nullptr, "GetAlbumFileListByAruid"},
131 {103, nullptr, "DeleteAlbumFileByAruid"}, 142 {103, nullptr, "DeleteAlbumFileByAruid"},
132 {104, nullptr, "GetAlbumFileSizeByAruid"}, 143 {104, nullptr, "GetAlbumFileSizeByAruid"},
144 {105, nullptr, "DeleteAlbumFileByAruidForDebug"},
133 {110, nullptr, "LoadAlbumScreenShotImageByAruid"}, 145 {110, nullptr, "LoadAlbumScreenShotImageByAruid"},
134 {120, nullptr, "LoadAlbumScreenShotThumbnailImageByAruid"}, 146 {120, nullptr, "LoadAlbumScreenShotThumbnailImageByAruid"},
147 {130, nullptr, "PrecheckToCreateContentsByAruid"},
148 {140, nullptr, "GetAlbumFileList1AafeAruidDeprecated"},
149 {141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"},
150 {142, nullptr, "GetAlbumFileList3AaeAruid"},
151 {143, nullptr, "GetAlbumFileList4AaeUidAruid"},
135 {60002, nullptr, "OpenAccessorSessionForApplication"}, 152 {60002, nullptr, "OpenAccessorSessionForApplication"},
136 }; 153 };
137 // clang-format on 154 // clang-format on
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 0249b6992..e7df8fd98 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -664,10 +664,13 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
664 {100, nullptr, "OpenImageDirectoryFileSystem"}, 664 {100, nullptr, "OpenImageDirectoryFileSystem"},
665 {110, nullptr, "OpenContentStorageFileSystem"}, 665 {110, nullptr, "OpenContentStorageFileSystem"},
666 {120, nullptr, "OpenCloudBackupWorkStorageFileSystem"}, 666 {120, nullptr, "OpenCloudBackupWorkStorageFileSystem"},
667 {130, nullptr, "OpenCustomStorageFileSystem"},
667 {200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"}, 668 {200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"},
668 {201, nullptr, "OpenDataStorageByProgramId"}, 669 {201, nullptr, "OpenDataStorageByProgramId"},
669 {202, &FSP_SRV::OpenDataStorageByDataId, "OpenDataStorageByDataId"}, 670 {202, &FSP_SRV::OpenDataStorageByDataId, "OpenDataStorageByDataId"},
670 {203, &FSP_SRV::OpenPatchDataStorageByCurrentProcess, "OpenPatchDataStorageByCurrentProcess"}, 671 {203, &FSP_SRV::OpenPatchDataStorageByCurrentProcess, "OpenPatchDataStorageByCurrentProcess"},
672 {204, nullptr, "OpenDataFileSystemByProgramIndex"},
673 {205, nullptr, "OpenDataStorageByProgramIndex"},
671 {400, nullptr, "OpenDeviceOperator"}, 674 {400, nullptr, "OpenDeviceOperator"},
672 {500, nullptr, "OpenSdCardDetectionEventNotifier"}, 675 {500, nullptr, "OpenSdCardDetectionEventNotifier"},
673 {501, nullptr, "OpenGameCardDetectionEventNotifier"}, 676 {501, nullptr, "OpenGameCardDetectionEventNotifier"},
@@ -691,6 +694,7 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
691 {614, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId"}, 694 {614, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId"},
692 {615, nullptr, "QuerySaveDataInternalStorageTotalSize"}, 695 {615, nullptr, "QuerySaveDataInternalStorageTotalSize"},
693 {616, nullptr, "GetSaveDataCommitId"}, 696 {616, nullptr, "GetSaveDataCommitId"},
697 {617, nullptr, "UnregisterExternalKey"},
694 {620, nullptr, "SetSdCardEncryptionSeed"}, 698 {620, nullptr, "SetSdCardEncryptionSeed"},
695 {630, nullptr, "SetSdCardAccessibility"}, 699 {630, nullptr, "SetSdCardAccessibility"},
696 {631, nullptr, "IsSdCardAccessible"}, 700 {631, nullptr, "IsSdCardAccessible"},
@@ -701,6 +705,7 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
701 {710, nullptr, "ResolveAccessFailure"}, 705 {710, nullptr, "ResolveAccessFailure"},
702 {720, nullptr, "AbandonAccessFailure"}, 706 {720, nullptr, "AbandonAccessFailure"},
703 {800, nullptr, "GetAndClearFileSystemProxyErrorInfo"}, 707 {800, nullptr, "GetAndClearFileSystemProxyErrorInfo"},
708 {810, nullptr, "RegisterProgramIndexMapInfo"},
704 {1000, nullptr, "SetBisRootForHost"}, 709 {1000, nullptr, "SetBisRootForHost"},
705 {1001, nullptr, "SetSaveDataSize"}, 710 {1001, nullptr, "SetSaveDataSize"},
706 {1002, nullptr, "SetSaveDataRootPath"}, 711 {1002, nullptr, "SetSaveDataRootPath"},
@@ -711,6 +716,8 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
711 {1007, nullptr, "RegisterUpdatePartition"}, 716 {1007, nullptr, "RegisterUpdatePartition"},
712 {1008, nullptr, "OpenRegisteredUpdatePartition"}, 717 {1008, nullptr, "OpenRegisteredUpdatePartition"},
713 {1009, nullptr, "GetAndClearMemoryReportInfo"}, 718 {1009, nullptr, "GetAndClearMemoryReportInfo"},
719 {1010, nullptr, "SetDataStorageRedirectTarget"},
720 {1011, nullptr, "OutputAccessLogToSdCard2"},
714 {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"}, 721 {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"},
715 {1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"}, 722 {1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"},
716 {1200, nullptr, "OpenMultiCommitManager"}, 723 {1200, nullptr, "OpenMultiCommitManager"},
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index d9225d624..5100e376c 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -12,6 +12,7 @@ namespace Service::Friend {
12class IFriendService final : public ServiceFramework<IFriendService> { 12class IFriendService final : public ServiceFramework<IFriendService> {
13public: 13public:
14 IFriendService() : ServiceFramework("IFriendService") { 14 IFriendService() : ServiceFramework("IFriendService") {
15 // clang-format off
15 static const FunctionInfo functions[] = { 16 static const FunctionInfo functions[] = {
16 {0, nullptr, "GetCompletionEvent"}, 17 {0, nullptr, "GetCompletionEvent"},
17 {1, nullptr, "Cancel"}, 18 {1, nullptr, "Cancel"},
@@ -24,8 +25,7 @@ public:
24 {10400, nullptr, "GetBlockedUserListIds"}, 25 {10400, nullptr, "GetBlockedUserListIds"},
25 {10500, nullptr, "GetProfileList"}, 26 {10500, nullptr, "GetProfileList"},
26 {10600, nullptr, "DeclareOpenOnlinePlaySession"}, 27 {10600, nullptr, "DeclareOpenOnlinePlaySession"},
27 {10601, &IFriendService::DeclareCloseOnlinePlaySession, 28 {10601, &IFriendService::DeclareCloseOnlinePlaySession, "DeclareCloseOnlinePlaySession"},
28 "DeclareCloseOnlinePlaySession"},
29 {10610, &IFriendService::UpdateUserPresence, "UpdateUserPresence"}, 29 {10610, &IFriendService::UpdateUserPresence, "UpdateUserPresence"},
30 {10700, nullptr, "GetPlayHistoryRegistrationKey"}, 30 {10700, nullptr, "GetPlayHistoryRegistrationKey"},
31 {10701, nullptr, "GetPlayHistoryRegistrationKeyWithNetworkServiceAccountId"}, 31 {10701, nullptr, "GetPlayHistoryRegistrationKeyWithNetworkServiceAccountId"},
@@ -88,6 +88,7 @@ public:
88 {30830, nullptr, "ClearPlayLog"}, 88 {30830, nullptr, "ClearPlayLog"},
89 {49900, nullptr, "DeleteNetworkServiceAccountCache"}, 89 {49900, nullptr, "DeleteNetworkServiceAccountCache"},
90 }; 90 };
91 // clang-format on
91 92
92 RegisterHandlers(functions); 93 RegisterHandlers(functions);
93 } 94 }
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 63b55758b..a4ad95d96 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -210,6 +210,7 @@ Hid::Hid() : ServiceFramework("hid") {
210 {131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"}, 210 {131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"},
211 {132, nullptr, "EnableUnintendedHomeButtonInputProtection"}, 211 {132, nullptr, "EnableUnintendedHomeButtonInputProtection"},
212 {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"}, 212 {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"},
213 {134, nullptr, "SetNpadAnalogStickUseCenterClamp"},
213 {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"}, 214 {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
214 {201, &Hid::SendVibrationValue, "SendVibrationValue"}, 215 {201, &Hid::SendVibrationValue, "SendVibrationValue"},
215 {202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"}, 216 {202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"},
@@ -221,6 +222,7 @@ Hid::Hid() : ServiceFramework("hid") {
221 {208, nullptr, "GetActualVibrationGcErmCommand"}, 222 {208, nullptr, "GetActualVibrationGcErmCommand"},
222 {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, 223 {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"},
223 {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"}, 224 {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"},
225 {211, nullptr, "IsVibrationDeviceMounted"},
224 {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, 226 {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"},
225 {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, 227 {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"},
226 {302, nullptr, "StopConsoleSixAxisSensor"}, 228 {302, nullptr, "StopConsoleSixAxisSensor"},
@@ -265,6 +267,7 @@ Hid::Hid() : ServiceFramework("hid") {
265 {523, nullptr, "SetIsPalmaPairedConnectable"}, 267 {523, nullptr, "SetIsPalmaPairedConnectable"},
266 {524, nullptr, "PairPalma"}, 268 {524, nullptr, "PairPalma"},
267 {525, &Hid::SetPalmaBoostMode, "SetPalmaBoostMode"}, 269 {525, &Hid::SetPalmaBoostMode, "SetPalmaBoostMode"},
270 {526, nullptr, "CancelWritePalmaWaveEntry"},
268 {1000, nullptr, "SetNpadCommunicationMode"}, 271 {1000, nullptr, "SetNpadCommunicationMode"},
269 {1001, nullptr, "GetNpadCommunicationMode"}, 272 {1001, nullptr, "GetNpadCommunicationMode"},
270 }; 273 };
@@ -797,12 +800,22 @@ public:
797 {232, nullptr, "EnableShipmentMode"}, 800 {232, nullptr, "EnableShipmentMode"},
798 {233, nullptr, "ClearPairingInfo"}, 801 {233, nullptr, "ClearPairingInfo"},
799 {234, nullptr, "GetUniquePadDeviceTypeSetInternal"}, 802 {234, nullptr, "GetUniquePadDeviceTypeSetInternal"},
803 {235, nullptr, "EnableAnalogStickPower"},
800 {301, nullptr, "GetAbstractedPadHandles"}, 804 {301, nullptr, "GetAbstractedPadHandles"},
801 {302, nullptr, "GetAbstractedPadState"}, 805 {302, nullptr, "GetAbstractedPadState"},
802 {303, nullptr, "GetAbstractedPadsState"}, 806 {303, nullptr, "GetAbstractedPadsState"},
803 {321, nullptr, "SetAutoPilotVirtualPadState"}, 807 {321, nullptr, "SetAutoPilotVirtualPadState"},
804 {322, nullptr, "UnsetAutoPilotVirtualPadState"}, 808 {322, nullptr, "UnsetAutoPilotVirtualPadState"},
805 {323, nullptr, "UnsetAllAutoPilotVirtualPadState"}, 809 {323, nullptr, "UnsetAllAutoPilotVirtualPadState"},
810 {324, nullptr, "AttachHdlsWorkBuffer"},
811 {325, nullptr, "ReleaseHdlsWorkBuffer"},
812 {326, nullptr, "DumpHdlsNpadAssignmentState"},
813 {327, nullptr, "DumpHdlsStates"},
814 {328, nullptr, "ApplyHdlsNpadAssignmentState"},
815 {329, nullptr, "ApplyHdlsStateList"},
816 {330, nullptr, "AttachHdlsVirtualDevice"},
817 {331, nullptr, "DetachHdlsVirtualDevice"},
818 {332, nullptr, "SetHdlsState"},
806 {350, nullptr, "AddRegisteredDevice"}, 819 {350, nullptr, "AddRegisteredDevice"},
807 {400, nullptr, "DisableExternalMcuOnNxDevice"}, 820 {400, nullptr, "DisableExternalMcuOnNxDevice"},
808 {401, nullptr, "DisableRailDeviceFiltering"}, 821 {401, nullptr, "DisableRailDeviceFiltering"},
@@ -825,6 +838,7 @@ public:
825 {131, nullptr, "ActivateSleepButton"}, 838 {131, nullptr, "ActivateSleepButton"},
826 {141, nullptr, "AcquireCaptureButtonEventHandle"}, 839 {141, nullptr, "AcquireCaptureButtonEventHandle"},
827 {151, nullptr, "ActivateCaptureButton"}, 840 {151, nullptr, "ActivateCaptureButton"},
841 {161, nullptr, "GetPlatformConfig"},
828 {210, nullptr, "AcquireNfcDeviceUpdateEventHandle"}, 842 {210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
829 {211, nullptr, "GetNpadsWithNfc"}, 843 {211, nullptr, "GetNpadsWithNfc"},
830 {212, nullptr, "AcquireNfcActivateEventHandle"}, 844 {212, nullptr, "AcquireNfcActivateEventHandle"},
@@ -894,6 +908,7 @@ public:
894 {827, nullptr, "IsAnalogStickButtonPressed"}, 908 {827, nullptr, "IsAnalogStickButtonPressed"},
895 {828, nullptr, "IsAnalogStickInReleasePosition"}, 909 {828, nullptr, "IsAnalogStickInReleasePosition"},
896 {829, nullptr, "IsAnalogStickInCircumference"}, 910 {829, nullptr, "IsAnalogStickInCircumference"},
911 {830, nullptr, "SetNotificationLedPattern"},
897 {850, nullptr, "IsUsbFullKeyControllerEnabled"}, 912 {850, nullptr, "IsUsbFullKeyControllerEnabled"},
898 {851, nullptr, "EnableUsbFullKeyController"}, 913 {851, nullptr, "EnableUsbFullKeyController"},
899 {852, nullptr, "IsUsbConnected"}, 914 {852, nullptr, "IsUsbConnected"},
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
index e250595e3..ed5059047 100644
--- a/src/core/hle/service/ldn/ldn.cpp
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -52,9 +52,11 @@ public:
52 } 52 }
53}; 53};
54 54
55class ILocalCommunicationService final : public ServiceFramework<ILocalCommunicationService> { 55class ISystemLocalCommunicationService final
56 : public ServiceFramework<ISystemLocalCommunicationService> {
56public: 57public:
57 explicit ILocalCommunicationService(const char* name) : ServiceFramework{name} { 58 explicit ISystemLocalCommunicationService()
59 : ServiceFramework{"ISystemLocalCommunicationService"} {
58 // clang-format off 60 // clang-format off
59 static const FunctionInfo functions[] = { 61 static const FunctionInfo functions[] = {
60 {0, nullptr, "GetState"}, 62 {0, nullptr, "GetState"},
@@ -84,6 +86,50 @@ public:
84 {304, nullptr, "Disconnect"}, 86 {304, nullptr, "Disconnect"},
85 {400, nullptr, "InitializeSystem"}, 87 {400, nullptr, "InitializeSystem"},
86 {401, nullptr, "FinalizeSystem"}, 88 {401, nullptr, "FinalizeSystem"},
89 {402, nullptr, "SetOperationMode"},
90 {403, nullptr, "InitializeSystem2"},
91 };
92 // clang-format on
93
94 RegisterHandlers(functions);
95 }
96};
97
98class IUserLocalCommunicationService final
99 : public ServiceFramework<IUserLocalCommunicationService> {
100public:
101 explicit IUserLocalCommunicationService() : ServiceFramework{"IUserLocalCommunicationService"} {
102 // clang-format off
103 static const FunctionInfo functions[] = {
104 {0, nullptr, "GetState"},
105 {1, nullptr, "GetNetworkInfo"},
106 {2, nullptr, "GetIpv4Address"},
107 {3, nullptr, "GetDisconnectReason"},
108 {4, nullptr, "GetSecurityParameter"},
109 {5, nullptr, "GetNetworkConfig"},
110 {100, nullptr, "AttachStateChangeEvent"},
111 {101, nullptr, "GetNetworkInfoLatestUpdate"},
112 {102, nullptr, "Scan"},
113 {103, nullptr, "ScanPrivate"},
114 {104, nullptr, "SetWirelessControllerRestriction"},
115 {200, nullptr, "OpenAccessPoint"},
116 {201, nullptr, "CloseAccessPoint"},
117 {202, nullptr, "CreateNetwork"},
118 {203, nullptr, "CreateNetworkPrivate"},
119 {204, nullptr, "DestroyNetwork"},
120 {205, nullptr, "Reject"},
121 {206, nullptr, "SetAdvertiseData"},
122 {207, nullptr, "SetStationAcceptPolicy"},
123 {208, nullptr, "AddAcceptFilterEntry"},
124 {209, nullptr, "ClearAcceptFilter"},
125 {300, nullptr, "OpenStation"},
126 {301, nullptr, "CloseStation"},
127 {302, nullptr, "Connect"},
128 {303, nullptr, "ConnectPrivate"},
129 {304, nullptr, "Disconnect"},
130 {400, nullptr, "Initialize"},
131 {401, nullptr, "Finalize"},
132 {402, nullptr, "SetOperationMode"},
87 }; 133 };
88 // clang-format on 134 // clang-format on
89 135
@@ -108,7 +154,7 @@ public:
108 154
109 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 155 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
110 rb.Push(RESULT_SUCCESS); 156 rb.Push(RESULT_SUCCESS);
111 rb.PushIpcInterface<ILocalCommunicationService>("ISystemLocalCommunicationService"); 157 rb.PushIpcInterface<ISystemLocalCommunicationService>();
112 } 158 }
113}; 159};
114 160
@@ -129,7 +175,7 @@ public:
129 175
130 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 176 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
131 rb.Push(RESULT_SUCCESS); 177 rb.Push(RESULT_SUCCESS);
132 rb.PushIpcInterface<ILocalCommunicationService>("IUserLocalCommunicationService"); 178 rb.PushIpcInterface<IUserLocalCommunicationService>();
133 } 179 }
134}; 180};
135 181
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index 609102f2c..5af925515 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -86,6 +86,7 @@ public:
86 {2, &RelocatableObject::LoadNrr, "LoadNrr"}, 86 {2, &RelocatableObject::LoadNrr, "LoadNrr"},
87 {3, &RelocatableObject::UnloadNrr, "UnloadNrr"}, 87 {3, &RelocatableObject::UnloadNrr, "UnloadNrr"},
88 {4, &RelocatableObject::Initialize, "Initialize"}, 88 {4, &RelocatableObject::Initialize, "Initialize"},
89 {10, nullptr, "LoadNrrEx"},
89 }; 90 };
90 // clang-format on 91 // clang-format on
91 92
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index 60479bb45..f92571008 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -15,12 +15,16 @@ namespace Service::NIFM {
15class IScanRequest final : public ServiceFramework<IScanRequest> { 15class IScanRequest final : public ServiceFramework<IScanRequest> {
16public: 16public:
17 explicit IScanRequest() : ServiceFramework("IScanRequest") { 17 explicit IScanRequest() : ServiceFramework("IScanRequest") {
18 // clang-format off
18 static const FunctionInfo functions[] = { 19 static const FunctionInfo functions[] = {
19 {0, nullptr, "Submit"}, 20 {0, nullptr, "Submit"},
20 {1, nullptr, "IsProcessing"}, 21 {1, nullptr, "IsProcessing"},
21 {2, nullptr, "GetResult"}, 22 {2, nullptr, "GetResult"},
22 {3, nullptr, "GetSystemEventReadableHandle"}, 23 {3, nullptr, "GetSystemEventReadableHandle"},
24 {4, nullptr, "SetChannels"},
23 }; 25 };
26 // clang-format on
27
24 RegisterHandlers(functions); 28 RegisterHandlers(functions);
25 } 29 }
26}; 30};
diff --git a/src/core/hle/service/npns/npns.cpp b/src/core/hle/service/npns/npns.cpp
index ccb6f9da9..8751522ca 100644
--- a/src/core/hle/service/npns/npns.cpp
+++ b/src/core/hle/service/npns/npns.cpp
@@ -45,7 +45,7 @@ public:
45 {114, nullptr, "AttachJid"}, 45 {114, nullptr, "AttachJid"},
46 {115, nullptr, "DetachJid"}, 46 {115, nullptr, "DetachJid"},
47 {201, nullptr, "RequestChangeStateForceTimed"}, 47 {201, nullptr, "RequestChangeStateForceTimed"},
48 {102, nullptr, "RequestChangeStateForceAsync"}, 48 {202, nullptr, "RequestChangeStateForceAsync"},
49 }; 49 };
50 // clang-format on 50 // clang-format on
51 51
@@ -73,6 +73,7 @@ public:
73 {103, nullptr, "GetState"}, 73 {103, nullptr, "GetState"},
74 {104, nullptr, "GetStatistics"}, 74 {104, nullptr, "GetStatistics"},
75 {111, nullptr, "GetJid"}, 75 {111, nullptr, "GetJid"},
76 {120, nullptr, "CreateNotificationReceiver"},
76 }; 77 };
77 // clang-format on 78 // clang-format on
78 79
diff --git a/src/core/hle/service/pctl/module.cpp b/src/core/hle/service/pctl/module.cpp
index 6081f41e1..c75b4ee34 100644
--- a/src/core/hle/service/pctl/module.cpp
+++ b/src/core/hle/service/pctl/module.cpp
@@ -12,10 +12,10 @@ namespace Service::PCTL {
12class IParentalControlService final : public ServiceFramework<IParentalControlService> { 12class IParentalControlService final : public ServiceFramework<IParentalControlService> {
13public: 13public:
14 IParentalControlService() : ServiceFramework("IParentalControlService") { 14 IParentalControlService() : ServiceFramework("IParentalControlService") {
15 // clang-format off
15 static const FunctionInfo functions[] = { 16 static const FunctionInfo functions[] = {
16 {1, &IParentalControlService::Initialize, "Initialize"}, 17 {1, &IParentalControlService::Initialize, "Initialize"},
17 {1001, &IParentalControlService::CheckFreeCommunicationPermission, 18 {1001, &IParentalControlService::CheckFreeCommunicationPermission, "CheckFreeCommunicationPermission"},
18 "CheckFreeCommunicationPermission"},
19 {1002, nullptr, "ConfirmLaunchApplicationPermission"}, 19 {1002, nullptr, "ConfirmLaunchApplicationPermission"},
20 {1003, nullptr, "ConfirmResumeApplicationPermission"}, 20 {1003, nullptr, "ConfirmResumeApplicationPermission"},
21 {1004, nullptr, "ConfirmSnsPostPermission"}, 21 {1004, nullptr, "ConfirmSnsPostPermission"},
@@ -30,6 +30,7 @@ public:
30 {1013, nullptr, "ConfirmStereoVisionPermission"}, 30 {1013, nullptr, "ConfirmStereoVisionPermission"},
31 {1014, nullptr, "ConfirmPlayableApplicationVideoOld"}, 31 {1014, nullptr, "ConfirmPlayableApplicationVideoOld"},
32 {1015, nullptr, "ConfirmPlayableApplicationVideo"}, 32 {1015, nullptr, "ConfirmPlayableApplicationVideo"},
33 {1016, nullptr, "ConfirmShowNewsPermission"},
33 {1031, nullptr, "IsRestrictionEnabled"}, 34 {1031, nullptr, "IsRestrictionEnabled"},
34 {1032, nullptr, "GetSafetyLevel"}, 35 {1032, nullptr, "GetSafetyLevel"},
35 {1033, nullptr, "SetSafetyLevel"}, 36 {1033, nullptr, "SetSafetyLevel"},
@@ -45,6 +46,7 @@ public:
45 {1045, nullptr, "UpdateFreeCommunicationApplicationList"}, 46 {1045, nullptr, "UpdateFreeCommunicationApplicationList"},
46 {1046, nullptr, "DisableFeaturesForReset"}, 47 {1046, nullptr, "DisableFeaturesForReset"},
47 {1047, nullptr, "NotifyApplicationDownloadStarted"}, 48 {1047, nullptr, "NotifyApplicationDownloadStarted"},
49 {1048, nullptr, "NotifyNetworkProfileCreated"},
48 {1061, nullptr, "ConfirmStereoVisionRestrictionConfigurable"}, 50 {1061, nullptr, "ConfirmStereoVisionRestrictionConfigurable"},
49 {1062, nullptr, "GetStereoVisionRestriction"}, 51 {1062, nullptr, "GetStereoVisionRestriction"},
50 {1063, nullptr, "SetStereoVisionRestriction"}, 52 {1063, nullptr, "SetStereoVisionRestriction"},
@@ -63,6 +65,7 @@ public:
63 {1411, nullptr, "GetPairingAccountInfo"}, 65 {1411, nullptr, "GetPairingAccountInfo"},
64 {1421, nullptr, "GetAccountNickname"}, 66 {1421, nullptr, "GetAccountNickname"},
65 {1424, nullptr, "GetAccountState"}, 67 {1424, nullptr, "GetAccountState"},
68 {1425, nullptr, "RequestPostEvents"},
66 {1432, nullptr, "GetSynchronizationEvent"}, 69 {1432, nullptr, "GetSynchronizationEvent"},
67 {1451, nullptr, "StartPlayTimer"}, 70 {1451, nullptr, "StartPlayTimer"},
68 {1452, nullptr, "StopPlayTimer"}, 71 {1452, nullptr, "StopPlayTimer"},
diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp
index 6b27dc4a3..ebcc41a43 100644
--- a/src/core/hle/service/pm/pm.cpp
+++ b/src/core/hle/service/pm/pm.cpp
@@ -42,15 +42,18 @@ private:
42class DebugMonitor final : public ServiceFramework<DebugMonitor> { 42class DebugMonitor final : public ServiceFramework<DebugMonitor> {
43public: 43public:
44 explicit DebugMonitor() : ServiceFramework{"pm:dmnt"} { 44 explicit DebugMonitor() : ServiceFramework{"pm:dmnt"} {
45 // clang-format off
45 static const FunctionInfo functions[] = { 46 static const FunctionInfo functions[] = {
46 {0, nullptr, "IsDebugMode"}, 47 {0, nullptr, "GetDebugProcesses"},
47 {1, nullptr, "GetDebugProcesses"}, 48 {1, nullptr, "StartDebugProcess"},
48 {2, nullptr, "StartDebugProcess"}, 49 {2, nullptr, "GetTitlePid"},
49 {3, nullptr, "GetTitlePid"}, 50 {3, nullptr, "EnableDebugForTitleId"},
50 {4, nullptr, "EnableDebugForTitleId"}, 51 {4, nullptr, "GetApplicationPid"},
51 {5, nullptr, "GetApplicationPid"}, 52 {5, nullptr, "EnableDebugForApplication"},
52 {6, nullptr, "EnableDebugForApplication"}, 53 {6, nullptr, "DisableDebug"},
53 }; 54 };
55 // clang-format on
56
54 RegisterHandlers(functions); 57 RegisterHandlers(functions);
55 } 58 }
56}; 59};
@@ -68,6 +71,7 @@ public:
68class Shell final : public ServiceFramework<Shell> { 71class Shell final : public ServiceFramework<Shell> {
69public: 72public:
70 explicit Shell() : ServiceFramework{"pm:shell"} { 73 explicit Shell() : ServiceFramework{"pm:shell"} {
74 // clang-format off
71 static const FunctionInfo functions[] = { 75 static const FunctionInfo functions[] = {
72 {0, nullptr, "LaunchProcess"}, 76 {0, nullptr, "LaunchProcess"},
73 {1, nullptr, "TerminateProcessByPid"}, 77 {1, nullptr, "TerminateProcessByPid"},
@@ -77,7 +81,10 @@ public:
77 {5, nullptr, "NotifyBootFinished"}, 81 {5, nullptr, "NotifyBootFinished"},
78 {6, nullptr, "GetApplicationPid"}, 82 {6, nullptr, "GetApplicationPid"},
79 {7, nullptr, "BoostSystemMemoryResourceLimit"}, 83 {7, nullptr, "BoostSystemMemoryResourceLimit"},
84 {8, nullptr, "EnableAdditionalSystemThreads"},
80 }; 85 };
86 // clang-format on
87
81 RegisterHandlers(functions); 88 RegisterHandlers(functions);
82 } 89 }
83}; 90};
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp
index 1afc43f75..4ecb6bcef 100644
--- a/src/core/hle/service/set/set.cpp
+++ b/src/core/hle/service/set/set.cpp
@@ -116,6 +116,7 @@ void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) {
116} 116}
117 117
118SET::SET() : ServiceFramework("set") { 118SET::SET() : ServiceFramework("set") {
119 // clang-format off
119 static const FunctionInfo functions[] = { 120 static const FunctionInfo functions[] = {
120 {0, &SET::GetLanguageCode, "GetLanguageCode"}, 121 {0, &SET::GetLanguageCode, "GetLanguageCode"},
121 {1, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"}, 122 {1, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"},
@@ -126,7 +127,10 @@ SET::SET() : ServiceFramework("set") {
126 {6, &SET::GetAvailableLanguageCodeCount2, "GetAvailableLanguageCodeCount2"}, 127 {6, &SET::GetAvailableLanguageCodeCount2, "GetAvailableLanguageCodeCount2"},
127 {7, nullptr, "GetKeyCodeMap"}, 128 {7, nullptr, "GetKeyCodeMap"},
128 {8, nullptr, "GetQuestFlag"}, 129 {8, nullptr, "GetQuestFlag"},
130 {9, nullptr, "GetKeyCodeMap2"},
129 }; 131 };
132 // clang-format on
133
130 RegisterHandlers(functions); 134 RegisterHandlers(functions);
131} 135}
132 136
diff --git a/src/core/hle/service/set/set_cal.cpp b/src/core/hle/service/set/set_cal.cpp
index 34654bb07..5981c575c 100644
--- a/src/core/hle/service/set/set_cal.cpp
+++ b/src/core/hle/service/set/set_cal.cpp
@@ -40,7 +40,7 @@ SET_CAL::SET_CAL() : ServiceFramework("set:cal") {
40 {30, nullptr, "GetAmiiboEcqvBlsCertificate"}, 40 {30, nullptr, "GetAmiiboEcqvBlsCertificate"},
41 {31, nullptr, "GetAmiiboEcqvBlsRootCertificate"}, 41 {31, nullptr, "GetAmiiboEcqvBlsRootCertificate"},
42 {32, nullptr, "GetUsbTypeCPowerSourceCircuitVersion"}, 42 {32, nullptr, "GetUsbTypeCPowerSourceCircuitVersion"},
43 {33, nullptr, "GetBatteryVersion"}, 43 {41, nullptr, "GetBatteryVersion"},
44 }; 44 };
45 RegisterHandlers(functions); 45 RegisterHandlers(functions);
46} 46}
diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp
index ecee554bf..98d0cfdfd 100644
--- a/src/core/hle/service/set/set_sys.cpp
+++ b/src/core/hle/service/set/set_sys.cpp
@@ -104,6 +104,7 @@ void SET_SYS::SetColorSetId(Kernel::HLERequestContext& ctx) {
104} 104}
105 105
106SET_SYS::SET_SYS() : ServiceFramework("set:sys") { 106SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
107 // clang-format off
107 static const FunctionInfo functions[] = { 108 static const FunctionInfo functions[] = {
108 {0, nullptr, "SetLanguageCode"}, 109 {0, nullptr, "SetLanguageCode"},
109 {1, nullptr, "SetNetworkSettings"}, 110 {1, nullptr, "SetNetworkSettings"},
@@ -252,7 +253,33 @@ SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
252 {147, nullptr, "GetConsoleSixAxisSensorAngularAcceleration"}, 253 {147, nullptr, "GetConsoleSixAxisSensorAngularAcceleration"},
253 {148, nullptr, "SetConsoleSixAxisSensorAngularAcceleration"}, 254 {148, nullptr, "SetConsoleSixAxisSensorAngularAcceleration"},
254 {149, nullptr, "GetRebootlessSystemUpdateVersion"}, 255 {149, nullptr, "GetRebootlessSystemUpdateVersion"},
256 {150, nullptr, "GetDeviceTimeZoneLocationUpdatedTime"},
257 {151, nullptr, "SetDeviceTimeZoneLocationUpdatedTime"},
258 {152, nullptr, "GetUserSystemClockAutomaticCorrectionUpdatedTime"},
259 {153, nullptr, "SetUserSystemClockAutomaticCorrectionUpdatedTime"},
260 {154, nullptr, "GetAccountOnlineStorageSettings"},
261 {155, nullptr, "SetAccountOnlineStorageSettings"},
262 {156, nullptr, "GetPctlReadyFlag"},
263 {157, nullptr, "SetPctlReadyFlag"},
264 {162, nullptr, "GetPtmBatteryVersion"},
265 {163, nullptr, "SetPtmBatteryVersion"},
266 {164, nullptr, "GetUsb30HostEnableFlag"},
267 {165, nullptr, "SetUsb30HostEnableFlag"},
268 {166, nullptr, "GetUsb30DeviceEnableFlag"},
269 {167, nullptr, "SetUsb30DeviceEnableFlag"},
270 {168, nullptr, "GetThemeId"},
271 {169, nullptr, "SetThemeId"},
272 {170, nullptr, "GetChineseTraditionalInputMethod"},
273 {171, nullptr, "SetChineseTraditionalInputMethod"},
274 {172, nullptr, "GetPtmCycleCountReliability"},
275 {173, nullptr, "SetPtmCycleCountReliability"},
276 {175, nullptr, "GetThemeSettings"},
277 {176, nullptr, "SetThemeSettings"},
278 {177, nullptr, "GetThemeKey"},
279 {178, nullptr, "SetThemeKey"},
255 }; 280 };
281 // clang-format on
282
256 RegisterHandlers(functions); 283 RegisterHandlers(functions);
257} 284}
258 285
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index 4342f3b2d..884ad173b 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -73,6 +73,7 @@ void BSD::Close(Kernel::HLERequestContext& ctx) {
73} 73}
74 74
75BSD::BSD(const char* name) : ServiceFramework(name) { 75BSD::BSD(const char* name) : ServiceFramework(name) {
76 // clang-format off
76 static const FunctionInfo functions[] = { 77 static const FunctionInfo functions[] = {
77 {0, &BSD::RegisterClient, "RegisterClient"}, 78 {0, &BSD::RegisterClient, "RegisterClient"},
78 {1, &BSD::StartMonitoring, "StartMonitoring"}, 79 {1, &BSD::StartMonitoring, "StartMonitoring"},
@@ -105,7 +106,11 @@ BSD::BSD(const char* name) : ServiceFramework(name) {
105 {28, nullptr, "GetResourceStatistics"}, 106 {28, nullptr, "GetResourceStatistics"},
106 {29, nullptr, "RecvMMsg"}, 107 {29, nullptr, "RecvMMsg"},
107 {30, nullptr, "SendMMsg"}, 108 {30, nullptr, "SendMMsg"},
109 {31, nullptr, "EventFd"},
110 {32, nullptr, "RegisterResourceStatisticsName"},
108 }; 111 };
112 // clang-format on
113
109 RegisterHandlers(functions); 114 RegisterHandlers(functions);
110} 115}
111 116
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp
index f7f87a958..65040c077 100644
--- a/src/core/hle/service/ssl/ssl.cpp
+++ b/src/core/hle/service/ssl/ssl.cpp
@@ -103,6 +103,8 @@ public:
103 {4, nullptr, "DebugIoctl"}, 103 {4, nullptr, "DebugIoctl"},
104 {5, &SSL::SetInterfaceVersion, "SetInterfaceVersion"}, 104 {5, &SSL::SetInterfaceVersion, "SetInterfaceVersion"},
105 {6, nullptr, "FlushSessionCache"}, 105 {6, nullptr, "FlushSessionCache"},
106 {7, nullptr, "SetDebugOption"},
107 {8, nullptr, "GetDebugOption"},
106 }; 108 };
107 // clang-format on 109 // clang-format on
108 110
diff --git a/src/core/hle/service/time/interface.cpp b/src/core/hle/service/time/interface.cpp
index b3a196f65..8d122ae33 100644
--- a/src/core/hle/service/time/interface.cpp
+++ b/src/core/hle/service/time/interface.cpp
@@ -8,6 +8,7 @@ namespace Service::Time {
8 8
9Time::Time(std::shared_ptr<Module> time, const char* name) 9Time::Time(std::shared_ptr<Module> time, const char* name)
10 : Module::Interface(std::move(time), name) { 10 : Module::Interface(std::move(time), name) {
11 // clang-format off
11 static const FunctionInfo functions[] = { 12 static const FunctionInfo functions[] = {
12 {0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, 13 {0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"},
13 {1, &Time::GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"}, 14 {1, &Time::GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
@@ -15,18 +16,23 @@ Time::Time(std::shared_ptr<Module> time, const char* name)
15 {3, &Time::GetTimeZoneService, "GetTimeZoneService"}, 16 {3, &Time::GetTimeZoneService, "GetTimeZoneService"},
16 {4, &Time::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, 17 {4, &Time::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
17 {5, nullptr, "GetEphemeralNetworkSystemClock"}, 18 {5, nullptr, "GetEphemeralNetworkSystemClock"},
19 {20, nullptr, "GetSharedMemoryNativeHandle"},
20 {30, nullptr, "GetStandardNetworkClockOperationEventReadableHandle"},
21 {31, nullptr, "GetEphemeralNetworkClockOperationEventReadableHandle"},
18 {50, nullptr, "SetStandardSteadyClockInternalOffset"}, 22 {50, nullptr, "SetStandardSteadyClockInternalOffset"},
19 {100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"}, 23 {100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
20 {101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"}, 24 {101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
21 {102, nullptr, "GetStandardUserSystemClockInitialYear"}, 25 {102, nullptr, "GetStandardUserSystemClockInitialYear"},
22 {200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"}, 26 {200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"},
27 {201, nullptr, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
23 {300, nullptr, "CalculateMonotonicSystemClockBaseTimePoint"}, 28 {300, nullptr, "CalculateMonotonicSystemClockBaseTimePoint"},
24 {400, &Time::GetClockSnapshot, "GetClockSnapshot"}, 29 {400, &Time::GetClockSnapshot, "GetClockSnapshot"},
25 {401, nullptr, "GetClockSnapshotFromSystemClockContext"}, 30 {401, nullptr, "GetClockSnapshotFromSystemClockContext"},
26 {500, &Time::CalculateStandardUserSystemClockDifferenceByUser, 31 {500, &Time::CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"},
27 "CalculateStandardUserSystemClockDifferenceByUser"},
28 {501, nullptr, "CalculateSpanBetween"}, 32 {501, nullptr, "CalculateSpanBetween"},
29 }; 33 };
34 // clang-format on
35
30 RegisterHandlers(functions); 36 RegisterHandlers(functions);
31} 37}
32 38
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 07aa7a1cd..10b13fb1d 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -86,25 +86,29 @@ FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::Virtua
86 return FileType::Error; 86 return FileType::Error;
87} 87}
88 88
89ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process) { 89AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirectory::Load(
90 Kernel::Process& process) {
90 if (is_loaded) { 91 if (is_loaded) {
91 return ResultStatus::ErrorAlreadyLoaded; 92 return {ResultStatus::ErrorAlreadyLoaded, {}};
92 } 93 }
93 94
94 if (dir == nullptr) { 95 if (dir == nullptr) {
95 if (file == nullptr) 96 if (file == nullptr) {
96 return ResultStatus::ErrorNullFile; 97 return {ResultStatus::ErrorNullFile, {}};
98 }
99
97 dir = file->GetContainingDirectory(); 100 dir = file->GetContainingDirectory();
98 } 101 }
99 102
100 // Read meta to determine title ID 103 // Read meta to determine title ID
101 FileSys::VirtualFile npdm = dir->GetFile("main.npdm"); 104 FileSys::VirtualFile npdm = dir->GetFile("main.npdm");
102 if (npdm == nullptr) 105 if (npdm == nullptr) {
103 return ResultStatus::ErrorMissingNPDM; 106 return {ResultStatus::ErrorMissingNPDM, {}};
107 }
104 108
105 ResultStatus result = metadata.Load(npdm); 109 const ResultStatus result = metadata.Load(npdm);
106 if (result != ResultStatus::Success) { 110 if (result != ResultStatus::Success) {
107 return result; 111 return {result, {}};
108 } 112 }
109 113
110 if (override_update) { 114 if (override_update) {
@@ -114,23 +118,24 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
114 118
115 // Reread in case PatchExeFS affected the main.npdm 119 // Reread in case PatchExeFS affected the main.npdm
116 npdm = dir->GetFile("main.npdm"); 120 npdm = dir->GetFile("main.npdm");
117 if (npdm == nullptr) 121 if (npdm == nullptr) {
118 return ResultStatus::ErrorMissingNPDM; 122 return {ResultStatus::ErrorMissingNPDM, {}};
123 }
119 124
120 ResultStatus result2 = metadata.Load(npdm); 125 const ResultStatus result2 = metadata.Load(npdm);
121 if (result2 != ResultStatus::Success) { 126 if (result2 != ResultStatus::Success) {
122 return result2; 127 return {result2, {}};
123 } 128 }
124 metadata.Print(); 129 metadata.Print();
125 130
126 const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()}; 131 const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()};
127 if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit || 132 if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit ||
128 arch_bits == FileSys::ProgramAddressSpaceType::Is32BitNoMap) { 133 arch_bits == FileSys::ProgramAddressSpaceType::Is32BitNoMap) {
129 return ResultStatus::Error32BitISA; 134 return {ResultStatus::Error32BitISA, {}};
130 } 135 }
131 136
132 if (process.LoadFromMetadata(metadata).IsError()) { 137 if (process.LoadFromMetadata(metadata).IsError()) {
133 return ResultStatus::ErrorUnableToParseKernelMetadata; 138 return {ResultStatus::ErrorUnableToParseKernelMetadata, {}};
134 } 139 }
135 140
136 const FileSys::PatchManager pm(metadata.GetTitleID()); 141 const FileSys::PatchManager pm(metadata.GetTitleID());
@@ -150,7 +155,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
150 const auto tentative_next_load_addr = 155 const auto tentative_next_load_addr =
151 AppLoader_NSO::LoadModule(process, *module_file, load_addr, should_pass_arguments, pm); 156 AppLoader_NSO::LoadModule(process, *module_file, load_addr, should_pass_arguments, pm);
152 if (!tentative_next_load_addr) { 157 if (!tentative_next_load_addr) {
153 return ResultStatus::ErrorLoadingNSO; 158 return {ResultStatus::ErrorLoadingNSO, {}};
154 } 159 }
155 160
156 next_load_addr = *tentative_next_load_addr; 161 next_load_addr = *tentative_next_load_addr;
@@ -159,8 +164,6 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
159 GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false); 164 GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false);
160 } 165 }
161 166
162 process.Run(base_address, metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize());
163
164 // Find the RomFS by searching for a ".romfs" file in this directory 167 // Find the RomFS by searching for a ".romfs" file in this directory
165 const auto& files = dir->GetFiles(); 168 const auto& files = dir->GetFiles();
166 const auto romfs_iter = 169 const auto romfs_iter =
@@ -175,7 +178,8 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
175 } 178 }
176 179
177 is_loaded = true; 180 is_loaded = true;
178 return ResultStatus::Success; 181 return {ResultStatus::Success,
182 LoadParameters{metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()}};
179} 183}
180 184
181ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(FileSys::VirtualFile& dir) { 185ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(FileSys::VirtualFile& dir) {
diff --git a/src/core/loader/deconstructed_rom_directory.h b/src/core/loader/deconstructed_rom_directory.h
index 1615cb5a8..1a65c16a4 100644
--- a/src/core/loader/deconstructed_rom_directory.h
+++ b/src/core/loader/deconstructed_rom_directory.h
@@ -37,7 +37,7 @@ public:
37 return IdentifyType(file); 37 return IdentifyType(file);
38 } 38 }
39 39
40 ResultStatus Load(Kernel::Process& process) override; 40 LoadResult Load(Kernel::Process& process) override;
41 41
42 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; 42 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
43 ResultStatus ReadIcon(std::vector<u8>& buffer) override; 43 ResultStatus ReadIcon(std::vector<u8>& buffer) override;
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index 46ac372f6..6d4b02375 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -382,13 +382,15 @@ FileType AppLoader_ELF::IdentifyType(const FileSys::VirtualFile& file) {
382 return FileType::Error; 382 return FileType::Error;
383} 383}
384 384
385ResultStatus AppLoader_ELF::Load(Kernel::Process& process) { 385AppLoader_ELF::LoadResult AppLoader_ELF::Load(Kernel::Process& process) {
386 if (is_loaded) 386 if (is_loaded) {
387 return ResultStatus::ErrorAlreadyLoaded; 387 return {ResultStatus::ErrorAlreadyLoaded, {}};
388 }
388 389
389 std::vector<u8> buffer = file->ReadAllBytes(); 390 std::vector<u8> buffer = file->ReadAllBytes();
390 if (buffer.size() != file->GetSize()) 391 if (buffer.size() != file->GetSize()) {
391 return ResultStatus::ErrorIncorrectELFFileSize; 392 return {ResultStatus::ErrorIncorrectELFFileSize, {}};
393 }
392 394
393 const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); 395 const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
394 ElfReader elf_reader(&buffer[0]); 396 ElfReader elf_reader(&buffer[0]);
@@ -396,10 +398,9 @@ ResultStatus AppLoader_ELF::Load(Kernel::Process& process) {
396 const VAddr entry_point = codeset.entrypoint; 398 const VAddr entry_point = codeset.entrypoint;
397 399
398 process.LoadModule(std::move(codeset), entry_point); 400 process.LoadModule(std::move(codeset), entry_point);
399 process.Run(entry_point, 48, Memory::DEFAULT_STACK_SIZE);
400 401
401 is_loaded = true; 402 is_loaded = true;
402 return ResultStatus::Success; 403 return {ResultStatus::Success, LoadParameters{48, Memory::DEFAULT_STACK_SIZE}};
403} 404}
404 405
405} // namespace Loader 406} // namespace Loader
diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h
index a2d33021c..7ef7770a6 100644
--- a/src/core/loader/elf.h
+++ b/src/core/loader/elf.h
@@ -26,7 +26,7 @@ public:
26 return IdentifyType(file); 26 return IdentifyType(file);
27 } 27 }
28 28
29 ResultStatus Load(Kernel::Process& process) override; 29 LoadResult Load(Kernel::Process& process) override;
30}; 30};
31 31
32} // namespace Loader 32} // namespace Loader
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index bb925f4a6..f7846db52 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -131,6 +131,12 @@ std::ostream& operator<<(std::ostream& os, ResultStatus status);
131/// Interface for loading an application 131/// Interface for loading an application
132class AppLoader : NonCopyable { 132class AppLoader : NonCopyable {
133public: 133public:
134 struct LoadParameters {
135 s32 main_thread_priority;
136 u64 main_thread_stack_size;
137 };
138 using LoadResult = std::pair<ResultStatus, std::optional<LoadParameters>>;
139
134 explicit AppLoader(FileSys::VirtualFile file); 140 explicit AppLoader(FileSys::VirtualFile file);
135 virtual ~AppLoader(); 141 virtual ~AppLoader();
136 142
@@ -145,7 +151,7 @@ public:
145 * @param process The newly created process. 151 * @param process The newly created process.
146 * @return The status result of the operation. 152 * @return The status result of the operation.
147 */ 153 */
148 virtual ResultStatus Load(Kernel::Process& process) = 0; 154 virtual LoadResult Load(Kernel::Process& process) = 0;
149 155
150 /** 156 /**
151 * Loads the system mode that this application needs. 157 * Loads the system mode that this application needs.
diff --git a/src/core/loader/nax.cpp b/src/core/loader/nax.cpp
index 93a970d10..34efef09a 100644
--- a/src/core/loader/nax.cpp
+++ b/src/core/loader/nax.cpp
@@ -41,31 +41,37 @@ FileType AppLoader_NAX::GetFileType() const {
41 return IdentifyTypeImpl(*nax); 41 return IdentifyTypeImpl(*nax);
42} 42}
43 43
44ResultStatus AppLoader_NAX::Load(Kernel::Process& process) { 44AppLoader_NAX::LoadResult AppLoader_NAX::Load(Kernel::Process& process) {
45 if (is_loaded) { 45 if (is_loaded) {
46 return ResultStatus::ErrorAlreadyLoaded; 46 return {ResultStatus::ErrorAlreadyLoaded, {}};
47 } 47 }
48 48
49 if (nax->GetStatus() != ResultStatus::Success) 49 const auto nax_status = nax->GetStatus();
50 return nax->GetStatus(); 50 if (nax_status != ResultStatus::Success) {
51 return {nax_status, {}};
52 }
51 53
52 const auto nca = nax->AsNCA(); 54 const auto nca = nax->AsNCA();
53 if (nca == nullptr) { 55 if (nca == nullptr) {
54 if (!Core::Crypto::KeyManager::KeyFileExists(false)) 56 if (!Core::Crypto::KeyManager::KeyFileExists(false)) {
55 return ResultStatus::ErrorMissingProductionKeyFile; 57 return {ResultStatus::ErrorMissingProductionKeyFile, {}};
56 return ResultStatus::ErrorNAXInconvertibleToNCA; 58 }
59
60 return {ResultStatus::ErrorNAXInconvertibleToNCA, {}};
57 } 61 }
58 62
59 if (nca->GetStatus() != ResultStatus::Success) 63 const auto nca_status = nca->GetStatus();
60 return nca->GetStatus(); 64 if (nca_status != ResultStatus::Success) {
65 return {nca_status, {}};
66 }
61 67
62 const auto result = nca_loader->Load(process); 68 const auto result = nca_loader->Load(process);
63 if (result != ResultStatus::Success) 69 if (result.first != ResultStatus::Success) {
64 return result; 70 return result;
71 }
65 72
66 is_loaded = true; 73 is_loaded = true;
67 74 return result;
68 return ResultStatus::Success;
69} 75}
70 76
71ResultStatus AppLoader_NAX::ReadRomFS(FileSys::VirtualFile& dir) { 77ResultStatus AppLoader_NAX::ReadRomFS(FileSys::VirtualFile& dir) {
diff --git a/src/core/loader/nax.h b/src/core/loader/nax.h
index f40079574..00f1659c1 100644
--- a/src/core/loader/nax.h
+++ b/src/core/loader/nax.h
@@ -33,7 +33,7 @@ public:
33 33
34 FileType GetFileType() const override; 34 FileType GetFileType() const override;
35 35
36 ResultStatus Load(Kernel::Process& process) override; 36 LoadResult Load(Kernel::Process& process) override;
37 37
38 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; 38 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
39 u64 ReadRomFSIVFCOffset() const override; 39 u64 ReadRomFSIVFCOffset() const override;
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index ce8196fcf..b3f8f1083 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -30,36 +30,38 @@ FileType AppLoader_NCA::IdentifyType(const FileSys::VirtualFile& file) {
30 return FileType::Error; 30 return FileType::Error;
31} 31}
32 32
33ResultStatus AppLoader_NCA::Load(Kernel::Process& process) { 33AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::Process& process) {
34 if (is_loaded) { 34 if (is_loaded) {
35 return ResultStatus::ErrorAlreadyLoaded; 35 return {ResultStatus::ErrorAlreadyLoaded, {}};
36 } 36 }
37 37
38 const auto result = nca->GetStatus(); 38 const auto result = nca->GetStatus();
39 if (result != ResultStatus::Success) { 39 if (result != ResultStatus::Success) {
40 return result; 40 return {result, {}};
41 } 41 }
42 42
43 if (nca->GetType() != FileSys::NCAContentType::Program) 43 if (nca->GetType() != FileSys::NCAContentType::Program) {
44 return ResultStatus::ErrorNCANotProgram; 44 return {ResultStatus::ErrorNCANotProgram, {}};
45 }
45 46
46 const auto exefs = nca->GetExeFS(); 47 const auto exefs = nca->GetExeFS();
47 48 if (exefs == nullptr) {
48 if (exefs == nullptr) 49 return {ResultStatus::ErrorNoExeFS, {}};
49 return ResultStatus::ErrorNoExeFS; 50 }
50 51
51 directory_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(exefs, true); 52 directory_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(exefs, true);
52 53
53 const auto load_result = directory_loader->Load(process); 54 const auto load_result = directory_loader->Load(process);
54 if (load_result != ResultStatus::Success) 55 if (load_result.first != ResultStatus::Success) {
55 return load_result; 56 return load_result;
57 }
56 58
57 if (nca->GetRomFS() != nullptr && nca->GetRomFS()->GetSize() > 0) 59 if (nca->GetRomFS() != nullptr && nca->GetRomFS()->GetSize() > 0) {
58 Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this)); 60 Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this));
61 }
59 62
60 is_loaded = true; 63 is_loaded = true;
61 64 return load_result;
62 return ResultStatus::Success;
63} 65}
64 66
65ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) { 67ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) {
diff --git a/src/core/loader/nca.h b/src/core/loader/nca.h
index b9f077468..94f0ed677 100644
--- a/src/core/loader/nca.h
+++ b/src/core/loader/nca.h
@@ -33,7 +33,7 @@ public:
33 return IdentifyType(file); 33 return IdentifyType(file);
34 } 34 }
35 35
36 ResultStatus Load(Kernel::Process& process) override; 36 LoadResult Load(Kernel::Process& process) override;
37 37
38 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; 38 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
39 u64 ReadRomFSIVFCOffset() const override; 39 u64 ReadRomFSIVFCOffset() const override;
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index 31e4a0c84..6a0ca389b 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -201,25 +201,25 @@ bool AppLoader_NRO::LoadNro(Kernel::Process& process, const FileSys::VfsFile& fi
201 return LoadNroImpl(process, file.ReadAllBytes(), file.GetName(), load_base); 201 return LoadNroImpl(process, file.ReadAllBytes(), file.GetName(), load_base);
202} 202}
203 203
204ResultStatus AppLoader_NRO::Load(Kernel::Process& process) { 204AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::Process& process) {
205 if (is_loaded) { 205 if (is_loaded) {
206 return ResultStatus::ErrorAlreadyLoaded; 206 return {ResultStatus::ErrorAlreadyLoaded, {}};
207 } 207 }
208 208
209 // Load NRO 209 // Load NRO
210 const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); 210 const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
211 211
212 if (!LoadNro(process, *file, base_address)) { 212 if (!LoadNro(process, *file, base_address)) {
213 return ResultStatus::ErrorLoadingNRO; 213 return {ResultStatus::ErrorLoadingNRO, {}};
214 } 214 }
215 215
216 if (romfs != nullptr) 216 if (romfs != nullptr) {
217 Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this)); 217 Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this));
218 218 }
219 process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);
220 219
221 is_loaded = true; 220 is_loaded = true;
222 return ResultStatus::Success; 221 return {ResultStatus::Success,
222 LoadParameters{Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE}};
223} 223}
224 224
225ResultStatus AppLoader_NRO::ReadIcon(std::vector<u8>& buffer) { 225ResultStatus AppLoader_NRO::ReadIcon(std::vector<u8>& buffer) {
diff --git a/src/core/loader/nro.h b/src/core/loader/nro.h
index 85b0ed644..1ffdae805 100644
--- a/src/core/loader/nro.h
+++ b/src/core/loader/nro.h
@@ -37,7 +37,7 @@ public:
37 return IdentifyType(file); 37 return IdentifyType(file);
38 } 38 }
39 39
40 ResultStatus Load(Kernel::Process& process) override; 40 LoadResult Load(Kernel::Process& process) override;
41 41
42 ResultStatus ReadIcon(std::vector<u8>& buffer) override; 42 ResultStatus ReadIcon(std::vector<u8>& buffer) override;
43 ResultStatus ReadProgramId(u64& out_program_id) override; 43 ResultStatus ReadProgramId(u64& out_program_id) override;
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index d7c47c197..a86653204 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -169,22 +169,21 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
169 return load_base + image_size; 169 return load_base + image_size;
170} 170}
171 171
172ResultStatus AppLoader_NSO::Load(Kernel::Process& process) { 172AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process) {
173 if (is_loaded) { 173 if (is_loaded) {
174 return ResultStatus::ErrorAlreadyLoaded; 174 return {ResultStatus::ErrorAlreadyLoaded, {}};
175 } 175 }
176 176
177 // Load module 177 // Load module
178 const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); 178 const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
179 if (!LoadModule(process, *file, base_address, true)) { 179 if (!LoadModule(process, *file, base_address, true)) {
180 return ResultStatus::ErrorLoadingNSO; 180 return {ResultStatus::ErrorLoadingNSO, {}};
181 } 181 }
182 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address); 182 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address);
183 183
184 process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);
185
186 is_loaded = true; 184 is_loaded = true;
187 return ResultStatus::Success; 185 return {ResultStatus::Success,
186 LoadParameters{Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE}};
188} 187}
189 188
190} // namespace Loader 189} // namespace Loader
diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h
index 4674c3724..fdce9191c 100644
--- a/src/core/loader/nso.h
+++ b/src/core/loader/nso.h
@@ -84,7 +84,7 @@ public:
84 VAddr load_base, bool should_pass_arguments, 84 VAddr load_base, bool should_pass_arguments,
85 std::optional<FileSys::PatchManager> pm = {}); 85 std::optional<FileSys::PatchManager> pm = {});
86 86
87 ResultStatus Load(Kernel::Process& process) override; 87 LoadResult Load(Kernel::Process& process) override;
88}; 88};
89 89
90} // namespace Loader 90} // namespace Loader
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp
index 7da1f8960..ad56bbb38 100644
--- a/src/core/loader/nsp.cpp
+++ b/src/core/loader/nsp.cpp
@@ -72,37 +72,45 @@ FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& file) {
72 return FileType::Error; 72 return FileType::Error;
73} 73}
74 74
75ResultStatus AppLoader_NSP::Load(Kernel::Process& process) { 75AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::Process& process) {
76 if (is_loaded) { 76 if (is_loaded) {
77 return ResultStatus::ErrorAlreadyLoaded; 77 return {ResultStatus::ErrorAlreadyLoaded, {}};
78 } 78 }
79 79
80 if (title_id == 0) 80 if (title_id == 0) {
81 return ResultStatus::ErrorNSPMissingProgramNCA; 81 return {ResultStatus::ErrorNSPMissingProgramNCA, {}};
82 }
82 83
83 if (nsp->GetStatus() != ResultStatus::Success) 84 const auto nsp_status = nsp->GetStatus();
84 return nsp->GetStatus(); 85 if (nsp_status != ResultStatus::Success) {
86 return {nsp_status, {}};
87 }
85 88
86 if (nsp->GetProgramStatus(title_id) != ResultStatus::Success) 89 const auto nsp_program_status = nsp->GetProgramStatus(title_id);
87 return nsp->GetProgramStatus(title_id); 90 if (nsp_program_status != ResultStatus::Success) {
91 return {nsp_program_status, {}};
92 }
88 93
89 if (nsp->GetNCA(title_id, FileSys::ContentRecordType::Program) == nullptr) { 94 if (nsp->GetNCA(title_id, FileSys::ContentRecordType::Program) == nullptr) {
90 if (!Core::Crypto::KeyManager::KeyFileExists(false)) 95 if (!Core::Crypto::KeyManager::KeyFileExists(false)) {
91 return ResultStatus::ErrorMissingProductionKeyFile; 96 return {ResultStatus::ErrorMissingProductionKeyFile, {}};
92 return ResultStatus::ErrorNSPMissingProgramNCA; 97 }
98
99 return {ResultStatus::ErrorNSPMissingProgramNCA, {}};
93 } 100 }
94 101
95 const auto result = secondary_loader->Load(process); 102 const auto result = secondary_loader->Load(process);
96 if (result != ResultStatus::Success) 103 if (result.first != ResultStatus::Success) {
97 return result; 104 return result;
105 }
98 106
99 FileSys::VirtualFile update_raw; 107 FileSys::VirtualFile update_raw;
100 if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) 108 if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
101 Service::FileSystem::SetPackedUpdate(std::move(update_raw)); 109 Service::FileSystem::SetPackedUpdate(std::move(update_raw));
110 }
102 111
103 is_loaded = true; 112 is_loaded = true;
104 113 return result;
105 return ResultStatus::Success;
106} 114}
107 115
108ResultStatus AppLoader_NSP::ReadRomFS(FileSys::VirtualFile& file) { 116ResultStatus AppLoader_NSP::ReadRomFS(FileSys::VirtualFile& file) {
diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h
index 953a1b508..85e870bdf 100644
--- a/src/core/loader/nsp.h
+++ b/src/core/loader/nsp.h
@@ -35,7 +35,7 @@ public:
35 return IdentifyType(file); 35 return IdentifyType(file);
36 } 36 }
37 37
38 ResultStatus Load(Kernel::Process& process) override; 38 LoadResult Load(Kernel::Process& process) override;
39 39
40 ResultStatus ReadRomFS(FileSys::VirtualFile& file) override; 40 ResultStatus ReadRomFS(FileSys::VirtualFile& file) override;
41 u64 ReadRomFSIVFCOffset() const override; 41 u64 ReadRomFSIVFCOffset() const override;
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index 89f7bbf77..1e285a053 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -48,31 +48,35 @@ FileType AppLoader_XCI::IdentifyType(const FileSys::VirtualFile& file) {
48 return FileType::Error; 48 return FileType::Error;
49} 49}
50 50
51ResultStatus AppLoader_XCI::Load(Kernel::Process& process) { 51AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::Process& process) {
52 if (is_loaded) { 52 if (is_loaded) {
53 return ResultStatus::ErrorAlreadyLoaded; 53 return {ResultStatus::ErrorAlreadyLoaded, {}};
54 } 54 }
55 55
56 if (xci->GetStatus() != ResultStatus::Success) 56 if (xci->GetStatus() != ResultStatus::Success) {
57 return xci->GetStatus(); 57 return {xci->GetStatus(), {}};
58 }
58 59
59 if (xci->GetProgramNCAStatus() != ResultStatus::Success) 60 if (xci->GetProgramNCAStatus() != ResultStatus::Success) {
60 return xci->GetProgramNCAStatus(); 61 return {xci->GetProgramNCAStatus(), {}};
62 }
61 63
62 if (!xci->HasProgramNCA() && !Core::Crypto::KeyManager::KeyFileExists(false)) 64 if (!xci->HasProgramNCA() && !Core::Crypto::KeyManager::KeyFileExists(false)) {
63 return ResultStatus::ErrorMissingProductionKeyFile; 65 return {ResultStatus::ErrorMissingProductionKeyFile, {}};
66 }
64 67
65 const auto result = nca_loader->Load(process); 68 const auto result = nca_loader->Load(process);
66 if (result != ResultStatus::Success) 69 if (result.first != ResultStatus::Success) {
67 return result; 70 return result;
71 }
68 72
69 FileSys::VirtualFile update_raw; 73 FileSys::VirtualFile update_raw;
70 if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) 74 if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
71 Service::FileSystem::SetPackedUpdate(std::move(update_raw)); 75 Service::FileSystem::SetPackedUpdate(std::move(update_raw));
76 }
72 77
73 is_loaded = true; 78 is_loaded = true;
74 79 return result;
75 return ResultStatus::Success;
76} 80}
77 81
78ResultStatus AppLoader_XCI::ReadRomFS(FileSys::VirtualFile& file) { 82ResultStatus AppLoader_XCI::ReadRomFS(FileSys::VirtualFile& file) {
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h
index 436f7387c..ae7145b14 100644
--- a/src/core/loader/xci.h
+++ b/src/core/loader/xci.h
@@ -35,7 +35,7 @@ public:
35 return IdentifyType(file); 35 return IdentifyType(file);
36 } 36 }
37 37
38 ResultStatus Load(Kernel::Process& process) override; 38 LoadResult Load(Kernel::Process& process) override;
39 39
40 ResultStatus ReadRomFS(FileSys::VirtualFile& file) override; 40 ResultStatus ReadRomFS(FileSys::VirtualFile& file) override;
41 u64 ReadRomFSIVFCOffset() const override; 41 u64 ReadRomFSIVFCOffset() const override;
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 4e0538bc2..f18f6226b 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -26,16 +26,16 @@ namespace Memory {
26 26
27static Common::PageTable* current_page_table = nullptr; 27static Common::PageTable* current_page_table = nullptr;
28 28
29void SetCurrentPageTable(Common::PageTable* page_table) { 29void SetCurrentPageTable(Kernel::Process& process) {
30 current_page_table = page_table; 30 current_page_table = &process.VMManager().page_table;
31
32 const std::size_t address_space_width = process.VMManager().GetAddressSpaceWidth();
31 33
32 auto& system = Core::System::GetInstance(); 34 auto& system = Core::System::GetInstance();
33 if (system.IsPoweredOn()) { 35 system.ArmInterface(0).PageTableChanged(*current_page_table, address_space_width);
34 system.ArmInterface(0).PageTableChanged(); 36 system.ArmInterface(1).PageTableChanged(*current_page_table, address_space_width);
35 system.ArmInterface(1).PageTableChanged(); 37 system.ArmInterface(2).PageTableChanged(*current_page_table, address_space_width);
36 system.ArmInterface(2).PageTableChanged(); 38 system.ArmInterface(3).PageTableChanged(*current_page_table, address_space_width);
37 system.ArmInterface(3).PageTableChanged();
38 }
39} 39}
40 40
41static void MapPages(Common::PageTable& page_table, VAddr base, u64 size, u8* memory, 41static void MapPages(Common::PageTable& page_table, VAddr base, u64 size, u8* memory,
diff --git a/src/core/memory.h b/src/core/memory.h
index 6845f5fe1..b9fa18b1d 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -40,8 +40,9 @@ enum : VAddr {
40 KERNEL_REGION_END = KERNEL_REGION_VADDR + KERNEL_REGION_SIZE, 40 KERNEL_REGION_END = KERNEL_REGION_VADDR + KERNEL_REGION_SIZE,
41}; 41};
42 42
43/// Changes the currently active page table. 43/// Changes the currently active page table to that of
44void SetCurrentPageTable(Common::PageTable* page_table); 44/// the given process instance.
45void SetCurrentPageTable(Kernel::Process& process);
45 46
46/// Determines if the given VAddr is valid for the specified process. 47/// Determines if the given VAddr is valid for the specified process.
47bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr); 48bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr);
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 6d32ebea3..c1365879b 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -90,6 +90,7 @@ void LogSettings() {
90 LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor); 90 LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor);
91 LogSetting("Renderer_UseFrameLimit", Settings::values.use_frame_limit); 91 LogSetting("Renderer_UseFrameLimit", Settings::values.use_frame_limit);
92 LogSetting("Renderer_FrameLimit", Settings::values.frame_limit); 92 LogSetting("Renderer_FrameLimit", Settings::values.frame_limit);
93 LogSetting("Renderer_UseCompatibilityProfile", Settings::values.use_compatibility_profile);
93 LogSetting("Renderer_UseDiskShaderCache", Settings::values.use_disk_shader_cache); 94 LogSetting("Renderer_UseDiskShaderCache", Settings::values.use_disk_shader_cache);
94 LogSetting("Renderer_UseAccurateGpuEmulation", Settings::values.use_accurate_gpu_emulation); 95 LogSetting("Renderer_UseAccurateGpuEmulation", Settings::values.use_accurate_gpu_emulation);
95 LogSetting("Renderer_UseAsynchronousGpuEmulation", 96 LogSetting("Renderer_UseAsynchronousGpuEmulation",
diff --git a/src/core/settings.h b/src/core/settings.h
index b84390745..5ff3634aa 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -390,6 +390,7 @@ struct Values {
390 float resolution_factor; 390 float resolution_factor;
391 bool use_frame_limit; 391 bool use_frame_limit;
392 u16 frame_limit; 392 u16 frame_limit;
393 bool use_compatibility_profile;
393 bool use_disk_shader_cache; 394 bool use_disk_shader_cache;
394 bool use_accurate_gpu_emulation; 395 bool use_accurate_gpu_emulation;
395 bool use_asynchronous_gpu_emulation; 396 bool use_asynchronous_gpu_emulation;