summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
m---------externals/Vulkan-Headers0
-rw-r--r--src/audio_core/device/device_session.cpp4
-rw-r--r--src/audio_core/renderer/adsp/adsp.cpp2
-rw-r--r--src/audio_core/renderer/adsp/command_list_processor.cpp2
-rw-r--r--src/audio_core/renderer/system.cpp3
-rw-r--r--src/common/CMakeLists.txt2
-rw-r--r--src/common/range_map.h6
-rw-r--r--src/common/telemetry.cpp1
-rw-r--r--src/common/x64/cpu_detect.cpp1
-rw-r--r--src/common/x64/cpu_detect.h1
-rw-r--r--src/common/x64/cpu_wait.cpp69
-rw-r--r--src/common/x64/cpu_wait.h10
-rw-r--r--src/common/x64/native_clock.cpp13
-rw-r--r--src/core/arm/arm_interface.cpp2
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp6
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp6
-rw-r--r--src/core/core.cpp6
-rw-r--r--src/core/core.h4
-rw-r--r--src/core/core_timing.cpp8
-rw-r--r--src/core/debugger/gdbstub.cpp34
-rw-r--r--src/core/frontend/applets/applet.h14
-rw-r--r--src/core/frontend/applets/cabinet.cpp2
-rw-r--r--src/core/frontend/applets/cabinet.h4
-rw-r--r--src/core/frontend/applets/controller.cpp4
-rw-r--r--src/core/frontend/applets/controller.h6
-rw-r--r--src/core/frontend/applets/error.cpp2
-rw-r--r--src/core/frontend/applets/error.h4
-rw-r--r--src/core/frontend/applets/general_frontend.cpp4
-rw-r--r--src/core/frontend/applets/general_frontend.h8
-rw-r--r--src/core/frontend/applets/mii_edit.cpp2
-rw-r--r--src/core/frontend/applets/mii_edit.h5
-rw-r--r--src/core/frontend/applets/profile_select.cpp5
-rw-r--r--src/core/frontend/applets/profile_select.h19
-rw-r--r--src/core/frontend/applets/software_keyboard.cpp2
-rw-r--r--src/core/frontend/applets/software_keyboard.h5
-rw-r--r--src/core/frontend/applets/web_browser.cpp2
-rw-r--r--src/core/frontend/applets/web_browser.h5
-rw-r--r--src/core/hle/kernel/k_address_arbiter.cpp76
-rw-r--r--src/core/hle/kernel/k_condition_variable.cpp45
-rw-r--r--src/core/hle/kernel/k_page_table.cpp54
-rw-r--r--src/core/hle/kernel/k_page_table.h4
-rw-r--r--src/core/hle/kernel/k_process.cpp22
-rw-r--r--src/core/hle/kernel/k_process.h15
-rw-r--r--src/core/hle/kernel/k_server_session.cpp4
-rw-r--r--src/core/hle/kernel/k_thread.cpp11
-rw-r--r--src/core/hle/kernel/k_thread.h4
-rw-r--r--src/core/hle/kernel/kernel.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_cache.cpp2
-rw-r--r--src/core/hle/kernel/svc/svc_debug_string.cpp3
-rw-r--r--src/core/hle/kernel/svc/svc_exception.cpp2
-rw-r--r--src/core/hle/kernel/svc/svc_ipc.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_port.cpp6
-rw-r--r--src/core/hle/kernel/svc/svc_process.cpp2
-rw-r--r--src/core/hle/kernel/svc/svc_query_memory.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_synchronization.cpp3
-rw-r--r--src/core/hle/kernel/svc/svc_thread.cpp4
-rw-r--r--src/core/hle/service/am/am.cpp17
-rw-r--r--src/core/hle/service/am/applets/applet_cabinet.cpp5
-rw-r--r--src/core/hle/service/am/applets/applet_cabinet.h1
-rw-r--r--src/core/hle/service/am/applets/applet_controller.cpp17
-rw-r--r--src/core/hle/service/am/applets/applet_controller.h10
-rw-r--r--src/core/hle/service/am/applets/applet_error.cpp5
-rw-r--r--src/core/hle/service/am/applets/applet_error.h1
-rw-r--r--src/core/hle/service/am/applets/applet_general_backend.cpp15
-rw-r--r--src/core/hle/service/am/applets/applet_general_backend.h3
-rw-r--r--src/core/hle/service/am/applets/applet_mii_edit.cpp5
-rw-r--r--src/core/hle/service/am/applets/applet_mii_edit.h1
-rw-r--r--src/core/hle/service/am/applets/applet_profile_select.cpp57
-rw-r--r--src/core/hle/service/am/applets/applet_profile_select.h103
-rw-r--r--src/core/hle/service/am/applets/applet_software_keyboard.cpp5
-rw-r--r--src/core/hle/service/am/applets/applet_software_keyboard.h1
-rw-r--r--src/core/hle/service/am/applets/applet_web_browser.cpp5
-rw-r--r--src/core/hle/service/am/applets/applet_web_browser.h1
-rw-r--r--src/core/hle/service/am/applets/applets.h1
-rw-r--r--src/core/hle/service/hid/controllers/console_sixaxis.cpp3
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp35
-rw-r--r--src/core/hle/service/hid/controllers/npad.h4
-rw-r--r--src/core/hle/service/hid/hid.cpp41
-rw-r--r--src/core/hle/service/hid/hid.h1
-rw-r--r--src/core/hle/service/hid/hidbus/ringcon.cpp4
-rw-r--r--src/core/hle/service/hid/irsensor/image_transfer_processor.cpp18
-rw-r--r--src/core/hle/service/hle_ipc.cpp3
-rw-r--r--src/core/hle/service/jit/jit.cpp4
-rw-r--r--src/core/hle/service/ldr/ldr.cpp10
-rw-r--r--src/core/hle/service/nfp/amiibo_crypto.cpp4
-rw-r--r--src/core/hle/service/nfp/amiibo_crypto.h3
-rw-r--r--src/core/hle/service/nfp/nfp_device.cpp34
-rw-r--r--src/core/hle/service/nfp/nfp_device.h1
-rw-r--r--src/core/hle/service/nfp/nfp_types.h3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp4
-rw-r--r--src/core/memory.cpp36
-rw-r--r--src/core/memory.h64
-rw-r--r--src/core/memory/cheat_engine.cpp4
-rw-r--r--src/core/reporter.cpp2
-rw-r--r--src/tests/common/range_map.cpp20
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h2
-rw-r--r--src/video_core/memory_manager.cpp36
-rw-r--r--src/video_core/memory_manager.h12
-rw-r--r--src/video_core/texture_cache/texture_cache.h2
-rw-r--r--src/video_core/video_core.cpp2
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.cpp2
-rw-r--r--src/yuzu/applets/qt_amiibo_settings.cpp11
-rw-r--r--src/yuzu/applets/qt_amiibo_settings.h2
-rw-r--r--src/yuzu/applets/qt_controller.cpp17
-rw-r--r--src/yuzu/applets/qt_controller.h4
-rw-r--r--src/yuzu/applets/qt_controller.ui8
-rw-r--r--src/yuzu/applets/qt_error.cpp11
-rw-r--r--src/yuzu/applets/qt_error.h2
-rw-r--r--src/yuzu/applets/qt_profile_select.cpp96
-rw-r--r--src/yuzu/applets/qt_profile_select.h13
-rw-r--r--src/yuzu/applets/qt_software_keyboard.h4
-rw-r--r--src/yuzu/applets/qt_web_browser.cpp11
-rw-r--r--src/yuzu/applets/qt_web_browser.h2
-rw-r--r--src/yuzu/main.cpp183
-rw-r--r--src/yuzu/main.h21
117 files changed, 1086 insertions, 454 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a6c43f401..561eaafb2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -222,7 +222,7 @@ find_package(ZLIB 1.2 REQUIRED)
222find_package(zstd 1.5 REQUIRED) 222find_package(zstd 1.5 REQUIRED)
223 223
224if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS) 224if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS)
225 find_package(Vulkan 1.3.238 REQUIRED) 225 find_package(Vulkan 1.3.246 REQUIRED)
226endif() 226endif()
227 227
228if (ENABLE_LIBUSB) 228if (ENABLE_LIBUSB)
diff --git a/externals/Vulkan-Headers b/externals/Vulkan-Headers
Subproject 00671c64ba5c488ade22ad572a0ef81d5e64c80 Subproject 63af1cf1ee906ba4dcd5a324bdd0201d4f4bfd1
diff --git a/src/audio_core/device/device_session.cpp b/src/audio_core/device/device_session.cpp
index ad0f40e28..b5c0ef0e6 100644
--- a/src/audio_core/device/device_session.cpp
+++ b/src/audio_core/device/device_session.cpp
@@ -93,7 +93,7 @@ void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) const {
93 stream->AppendBuffer(new_buffer, samples); 93 stream->AppendBuffer(new_buffer, samples);
94 } else { 94 } else {
95 std::vector<s16> samples(buffer.size / sizeof(s16)); 95 std::vector<s16> samples(buffer.size / sizeof(s16));
96 system.Memory().ReadBlockUnsafe(buffer.samples, samples.data(), buffer.size); 96 system.ApplicationMemory().ReadBlockUnsafe(buffer.samples, samples.data(), buffer.size);
97 stream->AppendBuffer(new_buffer, samples); 97 stream->AppendBuffer(new_buffer, samples);
98 } 98 }
99 } 99 }
@@ -102,7 +102,7 @@ void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) const {
102void DeviceSession::ReleaseBuffer(const AudioBuffer& buffer) const { 102void DeviceSession::ReleaseBuffer(const AudioBuffer& buffer) const {
103 if (type == Sink::StreamType::In) { 103 if (type == Sink::StreamType::In) {
104 auto samples{stream->ReleaseBuffer(buffer.size / sizeof(s16))}; 104 auto samples{stream->ReleaseBuffer(buffer.size / sizeof(s16))};
105 system.Memory().WriteBlockUnsafe(buffer.samples, samples.data(), buffer.size); 105 system.ApplicationMemory().WriteBlockUnsafe(buffer.samples, samples.data(), buffer.size);
106 } 106 }
107} 107}
108 108
diff --git a/src/audio_core/renderer/adsp/adsp.cpp b/src/audio_core/renderer/adsp/adsp.cpp
index a28395663..74772fc50 100644
--- a/src/audio_core/renderer/adsp/adsp.cpp
+++ b/src/audio_core/renderer/adsp/adsp.cpp
@@ -13,7 +13,7 @@
13namespace AudioCore::AudioRenderer::ADSP { 13namespace AudioCore::AudioRenderer::ADSP {
14 14
15ADSP::ADSP(Core::System& system_, Sink::Sink& sink_) 15ADSP::ADSP(Core::System& system_, Sink::Sink& sink_)
16 : system{system_}, memory{system.Memory()}, sink{sink_} {} 16 : system{system_}, memory{system.ApplicationMemory()}, sink{sink_} {}
17 17
18ADSP::~ADSP() { 18ADSP::~ADSP() {
19 ClearCommandBuffers(); 19 ClearCommandBuffers();
diff --git a/src/audio_core/renderer/adsp/command_list_processor.cpp b/src/audio_core/renderer/adsp/command_list_processor.cpp
index e3bf2d7ec..7a300d216 100644
--- a/src/audio_core/renderer/adsp/command_list_processor.cpp
+++ b/src/audio_core/renderer/adsp/command_list_processor.cpp
@@ -17,7 +17,7 @@ namespace AudioCore::AudioRenderer::ADSP {
17void CommandListProcessor::Initialize(Core::System& system_, CpuAddr buffer, u64 size, 17void CommandListProcessor::Initialize(Core::System& system_, CpuAddr buffer, u64 size,
18 Sink::SinkStream* stream_) { 18 Sink::SinkStream* stream_) {
19 system = &system_; 19 system = &system_;
20 memory = &system->Memory(); 20 memory = &system->ApplicationMemory();
21 stream = stream_; 21 stream = stream_;
22 header = reinterpret_cast<CommandListHeader*>(buffer); 22 header = reinterpret_cast<CommandListHeader*>(buffer);
23 commands = reinterpret_cast<u8*>(buffer + sizeof(CommandListHeader)); 23 commands = reinterpret_cast<u8*>(buffer + sizeof(CommandListHeader));
diff --git a/src/audio_core/renderer/system.cpp b/src/audio_core/renderer/system.cpp
index 28f063641..ad869facb 100644
--- a/src/audio_core/renderer/system.cpp
+++ b/src/audio_core/renderer/system.cpp
@@ -127,8 +127,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
127 render_device = params.rendering_device; 127 render_device = params.rendering_device;
128 execution_mode = params.execution_mode; 128 execution_mode = params.execution_mode;
129 129
130 core.Memory().ZeroBlock(*core.ApplicationProcess(), transfer_memory->GetSourceAddress(), 130 core.ApplicationMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size);
131 transfer_memory_size);
132 131
133 // Note: We're not actually using the transfer memory because it's a pain to code for. 132 // Note: We're not actually using the transfer memory because it's a pain to code for.
134 // Allocate the memory normally instead and hope the game doesn't try to read anything back 133 // Allocate the memory normally instead and hope the game doesn't try to read anything back
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index c1d2b24a1..13ed68b3f 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -160,6 +160,8 @@ if(ARCHITECTURE_x86_64)
160 PRIVATE 160 PRIVATE
161 x64/cpu_detect.cpp 161 x64/cpu_detect.cpp
162 x64/cpu_detect.h 162 x64/cpu_detect.h
163 x64/cpu_wait.cpp
164 x64/cpu_wait.h
163 x64/native_clock.cpp 165 x64/native_clock.cpp
164 x64/native_clock.h 166 x64/native_clock.h
165 x64/xbyak_abi.h 167 x64/xbyak_abi.h
diff --git a/src/common/range_map.h b/src/common/range_map.h
index 79c7ef547..ab73993e3 100644
--- a/src/common/range_map.h
+++ b/src/common/range_map.h
@@ -38,12 +38,12 @@ public:
38 Map(address, address_end, null_value); 38 Map(address, address_end, null_value);
39 } 39 }
40 40
41 [[nodiscard]] size_t GetContinousSizeFrom(KeyTBase address) const { 41 [[nodiscard]] size_t GetContinuousSizeFrom(KeyTBase address) const {
42 const KeyT new_address = static_cast<KeyT>(address); 42 const KeyT new_address = static_cast<KeyT>(address);
43 if (new_address < 0) { 43 if (new_address < 0) {
44 return 0; 44 return 0;
45 } 45 }
46 return ContinousSizeInternal(new_address); 46 return ContinuousSizeInternal(new_address);
47 } 47 }
48 48
49 [[nodiscard]] ValueT GetValueAt(KeyT address) const { 49 [[nodiscard]] ValueT GetValueAt(KeyT address) const {
@@ -59,7 +59,7 @@ private:
59 using IteratorType = typename MapType::iterator; 59 using IteratorType = typename MapType::iterator;
60 using ConstIteratorType = typename MapType::const_iterator; 60 using ConstIteratorType = typename MapType::const_iterator;
61 61
62 size_t ContinousSizeInternal(KeyT address) const { 62 size_t ContinuousSizeInternal(KeyT address) const {
63 const auto it = GetFirstElementBeforeOrOn(address); 63 const auto it = GetFirstElementBeforeOrOn(address);
64 if (it == container.end() || it->second == null_value) { 64 if (it == container.end() || it->second == null_value) {
65 return 0; 65 return 0;
diff --git a/src/common/telemetry.cpp b/src/common/telemetry.cpp
index d26394359..91352912d 100644
--- a/src/common/telemetry.cpp
+++ b/src/common/telemetry.cpp
@@ -97,6 +97,7 @@ void AppendCPUInfo(FieldCollection& fc) {
97 add_field("CPU_Extension_x64_PCLMULQDQ", caps.pclmulqdq); 97 add_field("CPU_Extension_x64_PCLMULQDQ", caps.pclmulqdq);
98 add_field("CPU_Extension_x64_POPCNT", caps.popcnt); 98 add_field("CPU_Extension_x64_POPCNT", caps.popcnt);
99 add_field("CPU_Extension_x64_SHA", caps.sha); 99 add_field("CPU_Extension_x64_SHA", caps.sha);
100 add_field("CPU_Extension_x64_WAITPKG", caps.waitpkg);
100#else 101#else
101 fc.AddField(FieldType::UserSystem, "CPU_Model", "Other"); 102 fc.AddField(FieldType::UserSystem, "CPU_Model", "Other");
102#endif 103#endif
diff --git a/src/common/x64/cpu_detect.cpp b/src/common/x64/cpu_detect.cpp
index e54383a4a..72ed6e96c 100644
--- a/src/common/x64/cpu_detect.cpp
+++ b/src/common/x64/cpu_detect.cpp
@@ -144,6 +144,7 @@ static CPUCaps Detect() {
144 caps.bmi2 = Common::Bit<8>(cpu_id[1]); 144 caps.bmi2 = Common::Bit<8>(cpu_id[1]);
145 caps.sha = Common::Bit<29>(cpu_id[1]); 145 caps.sha = Common::Bit<29>(cpu_id[1]);
146 146
147 caps.waitpkg = Common::Bit<5>(cpu_id[2]);
147 caps.gfni = Common::Bit<8>(cpu_id[2]); 148 caps.gfni = Common::Bit<8>(cpu_id[2]);
148 149
149 __cpuidex(cpu_id, 0x00000007, 0x00000001); 150 __cpuidex(cpu_id, 0x00000007, 0x00000001);
diff --git a/src/common/x64/cpu_detect.h b/src/common/x64/cpu_detect.h
index ca8db19d6..8253944d6 100644
--- a/src/common/x64/cpu_detect.h
+++ b/src/common/x64/cpu_detect.h
@@ -67,6 +67,7 @@ struct CPUCaps {
67 bool pclmulqdq : 1; 67 bool pclmulqdq : 1;
68 bool popcnt : 1; 68 bool popcnt : 1;
69 bool sha : 1; 69 bool sha : 1;
70 bool waitpkg : 1;
70}; 71};
71 72
72/** 73/**
diff --git a/src/common/x64/cpu_wait.cpp b/src/common/x64/cpu_wait.cpp
new file mode 100644
index 000000000..cfeef6a3d
--- /dev/null
+++ b/src/common/x64/cpu_wait.cpp
@@ -0,0 +1,69 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <thread>
5
6#ifdef _MSC_VER
7#include <intrin.h>
8#endif
9
10#include "common/x64/cpu_detect.h"
11#include "common/x64/cpu_wait.h"
12
13namespace Common::X64 {
14
15#ifdef _MSC_VER
16__forceinline static u64 FencedRDTSC() {
17 _mm_lfence();
18 _ReadWriteBarrier();
19 const u64 result = __rdtsc();
20 _mm_lfence();
21 _ReadWriteBarrier();
22 return result;
23}
24
25__forceinline static void TPAUSE() {
26 // 100,000 cycles is a reasonable amount of time to wait to save on CPU resources.
27 // For reference:
28 // At 1 GHz, 100K cycles is 100us
29 // At 2 GHz, 100K cycles is 50us
30 // At 4 GHz, 100K cycles is 25us
31 static constexpr auto PauseCycles = 100'000;
32 _tpause(0, FencedRDTSC() + PauseCycles);
33}
34#else
35static u64 FencedRDTSC() {
36 u64 eax;
37 u64 edx;
38 asm volatile("lfence\n\t"
39 "rdtsc\n\t"
40 "lfence\n\t"
41 : "=a"(eax), "=d"(edx));
42 return (edx << 32) | eax;
43}
44
45static void TPAUSE() {
46 // 100,000 cycles is a reasonable amount of time to wait to save on CPU resources.
47 // For reference:
48 // At 1 GHz, 100K cycles is 100us
49 // At 2 GHz, 100K cycles is 50us
50 // At 4 GHz, 100K cycles is 25us
51 static constexpr auto PauseCycles = 100'000;
52 const auto tsc = FencedRDTSC() + PauseCycles;
53 const auto eax = static_cast<u32>(tsc & 0xFFFFFFFF);
54 const auto edx = static_cast<u32>(tsc >> 32);
55 asm volatile("tpause %0" : : "r"(0), "d"(edx), "a"(eax));
56}
57#endif
58
59void MicroSleep() {
60 static const bool has_waitpkg = GetCPUCaps().waitpkg;
61
62 if (has_waitpkg) {
63 TPAUSE();
64 } else {
65 std::this_thread::yield();
66 }
67}
68
69} // namespace Common::X64
diff --git a/src/common/x64/cpu_wait.h b/src/common/x64/cpu_wait.h
new file mode 100644
index 000000000..99d3757a7
--- /dev/null
+++ b/src/common/x64/cpu_wait.h
@@ -0,0 +1,10 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6namespace Common::X64 {
7
8void MicroSleep();
9
10} // namespace Common::X64
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp
index 76c66e7ee..277b00662 100644
--- a/src/common/x64/native_clock.cpp
+++ b/src/common/x64/native_clock.cpp
@@ -27,16 +27,13 @@ __forceinline static u64 FencedRDTSC() {
27} 27}
28#else 28#else
29static u64 FencedRDTSC() { 29static u64 FencedRDTSC() {
30 u64 result; 30 u64 eax;
31 u64 edx;
31 asm volatile("lfence\n\t" 32 asm volatile("lfence\n\t"
32 "rdtsc\n\t" 33 "rdtsc\n\t"
33 "shl $32, %%rdx\n\t" 34 "lfence\n\t"
34 "or %%rdx, %0\n\t" 35 : "=a"(eax), "=d"(edx));
35 "lfence" 36 return (edx << 32) | eax;
36 : "=a"(result)
37 :
38 : "rdx", "memory", "cc");
39 return result;
40} 37}
41#endif 38#endif
42 39
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index be3f55cd2..d30914b7a 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -44,7 +44,7 @@ void ARM_Interface::SymbolicateBacktrace(Core::System& system, std::vector<Backt
44 std::map<std::string, Symbols::Symbols> symbols; 44 std::map<std::string, Symbols::Symbols> symbols;
45 for (const auto& module : modules) { 45 for (const auto& module : modules) {
46 symbols.insert_or_assign( 46 symbols.insert_or_assign(
47 module.second, Symbols::GetSymbols(module.first, system.Memory(), 47 module.second, Symbols::GetSymbols(module.first, system.ApplicationMemory(),
48 system.ApplicationProcess()->Is64BitProcess())); 48 system.ApplicationProcess()->Is64BitProcess()));
49 } 49 }
50 50
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index aa92d3fc3..cab21a88e 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -28,8 +28,8 @@ using namespace Common::Literals;
28class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { 28class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
29public: 29public:
30 explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) 30 explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)
31 : parent{parent_}, 31 : parent{parent_}, memory(parent.system.ApplicationMemory()),
32 memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()}, 32 debugger_enabled{parent.system.DebuggerEnabled()},
33 check_memory_access{debugger_enabled || 33 check_memory_access{debugger_enabled ||
34 !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {} 34 !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
35 35
@@ -468,7 +468,7 @@ void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table,
468std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace(Core::System& system, 468std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace(Core::System& system,
469 u64 fp, u64 lr, u64 pc) { 469 u64 fp, u64 lr, u64 pc) {
470 std::vector<BacktraceEntry> out; 470 std::vector<BacktraceEntry> out;
471 auto& memory = system.Memory(); 471 auto& memory = system.ApplicationMemory();
472 472
473 out.push_back({"", 0, pc, 0, ""}); 473 out.push_back({"", 0, pc, 0, ""});
474 474
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 67073c84d..bbbcb4f9d 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -28,8 +28,8 @@ using namespace Common::Literals;
28class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { 28class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
29public: 29public:
30 explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) 30 explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_)
31 : parent{parent_}, 31 : parent{parent_}, memory(parent.system.ApplicationMemory()),
32 memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()}, 32 debugger_enabled{parent.system.DebuggerEnabled()},
33 check_memory_access{debugger_enabled || 33 check_memory_access{debugger_enabled ||
34 !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {} 34 !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
35 35
@@ -529,7 +529,7 @@ void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table,
529std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::System& system, 529std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::System& system,
530 u64 fp, u64 lr, u64 pc) { 530 u64 fp, u64 lr, u64 pc) {
531 std::vector<BacktraceEntry> out; 531 std::vector<BacktraceEntry> out;
532 auto& memory = system.Memory(); 532 auto& memory = system.ApplicationMemory();
533 533
534 out.push_back({"", 0, pc, 0, ""}); 534 out.push_back({"", 0, pc, 0, ""});
535 535
diff --git a/src/core/core.cpp b/src/core/core.cpp
index f6273ac39..caa6a77be 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -293,6 +293,7 @@ struct System::Impl {
293 ASSERT(Kernel::KProcess::Initialize(main_process, system, "main", 293 ASSERT(Kernel::KProcess::Initialize(main_process, system, "main",
294 Kernel::KProcess::ProcessType::Userland, resource_limit) 294 Kernel::KProcess::ProcessType::Userland, resource_limit)
295 .IsSuccess()); 295 .IsSuccess());
296 kernel.MakeApplicationProcess(main_process);
296 const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); 297 const auto [load_result, load_parameters] = app_loader->Load(*main_process, system);
297 if (load_result != Loader::ResultStatus::Success) { 298 if (load_result != Loader::ResultStatus::Success) {
298 LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); 299 LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result);
@@ -302,7 +303,6 @@ struct System::Impl {
302 static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result)); 303 static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result));
303 } 304 }
304 AddGlueRegistrationForProcess(*app_loader, *main_process); 305 AddGlueRegistrationForProcess(*app_loader, *main_process);
305 kernel.MakeApplicationProcess(main_process);
306 kernel.InitializeCores(); 306 kernel.InitializeCores();
307 307
308 // Initialize cheat engine 308 // Initialize cheat engine
@@ -681,11 +681,11 @@ const ExclusiveMonitor& System::Monitor() const {
681 return impl->kernel.GetExclusiveMonitor(); 681 return impl->kernel.GetExclusiveMonitor();
682} 682}
683 683
684Memory::Memory& System::Memory() { 684Memory::Memory& System::ApplicationMemory() {
685 return impl->memory; 685 return impl->memory;
686} 686}
687 687
688const Core::Memory::Memory& System::Memory() const { 688const Core::Memory::Memory& System::ApplicationMemory() const {
689 return impl->memory; 689 return impl->memory;
690} 690}
691 691
diff --git a/src/core/core.h b/src/core/core.h
index 7032240be..4a5aba032 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -256,10 +256,10 @@ public:
256 [[nodiscard]] const ExclusiveMonitor& Monitor() const; 256 [[nodiscard]] const ExclusiveMonitor& Monitor() const;
257 257
258 /// Gets a mutable reference to the system memory instance. 258 /// Gets a mutable reference to the system memory instance.
259 [[nodiscard]] Core::Memory::Memory& Memory(); 259 [[nodiscard]] Core::Memory::Memory& ApplicationMemory();
260 260
261 /// Gets a constant reference to the system memory instance. 261 /// Gets a constant reference to the system memory instance.
262 [[nodiscard]] const Core::Memory::Memory& Memory() const; 262 [[nodiscard]] const Core::Memory::Memory& ApplicationMemory() const;
263 263
264 /// Gets a mutable reference to the GPU interface 264 /// Gets a mutable reference to the GPU interface
265 [[nodiscard]] Tegra::GPU& GPU(); 265 [[nodiscard]] Tegra::GPU& GPU();
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index cd4df4522..4f2692b05 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -10,6 +10,10 @@
10#include "common/windows/timer_resolution.h" 10#include "common/windows/timer_resolution.h"
11#endif 11#endif
12 12
13#ifdef ARCHITECTURE_x86_64
14#include "common/x64/cpu_wait.h"
15#endif
16
13#include "common/microprofile.h" 17#include "common/microprofile.h"
14#include "core/core_timing.h" 18#include "core/core_timing.h"
15#include "core/core_timing_util.h" 19#include "core/core_timing_util.h"
@@ -269,7 +273,11 @@ void CoreTiming::ThreadLoop() {
269 if (wait_time >= timer_resolution_ns) { 273 if (wait_time >= timer_resolution_ns) {
270 Common::Windows::SleepForOneTick(); 274 Common::Windows::SleepForOneTick();
271 } else { 275 } else {
276#ifdef ARCHITECTURE_x86_64
277 Common::X64::MicroSleep();
278#else
272 std::this_thread::yield(); 279 std::this_thread::yield();
280#endif
273 } 281 }
274 } 282 }
275 283
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp
index 5cfb66b93..e2a13bbd2 100644
--- a/src/core/debugger/gdbstub.cpp
+++ b/src/core/debugger/gdbstub.cpp
@@ -261,9 +261,9 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
261 const size_t addr{static_cast<size_t>(strtoll(command.data(), nullptr, 16))}; 261 const size_t addr{static_cast<size_t>(strtoll(command.data(), nullptr, 16))};
262 const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))}; 262 const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))};
263 263
264 if (system.Memory().IsValidVirtualAddressRange(addr, size)) { 264 if (system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) {
265 std::vector<u8> mem(size); 265 std::vector<u8> mem(size);
266 system.Memory().ReadBlock(addr, mem.data(), size); 266 system.ApplicationMemory().ReadBlock(addr, mem.data(), size);
267 267
268 SendReply(Common::HexToString(mem)); 268 SendReply(Common::HexToString(mem));
269 } else { 269 } else {
@@ -281,8 +281,8 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
281 const auto mem_substr{std::string_view(command).substr(mem_sep)}; 281 const auto mem_substr{std::string_view(command).substr(mem_sep)};
282 const auto mem{Common::HexStringToVector(mem_substr, false)}; 282 const auto mem{Common::HexStringToVector(mem_substr, false)};
283 283
284 if (system.Memory().IsValidVirtualAddressRange(addr, size)) { 284 if (system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) {
285 system.Memory().WriteBlock(addr, mem.data(), size); 285 system.ApplicationMemory().WriteBlock(addr, mem.data(), size);
286 system.InvalidateCpuInstructionCacheRange(addr, size); 286 system.InvalidateCpuInstructionCacheRange(addr, size);
287 SendReply(GDB_STUB_REPLY_OK); 287 SendReply(GDB_STUB_REPLY_OK);
288 } else { 288 } else {
@@ -325,7 +325,7 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
325 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))}; 325 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
326 const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))}; 326 const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
327 327
328 if (!system.Memory().IsValidVirtualAddressRange(addr, size)) { 328 if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) {
329 SendReply(GDB_STUB_REPLY_ERR); 329 SendReply(GDB_STUB_REPLY_ERR);
330 return; 330 return;
331 } 331 }
@@ -334,22 +334,22 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
334 334
335 switch (type) { 335 switch (type) {
336 case BreakpointType::Software: 336 case BreakpointType::Software:
337 replaced_instructions[addr] = system.Memory().Read32(addr); 337 replaced_instructions[addr] = system.ApplicationMemory().Read32(addr);
338 system.Memory().Write32(addr, arch->BreakpointInstruction()); 338 system.ApplicationMemory().Write32(addr, arch->BreakpointInstruction());
339 system.InvalidateCpuInstructionCacheRange(addr, sizeof(u32)); 339 system.InvalidateCpuInstructionCacheRange(addr, sizeof(u32));
340 success = true; 340 success = true;
341 break; 341 break;
342 case BreakpointType::WriteWatch: 342 case BreakpointType::WriteWatch:
343 success = system.ApplicationProcess()->InsertWatchpoint(system, addr, size, 343 success = system.ApplicationProcess()->InsertWatchpoint(addr, size,
344 Kernel::DebugWatchpointType::Write); 344 Kernel::DebugWatchpointType::Write);
345 break; 345 break;
346 case BreakpointType::ReadWatch: 346 case BreakpointType::ReadWatch:
347 success = system.ApplicationProcess()->InsertWatchpoint(system, addr, size, 347 success = system.ApplicationProcess()->InsertWatchpoint(addr, size,
348 Kernel::DebugWatchpointType::Read); 348 Kernel::DebugWatchpointType::Read);
349 break; 349 break;
350 case BreakpointType::AccessWatch: 350 case BreakpointType::AccessWatch:
351 success = system.ApplicationProcess()->InsertWatchpoint( 351 success = system.ApplicationProcess()->InsertWatchpoint(
352 system, addr, size, Kernel::DebugWatchpointType::ReadOrWrite); 352 addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
353 break; 353 break;
354 case BreakpointType::Hardware: 354 case BreakpointType::Hardware:
355 default: 355 default:
@@ -372,7 +372,7 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
372 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))}; 372 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
373 const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))}; 373 const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
374 374
375 if (!system.Memory().IsValidVirtualAddressRange(addr, size)) { 375 if (!system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) {
376 SendReply(GDB_STUB_REPLY_ERR); 376 SendReply(GDB_STUB_REPLY_ERR);
377 return; 377 return;
378 } 378 }
@@ -383,7 +383,7 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
383 case BreakpointType::Software: { 383 case BreakpointType::Software: {
384 const auto orig_insn{replaced_instructions.find(addr)}; 384 const auto orig_insn{replaced_instructions.find(addr)};
385 if (orig_insn != replaced_instructions.end()) { 385 if (orig_insn != replaced_instructions.end()) {
386 system.Memory().Write32(addr, orig_insn->second); 386 system.ApplicationMemory().Write32(addr, orig_insn->second);
387 system.InvalidateCpuInstructionCacheRange(addr, sizeof(u32)); 387 system.InvalidateCpuInstructionCacheRange(addr, sizeof(u32));
388 replaced_instructions.erase(addr); 388 replaced_instructions.erase(addr);
389 success = true; 389 success = true;
@@ -391,16 +391,16 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
391 break; 391 break;
392 } 392 }
393 case BreakpointType::WriteWatch: 393 case BreakpointType::WriteWatch:
394 success = system.ApplicationProcess()->RemoveWatchpoint(system, addr, size, 394 success = system.ApplicationProcess()->RemoveWatchpoint(addr, size,
395 Kernel::DebugWatchpointType::Write); 395 Kernel::DebugWatchpointType::Write);
396 break; 396 break;
397 case BreakpointType::ReadWatch: 397 case BreakpointType::ReadWatch:
398 success = system.ApplicationProcess()->RemoveWatchpoint(system, addr, size, 398 success = system.ApplicationProcess()->RemoveWatchpoint(addr, size,
399 Kernel::DebugWatchpointType::Read); 399 Kernel::DebugWatchpointType::Read);
400 break; 400 break;
401 case BreakpointType::AccessWatch: 401 case BreakpointType::AccessWatch:
402 success = system.ApplicationProcess()->RemoveWatchpoint( 402 success = system.ApplicationProcess()->RemoveWatchpoint(
403 system, addr, size, Kernel::DebugWatchpointType::ReadOrWrite); 403 addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
404 break; 404 break;
405 case BreakpointType::Hardware: 405 case BreakpointType::Hardware:
406 default: 406 default:
@@ -483,9 +483,9 @@ static std::optional<std::string> GetNameFromThreadType64(Core::Memory::Memory&
483static std::optional<std::string> GetThreadName(Core::System& system, 483static std::optional<std::string> GetThreadName(Core::System& system,
484 const Kernel::KThread* thread) { 484 const Kernel::KThread* thread) {
485 if (system.ApplicationProcess()->Is64BitProcess()) { 485 if (system.ApplicationProcess()->Is64BitProcess()) {
486 return GetNameFromThreadType64(system.Memory(), thread); 486 return GetNameFromThreadType64(system.ApplicationMemory(), thread);
487 } else { 487 } else {
488 return GetNameFromThreadType32(system.Memory(), thread); 488 return GetNameFromThreadType32(system.ApplicationMemory(), thread);
489 } 489 }
490} 490}
491 491
diff --git a/src/core/frontend/applets/applet.h b/src/core/frontend/applets/applet.h
new file mode 100644
index 000000000..77fffe306
--- /dev/null
+++ b/src/core/frontend/applets/applet.h
@@ -0,0 +1,14 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6namespace Core::Frontend {
7
8class Applet {
9public:
10 virtual ~Applet() = default;
11 virtual void Close() const = 0;
12};
13
14} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/cabinet.cpp b/src/core/frontend/applets/cabinet.cpp
index 26c7fefe3..2d501eeae 100644
--- a/src/core/frontend/applets/cabinet.cpp
+++ b/src/core/frontend/applets/cabinet.cpp
@@ -10,6 +10,8 @@ namespace Core::Frontend {
10 10
11CabinetApplet::~CabinetApplet() = default; 11CabinetApplet::~CabinetApplet() = default;
12 12
13void DefaultCabinetApplet::Close() const {}
14
13void DefaultCabinetApplet::ShowCabinetApplet( 15void DefaultCabinetApplet::ShowCabinetApplet(
14 const CabinetCallback& callback, const CabinetParameters& parameters, 16 const CabinetCallback& callback, const CabinetParameters& parameters,
15 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const { 17 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const {
diff --git a/src/core/frontend/applets/cabinet.h b/src/core/frontend/applets/cabinet.h
index c28a235c1..74dc5a4f6 100644
--- a/src/core/frontend/applets/cabinet.h
+++ b/src/core/frontend/applets/cabinet.h
@@ -4,6 +4,7 @@
4#pragma once 4#pragma once
5 5
6#include <functional> 6#include <functional>
7#include "core/frontend/applets/applet.h"
7#include "core/hle/service/nfp/nfp_types.h" 8#include "core/hle/service/nfp/nfp_types.h"
8 9
9namespace Service::NFP { 10namespace Service::NFP {
@@ -20,7 +21,7 @@ struct CabinetParameters {
20 21
21using CabinetCallback = std::function<void(bool, const std::string&)>; 22using CabinetCallback = std::function<void(bool, const std::string&)>;
22 23
23class CabinetApplet { 24class CabinetApplet : public Applet {
24public: 25public:
25 virtual ~CabinetApplet(); 26 virtual ~CabinetApplet();
26 virtual void ShowCabinetApplet(const CabinetCallback& callback, 27 virtual void ShowCabinetApplet(const CabinetCallback& callback,
@@ -30,6 +31,7 @@ public:
30 31
31class DefaultCabinetApplet final : public CabinetApplet { 32class DefaultCabinetApplet final : public CabinetApplet {
32public: 33public:
34 void Close() const override;
33 void ShowCabinetApplet(const CabinetCallback& callback, const CabinetParameters& parameters, 35 void ShowCabinetApplet(const CabinetCallback& callback, const CabinetParameters& parameters,
34 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const override; 36 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const override;
35}; 37};
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp
index 52919484e..3300d4f79 100644
--- a/src/core/frontend/applets/controller.cpp
+++ b/src/core/frontend/applets/controller.cpp
@@ -16,6 +16,8 @@ DefaultControllerApplet::DefaultControllerApplet(HID::HIDCore& hid_core_) : hid_
16 16
17DefaultControllerApplet::~DefaultControllerApplet() = default; 17DefaultControllerApplet::~DefaultControllerApplet() = default;
18 18
19void DefaultControllerApplet::Close() const {}
20
19void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callback, 21void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callback,
20 const ControllerParameters& parameters) const { 22 const ControllerParameters& parameters) const {
21 LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!"); 23 LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!");
@@ -69,7 +71,7 @@ void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callbac
69 } 71 }
70 } 72 }
71 73
72 callback(); 74 callback(true);
73} 75}
74 76
75} // namespace Core::Frontend 77} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/controller.h b/src/core/frontend/applets/controller.h
index adb2feefd..19a2db6bf 100644
--- a/src/core/frontend/applets/controller.h
+++ b/src/core/frontend/applets/controller.h
@@ -7,6 +7,7 @@
7#include <vector> 7#include <vector>
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "core/frontend/applets/applet.h"
10 11
11namespace Core::HID { 12namespace Core::HID {
12class HIDCore; 13class HIDCore;
@@ -34,9 +35,9 @@ struct ControllerParameters {
34 bool allow_gamecube_controller{}; 35 bool allow_gamecube_controller{};
35}; 36};
36 37
37class ControllerApplet { 38class ControllerApplet : public Applet {
38public: 39public:
39 using ReconfigureCallback = std::function<void()>; 40 using ReconfigureCallback = std::function<void(bool)>;
40 41
41 virtual ~ControllerApplet(); 42 virtual ~ControllerApplet();
42 43
@@ -49,6 +50,7 @@ public:
49 explicit DefaultControllerApplet(HID::HIDCore& hid_core_); 50 explicit DefaultControllerApplet(HID::HIDCore& hid_core_);
50 ~DefaultControllerApplet() override; 51 ~DefaultControllerApplet() override;
51 52
53 void Close() const override;
52 void ReconfigureControllers(ReconfigureCallback callback, 54 void ReconfigureControllers(ReconfigureCallback callback,
53 const ControllerParameters& parameters) const override; 55 const ControllerParameters& parameters) const override;
54 56
diff --git a/src/core/frontend/applets/error.cpp b/src/core/frontend/applets/error.cpp
index 69c2b2b4d..2e6f7a3d9 100644
--- a/src/core/frontend/applets/error.cpp
+++ b/src/core/frontend/applets/error.cpp
@@ -8,6 +8,8 @@ namespace Core::Frontend {
8 8
9ErrorApplet::~ErrorApplet() = default; 9ErrorApplet::~ErrorApplet() = default;
10 10
11void DefaultErrorApplet::Close() const {}
12
11void DefaultErrorApplet::ShowError(Result error, FinishedCallback finished) const { 13void DefaultErrorApplet::ShowError(Result error, FinishedCallback finished) const {
12 LOG_CRITICAL(Service_Fatal, "Application requested error display: {:04}-{:04} (raw={:08X})", 14 LOG_CRITICAL(Service_Fatal, "Application requested error display: {:04}-{:04} (raw={:08X})",
13 error.module.Value(), error.description.Value(), error.raw); 15 error.module.Value(), error.description.Value(), error.raw);
diff --git a/src/core/frontend/applets/error.h b/src/core/frontend/applets/error.h
index 884f2f653..3a12196ce 100644
--- a/src/core/frontend/applets/error.h
+++ b/src/core/frontend/applets/error.h
@@ -6,11 +6,12 @@
6#include <chrono> 6#include <chrono>
7#include <functional> 7#include <functional>
8 8
9#include "core/frontend/applets/applet.h"
9#include "core/hle/result.h" 10#include "core/hle/result.h"
10 11
11namespace Core::Frontend { 12namespace Core::Frontend {
12 13
13class ErrorApplet { 14class ErrorApplet : public Applet {
14public: 15public:
15 using FinishedCallback = std::function<void()>; 16 using FinishedCallback = std::function<void()>;
16 17
@@ -28,6 +29,7 @@ public:
28 29
29class DefaultErrorApplet final : public ErrorApplet { 30class DefaultErrorApplet final : public ErrorApplet {
30public: 31public:
32 void Close() const override;
31 void ShowError(Result error, FinishedCallback finished) const override; 33 void ShowError(Result error, FinishedCallback finished) const override;
32 void ShowErrorWithTimestamp(Result error, std::chrono::seconds time, 34 void ShowErrorWithTimestamp(Result error, std::chrono::seconds time,
33 FinishedCallback finished) const override; 35 FinishedCallback finished) const override;
diff --git a/src/core/frontend/applets/general_frontend.cpp b/src/core/frontend/applets/general_frontend.cpp
index 29a00fb6f..b4b213a31 100644
--- a/src/core/frontend/applets/general_frontend.cpp
+++ b/src/core/frontend/applets/general_frontend.cpp
@@ -10,6 +10,8 @@ ParentalControlsApplet::~ParentalControlsApplet() = default;
10 10
11DefaultParentalControlsApplet::~DefaultParentalControlsApplet() = default; 11DefaultParentalControlsApplet::~DefaultParentalControlsApplet() = default;
12 12
13void DefaultParentalControlsApplet::Close() const {}
14
13void DefaultParentalControlsApplet::VerifyPIN(std::function<void(bool)> finished, 15void DefaultParentalControlsApplet::VerifyPIN(std::function<void(bool)> finished,
14 bool suspend_future_verification_temporarily) { 16 bool suspend_future_verification_temporarily) {
15 LOG_INFO(Service_AM, 17 LOG_INFO(Service_AM,
@@ -39,6 +41,8 @@ PhotoViewerApplet::~PhotoViewerApplet() = default;
39 41
40DefaultPhotoViewerApplet::~DefaultPhotoViewerApplet() = default; 42DefaultPhotoViewerApplet::~DefaultPhotoViewerApplet() = default;
41 43
44void DefaultPhotoViewerApplet::Close() const {}
45
42void DefaultPhotoViewerApplet::ShowPhotosForApplication(u64 title_id, 46void DefaultPhotoViewerApplet::ShowPhotosForApplication(u64 title_id,
43 std::function<void()> finished) const { 47 std::function<void()> finished) const {
44 LOG_INFO(Service_AM, 48 LOG_INFO(Service_AM,
diff --git a/src/core/frontend/applets/general_frontend.h b/src/core/frontend/applets/general_frontend.h
index cbec8b4ad..319838ac7 100644
--- a/src/core/frontend/applets/general_frontend.h
+++ b/src/core/frontend/applets/general_frontend.h
@@ -6,9 +6,11 @@
6#include <functional> 6#include <functional>
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9#include "core/frontend/applets/applet.h"
10
9namespace Core::Frontend { 11namespace Core::Frontend {
10 12
11class ParentalControlsApplet { 13class ParentalControlsApplet : public Applet {
12public: 14public:
13 virtual ~ParentalControlsApplet(); 15 virtual ~ParentalControlsApplet();
14 16
@@ -33,6 +35,7 @@ class DefaultParentalControlsApplet final : public ParentalControlsApplet {
33public: 35public:
34 ~DefaultParentalControlsApplet() override; 36 ~DefaultParentalControlsApplet() override;
35 37
38 void Close() const override;
36 void VerifyPIN(std::function<void(bool)> finished, 39 void VerifyPIN(std::function<void(bool)> finished,
37 bool suspend_future_verification_temporarily) override; 40 bool suspend_future_verification_temporarily) override;
38 void VerifyPINForSettings(std::function<void(bool)> finished) override; 41 void VerifyPINForSettings(std::function<void(bool)> finished) override;
@@ -40,7 +43,7 @@ public:
40 void ChangePIN(std::function<void()> finished) override; 43 void ChangePIN(std::function<void()> finished) override;
41}; 44};
42 45
43class PhotoViewerApplet { 46class PhotoViewerApplet : public Applet {
44public: 47public:
45 virtual ~PhotoViewerApplet(); 48 virtual ~PhotoViewerApplet();
46 49
@@ -52,6 +55,7 @@ class DefaultPhotoViewerApplet final : public PhotoViewerApplet {
52public: 55public:
53 ~DefaultPhotoViewerApplet() override; 56 ~DefaultPhotoViewerApplet() override;
54 57
58 void Close() const override;
55 void ShowPhotosForApplication(u64 title_id, std::function<void()> finished) const override; 59 void ShowPhotosForApplication(u64 title_id, std::function<void()> finished) const override;
56 void ShowAllPhotos(std::function<void()> finished) const override; 60 void ShowAllPhotos(std::function<void()> finished) const override;
57}; 61};
diff --git a/src/core/frontend/applets/mii_edit.cpp b/src/core/frontend/applets/mii_edit.cpp
index bc8c57067..2988c3e72 100644
--- a/src/core/frontend/applets/mii_edit.cpp
+++ b/src/core/frontend/applets/mii_edit.cpp
@@ -8,6 +8,8 @@ namespace Core::Frontend {
8 8
9MiiEditApplet::~MiiEditApplet() = default; 9MiiEditApplet::~MiiEditApplet() = default;
10 10
11void DefaultMiiEditApplet::Close() const {}
12
11void DefaultMiiEditApplet::ShowMiiEdit(const MiiEditCallback& callback) const { 13void DefaultMiiEditApplet::ShowMiiEdit(const MiiEditCallback& callback) const {
12 LOG_WARNING(Service_AM, "(STUBBED) called"); 14 LOG_WARNING(Service_AM, "(STUBBED) called");
13 15
diff --git a/src/core/frontend/applets/mii_edit.h b/src/core/frontend/applets/mii_edit.h
index d828f06ec..9d86ee658 100644
--- a/src/core/frontend/applets/mii_edit.h
+++ b/src/core/frontend/applets/mii_edit.h
@@ -5,9 +5,11 @@
5 5
6#include <functional> 6#include <functional>
7 7
8#include "core/frontend/applets/applet.h"
9
8namespace Core::Frontend { 10namespace Core::Frontend {
9 11
10class MiiEditApplet { 12class MiiEditApplet : public Applet {
11public: 13public:
12 using MiiEditCallback = std::function<void()>; 14 using MiiEditCallback = std::function<void()>;
13 15
@@ -18,6 +20,7 @@ public:
18 20
19class DefaultMiiEditApplet final : public MiiEditApplet { 21class DefaultMiiEditApplet final : public MiiEditApplet {
20public: 22public:
23 void Close() const override;
21 void ShowMiiEdit(const MiiEditCallback& callback) const override; 24 void ShowMiiEdit(const MiiEditCallback& callback) const override;
22}; 25};
23 26
diff --git a/src/core/frontend/applets/profile_select.cpp b/src/core/frontend/applets/profile_select.cpp
index da4cfbf87..c18f17a36 100644
--- a/src/core/frontend/applets/profile_select.cpp
+++ b/src/core/frontend/applets/profile_select.cpp
@@ -9,7 +9,10 @@ namespace Core::Frontend {
9 9
10ProfileSelectApplet::~ProfileSelectApplet() = default; 10ProfileSelectApplet::~ProfileSelectApplet() = default;
11 11
12void DefaultProfileSelectApplet::SelectProfile(SelectProfileCallback callback) const { 12void DefaultProfileSelectApplet::Close() const {}
13
14void DefaultProfileSelectApplet::SelectProfile(SelectProfileCallback callback,
15 const ProfileSelectParameters& parameters) const {
13 Service::Account::ProfileManager manager; 16 Service::Account::ProfileManager manager;
14 callback(manager.GetUser(Settings::values.current_user.GetValue()).value_or(Common::UUID{})); 17 callback(manager.GetUser(Settings::values.current_user.GetValue()).value_or(Common::UUID{}));
15 LOG_INFO(Service_ACC, "called, selecting current user instead of prompting..."); 18 LOG_INFO(Service_ACC, "called, selecting current user instead of prompting...");
diff --git a/src/core/frontend/applets/profile_select.h b/src/core/frontend/applets/profile_select.h
index 138429533..92e2737ea 100644
--- a/src/core/frontend/applets/profile_select.h
+++ b/src/core/frontend/applets/profile_select.h
@@ -5,22 +5,35 @@
5 5
6#include <functional> 6#include <functional>
7#include <optional> 7#include <optional>
8
8#include "common/uuid.h" 9#include "common/uuid.h"
10#include "core/frontend/applets/applet.h"
11#include "core/hle/service/am/applets/applet_profile_select.h"
9 12
10namespace Core::Frontend { 13namespace Core::Frontend {
11 14
12class ProfileSelectApplet { 15struct ProfileSelectParameters {
16 Service::AM::Applets::UiMode mode;
17 std::array<Common::UUID, 8> invalid_uid_list;
18 Service::AM::Applets::UiSettingsDisplayOptions display_options;
19 Service::AM::Applets::UserSelectionPurpose purpose;
20};
21
22class ProfileSelectApplet : public Applet {
13public: 23public:
14 using SelectProfileCallback = std::function<void(std::optional<Common::UUID>)>; 24 using SelectProfileCallback = std::function<void(std::optional<Common::UUID>)>;
15 25
16 virtual ~ProfileSelectApplet(); 26 virtual ~ProfileSelectApplet();
17 27
18 virtual void SelectProfile(SelectProfileCallback callback) const = 0; 28 virtual void SelectProfile(SelectProfileCallback callback,
29 const ProfileSelectParameters& parameters) const = 0;
19}; 30};
20 31
21class DefaultProfileSelectApplet final : public ProfileSelectApplet { 32class DefaultProfileSelectApplet final : public ProfileSelectApplet {
22public: 33public:
23 void SelectProfile(SelectProfileCallback callback) const override; 34 void Close() const override;
35 void SelectProfile(SelectProfileCallback callback,
36 const ProfileSelectParameters& parameters) const override;
24}; 37};
25 38
26} // namespace Core::Frontend 39} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp
index a3720f4d7..7655d215b 100644
--- a/src/core/frontend/applets/software_keyboard.cpp
+++ b/src/core/frontend/applets/software_keyboard.cpp
@@ -13,6 +13,8 @@ SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default;
13 13
14DefaultSoftwareKeyboardApplet::~DefaultSoftwareKeyboardApplet() = default; 14DefaultSoftwareKeyboardApplet::~DefaultSoftwareKeyboardApplet() = default;
15 15
16void DefaultSoftwareKeyboardApplet::Close() const {}
17
16void DefaultSoftwareKeyboardApplet::InitializeKeyboard( 18void DefaultSoftwareKeyboardApplet::InitializeKeyboard(
17 bool is_inline, KeyboardInitializeParameters initialize_parameters, 19 bool is_inline, KeyboardInitializeParameters initialize_parameters,
18 SubmitNormalCallback submit_normal_callback_, SubmitInlineCallback submit_inline_callback_) { 20 SubmitNormalCallback submit_normal_callback_, SubmitInlineCallback submit_inline_callback_) {
diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h
index 8aef103d3..8ed96da24 100644
--- a/src/core/frontend/applets/software_keyboard.h
+++ b/src/core/frontend/applets/software_keyboard.h
@@ -7,6 +7,7 @@
7 7
8#include "common/common_types.h" 8#include "common/common_types.h"
9 9
10#include "core/frontend/applets/applet.h"
10#include "core/hle/service/am/applets/applet_software_keyboard_types.h" 11#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
11 12
12namespace Core::Frontend { 13namespace Core::Frontend {
@@ -52,7 +53,7 @@ struct InlineTextParameters {
52 s32 cursor_position; 53 s32 cursor_position;
53}; 54};
54 55
55class SoftwareKeyboardApplet { 56class SoftwareKeyboardApplet : public Applet {
56public: 57public:
57 using SubmitInlineCallback = 58 using SubmitInlineCallback =
58 std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>; 59 std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>;
@@ -84,6 +85,8 @@ class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet {
84public: 85public:
85 ~DefaultSoftwareKeyboardApplet() override; 86 ~DefaultSoftwareKeyboardApplet() override;
86 87
88 void Close() const override;
89
87 void InitializeKeyboard(bool is_inline, KeyboardInitializeParameters initialize_parameters, 90 void InitializeKeyboard(bool is_inline, KeyboardInitializeParameters initialize_parameters,
88 SubmitNormalCallback submit_normal_callback_, 91 SubmitNormalCallback submit_normal_callback_,
89 SubmitInlineCallback submit_inline_callback_) override; 92 SubmitInlineCallback submit_inline_callback_) override;
diff --git a/src/core/frontend/applets/web_browser.cpp b/src/core/frontend/applets/web_browser.cpp
index b09cb7102..6e703ef06 100644
--- a/src/core/frontend/applets/web_browser.cpp
+++ b/src/core/frontend/applets/web_browser.cpp
@@ -10,6 +10,8 @@ WebBrowserApplet::~WebBrowserApplet() = default;
10 10
11DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default; 11DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default;
12 12
13void DefaultWebBrowserApplet::Close() const {}
14
13void DefaultWebBrowserApplet::OpenLocalWebPage(const std::string& local_url, 15void DefaultWebBrowserApplet::OpenLocalWebPage(const std::string& local_url,
14 ExtractROMFSCallback extract_romfs_callback, 16 ExtractROMFSCallback extract_romfs_callback,
15 OpenWebPageCallback callback) const { 17 OpenWebPageCallback callback) const {
diff --git a/src/core/frontend/applets/web_browser.h b/src/core/frontend/applets/web_browser.h
index 4f72284ad..178bbdd3f 100644
--- a/src/core/frontend/applets/web_browser.h
+++ b/src/core/frontend/applets/web_browser.h
@@ -5,11 +5,12 @@
5 5
6#include <functional> 6#include <functional>
7 7
8#include "core/frontend/applets/applet.h"
8#include "core/hle/service/am/applets/applet_web_browser_types.h" 9#include "core/hle/service/am/applets/applet_web_browser_types.h"
9 10
10namespace Core::Frontend { 11namespace Core::Frontend {
11 12
12class WebBrowserApplet { 13class WebBrowserApplet : public Applet {
13public: 14public:
14 using ExtractROMFSCallback = std::function<void()>; 15 using ExtractROMFSCallback = std::function<void()>;
15 using OpenWebPageCallback = 16 using OpenWebPageCallback =
@@ -29,6 +30,8 @@ class DefaultWebBrowserApplet final : public WebBrowserApplet {
29public: 30public:
30 ~DefaultWebBrowserApplet() override; 31 ~DefaultWebBrowserApplet() override;
31 32
33 void Close() const override;
34
32 void OpenLocalWebPage(const std::string& local_url, ExtractROMFSCallback extract_romfs_callback, 35 void OpenLocalWebPage(const std::string& local_url, ExtractROMFSCallback extract_romfs_callback,
33 OpenWebPageCallback callback) const override; 36 OpenWebPageCallback callback) const override;
34 37
diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp
index 274928dcf..78d43d729 100644
--- a/src/core/hle/kernel/k_address_arbiter.cpp
+++ b/src/core/hle/kernel/k_address_arbiter.cpp
@@ -21,8 +21,8 @@ KAddressArbiter::~KAddressArbiter() = default;
21 21
22namespace { 22namespace {
23 23
24bool ReadFromUser(Core::System& system, s32* out, KProcessAddress address) { 24bool ReadFromUser(KernelCore& kernel, s32* out, KProcessAddress address) {
25 *out = system.Memory().Read32(GetInteger(address)); 25 *out = GetCurrentMemory(kernel).Read32(GetInteger(address));
26 return true; 26 return true;
27} 27}
28 28
@@ -35,24 +35,30 @@ bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address
35 35
36 // TODO(bunnei): We should call CanAccessAtomic(..) here. 36 // TODO(bunnei): We should call CanAccessAtomic(..) here.
37 37
38 // Load the value from the address. 38 s32 current_value{};
39 const s32 current_value = 39
40 static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address))); 40 while (true) {
41 // Load the value from the address.
42 current_value =
43 static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address)));
41 44
42 // Compare it to the desired one. 45 // Compare it to the desired one.
43 if (current_value < value) { 46 if (current_value < value) {
44 // If less than, we want to try to decrement. 47 // If less than, we want to try to decrement.
45 const s32 decrement_value = current_value - 1; 48 const s32 decrement_value = current_value - 1;
49
50 // Decrement and try to store.
51 if (monitor.ExclusiveWrite32(current_core, GetInteger(address),
52 static_cast<u32>(decrement_value))) {
53 break;
54 }
46 55
47 // Decrement and try to store.
48 if (!monitor.ExclusiveWrite32(current_core, GetInteger(address),
49 static_cast<u32>(decrement_value))) {
50 // If we failed to store, try again. 56 // If we failed to store, try again.
51 DecrementIfLessThan(system, out, address, value); 57 } else {
58 // Otherwise, clear our exclusive hold and finish
59 monitor.ClearExclusive(current_core);
60 break;
52 } 61 }
53 } else {
54 // Otherwise, clear our exclusive hold and finish
55 monitor.ClearExclusive(current_core);
56 } 62 }
57 63
58 // We're done. 64 // We're done.
@@ -70,23 +76,29 @@ bool UpdateIfEqual(Core::System& system, s32* out, KProcessAddress address, s32
70 76
71 // TODO(bunnei): We should call CanAccessAtomic(..) here. 77 // TODO(bunnei): We should call CanAccessAtomic(..) here.
72 78
73 // Load the value from the address. 79 s32 current_value{};
74 const s32 current_value =
75 static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address)));
76 80
77 // Compare it to the desired one. 81 // Load the value from the address.
78 if (current_value == value) { 82 while (true) {
79 // If equal, we want to try to write the new value. 83 current_value =
84 static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address)));
85
86 // Compare it to the desired one.
87 if (current_value == value) {
88 // If equal, we want to try to write the new value.
89
90 // Try to store.
91 if (monitor.ExclusiveWrite32(current_core, GetInteger(address),
92 static_cast<u32>(new_value))) {
93 break;
94 }
80 95
81 // Try to store.
82 if (!monitor.ExclusiveWrite32(current_core, GetInteger(address),
83 static_cast<u32>(new_value))) {
84 // If we failed to store, try again. 96 // If we failed to store, try again.
85 UpdateIfEqual(system, out, address, value, new_value); 97 } else {
98 // Otherwise, clear our exclusive hold and finish.
99 monitor.ClearExclusive(current_core);
100 break;
86 } 101 }
87 } else {
88 // Otherwise, clear our exclusive hold and finish.
89 monitor.ClearExclusive(current_core);
90 } 102 }
91 103
92 // We're done. 104 // We're done.
@@ -209,7 +221,7 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32
209 if (value != new_value) { 221 if (value != new_value) {
210 succeeded = UpdateIfEqual(m_system, std::addressof(user_value), addr, value, new_value); 222 succeeded = UpdateIfEqual(m_system, std::addressof(user_value), addr, value, new_value);
211 } else { 223 } else {
212 succeeded = ReadFromUser(m_system, std::addressof(user_value), addr); 224 succeeded = ReadFromUser(m_kernel, std::addressof(user_value), addr);
213 } 225 }
214 226
215 R_UNLESS(succeeded, ResultInvalidCurrentMemory); 227 R_UNLESS(succeeded, ResultInvalidCurrentMemory);
@@ -252,7 +264,7 @@ Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement,
252 if (decrement) { 264 if (decrement) {
253 succeeded = DecrementIfLessThan(m_system, std::addressof(user_value), addr, value); 265 succeeded = DecrementIfLessThan(m_system, std::addressof(user_value), addr, value);
254 } else { 266 } else {
255 succeeded = ReadFromUser(m_system, std::addressof(user_value), addr); 267 succeeded = ReadFromUser(m_kernel, std::addressof(user_value), addr);
256 } 268 }
257 269
258 if (!succeeded) { 270 if (!succeeded) {
@@ -303,7 +315,7 @@ Result KAddressArbiter::WaitIfEqual(uint64_t addr, s32 value, s64 timeout) {
303 315
304 // Read the value from userspace. 316 // Read the value from userspace.
305 s32 user_value{}; 317 s32 user_value{};
306 if (!ReadFromUser(m_system, std::addressof(user_value), addr)) { 318 if (!ReadFromUser(m_kernel, std::addressof(user_value), addr)) {
307 slp.CancelSleep(); 319 slp.CancelSleep();
308 R_THROW(ResultInvalidCurrentMemory); 320 R_THROW(ResultInvalidCurrentMemory);
309 } 321 }
diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp
index c6634313f..efbac0e6a 100644
--- a/src/core/hle/kernel/k_condition_variable.cpp
+++ b/src/core/hle/kernel/k_condition_variable.cpp
@@ -18,13 +18,13 @@ namespace Kernel {
18 18
19namespace { 19namespace {
20 20
21bool ReadFromUser(Core::System& system, u32* out, KProcessAddress address) { 21bool ReadFromUser(KernelCore& kernel, u32* out, KProcessAddress address) {
22 *out = system.Memory().Read32(GetInteger(address)); 22 *out = GetCurrentMemory(kernel).Read32(GetInteger(address));
23 return true; 23 return true;
24} 24}
25 25
26bool WriteToUser(Core::System& system, KProcessAddress address, const u32* p) { 26bool WriteToUser(KernelCore& kernel, KProcessAddress address, const u32* p) {
27 system.Memory().Write32(GetInteger(address), *p); 27 GetCurrentMemory(kernel).Write32(GetInteger(address), *p);
28 return true; 28 return true;
29} 29}
30 30
@@ -33,21 +33,26 @@ bool UpdateLockAtomic(Core::System& system, u32* out, KProcessAddress address, u
33 auto& monitor = system.Monitor(); 33 auto& monitor = system.Monitor();
34 const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); 34 const auto current_core = system.Kernel().CurrentPhysicalCoreIndex();
35 35
36 // Load the value from the address. 36 u32 expected{};
37 const auto expected = monitor.ExclusiveRead32(current_core, GetInteger(address));
38 37
39 // Orr in the new mask. 38 while (true) {
40 u32 value = expected | new_orr_mask; 39 // Load the value from the address.
40 expected = monitor.ExclusiveRead32(current_core, GetInteger(address));
41 41
42 // If the value is zero, use the if_zero value, otherwise use the newly orr'd value. 42 // Orr in the new mask.
43 if (!expected) { 43 u32 value = expected | new_orr_mask;
44 value = if_zero; 44
45 } 45 // If the value is zero, use the if_zero value, otherwise use the newly orr'd value.
46 if (!expected) {
47 value = if_zero;
48 }
49
50 // Try to store.
51 if (monitor.ExclusiveWrite32(current_core, GetInteger(address), value)) {
52 break;
53 }
46 54
47 // Try to store.
48 if (!monitor.ExclusiveWrite32(current_core, GetInteger(address), value)) {
49 // If we failed to store, try again. 55 // If we failed to store, try again.
50 return UpdateLockAtomic(system, out, address, if_zero, new_orr_mask);
51 } 56 }
52 57
53 // We're done. 58 // We're done.
@@ -128,7 +133,7 @@ Result KConditionVariable::SignalToAddress(KProcessAddress addr) {
128 133
129 // Write the value to userspace. 134 // Write the value to userspace.
130 Result result{ResultSuccess}; 135 Result result{ResultSuccess};
131 if (WriteToUser(m_system, addr, std::addressof(next_value))) [[likely]] { 136 if (WriteToUser(m_kernel, addr, std::addressof(next_value))) [[likely]] {
132 result = ResultSuccess; 137 result = ResultSuccess;
133 } else { 138 } else {
134 result = ResultInvalidCurrentMemory; 139 result = ResultInvalidCurrentMemory;
@@ -157,7 +162,7 @@ Result KConditionVariable::WaitForAddress(Handle handle, KProcessAddress addr, u
157 162
158 // Read the tag from userspace. 163 // Read the tag from userspace.
159 u32 test_tag{}; 164 u32 test_tag{};
160 R_UNLESS(ReadFromUser(m_system, std::addressof(test_tag), addr), 165 R_UNLESS(ReadFromUser(m_kernel, std::addressof(test_tag), addr),
161 ResultInvalidCurrentMemory); 166 ResultInvalidCurrentMemory);
162 167
163 // If the tag isn't the handle (with wait mask), we're done. 168 // If the tag isn't the handle (with wait mask), we're done.
@@ -257,7 +262,7 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
257 // If we have no waiters, clear the has waiter flag. 262 // If we have no waiters, clear the has waiter flag.
258 if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) { 263 if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) {
259 const u32 has_waiter_flag{}; 264 const u32 has_waiter_flag{};
260 WriteToUser(m_system, cv_key, std::addressof(has_waiter_flag)); 265 WriteToUser(m_kernel, cv_key, std::addressof(has_waiter_flag));
261 } 266 }
262 } 267 }
263} 268}
@@ -301,12 +306,12 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti
301 // Write to the cv key. 306 // Write to the cv key.
302 { 307 {
303 const u32 has_waiter_flag = 1; 308 const u32 has_waiter_flag = 1;
304 WriteToUser(m_system, key, std::addressof(has_waiter_flag)); 309 WriteToUser(m_kernel, key, std::addressof(has_waiter_flag));
305 std::atomic_thread_fence(std::memory_order_seq_cst); 310 std::atomic_thread_fence(std::memory_order_seq_cst);
306 } 311 }
307 312
308 // Write the value to userspace. 313 // Write the value to userspace.
309 if (!WriteToUser(m_system, addr, std::addressof(next_value))) { 314 if (!WriteToUser(m_kernel, addr, std::addressof(next_value))) {
310 slp.CancelSleep(); 315 slp.CancelSleep();
311 R_THROW(ResultInvalidCurrentMemory); 316 R_THROW(ResultInvalidCurrentMemory);
312 } 317 }
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp
index cb39387ea..02b5cada4 100644
--- a/src/core/hle/kernel/k_page_table.cpp
+++ b/src/core/hle/kernel/k_page_table.cpp
@@ -108,7 +108,8 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type
108 bool enable_das_merge, bool from_back, 108 bool enable_das_merge, bool from_back,
109 KMemoryManager::Pool pool, KProcessAddress code_addr, 109 KMemoryManager::Pool pool, KProcessAddress code_addr,
110 size_t code_size, KSystemResource* system_resource, 110 size_t code_size, KSystemResource* system_resource,
111 KResourceLimit* resource_limit) { 111 KResourceLimit* resource_limit,
112 Core::Memory::Memory& memory) {
112 113
113 const auto GetSpaceStart = [this](KAddressSpaceInfo::Type type) { 114 const auto GetSpaceStart = [this](KAddressSpaceInfo::Type type) {
114 return KAddressSpaceInfo::GetAddressSpaceStart(m_address_space_width, type); 115 return KAddressSpaceInfo::GetAddressSpaceStart(m_address_space_width, type);
@@ -117,6 +118,9 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type
117 return KAddressSpaceInfo::GetAddressSpaceSize(m_address_space_width, type); 118 return KAddressSpaceInfo::GetAddressSpaceSize(m_address_space_width, type);
118 }; 119 };
119 120
121 // Set the tracking memory
122 m_memory = std::addressof(memory);
123
120 // Set our width and heap/alias sizes 124 // Set our width and heap/alias sizes
121 m_address_space_width = GetAddressSpaceWidthFromType(as_type); 125 m_address_space_width = GetAddressSpaceWidthFromType(as_type);
122 const KProcessAddress start = 0; 126 const KProcessAddress start = 0;
@@ -334,10 +338,10 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type
334 338
335void KPageTable::Finalize() { 339void KPageTable::Finalize() {
336 // Finalize memory blocks. 340 // Finalize memory blocks.
337 m_memory_block_manager.Finalize( 341 m_memory_block_manager.Finalize(m_memory_block_slab_manager,
338 m_memory_block_slab_manager, [&](KProcessAddress addr, u64 size) { 342 [&](KProcessAddress addr, u64 size) {
339 m_system.Memory().UnmapRegion(*m_page_table_impl, addr, size); 343 m_memory->UnmapRegion(*m_page_table_impl, addr, size);
340 }); 344 });
341 345
342 // Release any insecure mapped memory. 346 // Release any insecure mapped memory.
343 if (m_mapped_insecure_memory) { 347 if (m_mapped_insecure_memory) {
@@ -1010,23 +1014,22 @@ Result KPageTable::SetupForIpcServer(KProcessAddress* out_addr, size_t size,
1010 clear_size = 0; 1014 clear_size = 0;
1011 } 1015 }
1012 1016
1013 std::memset(m_system.Memory().GetPointer<void>(GetInteger(start_partial_virt)), 1017 std::memset(m_memory->GetPointer<void>(GetInteger(start_partial_virt)), fill_val,
1014 fill_val, partial_offset); 1018 partial_offset);
1015 std::memcpy( 1019 std::memcpy(
1016 m_system.Memory().GetPointer<void>(GetInteger(start_partial_virt) + partial_offset), 1020 m_memory->GetPointer<void>(GetInteger(start_partial_virt) + partial_offset),
1017 m_system.Memory().GetPointer<void>( 1021 m_memory->GetPointer<void>(GetInteger(GetHeapVirtualAddress(
1018 GetInteger( 1022 m_system.Kernel().MemoryLayout(), cur_block_addr)) +
1019 GetHeapVirtualAddress(m_system.Kernel().MemoryLayout(), cur_block_addr)) + 1023 partial_offset),
1020 partial_offset),
1021 copy_size); 1024 copy_size);
1022 if (clear_size > 0) { 1025 if (clear_size > 0) {
1023 std::memset(m_system.Memory().GetPointer<void>(GetInteger(start_partial_virt) + 1026 std::memset(m_memory->GetPointer<void>(GetInteger(start_partial_virt) +
1024 partial_offset + copy_size), 1027 partial_offset + copy_size),
1025 fill_val, clear_size); 1028 fill_val, clear_size);
1026 } 1029 }
1027 } else { 1030 } else {
1028 std::memset(m_system.Memory().GetPointer<void>(GetInteger(start_partial_virt)), 1031 std::memset(m_memory->GetPointer<void>(GetInteger(start_partial_virt)), fill_val,
1029 fill_val, PageSize); 1032 PageSize);
1030 } 1033 }
1031 1034
1032 // Map the page. 1035 // Map the page.
@@ -1099,15 +1102,14 @@ Result KPageTable::SetupForIpcServer(KProcessAddress* out_addr, size_t size,
1099 GetHeapVirtualAddress(m_system.Kernel().MemoryLayout(), end_partial_page); 1102 GetHeapVirtualAddress(m_system.Kernel().MemoryLayout(), end_partial_page);
1100 if (send) { 1103 if (send) {
1101 const size_t copy_size = src_end - mapping_src_end; 1104 const size_t copy_size = src_end - mapping_src_end;
1102 std::memcpy(m_system.Memory().GetPointer<void>(GetInteger(end_partial_virt)), 1105 std::memcpy(m_memory->GetPointer<void>(GetInteger(end_partial_virt)),
1103 m_system.Memory().GetPointer<void>(GetInteger(GetHeapVirtualAddress( 1106 m_memory->GetPointer<void>(GetInteger(GetHeapVirtualAddress(
1104 m_system.Kernel().MemoryLayout(), cur_block_addr))), 1107 m_system.Kernel().MemoryLayout(), cur_block_addr))),
1105 copy_size); 1108 copy_size);
1106 std::memset( 1109 std::memset(m_memory->GetPointer<void>(GetInteger(end_partial_virt) + copy_size),
1107 m_system.Memory().GetPointer<void>(GetInteger(end_partial_virt) + copy_size), 1110 fill_val, PageSize - copy_size);
1108 fill_val, PageSize - copy_size);
1109 } else { 1111 } else {
1110 std::memset(m_system.Memory().GetPointer<void>(GetInteger(end_partial_virt)), fill_val, 1112 std::memset(m_memory->GetPointer<void>(GetInteger(end_partial_virt)), fill_val,
1111 PageSize); 1113 PageSize);
1112 } 1114 }
1113 1115
@@ -2800,7 +2802,7 @@ Result KPageTable::SetHeapSize(u64* out, size_t size) {
2800 2802
2801 // Clear all the newly allocated pages. 2803 // Clear all the newly allocated pages.
2802 for (size_t cur_page = 0; cur_page < num_pages; ++cur_page) { 2804 for (size_t cur_page = 0; cur_page < num_pages; ++cur_page) {
2803 std::memset(m_system.Memory().GetPointer(m_current_heap_end + (cur_page * PageSize)), 0, 2805 std::memset(m_memory->GetPointer(m_current_heap_end + (cur_page * PageSize)), 0,
2804 PageSize); 2806 PageSize);
2805 } 2807 }
2806 2808
@@ -3006,7 +3008,7 @@ Result KPageTable::Operate(KProcessAddress addr, size_t num_pages, const KPageGr
3006 const size_t size{node.GetNumPages() * PageSize}; 3008 const size_t size{node.GetNumPages() * PageSize};
3007 3009
3008 // Map the pages. 3010 // Map the pages.
3009 m_system.Memory().MapMemoryRegion(*m_page_table_impl, addr, size, node.GetAddress()); 3011 m_memory->MapMemoryRegion(*m_page_table_impl, addr, size, node.GetAddress());
3010 3012
3011 addr += size; 3013 addr += size;
3012 } 3014 }
@@ -3039,14 +3041,14 @@ Result KPageTable::Operate(KProcessAddress addr, size_t num_pages, KMemoryPermis
3039 SCOPE_EXIT({ pages_to_close.CloseAndReset(); }); 3041 SCOPE_EXIT({ pages_to_close.CloseAndReset(); });
3040 3042
3041 this->AddRegionToPages(addr, num_pages, pages_to_close); 3043 this->AddRegionToPages(addr, num_pages, pages_to_close);
3042 m_system.Memory().UnmapRegion(*m_page_table_impl, addr, num_pages * PageSize); 3044 m_memory->UnmapRegion(*m_page_table_impl, addr, num_pages * PageSize);
3043 break; 3045 break;
3044 } 3046 }
3045 case OperationType::MapFirst: 3047 case OperationType::MapFirst:
3046 case OperationType::Map: { 3048 case OperationType::Map: {
3047 ASSERT(map_addr); 3049 ASSERT(map_addr);
3048 ASSERT(Common::IsAligned(GetInteger(map_addr), PageSize)); 3050 ASSERT(Common::IsAligned(GetInteger(map_addr), PageSize));
3049 m_system.Memory().MapMemoryRegion(*m_page_table_impl, addr, num_pages * PageSize, map_addr); 3051 m_memory->MapMemoryRegion(*m_page_table_impl, addr, num_pages * PageSize, map_addr);
3050 3052
3051 // Open references to pages, if we should. 3053 // Open references to pages, if we should.
3052 if (IsHeapPhysicalAddress(m_kernel.MemoryLayout(), map_addr)) { 3054 if (IsHeapPhysicalAddress(m_kernel.MemoryLayout(), map_addr)) {
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h
index 1917b2a98..022d15f35 100644
--- a/src/core/hle/kernel/k_page_table.h
+++ b/src/core/hle/kernel/k_page_table.h
@@ -66,7 +66,8 @@ public:
66 Result InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr, 66 Result InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr,
67 bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, 67 bool enable_das_merge, bool from_back, KMemoryManager::Pool pool,
68 KProcessAddress code_addr, size_t code_size, 68 KProcessAddress code_addr, size_t code_size,
69 KSystemResource* system_resource, KResourceLimit* resource_limit); 69 KSystemResource* system_resource, KResourceLimit* resource_limit,
70 Core::Memory::Memory& memory);
70 71
71 void Finalize(); 72 void Finalize();
72 73
@@ -546,6 +547,7 @@ private:
546 547
547 Core::System& m_system; 548 Core::System& m_system;
548 KernelCore& m_kernel; 549 KernelCore& m_kernel;
550 Core::Memory::Memory* m_memory{};
549}; 551};
550 552
551} // namespace Kernel 553} // namespace Kernel
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 53f8139f3..efe86ad27 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -367,8 +367,8 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
367 // Initialize process address space 367 // Initialize process address space
368 if (const Result result{m_page_table.InitializeForProcess( 368 if (const Result result{m_page_table.InitializeForProcess(
369 metadata.GetAddressSpaceType(), false, false, false, KMemoryManager::Pool::Application, 369 metadata.GetAddressSpaceType(), false, false, false, KMemoryManager::Pool::Application,
370 0x8000000, code_size, std::addressof(m_kernel.GetAppSystemResource()), 370 0x8000000, code_size, std::addressof(m_kernel.GetAppSystemResource()), m_resource_limit,
371 m_resource_limit)}; 371 m_kernel.System().ApplicationMemory())};
372 result.IsError()) { 372 result.IsError()) {
373 R_RETURN(result); 373 R_RETURN(result);
374 } 374 }
@@ -592,8 +592,7 @@ Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) {
592 R_SUCCEED(); 592 R_SUCCEED();
593} 593}
594 594
595bool KProcess::InsertWatchpoint(Core::System& system, KProcessAddress addr, u64 size, 595bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) {
596 DebugWatchpointType type) {
597 const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) { 596 const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) {
598 return wp.type == DebugWatchpointType::None; 597 return wp.type == DebugWatchpointType::None;
599 })}; 598 })};
@@ -609,14 +608,13 @@ bool KProcess::InsertWatchpoint(Core::System& system, KProcessAddress addr, u64
609 for (KProcessAddress page = Common::AlignDown(GetInteger(addr), PageSize); page < addr + size; 608 for (KProcessAddress page = Common::AlignDown(GetInteger(addr), PageSize); page < addr + size;
610 page += PageSize) { 609 page += PageSize) {
611 m_debug_page_refcounts[page]++; 610 m_debug_page_refcounts[page]++;
612 system.Memory().MarkRegionDebug(page, PageSize, true); 611 this->GetMemory().MarkRegionDebug(page, PageSize, true);
613 } 612 }
614 613
615 return true; 614 return true;
616} 615}
617 616
618bool KProcess::RemoveWatchpoint(Core::System& system, KProcessAddress addr, u64 size, 617bool KProcess::RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) {
619 DebugWatchpointType type) {
620 const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) { 618 const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) {
621 return wp.start_address == addr && wp.end_address == addr + size && wp.type == type; 619 return wp.start_address == addr && wp.end_address == addr + size && wp.type == type;
622 })}; 620 })};
@@ -633,7 +631,7 @@ bool KProcess::RemoveWatchpoint(Core::System& system, KProcessAddress addr, u64
633 page += PageSize) { 631 page += PageSize) {
634 m_debug_page_refcounts[page]--; 632 m_debug_page_refcounts[page]--;
635 if (!m_debug_page_refcounts[page]) { 633 if (!m_debug_page_refcounts[page]) {
636 system.Memory().MarkRegionDebug(page, PageSize, false); 634 this->GetMemory().MarkRegionDebug(page, PageSize, false);
637 } 635 }
638 } 636 }
639 637
@@ -646,8 +644,7 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) {
646 m_page_table.SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission); 644 m_page_table.SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission);
647 }; 645 };
648 646
649 m_kernel.System().Memory().WriteBlock(*this, base_addr, code_set.memory.data(), 647 this->GetMemory().WriteBlock(base_addr, code_set.memory.data(), code_set.memory.size());
650 code_set.memory.size());
651 648
652 ReprotectSegment(code_set.CodeSegment(), Svc::MemoryPermission::ReadExecute); 649 ReprotectSegment(code_set.CodeSegment(), Svc::MemoryPermission::ReadExecute);
653 ReprotectSegment(code_set.RODataSegment(), Svc::MemoryPermission::Read); 650 ReprotectSegment(code_set.RODataSegment(), Svc::MemoryPermission::Read);
@@ -706,4 +703,9 @@ Result KProcess::AllocateMainThreadStack(std::size_t stack_size) {
706 R_SUCCEED(); 703 R_SUCCEED();
707} 704}
708 705
706Core::Memory::Memory& KProcess::GetMemory() const {
707 // TODO: per-process memory
708 return m_kernel.System().ApplicationMemory();
709}
710
709} // namespace Kernel 711} // namespace Kernel
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 04b6bbb86..925981d06 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -22,8 +22,12 @@
22#include "core/hle/result.h" 22#include "core/hle/result.h"
23 23
24namespace Core { 24namespace Core {
25namespace Memory {
26class Memory;
27};
28
25class System; 29class System;
26} 30} // namespace Core
27 31
28namespace FileSys { 32namespace FileSys {
29class ProgramMetadata; 33class ProgramMetadata;
@@ -135,6 +139,9 @@ public:
135 return m_handle_table; 139 return m_handle_table;
136 } 140 }
137 141
142 /// Gets a reference to process's memory.
143 Core::Memory::Memory& GetMemory() const;
144
138 Result SignalToAddress(KProcessAddress address) { 145 Result SignalToAddress(KProcessAddress address) {
139 return m_condition_var.SignalToAddress(address); 146 return m_condition_var.SignalToAddress(address);
140 } 147 }
@@ -397,12 +404,10 @@ public:
397 // Debug watchpoint management 404 // Debug watchpoint management
398 405
399 // Attempts to insert a watchpoint into a free slot. Returns false if none are available. 406 // Attempts to insert a watchpoint into a free slot. Returns false if none are available.
400 bool InsertWatchpoint(Core::System& system, KProcessAddress addr, u64 size, 407 bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type);
401 DebugWatchpointType type);
402 408
403 // Attempts to remove the watchpoint specified by the given parameters. 409 // Attempts to remove the watchpoint specified by the given parameters.
404 bool RemoveWatchpoint(Core::System& system, KProcessAddress addr, u64 size, 410 bool RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type);
405 DebugWatchpointType type);
406 411
407 const std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>& GetWatchpoints() const { 412 const std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>& GetWatchpoints() const {
408 return m_watchpoints; 413 return m_watchpoints;
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp
index 2288ee435..c66aff501 100644
--- a/src/core/hle/kernel/k_server_session.cpp
+++ b/src/core/hle/kernel/k_server_session.cpp
@@ -222,7 +222,7 @@ Result KServerSession::SendReply(bool is_hle) {
222 // HLE servers write directly to a pointer to the thread command buffer. Therefore 222 // HLE servers write directly to a pointer to the thread command buffer. Therefore
223 // the reply has already been written in this case. 223 // the reply has already been written in this case.
224 } else { 224 } else {
225 Core::Memory::Memory& memory{m_kernel.System().Memory()}; 225 Core::Memory::Memory& memory{client_thread->GetOwnerProcess()->GetMemory()};
226 KThread* server_thread{GetCurrentThreadPointer(m_kernel)}; 226 KThread* server_thread{GetCurrentThreadPointer(m_kernel)};
227 UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess()); 227 UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess());
228 228
@@ -319,7 +319,7 @@ Result KServerSession::ReceiveRequest(std::shared_ptr<Service::HLERequestContext
319 // bool recv_list_broken = false; 319 // bool recv_list_broken = false;
320 320
321 // Receive the message. 321 // Receive the message.
322 Core::Memory::Memory& memory{m_kernel.System().Memory()}; 322 Core::Memory::Memory& memory{client_thread->GetOwnerProcess()->GetMemory()};
323 if (out_context != nullptr) { 323 if (out_context != nullptr) {
324 // HLE request. 324 // HLE request.
325 u32* cmd_buf{reinterpret_cast<u32*>(memory.GetPointer(client_message))}; 325 u32* cmd_buf{reinterpret_cast<u32*>(memory.GetPointer(client_message))};
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 9d101c640..70480b725 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -546,7 +546,7 @@ u16 KThread::GetUserDisableCount() const {
546 return {}; 546 return {};
547 } 547 }
548 548
549 auto& memory = m_kernel.System().Memory(); 549 auto& memory = this->GetOwnerProcess()->GetMemory();
550 return memory.Read16(m_tls_address + offsetof(ThreadLocalRegion, disable_count)); 550 return memory.Read16(m_tls_address + offsetof(ThreadLocalRegion, disable_count));
551} 551}
552 552
@@ -556,7 +556,7 @@ void KThread::SetInterruptFlag() {
556 return; 556 return;
557 } 557 }
558 558
559 auto& memory = m_kernel.System().Memory(); 559 auto& memory = this->GetOwnerProcess()->GetMemory();
560 memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 1); 560 memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 1);
561} 561}
562 562
@@ -566,7 +566,7 @@ void KThread::ClearInterruptFlag() {
566 return; 566 return;
567 } 567 }
568 568
569 auto& memory = m_kernel.System().Memory(); 569 auto& memory = this->GetOwnerProcess()->GetMemory();
570 memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 0); 570 memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 0);
571} 571}
572 572
@@ -1422,6 +1422,11 @@ s32 GetCurrentCoreId(KernelCore& kernel) {
1422 return GetCurrentThread(kernel).GetCurrentCore(); 1422 return GetCurrentThread(kernel).GetCurrentCore();
1423} 1423}
1424 1424
1425Core::Memory::Memory& GetCurrentMemory(KernelCore& kernel) {
1426 // TODO: per-process memory
1427 return kernel.System().ApplicationMemory();
1428}
1429
1425KScopedDisableDispatch::~KScopedDisableDispatch() { 1430KScopedDisableDispatch::~KScopedDisableDispatch() {
1426 // If we are shutting down the kernel, none of this is relevant anymore. 1431 // If we are shutting down the kernel, none of this is relevant anymore.
1427 if (m_kernel.IsShuttingDown()) { 1432 if (m_kernel.IsShuttingDown()) {
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index 0fa9672bf..9c1a41128 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -34,6 +34,9 @@ class Fiber;
34} 34}
35 35
36namespace Core { 36namespace Core {
37namespace Memory {
38class Memory;
39}
37class ARM_Interface; 40class ARM_Interface;
38class System; 41class System;
39} // namespace Core 42} // namespace Core
@@ -113,6 +116,7 @@ KThread& GetCurrentThread(KernelCore& kernel);
113KProcess* GetCurrentProcessPointer(KernelCore& kernel); 116KProcess* GetCurrentProcessPointer(KernelCore& kernel);
114KProcess& GetCurrentProcess(KernelCore& kernel); 117KProcess& GetCurrentProcess(KernelCore& kernel);
115s32 GetCurrentCoreId(KernelCore& kernel); 118s32 GetCurrentCoreId(KernelCore& kernel);
119Core::Memory::Memory& GetCurrentMemory(KernelCore& kernel);
116 120
117class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>, 121class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>,
118 public boost::intrusive::list_base_hook<>, 122 public boost::intrusive::list_base_hook<>,
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 29809b2c5..4f3366c9d 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -102,7 +102,7 @@ struct KernelCore::Impl {
102 void InitializeCores() { 102 void InitializeCores() {
103 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { 103 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
104 cores[core_id]->Initialize((*application_process).Is64BitProcess()); 104 cores[core_id]->Initialize((*application_process).Is64BitProcess());
105 system.Memory().SetCurrentPageTable(*application_process, core_id); 105 system.ApplicationMemory().SetCurrentPageTable(*application_process, core_id);
106 } 106 }
107 } 107 }
108 108
@@ -206,7 +206,7 @@ struct KernelCore::Impl {
206 206
207 void InitializePhysicalCores() { 207 void InitializePhysicalCores() {
208 exclusive_monitor = 208 exclusive_monitor =
209 Core::MakeExclusiveMonitor(system.Memory(), Core::Hardware::NUM_CPU_CORES); 209 Core::MakeExclusiveMonitor(system.ApplicationMemory(), Core::Hardware::NUM_CPU_CORES);
210 for (u32 i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { 210 for (u32 i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
211 const s32 core{static_cast<s32>(i)}; 211 const s32 core{static_cast<s32>(i)};
212 212
diff --git a/src/core/hle/kernel/svc/svc_cache.cpp b/src/core/hle/kernel/svc/svc_cache.cpp
index 1779832d3..082942dab 100644
--- a/src/core/hle/kernel/svc/svc_cache.cpp
+++ b/src/core/hle/kernel/svc/svc_cache.cpp
@@ -46,7 +46,7 @@ Result FlushProcessDataCache(Core::System& system, Handle process_handle, u64 ad
46 R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); 46 R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
47 47
48 // Perform the operation. 48 // Perform the operation.
49 R_RETURN(system.Memory().FlushDataCache(*process, address, size)); 49 R_RETURN(GetCurrentMemory(system.Kernel()).FlushDataCache(address, size));
50} 50}
51 51
52void FlushEntireDataCache64(Core::System& system) { 52void FlushEntireDataCache64(Core::System& system) {
diff --git a/src/core/hle/kernel/svc/svc_debug_string.cpp b/src/core/hle/kernel/svc/svc_debug_string.cpp
index 8771d2b01..4c14ce668 100644
--- a/src/core/hle/kernel/svc/svc_debug_string.cpp
+++ b/src/core/hle/kernel/svc/svc_debug_string.cpp
@@ -2,6 +2,7 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/core.h" 4#include "core/core.h"
5#include "core/hle/kernel/k_thread.h"
5#include "core/hle/kernel/svc.h" 6#include "core/hle/kernel/svc.h"
6#include "core/memory.h" 7#include "core/memory.h"
7 8
@@ -12,7 +13,7 @@ Result OutputDebugString(Core::System& system, u64 address, u64 len) {
12 R_SUCCEED_IF(len == 0); 13 R_SUCCEED_IF(len == 0);
13 14
14 std::string str(len, '\0'); 15 std::string str(len, '\0');
15 system.Memory().ReadBlock(address, str.data(), str.size()); 16 GetCurrentMemory(system.Kernel()).ReadBlock(address, str.data(), str.size());
16 LOG_DEBUG(Debug_Emulated, "{}", str); 17 LOG_DEBUG(Debug_Emulated, "{}", str);
17 18
18 R_SUCCEED(); 19 R_SUCCEED();
diff --git a/src/core/hle/kernel/svc/svc_exception.cpp b/src/core/hle/kernel/svc/svc_exception.cpp
index 4ab5f471f..580cf2f75 100644
--- a/src/core/hle/kernel/svc/svc_exception.cpp
+++ b/src/core/hle/kernel/svc/svc_exception.cpp
@@ -25,7 +25,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
25 return; 25 return;
26 } 26 }
27 27
28 auto& memory = system.Memory(); 28 auto& memory = GetCurrentMemory(system.Kernel());
29 29
30 // This typically is an error code so we're going to assume this is the case 30 // This typically is an error code so we're going to assume this is the case
31 if (sz == sizeof(u32)) { 31 if (sz == sizeof(u32)) {
diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp
index 2a8c09a79..ea03068aa 100644
--- a/src/core/hle/kernel/svc/svc_ipc.cpp
+++ b/src/core/hle/kernel/svc/svc_ipc.cpp
@@ -41,12 +41,12 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad
41 auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); 41 auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
42 42
43 R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange); 43 R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
44 R_UNLESS(system.Memory().IsValidVirtualAddressRange( 44 R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
45 handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)), 45 handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
46 ResultInvalidPointer); 46 ResultInvalidPointer);
47 47
48 std::vector<Handle> handles(num_handles); 48 std::vector<Handle> handles(num_handles);
49 system.Memory().ReadBlock(handles_addr, handles.data(), sizeof(Handle) * num_handles); 49 GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), sizeof(Handle) * num_handles);
50 50
51 // Convert handle list to object table. 51 // Convert handle list to object table.
52 std::vector<KSynchronizationObject*> objs(num_handles); 52 std::vector<KSynchronizationObject*> objs(num_handles);
diff --git a/src/core/hle/kernel/svc/svc_port.cpp b/src/core/hle/kernel/svc/svc_port.cpp
index c6eb70422..abba757c7 100644
--- a/src/core/hle/kernel/svc/svc_port.cpp
+++ b/src/core/hle/kernel/svc/svc_port.cpp
@@ -14,7 +14,8 @@ namespace Kernel::Svc {
14 14
15Result ConnectToNamedPort(Core::System& system, Handle* out, u64 user_name) { 15Result ConnectToNamedPort(Core::System& system, Handle* out, u64 user_name) {
16 // Copy the provided name from user memory to kernel memory. 16 // Copy the provided name from user memory to kernel memory.
17 auto string_name = system.Memory().ReadCString(user_name, KObjectName::NameLengthMax); 17 auto string_name =
18 GetCurrentMemory(system.Kernel()).ReadCString(user_name, KObjectName::NameLengthMax);
18 19
19 std::array<char, KObjectName::NameLengthMax> name{}; 20 std::array<char, KObjectName::NameLengthMax> name{};
20 std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1); 21 std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1);
@@ -62,7 +63,8 @@ Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) {
62Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name, 63Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name,
63 int32_t max_sessions) { 64 int32_t max_sessions) {
64 // Copy the provided name from user memory to kernel memory. 65 // Copy the provided name from user memory to kernel memory.
65 auto string_name = system.Memory().ReadCString(user_name, KObjectName::NameLengthMax); 66 auto string_name =
67 GetCurrentMemory(system.Kernel()).ReadCString(user_name, KObjectName::NameLengthMax);
66 68
67 // Copy the provided name from user memory to kernel memory. 69 // Copy the provided name from user memory to kernel memory.
68 std::array<char, KObjectName::NameLengthMax> name{}; 70 std::array<char, KObjectName::NameLengthMax> name{};
diff --git a/src/core/hle/kernel/svc/svc_process.cpp b/src/core/hle/kernel/svc/svc_process.cpp
index 3c3579947..619ed16a3 100644
--- a/src/core/hle/kernel/svc/svc_process.cpp
+++ b/src/core/hle/kernel/svc/svc_process.cpp
@@ -73,7 +73,7 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc
73 R_THROW(ResultInvalidCurrentMemory); 73 R_THROW(ResultInvalidCurrentMemory);
74 } 74 }
75 75
76 auto& memory = system.Memory(); 76 auto& memory = GetCurrentMemory(kernel);
77 const auto& process_list = kernel.GetProcessList(); 77 const auto& process_list = kernel.GetProcessList();
78 const auto num_processes = process_list.size(); 78 const auto num_processes = process_list.size();
79 const auto copy_amount = 79 const auto copy_amount =
diff --git a/src/core/hle/kernel/svc/svc_query_memory.cpp b/src/core/hle/kernel/svc/svc_query_memory.cpp
index 5db5611f0..4d9fcd25f 100644
--- a/src/core/hle/kernel/svc/svc_query_memory.cpp
+++ b/src/core/hle/kernel/svc/svc_query_memory.cpp
@@ -30,10 +30,10 @@ Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageIn
30 R_THROW(ResultInvalidHandle); 30 R_THROW(ResultInvalidHandle);
31 } 31 }
32 32
33 auto& memory{system.Memory()}; 33 auto& current_memory{GetCurrentMemory(system.Kernel())};
34 const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()}; 34 const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()};
35 35
36 memory.WriteBlock(out_memory_info, std::addressof(memory_info), sizeof(memory_info)); 36 current_memory.WriteBlock(out_memory_info, std::addressof(memory_info), sizeof(memory_info));
37 37
38 //! This is supposed to be part of the QueryInfo call. 38 //! This is supposed to be part of the QueryInfo call.
39 *out_page_info = {}; 39 *out_page_info = {};
diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp
index e490a13ae..04d65f0bd 100644
--- a/src/core/hle/kernel/svc/svc_synchronization.cpp
+++ b/src/core/hle/kernel/svc/svc_synchronization.cpp
@@ -90,7 +90,8 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha
90 90
91 std::vector<Handle> handles(num_handles); 91 std::vector<Handle> handles(num_handles);
92 if (num_handles > 0) { 92 if (num_handles > 0) {
93 system.Memory().ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle)); 93 GetCurrentMemory(system.Kernel())
94 .ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle));
94 } 95 }
95 96
96 R_RETURN(WaitSynchronization(system, out_index, handles.data(), num_handles, timeout_ns)); 97 R_RETURN(WaitSynchronization(system, out_index, handles.data(), num_handles, timeout_ns));
diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp
index 0be4858a2..37b54079c 100644
--- a/src/core/hle/kernel/svc/svc_thread.cpp
+++ b/src/core/hle/kernel/svc/svc_thread.cpp
@@ -178,7 +178,7 @@ Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_ha
178 R_TRY(thread->GetThreadContext3(context)); 178 R_TRY(thread->GetThreadContext3(context));
179 179
180 // Copy the thread context to user space. 180 // Copy the thread context to user space.
181 system.Memory().WriteBlock(out_context, context.data(), context.size()); 181 GetCurrentMemory(kernel).WriteBlock(out_context, context.data(), context.size());
182 182
183 R_SUCCEED(); 183 R_SUCCEED();
184 } 184 }
@@ -242,7 +242,7 @@ Result GetThreadList(Core::System& system, s32* out_num_threads, u64 out_thread_
242 R_THROW(ResultInvalidCurrentMemory); 242 R_THROW(ResultInvalidCurrentMemory);
243 } 243 }
244 244
245 auto& memory = system.Memory(); 245 auto& memory = GetCurrentMemory(system.Kernel());
246 const auto& thread_list = current_process->GetThreadList(); 246 const auto& thread_list = current_process->GetThreadList();
247 const auto num_threads = thread_list.size(); 247 const auto num_threads = thread_list.size();
248 const auto copy_amount = std::min(static_cast<std::size_t>(out_thread_ids_size), num_threads); 248 const auto copy_amount = std::min(static_cast<std::size_t>(out_thread_ids_size), num_threads);
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index deeca925d..a17c46121 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -945,7 +945,7 @@ public:
945 {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, 945 {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
946 {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"}, 946 {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"},
947 {10, &ILibraryAppletAccessor::Start, "Start"}, 947 {10, &ILibraryAppletAccessor::Start, "Start"},
948 {20, nullptr, "RequestExit"}, 948 {20, &ILibraryAppletAccessor::RequestExit, "RequestExit"},
949 {25, nullptr, "Terminate"}, 949 {25, nullptr, "Terminate"},
950 {30, &ILibraryAppletAccessor::GetResult, "GetResult"}, 950 {30, &ILibraryAppletAccessor::GetResult, "GetResult"},
951 {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"}, 951 {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
@@ -1010,6 +1010,15 @@ private:
1010 rb.Push(ResultSuccess); 1010 rb.Push(ResultSuccess);
1011 } 1011 }
1012 1012
1013 void RequestExit(HLERequestContext& ctx) {
1014 LOG_DEBUG(Service_AM, "called");
1015
1016 ASSERT(applet != nullptr);
1017
1018 IPC::ResponseBuilder rb{ctx, 2};
1019 rb.Push(applet->RequestExit());
1020 }
1021
1013 void PushInData(HLERequestContext& ctx) { 1022 void PushInData(HLERequestContext& ctx) {
1014 LOG_DEBUG(Service_AM, "called"); 1023 LOG_DEBUG(Service_AM, "called");
1015 1024
@@ -1265,7 +1274,8 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx)
1265 } 1274 }
1266 1275
1267 std::vector<u8> memory(transfer_mem->GetSize()); 1276 std::vector<u8> memory(transfer_mem->GetSize());
1268 system.Memory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size()); 1277 system.ApplicationMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(),
1278 memory.size());
1269 1279
1270 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 1280 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1271 rb.Push(ResultSuccess); 1281 rb.Push(ResultSuccess);
@@ -1298,7 +1308,8 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
1298 } 1308 }
1299 1309
1300 std::vector<u8> memory(transfer_mem->GetSize()); 1310 std::vector<u8> memory(transfer_mem->GetSize());
1301 system.Memory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size()); 1311 system.ApplicationMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(),
1312 memory.size());
1302 1313
1303 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 1314 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
1304 rb.Push(ResultSuccess); 1315 rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp
index 162687b29..93c9f2a55 100644
--- a/src/core/hle/service/am/applets/applet_cabinet.cpp
+++ b/src/core/hle/service/am/applets/applet_cabinet.cpp
@@ -174,4 +174,9 @@ void Cabinet::Cancel() {
174 broker.SignalStateChanged(); 174 broker.SignalStateChanged();
175} 175}
176 176
177Result Cabinet::RequestExit() {
178 frontend.Close();
179 R_SUCCEED();
180}
181
177} // namespace Service::AM::Applets 182} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applet_cabinet.h b/src/core/hle/service/am/applets/applet_cabinet.h
index 84197a807..edd295a27 100644
--- a/src/core/hle/service/am/applets/applet_cabinet.h
+++ b/src/core/hle/service/am/applets/applet_cabinet.h
@@ -89,6 +89,7 @@ public:
89 void Execute() override; 89 void Execute() override;
90 void DisplayCompleted(bool apply_changes, std::string_view amiibo_name); 90 void DisplayCompleted(bool apply_changes, std::string_view amiibo_name);
91 void Cancel(); 91 void Cancel();
92 Result RequestExit() override;
92 93
93private: 94private:
94 const Core::Frontend::CabinetApplet& frontend; 95 const Core::Frontend::CabinetApplet& frontend;
diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp
index 58484519b..9840d2547 100644
--- a/src/core/hle/service/am/applets/applet_controller.cpp
+++ b/src/core/hle/service/am/applets/applet_controller.cpp
@@ -224,7 +224,8 @@ void Controller::Execute() {
224 parameters.allow_dual_joycons, parameters.allow_left_joycon, 224 parameters.allow_dual_joycons, parameters.allow_left_joycon,
225 parameters.allow_right_joycon); 225 parameters.allow_right_joycon);
226 226
227 frontend.ReconfigureControllers([this] { ConfigurationComplete(); }, parameters); 227 frontend.ReconfigureControllers(
228 [this](bool is_success) { ConfigurationComplete(is_success); }, parameters);
228 break; 229 break;
229 } 230 }
230 case ControllerSupportMode::ShowControllerStrapGuide: 231 case ControllerSupportMode::ShowControllerStrapGuide:
@@ -232,16 +233,16 @@ void Controller::Execute() {
232 case ControllerSupportMode::ShowControllerKeyRemappingForSystem: 233 case ControllerSupportMode::ShowControllerKeyRemappingForSystem:
233 UNIMPLEMENTED_MSG("ControllerSupportMode={} is not implemented", 234 UNIMPLEMENTED_MSG("ControllerSupportMode={} is not implemented",
234 controller_private_arg.mode); 235 controller_private_arg.mode);
235 ConfigurationComplete(); 236 ConfigurationComplete(true);
236 break; 237 break;
237 default: { 238 default: {
238 ConfigurationComplete(); 239 ConfigurationComplete(true);
239 break; 240 break;
240 } 241 }
241 } 242 }
242} 243}
243 244
244void Controller::ConfigurationComplete() { 245void Controller::ConfigurationComplete(bool is_success) {
245 ControllerSupportResultInfo result_info{}; 246 ControllerSupportResultInfo result_info{};
246 247
247 // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters. 248 // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters.
@@ -250,7 +251,8 @@ void Controller::ConfigurationComplete() {
250 251
251 result_info.selected_id = static_cast<u32>(system.HIDCore().GetFirstNpadId()); 252 result_info.selected_id = static_cast<u32>(system.HIDCore().GetFirstNpadId());
252 253
253 result_info.result = 0; 254 result_info.result =
255 is_success ? ControllerSupportResult::Success : ControllerSupportResult::Cancel;
254 256
255 LOG_DEBUG(Service_HID, "Result Info: player_count={}, selected_id={}, result={}", 257 LOG_DEBUG(Service_HID, "Result Info: player_count={}, selected_id={}, result={}",
256 result_info.player_count, result_info.selected_id, result_info.result); 258 result_info.player_count, result_info.selected_id, result_info.result);
@@ -262,4 +264,9 @@ void Controller::ConfigurationComplete() {
262 broker.SignalStateChanged(); 264 broker.SignalStateChanged();
263} 265}
264 266
267Result Controller::RequestExit() {
268 frontend.Close();
269 R_SUCCEED();
270}
271
265} // namespace Service::AM::Applets 272} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applet_controller.h b/src/core/hle/service/am/applets/applet_controller.h
index 1f9adec65..f6c64f633 100644
--- a/src/core/hle/service/am/applets/applet_controller.h
+++ b/src/core/hle/service/am/applets/applet_controller.h
@@ -48,6 +48,11 @@ enum class ControllerSupportCaller : u8 {
48 MaxControllerSupportCaller, 48 MaxControllerSupportCaller,
49}; 49};
50 50
51enum class ControllerSupportResult : u32 {
52 Success = 0,
53 Cancel = 2,
54};
55
51struct ControllerSupportArgPrivate { 56struct ControllerSupportArgPrivate {
52 u32 arg_private_size{}; 57 u32 arg_private_size{};
53 u32 arg_size{}; 58 u32 arg_size{};
@@ -112,7 +117,7 @@ struct ControllerSupportResultInfo {
112 s8 player_count{}; 117 s8 player_count{};
113 INSERT_PADDING_BYTES(3); 118 INSERT_PADDING_BYTES(3);
114 u32 selected_id{}; 119 u32 selected_id{};
115 u32 result{}; 120 ControllerSupportResult result{};
116}; 121};
117static_assert(sizeof(ControllerSupportResultInfo) == 0xC, 122static_assert(sizeof(ControllerSupportResultInfo) == 0xC,
118 "ControllerSupportResultInfo has incorrect size."); 123 "ControllerSupportResultInfo has incorrect size.");
@@ -129,8 +134,9 @@ public:
129 Result GetStatus() const override; 134 Result GetStatus() const override;
130 void ExecuteInteractive() override; 135 void ExecuteInteractive() override;
131 void Execute() override; 136 void Execute() override;
137 Result RequestExit() override;
132 138
133 void ConfigurationComplete(); 139 void ConfigurationComplete(bool is_success);
134 140
135private: 141private:
136 const Core::Frontend::ControllerApplet& frontend; 142 const Core::Frontend::ControllerApplet& frontend;
diff --git a/src/core/hle/service/am/applets/applet_error.cpp b/src/core/hle/service/am/applets/applet_error.cpp
index b013896b4..b46ea840c 100644
--- a/src/core/hle/service/am/applets/applet_error.cpp
+++ b/src/core/hle/service/am/applets/applet_error.cpp
@@ -209,4 +209,9 @@ void Error::DisplayCompleted() {
209 broker.SignalStateChanged(); 209 broker.SignalStateChanged();
210} 210}
211 211
212Result Error::RequestExit() {
213 frontend.Close();
214 R_SUCCEED();
215}
216
212} // namespace Service::AM::Applets 217} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applet_error.h b/src/core/hle/service/am/applets/applet_error.h
index d78d6f1d1..d822a32bb 100644
--- a/src/core/hle/service/am/applets/applet_error.h
+++ b/src/core/hle/service/am/applets/applet_error.h
@@ -34,6 +34,7 @@ public:
34 Result GetStatus() const override; 34 Result GetStatus() const override;
35 void ExecuteInteractive() override; 35 void ExecuteInteractive() override;
36 void Execute() override; 36 void Execute() override;
37 Result RequestExit() override;
37 38
38 void DisplayCompleted(); 39 void DisplayCompleted();
39 40
diff --git a/src/core/hle/service/am/applets/applet_general_backend.cpp b/src/core/hle/service/am/applets/applet_general_backend.cpp
index 1eefa85e3..8b352020e 100644
--- a/src/core/hle/service/am/applets/applet_general_backend.cpp
+++ b/src/core/hle/service/am/applets/applet_general_backend.cpp
@@ -150,6 +150,11 @@ void Auth::AuthFinished(bool is_successful) {
150 broker.SignalStateChanged(); 150 broker.SignalStateChanged();
151} 151}
152 152
153Result Auth::RequestExit() {
154 frontend.Close();
155 R_SUCCEED();
156}
157
153PhotoViewer::PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_, 158PhotoViewer::PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_,
154 const Core::Frontend::PhotoViewerApplet& frontend_) 159 const Core::Frontend::PhotoViewerApplet& frontend_)
155 : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {} 160 : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
@@ -202,6 +207,11 @@ void PhotoViewer::ViewFinished() {
202 broker.SignalStateChanged(); 207 broker.SignalStateChanged();
203} 208}
204 209
210Result PhotoViewer::RequestExit() {
211 frontend.Close();
212 R_SUCCEED();
213}
214
205StubApplet::StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_) 215StubApplet::StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_)
206 : Applet{system_, applet_mode_}, id{id_}, system{system_} {} 216 : Applet{system_, applet_mode_}, id{id_}, system{system_} {}
207 217
@@ -250,4 +260,9 @@ void StubApplet::Execute() {
250 broker.SignalStateChanged(); 260 broker.SignalStateChanged();
251} 261}
252 262
263Result StubApplet::RequestExit() {
264 // Nothing to do.
265 R_SUCCEED();
266}
267
253} // namespace Service::AM::Applets 268} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applet_general_backend.h b/src/core/hle/service/am/applets/applet_general_backend.h
index a9f2535a2..34ecaebb9 100644
--- a/src/core/hle/service/am/applets/applet_general_backend.h
+++ b/src/core/hle/service/am/applets/applet_general_backend.h
@@ -28,6 +28,7 @@ public:
28 Result GetStatus() const override; 28 Result GetStatus() const override;
29 void ExecuteInteractive() override; 29 void ExecuteInteractive() override;
30 void Execute() override; 30 void Execute() override;
31 Result RequestExit() override;
31 32
32 void AuthFinished(bool is_successful = true); 33 void AuthFinished(bool is_successful = true);
33 34
@@ -59,6 +60,7 @@ public:
59 Result GetStatus() const override; 60 Result GetStatus() const override;
60 void ExecuteInteractive() override; 61 void ExecuteInteractive() override;
61 void Execute() override; 62 void Execute() override;
63 Result RequestExit() override;
62 64
63 void ViewFinished(); 65 void ViewFinished();
64 66
@@ -80,6 +82,7 @@ public:
80 Result GetStatus() const override; 82 Result GetStatus() const override;
81 void ExecuteInteractive() override; 83 void ExecuteInteractive() override;
82 void Execute() override; 84 void Execute() override;
85 Result RequestExit() override;
83 86
84private: 87private:
85 AppletId id; 88 AppletId id;
diff --git a/src/core/hle/service/am/applets/applet_mii_edit.cpp b/src/core/hle/service/am/applets/applet_mii_edit.cpp
index ae80ef506..d1f652c09 100644
--- a/src/core/hle/service/am/applets/applet_mii_edit.cpp
+++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp
@@ -135,4 +135,9 @@ void MiiEdit::MiiEditOutputForCharInfoEditing(MiiEditResult result,
135 broker.SignalStateChanged(); 135 broker.SignalStateChanged();
136} 136}
137 137
138Result MiiEdit::RequestExit() {
139 frontend.Close();
140 R_SUCCEED();
141}
142
138} // namespace Service::AM::Applets 143} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applet_mii_edit.h b/src/core/hle/service/am/applets/applet_mii_edit.h
index d18dd3cf5..3f46fae1b 100644
--- a/src/core/hle/service/am/applets/applet_mii_edit.h
+++ b/src/core/hle/service/am/applets/applet_mii_edit.h
@@ -25,6 +25,7 @@ public:
25 Result GetStatus() const override; 25 Result GetStatus() const override;
26 void ExecuteInteractive() override; 26 void ExecuteInteractive() override;
27 void Execute() override; 27 void Execute() override;
28 Result RequestExit() override;
28 29
29 void MiiEditOutput(MiiEditResult result, s32 index); 30 void MiiEditOutput(MiiEditResult result, s32 index);
30 31
diff --git a/src/core/hle/service/am/applets/applet_profile_select.cpp b/src/core/hle/service/am/applets/applet_profile_select.cpp
index 1d69f5447..89cb323e9 100644
--- a/src/core/hle/service/am/applets/applet_profile_select.cpp
+++ b/src/core/hle/service/am/applets/applet_profile_select.cpp
@@ -25,13 +25,29 @@ void ProfileSelect::Initialize() {
25 final_data.clear(); 25 final_data.clear();
26 26
27 Applet::Initialize(); 27 Applet::Initialize();
28 profile_select_version = ProfileSelectAppletVersion{common_args.library_version};
28 29
29 const auto user_config_storage = broker.PopNormalDataToApplet(); 30 const auto user_config_storage = broker.PopNormalDataToApplet();
30 ASSERT(user_config_storage != nullptr); 31 ASSERT(user_config_storage != nullptr);
31 const auto& user_config = user_config_storage->GetData(); 32 const auto& user_config = user_config_storage->GetData();
32 33
33 ASSERT(user_config.size() >= sizeof(UserSelectionConfig)); 34 LOG_INFO(Service_AM, "Initializing Profile Select Applet with version={}",
34 std::memcpy(&config, user_config.data(), sizeof(UserSelectionConfig)); 35 profile_select_version);
36
37 switch (profile_select_version) {
38 case ProfileSelectAppletVersion::Version1:
39 ASSERT(user_config.size() == sizeof(UiSettingsV1));
40 std::memcpy(&config_old, user_config.data(), sizeof(UiSettingsV1));
41 break;
42 case ProfileSelectAppletVersion::Version2:
43 case ProfileSelectAppletVersion::Version3:
44 ASSERT(user_config.size() == sizeof(UiSettings));
45 std::memcpy(&config, user_config.data(), sizeof(UiSettings));
46 break;
47 default:
48 UNIMPLEMENTED_MSG("Unknown profile_select_version = {}", profile_select_version);
49 break;
50 }
35} 51}
36 52
37bool ProfileSelect::TransactionComplete() const { 53bool ProfileSelect::TransactionComplete() const {
@@ -52,11 +68,37 @@ void ProfileSelect::Execute() {
52 return; 68 return;
53 } 69 }
54 70
55 frontend.SelectProfile([this](std::optional<Common::UUID> uuid) { SelectionComplete(uuid); }); 71 Core::Frontend::ProfileSelectParameters parameters{};
72
73 switch (profile_select_version) {
74 case ProfileSelectAppletVersion::Version1:
75 parameters = {
76 .mode = config_old.mode,
77 .invalid_uid_list = config_old.invalid_uid_list,
78 .display_options = config_old.display_options,
79 .purpose = UserSelectionPurpose::General,
80 };
81 break;
82 case ProfileSelectAppletVersion::Version2:
83 case ProfileSelectAppletVersion::Version3:
84 parameters = {
85 .mode = config.mode,
86 .invalid_uid_list = config.invalid_uid_list,
87 .display_options = config.display_options,
88 .purpose = config.purpose,
89 };
90 break;
91 default:
92 UNIMPLEMENTED_MSG("Unknown profile_select_version = {}", profile_select_version);
93 break;
94 }
95
96 frontend.SelectProfile([this](std::optional<Common::UUID> uuid) { SelectionComplete(uuid); },
97 parameters);
56} 98}
57 99
58void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) { 100void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) {
59 UserSelectionOutput output{}; 101 UiReturnArg output{};
60 102
61 if (uuid.has_value() && uuid->IsValid()) { 103 if (uuid.has_value() && uuid->IsValid()) {
62 output.result = 0; 104 output.result = 0;
@@ -67,10 +109,15 @@ void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) {
67 output.uuid_selected = Common::InvalidUUID; 109 output.uuid_selected = Common::InvalidUUID;
68 } 110 }
69 111
70 final_data = std::vector<u8>(sizeof(UserSelectionOutput)); 112 final_data = std::vector<u8>(sizeof(UiReturnArg));
71 std::memcpy(final_data.data(), &output, final_data.size()); 113 std::memcpy(final_data.data(), &output, final_data.size());
72 broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data))); 114 broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data)));
73 broker.SignalStateChanged(); 115 broker.SignalStateChanged();
74} 116}
75 117
118Result ProfileSelect::RequestExit() {
119 frontend.Close();
120 R_SUCCEED();
121}
122
76} // namespace Service::AM::Applets 123} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applet_profile_select.h b/src/core/hle/service/am/applets/applet_profile_select.h
index b77f1d205..369f9250f 100644
--- a/src/core/hle/service/am/applets/applet_profile_select.h
+++ b/src/core/hle/service/am/applets/applet_profile_select.h
@@ -16,19 +16,100 @@ class System;
16 16
17namespace Service::AM::Applets { 17namespace Service::AM::Applets {
18 18
19struct UserSelectionConfig { 19enum class ProfileSelectAppletVersion : u32 {
20 // TODO(DarkLordZach): RE this structure 20 Version1 = 0x1, // 1.0.0+
21 // It seems to be flags and the like that determine the UI of the applet on the switch... from 21 Version2 = 0x10000, // 2.0.0+
22 // my research this is safe to ignore for now. 22 Version3 = 0x20000, // 6.0.0+
23 INSERT_PADDING_BYTES(0xA0);
24}; 23};
25static_assert(sizeof(UserSelectionConfig) == 0xA0, "UserSelectionConfig has incorrect size.");
26 24
27struct UserSelectionOutput { 25// This is nn::account::UiMode
26enum class UiMode {
27 UserSelector,
28 UserCreator,
29 EnsureNetworkServiceAccountAvailable,
30 UserIconEditor,
31 UserNicknameEditor,
32 UserCreatorForStarter,
33 NintendoAccountAuthorizationRequestContext,
34 IntroduceExternalNetworkServiceAccount,
35 IntroduceExternalNetworkServiceAccountForRegistration,
36 NintendoAccountNnidLinker,
37 LicenseRequirementsForNetworkService,
38 LicenseRequirementsForNetworkServiceWithUserContextImpl,
39 UserCreatorForImmediateNaLoginTest,
40 UserQualificationPromoter,
41};
42
43// This is nn::account::UserSelectionPurpose
44enum class UserSelectionPurpose {
45 General,
46 GameCardRegistration,
47 EShopLaunch,
48 EShopItemShow,
49 PicturePost,
50 NintendoAccountLinkage,
51 SettingsUpdate,
52 SaveDataDeletion,
53 UserMigration,
54 SaveDataTransfer,
55};
56
57// This is nn::account::NintendoAccountStartupDialogType
58enum class NintendoAccountStartupDialogType {
59 LoginAndCreate,
60 Login,
61 Create,
62};
63
64// This is nn::account::UserSelectionSettingsForSystemService
65struct UserSelectionSettingsForSystemService {
66 UserSelectionPurpose purpose;
67 bool enable_user_creation;
68 INSERT_PADDING_BYTES(0x3);
69};
70static_assert(sizeof(UserSelectionSettingsForSystemService) == 0x8,
71 "UserSelectionSettingsForSystemService has incorrect size.");
72
73struct UiSettingsDisplayOptions {
74 bool is_network_service_account_required;
75 bool is_skip_enabled;
76 bool is_system_or_launcher;
77 bool is_registration_permitted;
78 bool show_skip_button;
79 bool aditional_select;
80 bool show_user_selector;
81 bool is_unqualified_user_selectable;
82};
83static_assert(sizeof(UiSettingsDisplayOptions) == 0x8,
84 "UiSettingsDisplayOptions has incorrect size.");
85
86struct UiSettingsV1 {
87 UiMode mode;
88 INSERT_PADDING_BYTES(0x4);
89 std::array<Common::UUID, 8> invalid_uid_list;
90 u64 application_id;
91 UiSettingsDisplayOptions display_options;
92};
93static_assert(sizeof(UiSettingsV1) == 0x98, "UiSettings has incorrect size.");
94
95// This is nn::account::UiSettings
96struct UiSettings {
97 UiMode mode;
98 INSERT_PADDING_BYTES(0x4);
99 std::array<Common::UUID, 8> invalid_uid_list;
100 u64 application_id;
101 UiSettingsDisplayOptions display_options;
102 UserSelectionPurpose purpose;
103 INSERT_PADDING_BYTES(0x4);
104};
105static_assert(sizeof(UiSettings) == 0xA0, "UiSettings has incorrect size.");
106
107// This is nn::account::UiReturnArg
108struct UiReturnArg {
28 u64 result; 109 u64 result;
29 Common::UUID uuid_selected; 110 Common::UUID uuid_selected;
30}; 111};
31static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has incorrect size."); 112static_assert(sizeof(UiReturnArg) == 0x18, "UiReturnArg has incorrect size.");
32 113
33class ProfileSelect final : public Applet { 114class ProfileSelect final : public Applet {
34public: 115public:
@@ -42,13 +123,17 @@ public:
42 Result GetStatus() const override; 123 Result GetStatus() const override;
43 void ExecuteInteractive() override; 124 void ExecuteInteractive() override;
44 void Execute() override; 125 void Execute() override;
126 Result RequestExit() override;
45 127
46 void SelectionComplete(std::optional<Common::UUID> uuid); 128 void SelectionComplete(std::optional<Common::UUID> uuid);
47 129
48private: 130private:
49 const Core::Frontend::ProfileSelectApplet& frontend; 131 const Core::Frontend::ProfileSelectApplet& frontend;
50 132
51 UserSelectionConfig config; 133 UiSettings config;
134 UiSettingsV1 config_old;
135 ProfileSelectAppletVersion profile_select_version;
136
52 bool complete = false; 137 bool complete = false;
53 Result status = ResultSuccess; 138 Result status = ResultSuccess;
54 std::vector<u8> final_data; 139 std::vector<u8> final_data;
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.cpp b/src/core/hle/service/am/applets/applet_software_keyboard.cpp
index c18236045..4145bb84f 100644
--- a/src/core/hle/service/am/applets/applet_software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/applet_software_keyboard.cpp
@@ -770,6 +770,11 @@ void SoftwareKeyboard::ExitKeyboard() {
770 broker.SignalStateChanged(); 770 broker.SignalStateChanged();
771} 771}
772 772
773Result SoftwareKeyboard::RequestExit() {
774 frontend.Close();
775 R_SUCCEED();
776}
777
773// Inline Software Keyboard Requests 778// Inline Software Keyboard Requests
774 779
775void SoftwareKeyboard::RequestFinalize(const std::vector<u8>& request_data) { 780void SoftwareKeyboard::RequestFinalize(const std::vector<u8>& request_data) {
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.h b/src/core/hle/service/am/applets/applet_software_keyboard.h
index b01b31c98..2e919811b 100644
--- a/src/core/hle/service/am/applets/applet_software_keyboard.h
+++ b/src/core/hle/service/am/applets/applet_software_keyboard.h
@@ -31,6 +31,7 @@ public:
31 Result GetStatus() const override; 31 Result GetStatus() const override;
32 void ExecuteInteractive() override; 32 void ExecuteInteractive() override;
33 void Execute() override; 33 void Execute() override;
34 Result RequestExit() override;
34 35
35 /** 36 /**
36 * Submits the input text to the application. 37 * Submits the input text to the application.
diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp
index f061bae80..2accf7898 100644
--- a/src/core/hle/service/am/applets/applet_web_browser.cpp
+++ b/src/core/hle/service/am/applets/applet_web_browser.cpp
@@ -363,6 +363,11 @@ void WebBrowser::WebBrowserExit(WebExitReason exit_reason, std::string last_url)
363 broker.SignalStateChanged(); 363 broker.SignalStateChanged();
364} 364}
365 365
366Result WebBrowser::RequestExit() {
367 frontend.Close();
368 R_SUCCEED();
369}
370
366bool WebBrowser::InputTLVExistsInMap(WebArgInputTLVType input_tlv_type) const { 371bool WebBrowser::InputTLVExistsInMap(WebArgInputTLVType input_tlv_type) const {
367 return web_arg_input_tlv_map.find(input_tlv_type) != web_arg_input_tlv_map.end(); 372 return web_arg_input_tlv_map.find(input_tlv_type) != web_arg_input_tlv_map.end();
368} 373}
diff --git a/src/core/hle/service/am/applets/applet_web_browser.h b/src/core/hle/service/am/applets/applet_web_browser.h
index fd727fac8..99fe18659 100644
--- a/src/core/hle/service/am/applets/applet_web_browser.h
+++ b/src/core/hle/service/am/applets/applet_web_browser.h
@@ -35,6 +35,7 @@ public:
35 Result GetStatus() const override; 35 Result GetStatus() const override;
36 void ExecuteInteractive() override; 36 void ExecuteInteractive() override;
37 void Execute() override; 37 void Execute() override;
38 Result RequestExit() override;
38 39
39 void ExtractOfflineRomFS(); 40 void ExtractOfflineRomFS();
40 41
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index a22eb62a8..12f374199 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -142,6 +142,7 @@ public:
142 virtual Result GetStatus() const = 0; 142 virtual Result GetStatus() const = 0;
143 virtual void ExecuteInteractive() = 0; 143 virtual void ExecuteInteractive() = 0;
144 virtual void Execute() = 0; 144 virtual void Execute() = 0;
145 virtual Result RequestExit() = 0;
145 146
146 AppletDataBroker& GetBroker() { 147 AppletDataBroker& GetBroker() {
147 return broker; 148 return broker;
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
index 37f2e4405..bcb272eaf 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
@@ -60,7 +60,8 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
60 60
61 // Update seven six axis transfer memory 61 // Update seven six axis transfer memory
62 seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state); 62 seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state);
63 system.Memory().WriteBlock(transfer_memory, &seven_sixaxis_lifo, sizeof(seven_sixaxis_lifo)); 63 system.ApplicationMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo,
64 sizeof(seven_sixaxis_lifo));
64} 65}
65 66
66void Controller_ConsoleSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) { 67void Controller_ConsoleSixAxis::SetTransferMemoryAddress(Common::ProcessAddress t_mem) {
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index ba6f04d8d..b070327ec 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -819,12 +819,12 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode
819 return communication_mode; 819 return communication_mode;
820} 820}
821 821
822Result Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, 822bool Controller_NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id,
823 NpadJoyDeviceType npad_device_type, 823 NpadJoyDeviceType npad_device_type,
824 NpadJoyAssignmentMode assignment_mode) { 824 NpadJoyAssignmentMode assignment_mode) {
825 if (!IsNpadIdValid(npad_id)) { 825 if (!IsNpadIdValid(npad_id)) {
826 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 826 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
827 return InvalidNpadId; 827 return false;
828 } 828 }
829 829
830 auto& controller = GetControllerFromNpadIdType(npad_id); 830 auto& controller = GetControllerFromNpadIdType(npad_id);
@@ -833,7 +833,7 @@ Result Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id,
833 } 833 }
834 834
835 if (!controller.device->IsConnected()) { 835 if (!controller.device->IsConnected()) {
836 return ResultSuccess; 836 return false;
837 } 837 }
838 838
839 if (assignment_mode == NpadJoyAssignmentMode::Dual) { 839 if (assignment_mode == NpadJoyAssignmentMode::Dual) {
@@ -842,52 +842,52 @@ Result Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id,
842 controller.is_dual_left_connected = true; 842 controller.is_dual_left_connected = true;
843 controller.is_dual_right_connected = false; 843 controller.is_dual_right_connected = false;
844 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); 844 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
845 return ResultSuccess; 845 return false;
846 } 846 }
847 if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) { 847 if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) {
848 DisconnectNpad(npad_id); 848 DisconnectNpad(npad_id);
849 controller.is_dual_left_connected = false; 849 controller.is_dual_left_connected = false;
850 controller.is_dual_right_connected = true; 850 controller.is_dual_right_connected = true;
851 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); 851 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
852 return ResultSuccess; 852 return false;
853 } 853 }
854 return ResultSuccess; 854 return false;
855 } 855 }
856 856
857 // This is for NpadJoyAssignmentMode::Single 857 // This is for NpadJoyAssignmentMode::Single
858 858
859 // Only JoyconDual get affected by this function 859 // Only JoyconDual get affected by this function
860 if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) { 860 if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) {
861 return ResultSuccess; 861 return false;
862 } 862 }
863 863
864 if (controller.is_dual_left_connected && !controller.is_dual_right_connected) { 864 if (controller.is_dual_left_connected && !controller.is_dual_right_connected) {
865 DisconnectNpad(npad_id); 865 DisconnectNpad(npad_id);
866 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); 866 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true);
867 return ResultSuccess; 867 return false;
868 } 868 }
869 if (!controller.is_dual_left_connected && controller.is_dual_right_connected) { 869 if (!controller.is_dual_left_connected && controller.is_dual_right_connected) {
870 DisconnectNpad(npad_id); 870 DisconnectNpad(npad_id);
871 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); 871 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true);
872 return ResultSuccess; 872 return false;
873 } 873 }
874 874
875 // We have two controllers connected to the same npad_id we need to split them 875 // We have two controllers connected to the same npad_id we need to split them
876 const auto npad_id_2 = hid_core.GetFirstDisconnectedNpadId(); 876 new_npad_id = hid_core.GetFirstDisconnectedNpadId();
877 auto& controller_2 = GetControllerFromNpadIdType(npad_id_2); 877 auto& controller_2 = GetControllerFromNpadIdType(new_npad_id);
878 DisconnectNpad(npad_id); 878 DisconnectNpad(npad_id);
879 if (npad_device_type == NpadJoyDeviceType::Left) { 879 if (npad_device_type == NpadJoyDeviceType::Left) {
880 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); 880 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true);
881 controller_2.is_dual_left_connected = false; 881 controller_2.is_dual_left_connected = false;
882 controller_2.is_dual_right_connected = true; 882 controller_2.is_dual_right_connected = true;
883 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true); 883 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true);
884 } else { 884 } else {
885 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); 885 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true);
886 controller_2.is_dual_left_connected = true; 886 controller_2.is_dual_left_connected = true;
887 controller_2.is_dual_right_connected = false; 887 controller_2.is_dual_right_connected = false;
888 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true); 888 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true);
889 } 889 }
890 return ResultSuccess; 890 return true;
891} 891}
892 892
893bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, 893bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
@@ -1388,7 +1388,8 @@ Result Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
1388 return NpadIsDualJoycon; 1388 return NpadIsDualJoycon;
1389 } 1389 }
1390 1390
1391 // Disconnect the joycon at the second id and connect the dual joycon at the first index. 1391 // Disconnect the joycons and connect them as dual joycon at the first index.
1392 DisconnectNpad(npad_id_1);
1392 DisconnectNpad(npad_id_2); 1393 DisconnectNpad(npad_id_2);
1393 controller_1.is_dual_left_connected = true; 1394 controller_1.is_dual_left_connected = true;
1394 controller_1.is_dual_right_connected = true; 1395 controller_1.is_dual_right_connected = true;
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index a5998c453..9cfe298f1 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -102,8 +102,8 @@ public:
102 void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); 102 void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_);
103 NpadCommunicationMode GetNpadCommunicationMode() const; 103 NpadCommunicationMode GetNpadCommunicationMode() const;
104 104
105 Result SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, 105 bool SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id,
106 NpadJoyAssignmentMode assignment_mode); 106 NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode);
107 107
108 bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index, 108 bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index,
109 const Core::HID::VibrationValue& vibration_value); 109 const Core::HID::VibrationValue& vibration_value);
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 4529ad643..87e7b864a 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -302,7 +302,7 @@ Hid::Hid(Core::System& system_)
302 {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"}, 302 {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"},
303 {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"}, 303 {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"},
304 {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"}, 304 {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"},
305 {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"}, 305 {133, &Hid::SetNpadJoyAssignmentModeSingleWithDestination, "SetNpadJoyAssignmentModeSingleWithDestination"},
306 {134, &Hid::SetNpadAnalogStickUseCenterClamp, "SetNpadAnalogStickUseCenterClamp"}, 306 {134, &Hid::SetNpadAnalogStickUseCenterClamp, "SetNpadAnalogStickUseCenterClamp"},
307 {135, &Hid::SetNpadCaptureButtonAssignment, "SetNpadCaptureButtonAssignment"}, 307 {135, &Hid::SetNpadCaptureButtonAssignment, "SetNpadCaptureButtonAssignment"},
308 {136, &Hid::ClearNpadCaptureButtonAssignment, "ClearNpadCaptureButtonAssignment"}, 308 {136, &Hid::ClearNpadCaptureButtonAssignment, "ClearNpadCaptureButtonAssignment"},
@@ -1180,8 +1180,10 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(HLERequestContext& ctx) {
1180 1180
1181 const auto parameters{rp.PopRaw<Parameters>()}; 1181 const auto parameters{rp.PopRaw<Parameters>()};
1182 1182
1183 Core::HID::NpadIdType new_npad_id{};
1183 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); 1184 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1184 controller.SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyDeviceType::Left, 1185 controller.SetNpadMode(new_npad_id, parameters.npad_id,
1186 Controller_NPad::NpadJoyDeviceType::Left,
1185 Controller_NPad::NpadJoyAssignmentMode::Single); 1187 Controller_NPad::NpadJoyAssignmentMode::Single);
1186 1188
1187 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, 1189 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
@@ -1203,8 +1205,9 @@ void Hid::SetNpadJoyAssignmentModeSingle(HLERequestContext& ctx) {
1203 1205
1204 const auto parameters{rp.PopRaw<Parameters>()}; 1206 const auto parameters{rp.PopRaw<Parameters>()};
1205 1207
1208 Core::HID::NpadIdType new_npad_id{};
1206 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); 1209 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1207 controller.SetNpadMode(parameters.npad_id, parameters.npad_joy_device_type, 1210 controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
1208 Controller_NPad::NpadJoyAssignmentMode::Single); 1211 Controller_NPad::NpadJoyAssignmentMode::Single);
1209 1212
1210 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", 1213 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
@@ -1226,8 +1229,10 @@ void Hid::SetNpadJoyAssignmentModeDual(HLERequestContext& ctx) {
1226 1229
1227 const auto parameters{rp.PopRaw<Parameters>()}; 1230 const auto parameters{rp.PopRaw<Parameters>()};
1228 1231
1232 Core::HID::NpadIdType new_npad_id{};
1229 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); 1233 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1230 controller.SetNpadMode(parameters.npad_id, {}, Controller_NPad::NpadJoyAssignmentMode::Dual); 1234 controller.SetNpadMode(new_npad_id, parameters.npad_id, {},
1235 Controller_NPad::NpadJoyAssignmentMode::Dual);
1231 1236
1232 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, 1237 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1233 parameters.applet_resource_user_id); 1238 parameters.applet_resource_user_id);
@@ -1369,6 +1374,34 @@ void Hid::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) {
1369 rb.Push(result); 1374 rb.Push(result);
1370} 1375}
1371 1376
1377void Hid::SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx) {
1378 IPC::RequestParser rp{ctx};
1379 struct Parameters {
1380 Core::HID::NpadIdType npad_id;
1381 INSERT_PADDING_WORDS_NOINIT(1);
1382 u64 applet_resource_user_id;
1383 Controller_NPad::NpadJoyDeviceType npad_joy_device_type;
1384 };
1385 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1386
1387 const auto parameters{rp.PopRaw<Parameters>()};
1388
1389 Core::HID::NpadIdType new_npad_id{};
1390 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1391 const auto is_reassigned =
1392 controller.SetNpadMode(new_npad_id, parameters.npad_id, parameters.npad_joy_device_type,
1393 Controller_NPad::NpadJoyAssignmentMode::Single);
1394
1395 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
1396 parameters.npad_id, parameters.applet_resource_user_id,
1397 parameters.npad_joy_device_type);
1398
1399 IPC::ResponseBuilder rb{ctx, 4};
1400 rb.Push(ResultSuccess);
1401 rb.Push(is_reassigned);
1402 rb.PushEnum(new_npad_id);
1403}
1404
1372void Hid::SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx) { 1405void Hid::SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx) {
1373 IPC::RequestParser rp{ctx}; 1406 IPC::RequestParser rp{ctx};
1374 struct Parameters { 1407 struct Parameters {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index c69e5f3fb..f247b83c2 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -151,6 +151,7 @@ private:
151 void SwapNpadAssignment(HLERequestContext& ctx); 151 void SwapNpadAssignment(HLERequestContext& ctx);
152 void IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx); 152 void IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx);
153 void EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx); 153 void EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx);
154 void SetNpadJoyAssignmentModeSingleWithDestination(HLERequestContext& ctx);
154 void SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx); 155 void SetNpadAnalogStickUseCenterClamp(HLERequestContext& ctx);
155 void SetNpadCaptureButtonAssignment(HLERequestContext& ctx); 156 void SetNpadCaptureButtonAssignment(HLERequestContext& ctx);
156 void ClearNpadCaptureButtonAssignment(HLERequestContext& ctx); 157 void ClearNpadCaptureButtonAssignment(HLERequestContext& ctx);
diff --git a/src/core/hle/service/hid/hidbus/ringcon.cpp b/src/core/hle/service/hid/hidbus/ringcon.cpp
index 65a2dd521..378108012 100644
--- a/src/core/hle/service/hid/hidbus/ringcon.cpp
+++ b/src/core/hle/service/hid/hidbus/ringcon.cpp
@@ -64,8 +64,8 @@ void RingController::OnUpdate() {
64 curr_entry.polling_data.out_size = sizeof(ringcon_value); 64 curr_entry.polling_data.out_size = sizeof(ringcon_value);
65 std::memcpy(curr_entry.polling_data.data.data(), &ringcon_value, sizeof(ringcon_value)); 65 std::memcpy(curr_entry.polling_data.data.data(), &ringcon_value, sizeof(ringcon_value));
66 66
67 system.Memory().WriteBlock(transfer_memory, &enable_sixaxis_data, 67 system.ApplicationMemory().WriteBlock(transfer_memory, &enable_sixaxis_data,
68 sizeof(enable_sixaxis_data)); 68 sizeof(enable_sixaxis_data));
69 break; 69 break;
70 } 70 }
71 default: 71 default:
diff --git a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp
index ca5d067e8..803a6277c 100644
--- a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp
+++ b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp
@@ -58,16 +58,16 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType
58 if (camera_data.format != current_config.origin_format) { 58 if (camera_data.format != current_config.origin_format) {
59 LOG_WARNING(Service_IRS, "Wrong Input format {} expected {}", camera_data.format, 59 LOG_WARNING(Service_IRS, "Wrong Input format {} expected {}", camera_data.format,
60 current_config.origin_format); 60 current_config.origin_format);
61 system.Memory().ZeroBlock(*system.ApplicationProcess(), transfer_memory, 61 system.ApplicationMemory().ZeroBlock(transfer_memory,
62 GetDataSize(current_config.trimming_format)); 62 GetDataSize(current_config.trimming_format));
63 return; 63 return;
64 } 64 }
65 65
66 if (current_config.origin_format > current_config.trimming_format) { 66 if (current_config.origin_format > current_config.trimming_format) {
67 LOG_WARNING(Service_IRS, "Origin format {} is smaller than trimming format {}", 67 LOG_WARNING(Service_IRS, "Origin format {} is smaller than trimming format {}",
68 current_config.origin_format, current_config.trimming_format); 68 current_config.origin_format, current_config.trimming_format);
69 system.Memory().ZeroBlock(*system.ApplicationProcess(), transfer_memory, 69 system.ApplicationMemory().ZeroBlock(transfer_memory,
70 GetDataSize(current_config.trimming_format)); 70 GetDataSize(current_config.trimming_format));
71 return; 71 return;
72 } 72 }
73 73
@@ -84,8 +84,8 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType
84 "Trimming area ({}, {}, {}, {}) is outside of origin area ({}, {})", 84 "Trimming area ({}, {}, {}, {}) is outside of origin area ({}, {})",
85 current_config.trimming_start_x, current_config.trimming_start_y, 85 current_config.trimming_start_x, current_config.trimming_start_y,
86 trimming_width, trimming_height, origin_width, origin_height); 86 trimming_width, trimming_height, origin_width, origin_height);
87 system.Memory().ZeroBlock(*system.ApplicationProcess(), transfer_memory, 87 system.ApplicationMemory().ZeroBlock(transfer_memory,
88 GetDataSize(current_config.trimming_format)); 88 GetDataSize(current_config.trimming_format));
89 return; 89 return;
90 } 90 }
91 91
@@ -99,8 +99,8 @@ void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType
99 } 99 }
100 } 100 }
101 101
102 system.Memory().WriteBlock(transfer_memory, window_data.data(), 102 system.ApplicationMemory().WriteBlock(transfer_memory, window_data.data(),
103 GetDataSize(current_config.trimming_format)); 103 GetDataSize(current_config.trimming_format));
104 104
105 if (!IsProcessorActive()) { 105 if (!IsProcessorActive()) {
106 StartProcessor(); 106 StartProcessor();
@@ -148,7 +148,7 @@ Core::IrSensor::ImageTransferProcessorState ImageTransferProcessor::GetState(
148 std::vector<u8>& data) const { 148 std::vector<u8>& data) const {
149 const auto size = GetDataSize(current_config.trimming_format); 149 const auto size = GetDataSize(current_config.trimming_format);
150 data.resize(size); 150 data.resize(size);
151 system.Memory().ReadBlock(transfer_memory, data.data(), size); 151 system.ApplicationMemory().ReadBlock(transfer_memory, data.data(), size);
152 return processor_state; 152 return processor_state;
153} 153}
154 154
diff --git a/src/core/hle/service/hle_ipc.cpp b/src/core/hle/service/hle_ipc.cpp
index cca697c64..2290df705 100644
--- a/src/core/hle/service/hle_ipc.cpp
+++ b/src/core/hle/service/hle_ipc.cpp
@@ -303,8 +303,7 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer(Kernel::KThread& requesti
303 } 303 }
304 304
305 // Copy the translated command buffer back into the thread's command buffer area. 305 // Copy the translated command buffer back into the thread's command buffer area.
306 memory.WriteBlock(owner_process, requesting_thread.GetTlsAddress(), cmd_buf.data(), 306 memory.WriteBlock(requesting_thread.GetTlsAddress(), cmd_buf.data(), write_size * sizeof(u32));
307 write_size * sizeof(u32));
308 307
309 return ResultSuccess; 308 return ResultSuccess;
310} 309}
diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp
index 607f27b21..be996870f 100644
--- a/src/core/hle/service/jit/jit.cpp
+++ b/src/core/hle/service/jit/jit.cpp
@@ -24,8 +24,8 @@ class IJitEnvironment final : public ServiceFramework<IJitEnvironment> {
24public: 24public:
25 explicit IJitEnvironment(Core::System& system_, Kernel::KProcess& process_, CodeRange user_rx, 25 explicit IJitEnvironment(Core::System& system_, Kernel::KProcess& process_, CodeRange user_rx,
26 CodeRange user_ro) 26 CodeRange user_ro)
27 : ServiceFramework{system_, "IJitEnvironment"}, process{&process_}, context{ 27 : ServiceFramework{system_, "IJitEnvironment"}, process{&process_},
28 system_.Memory()} { 28 context{system_.ApplicationMemory()} {
29 // clang-format off 29 // clang-format off
30 static const FunctionInfo functions[] = { 30 static const FunctionInfo functions[] = {
31 {0, &IJitEnvironment::GenerateCode, "GenerateCode"}, 31 {0, &IJitEnvironment::GenerateCode, "GenerateCode"},
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index 437dc2ea5..c42489ff9 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -225,7 +225,7 @@ public:
225 225
226 // Read NRR data from memory 226 // Read NRR data from memory
227 std::vector<u8> nrr_data(nrr_size); 227 std::vector<u8> nrr_data(nrr_size);
228 system.Memory().ReadBlock(nrr_address, nrr_data.data(), nrr_size); 228 system.ApplicationMemory().ReadBlock(nrr_address, nrr_data.data(), nrr_size);
229 NRRHeader header; 229 NRRHeader header;
230 std::memcpy(&header, nrr_data.data(), sizeof(NRRHeader)); 230 std::memcpy(&header, nrr_data.data(), sizeof(NRRHeader));
231 231
@@ -314,7 +314,7 @@ public:
314 const auto is_region_available = [&](VAddr addr) { 314 const auto is_region_available = [&](VAddr addr) {
315 const auto end_addr = addr + size; 315 const auto end_addr = addr + size;
316 while (addr < end_addr) { 316 while (addr < end_addr) {
317 if (system.Memory().IsValidVirtualAddress(addr)) { 317 if (system.ApplicationMemory().IsValidVirtualAddress(addr)) {
318 return false; 318 return false;
319 } 319 }
320 320
@@ -427,8 +427,8 @@ public:
427 const VAddr bss_end_addr{ 427 const VAddr bss_end_addr{
428 Common::AlignUp(bss_start + nro_header.bss_size, Kernel::PageSize)}; 428 Common::AlignUp(bss_start + nro_header.bss_size, Kernel::PageSize)};
429 429
430 const auto CopyCode = [this, process](VAddr src_addr, VAddr dst_addr, u64 size) { 430 const auto CopyCode = [this](VAddr src_addr, VAddr dst_addr, u64 size) {
431 system.Memory().CopyBlock(*process, dst_addr, src_addr, size); 431 system.ApplicationMemory().CopyBlock(dst_addr, src_addr, size);
432 }; 432 };
433 CopyCode(nro_addr + nro_header.segment_headers[TEXT_INDEX].memory_offset, text_start, 433 CopyCode(nro_addr + nro_header.segment_headers[TEXT_INDEX].memory_offset, text_start,
434 nro_header.segment_headers[TEXT_INDEX].memory_size); 434 nro_header.segment_headers[TEXT_INDEX].memory_size);
@@ -506,7 +506,7 @@ public:
506 506
507 // Read NRO data from memory 507 // Read NRO data from memory
508 std::vector<u8> nro_data(nro_size); 508 std::vector<u8> nro_data(nro_size);
509 system.Memory().ReadBlock(nro_address, nro_data.data(), nro_size); 509 system.ApplicationMemory().ReadBlock(nro_address, nro_data.data(), nro_size);
510 510
511 SHA256Hash hash{}; 511 SHA256Hash hash{};
512 mbedtls_sha256_ret(nro_data.data(), nro_data.size(), hash.data(), 0); 512 mbedtls_sha256_ret(nro_data.data(), nro_data.size(), hash.data(), 0);
diff --git a/src/core/hle/service/nfp/amiibo_crypto.cpp b/src/core/hle/service/nfp/amiibo_crypto.cpp
index bba862fb2..a3622e792 100644
--- a/src/core/hle/service/nfp/amiibo_crypto.cpp
+++ b/src/core/hle/service/nfp/amiibo_crypto.cpp
@@ -70,6 +70,10 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) {
70 return true; 70 return true;
71} 71}
72 72
73bool IsAmiiboValid(const NTAG215File& ntag_file) {
74 return IsAmiiboValid(EncodedDataToNfcData(ntag_file));
75}
76
73NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) { 77NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) {
74 NTAG215File encoded_data{}; 78 NTAG215File encoded_data{};
75 79
diff --git a/src/core/hle/service/nfp/amiibo_crypto.h b/src/core/hle/service/nfp/amiibo_crypto.h
index c9fd67a39..f6208ee6b 100644
--- a/src/core/hle/service/nfp/amiibo_crypto.h
+++ b/src/core/hle/service/nfp/amiibo_crypto.h
@@ -60,6 +60,9 @@ static_assert(sizeof(DerivedKeys) == 0x30, "DerivedKeys is an invalid size");
60/// Validates that the amiibo file is not corrupted 60/// Validates that the amiibo file is not corrupted
61bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file); 61bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file);
62 62
63/// Validates that the amiibo file is not corrupted
64bool IsAmiiboValid(const NTAG215File& ntag_file);
65
63/// Converts from encrypted file format to encoded file format 66/// Converts from encrypted file format to encoded file format
64NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data); 67NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data);
65 68
diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp
index 5990e1473..607e70968 100644
--- a/src/core/hle/service/nfp/nfp_device.cpp
+++ b/src/core/hle/service/nfp/nfp_device.cpp
@@ -121,7 +121,16 @@ bool NfpDevice::LoadAmiibo(std::span<const u8> data) {
121 121
122 // TODO: Filter by allowed_protocols here 122 // TODO: Filter by allowed_protocols here
123 123
124 memcpy(&encrypted_tag_data, data.data(), sizeof(EncryptedNTAG215File)); 124 memcpy(&tag_data, data.data(), sizeof(EncryptedNTAG215File));
125 is_plain_amiibo = AmiiboCrypto::IsAmiiboValid(tag_data);
126
127 if (is_plain_amiibo) {
128 encrypted_tag_data = AmiiboCrypto::EncodedDataToNfcData(tag_data);
129 LOG_INFO(Service_NFP, "Using plain amiibo");
130 } else {
131 tag_data = {};
132 memcpy(&encrypted_tag_data, data.data(), sizeof(EncryptedNTAG215File));
133 }
125 134
126 device_state = DeviceState::TagFound; 135 device_state = DeviceState::TagFound;
127 deactivate_event->GetReadableEvent().Clear(); 136 deactivate_event->GetReadableEvent().Clear();
@@ -232,13 +241,17 @@ Result NfpDevice::Flush() {
232 241
233 tag_data.write_counter++; 242 tag_data.write_counter++;
234 243
235 if (!AmiiboCrypto::EncodeAmiibo(tag_data, encrypted_tag_data)) { 244 std::vector<u8> data(sizeof(EncryptedNTAG215File));
236 LOG_ERROR(Service_NFP, "Failed to encode data"); 245 if (is_plain_amiibo) {
237 return WriteAmiiboFailed; 246 memcpy(data.data(), &tag_data, sizeof(tag_data));
238 } 247 } else {
248 if (!AmiiboCrypto::EncodeAmiibo(tag_data, encrypted_tag_data)) {
249 LOG_ERROR(Service_NFP, "Failed to encode data");
250 return WriteAmiiboFailed;
251 }
239 252
240 std::vector<u8> data(sizeof(encrypted_tag_data)); 253 memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data));
241 memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data)); 254 }
242 255
243 if (!npad_device->WriteNfc(data)) { 256 if (!npad_device->WriteNfc(data)) {
244 LOG_ERROR(Service_NFP, "Error writing to file"); 257 LOG_ERROR(Service_NFP, "Error writing to file");
@@ -256,6 +269,13 @@ Result NfpDevice::Mount(MountTarget mount_target_) {
256 return WrongDeviceState; 269 return WrongDeviceState;
257 } 270 }
258 271
272 // The loaded amiibo is not encrypted
273 if (is_plain_amiibo) {
274 device_state = DeviceState::TagMounted;
275 mount_target = mount_target_;
276 return ResultSuccess;
277 }
278
259 if (!AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) { 279 if (!AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) {
260 LOG_ERROR(Service_NFP, "Not an amiibo"); 280 LOG_ERROR(Service_NFP, "Not an amiibo");
261 return NotAnAmiibo; 281 return NotAnAmiibo;
diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h
index 27122e86e..7f963730d 100644
--- a/src/core/hle/service/nfp/nfp_device.h
+++ b/src/core/hle/service/nfp/nfp_device.h
@@ -95,6 +95,7 @@ private:
95 bool is_initalized{}; 95 bool is_initalized{};
96 bool is_data_moddified{}; 96 bool is_data_moddified{};
97 bool is_app_area_open{}; 97 bool is_app_area_open{};
98 bool is_plain_amiibo{};
98 TagProtocol allowed_protocols{}; 99 TagProtocol allowed_protocols{};
99 s64 current_posix_time{}; 100 s64 current_posix_time{};
100 MountTarget mount_target{MountTarget::None}; 101 MountTarget mount_target{MountTarget::None};
diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h
index b3599a513..70c878552 100644
--- a/src/core/hle/service/nfp/nfp_types.h
+++ b/src/core/hle/service/nfp/nfp_types.h
@@ -309,7 +309,8 @@ struct EncryptedNTAG215File {
309 u32 CFG1; // Defines number of verification attempts 309 u32 CFG1; // Defines number of verification attempts
310 NTAG215Password password; // Password data 310 NTAG215Password password; // Password data
311}; 311};
312static_assert(sizeof(EncryptedNTAG215File) == 0x21C, "EncryptedNTAG215File is an invalid size"); 312static_assert(sizeof(EncryptedNTAG215File) == sizeof(NTAG215File),
313 "EncryptedNTAG215File is an invalid size");
313static_assert(std::is_trivially_copyable_v<EncryptedNTAG215File>, 314static_assert(std::is_trivially_copyable_v<EncryptedNTAG215File>,
314 "EncryptedNTAG215File must be trivially copyable."); 315 "EncryptedNTAG215File must be trivially copyable.");
315 316
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index d2308fffc..453a965dc 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -304,8 +304,8 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8>
304 Tegra::CommandList entries(params.num_entries); 304 Tegra::CommandList entries(params.num_entries);
305 305
306 if (kickoff) { 306 if (kickoff) {
307 system.Memory().ReadBlock(params.address, entries.command_lists.data(), 307 system.ApplicationMemory().ReadBlock(params.address, entries.command_lists.data(),
308 params.num_entries * sizeof(Tegra::CommandListHeader)); 308 params.num_entries * sizeof(Tegra::CommandListHeader));
309 } else { 309 } else {
310 std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)], 310 std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)],
311 params.num_entries * sizeof(Tegra::CommandListHeader)); 311 params.num_entries * sizeof(Tegra::CommandListHeader));
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
index 7bcef105b..1ab51f10b 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
@@ -105,8 +105,8 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input,
105 const auto object = nvmap.GetHandle(cmd_buffer.memory_id); 105 const auto object = nvmap.GetHandle(cmd_buffer.memory_id);
106 ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;); 106 ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;);
107 Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); 107 Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count);
108 system.Memory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(), 108 system.ApplicationMemory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(),
109 cmdlist.size() * sizeof(u32)); 109 cmdlist.size() * sizeof(u32));
110 gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist); 110 gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist);
111 } 111 }
112 std::memcpy(output.data(), &params, sizeof(IoctlSubmit)); 112 std::memcpy(output.data(), &params, sizeof(IoctlSubmit));
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 95e070825..432310632 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -832,11 +832,6 @@ std::string Memory::ReadCString(Common::ProcessAddress vaddr, std::size_t max_le
832 return impl->ReadCString(vaddr, max_length); 832 return impl->ReadCString(vaddr, max_length);
833} 833}
834 834
835void Memory::ReadBlock(const Kernel::KProcess& process, const Common::ProcessAddress src_addr,
836 void* dest_buffer, const std::size_t size) {
837 impl->ReadBlockImpl<false>(process, src_addr, dest_buffer, size);
838}
839
840void Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer, 835void Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer,
841 const std::size_t size) { 836 const std::size_t size) {
842 impl->ReadBlock(src_addr, dest_buffer, size); 837 impl->ReadBlock(src_addr, dest_buffer, size);
@@ -847,11 +842,6 @@ void Memory::ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_b
847 impl->ReadBlockUnsafe(src_addr, dest_buffer, size); 842 impl->ReadBlockUnsafe(src_addr, dest_buffer, size);
848} 843}
849 844
850void Memory::WriteBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
851 const void* src_buffer, std::size_t size) {
852 impl->WriteBlockImpl<false>(process, dest_addr, src_buffer, size);
853}
854
855void Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer, 845void Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer,
856 const std::size_t size) { 846 const std::size_t size) {
857 impl->WriteBlock(dest_addr, src_buffer, size); 847 impl->WriteBlock(dest_addr, src_buffer, size);
@@ -862,29 +852,25 @@ void Memory::WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void
862 impl->WriteBlockUnsafe(dest_addr, src_buffer, size); 852 impl->WriteBlockUnsafe(dest_addr, src_buffer, size);
863} 853}
864 854
865void Memory::CopyBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, 855void Memory::CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
866 Common::ProcessAddress src_addr, const std::size_t size) { 856 const std::size_t size) {
867 impl->CopyBlock(process, dest_addr, src_addr, size); 857 impl->CopyBlock(*system.ApplicationProcess(), dest_addr, src_addr, size);
868} 858}
869 859
870void Memory::ZeroBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, 860void Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size) {
871 const std::size_t size) { 861 impl->ZeroBlock(*system.ApplicationProcess(), dest_addr, size);
872 impl->ZeroBlock(process, dest_addr, size);
873} 862}
874 863
875Result Memory::InvalidateDataCache(const Kernel::KProcess& process, 864Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
876 Common::ProcessAddress dest_addr, const std::size_t size) { 865 return impl->InvalidateDataCache(*system.ApplicationProcess(), dest_addr, size);
877 return impl->InvalidateDataCache(process, dest_addr, size);
878} 866}
879 867
880Result Memory::StoreDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, 868Result Memory::StoreDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
881 const std::size_t size) { 869 return impl->StoreDataCache(*system.ApplicationProcess(), dest_addr, size);
882 return impl->StoreDataCache(process, dest_addr, size);
883} 870}
884 871
885Result Memory::FlushDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, 872Result Memory::FlushDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
886 const std::size_t size) { 873 return impl->FlushDataCache(*system.ApplicationProcess(), dest_addr, size);
887 return impl->FlushDataCache(process, dest_addr, size);
888} 874}
889 875
890void Memory::RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached) { 876void Memory::RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached) {
diff --git a/src/core/memory.h b/src/core/memory.h
index ed4e87739..72a0be813 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -305,26 +305,6 @@ public:
305 std::string ReadCString(Common::ProcessAddress vaddr, std::size_t max_length); 305 std::string ReadCString(Common::ProcessAddress vaddr, std::size_t max_length);
306 306
307 /** 307 /**
308 * Reads a contiguous block of bytes from a specified process' address space.
309 *
310 * @param process The process to read the data from.
311 * @param src_addr The virtual address to begin reading from.
312 * @param dest_buffer The buffer to place the read bytes into.
313 * @param size The amount of data to read, in bytes.
314 *
315 * @note If a size of 0 is specified, then this function reads nothing and
316 * no attempts to access memory are made at all.
317 *
318 * @pre dest_buffer must be at least size bytes in length, otherwise a
319 * buffer overrun will occur.
320 *
321 * @post The range [dest_buffer, size) contains the read bytes from the
322 * process' address space.
323 */
324 void ReadBlock(const Kernel::KProcess& process, Common::ProcessAddress src_addr,
325 void* dest_buffer, std::size_t size);
326
327 /**
328 * Reads a contiguous block of bytes from the current process' address space. 308 * Reads a contiguous block of bytes from the current process' address space.
329 * 309 *
330 * @param src_addr The virtual address to begin reading from. 310 * @param src_addr The virtual address to begin reading from.
@@ -362,29 +342,6 @@ public:
362 void ReadBlockUnsafe(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size); 342 void ReadBlockUnsafe(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size);
363 343
364 /** 344 /**
365 * Writes a range of bytes into a given process' address space at the specified
366 * virtual address.
367 *
368 * @param process The process to write data into the address space of.
369 * @param dest_addr The destination virtual address to begin writing the data at.
370 * @param src_buffer The data to write into the process' address space.
371 * @param size The size of the data to write, in bytes.
372 *
373 * @post The address range [dest_addr, size) in the process' address space
374 * contains the data that was within src_buffer.
375 *
376 * @post If an attempt is made to write into an unmapped region of memory, the writes
377 * will be ignored and an error will be logged.
378 *
379 * @post If a write is performed into a region of memory that is considered cached
380 * rasterizer memory, will cause the currently active rasterizer to be notified
381 * and will mark that region as invalidated to caches that the active
382 * graphics backend may be maintaining over the course of execution.
383 */
384 void WriteBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
385 const void* src_buffer, std::size_t size);
386
387 /**
388 * Writes a range of bytes into the current process' address space at the specified 345 * Writes a range of bytes into the current process' address space at the specified
389 * virtual address. 346 * virtual address.
390 * 347 *
@@ -428,7 +385,6 @@ public:
428 * Copies data within a process' address space to another location within the 385 * Copies data within a process' address space to another location within the
429 * same address space. 386 * same address space.
430 * 387 *
431 * @param process The process that will have data copied within its address space.
432 * @param dest_addr The destination virtual address to begin copying the data into. 388 * @param dest_addr The destination virtual address to begin copying the data into.
433 * @param src_addr The source virtual address to begin copying the data from. 389 * @param src_addr The source virtual address to begin copying the data from.
434 * @param size The size of the data to copy, in bytes. 390 * @param size The size of the data to copy, in bytes.
@@ -436,58 +392,50 @@ public:
436 * @post The range [dest_addr, size) within the process' address space contains the 392 * @post The range [dest_addr, size) within the process' address space contains the
437 * same data within the range [src_addr, size). 393 * same data within the range [src_addr, size).
438 */ 394 */
439 void CopyBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, 395 void CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
440 Common::ProcessAddress src_addr, std::size_t size); 396 std::size_t size);
441 397
442 /** 398 /**
443 * Zeros a range of bytes within the current process' address space at the specified 399 * Zeros a range of bytes within the current process' address space at the specified
444 * virtual address. 400 * virtual address.
445 * 401 *
446 * @param process The process that will have data zeroed within its address space.
447 * @param dest_addr The destination virtual address to zero the data from. 402 * @param dest_addr The destination virtual address to zero the data from.
448 * @param size The size of the range to zero out, in bytes. 403 * @param size The size of the range to zero out, in bytes.
449 * 404 *
450 * @post The range [dest_addr, size) within the process' address space contains the 405 * @post The range [dest_addr, size) within the process' address space contains the
451 * value 0. 406 * value 0.
452 */ 407 */
453 void ZeroBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, 408 void ZeroBlock(Common::ProcessAddress dest_addr, std::size_t size);
454 std::size_t size);
455 409
456 /** 410 /**
457 * Invalidates a range of bytes within the current process' address space at the specified 411 * Invalidates a range of bytes within the current process' address space at the specified
458 * virtual address. 412 * virtual address.
459 * 413 *
460 * @param process The process that will have data invalidated within its address space.
461 * @param dest_addr The destination virtual address to invalidate the data from. 414 * @param dest_addr The destination virtual address to invalidate the data from.
462 * @param size The size of the range to invalidate, in bytes. 415 * @param size The size of the range to invalidate, in bytes.
463 * 416 *
464 */ 417 */
465 Result InvalidateDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, 418 Result InvalidateDataCache(Common::ProcessAddress dest_addr, std::size_t size);
466 std::size_t size);
467 419
468 /** 420 /**
469 * Stores a range of bytes within the current process' address space at the specified 421 * Stores a range of bytes within the current process' address space at the specified
470 * virtual address. 422 * virtual address.
471 * 423 *
472 * @param process The process that will have data stored within its address space.
473 * @param dest_addr The destination virtual address to store the data from. 424 * @param dest_addr The destination virtual address to store the data from.
474 * @param size The size of the range to store, in bytes. 425 * @param size The size of the range to store, in bytes.
475 * 426 *
476 */ 427 */
477 Result StoreDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, 428 Result StoreDataCache(Common::ProcessAddress dest_addr, std::size_t size);
478 std::size_t size);
479 429
480 /** 430 /**
481 * Flushes a range of bytes within the current process' address space at the specified 431 * Flushes a range of bytes within the current process' address space at the specified
482 * virtual address. 432 * virtual address.
483 * 433 *
484 * @param process The process that will have data flushed within its address space.
485 * @param dest_addr The destination virtual address to flush the data from. 434 * @param dest_addr The destination virtual address to flush the data from.
486 * @param size The size of the range to flush, in bytes. 435 * @param size The size of the range to flush, in bytes.
487 * 436 *
488 */ 437 */
489 Result FlushDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, 438 Result FlushDataCache(Common::ProcessAddress dest_addr, std::size_t size);
490 std::size_t size);
491 439
492 /** 440 /**
493 * Marks each page within the specified address range as cached or uncached. 441 * Marks each page within the specified address range as cached or uncached.
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index d1284a3a7..8742dd164 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -39,11 +39,11 @@ StandardVmCallbacks::StandardVmCallbacks(System& system_, const CheatProcessMeta
39StandardVmCallbacks::~StandardVmCallbacks() = default; 39StandardVmCallbacks::~StandardVmCallbacks() = default;
40 40
41void StandardVmCallbacks::MemoryRead(VAddr address, void* data, u64 size) { 41void StandardVmCallbacks::MemoryRead(VAddr address, void* data, u64 size) {
42 system.Memory().ReadBlock(SanitizeAddress(address), data, size); 42 system.ApplicationMemory().ReadBlock(SanitizeAddress(address), data, size);
43} 43}
44 44
45void StandardVmCallbacks::MemoryWrite(VAddr address, const void* data, u64 size) { 45void StandardVmCallbacks::MemoryWrite(VAddr address, const void* data, u64 size) {
46 system.Memory().WriteBlock(SanitizeAddress(address), data, size); 46 system.ApplicationMemory().WriteBlock(SanitizeAddress(address), data, size);
47} 47}
48 48
49u64 StandardVmCallbacks::HidKeysDown() { 49u64 StandardVmCallbacks::HidKeysDown() {
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp
index 146c3f21e..6c3dc7369 100644
--- a/src/core/reporter.cpp
+++ b/src/core/reporter.cpp
@@ -264,7 +264,7 @@ void Reporter::SaveUnimplementedFunctionReport(Service::HLERequestContext& ctx,
264 const auto title_id = system.GetApplicationProcessProgramID(); 264 const auto title_id = system.GetApplicationProcessProgramID();
265 auto out = GetFullDataAuto(timestamp, title_id, system); 265 auto out = GetFullDataAuto(timestamp, title_id, system);
266 266
267 auto function_out = GetHLERequestContextData(ctx, system.Memory()); 267 auto function_out = GetHLERequestContextData(ctx, system.ApplicationMemory());
268 function_out["command_id"] = command_id; 268 function_out["command_id"] = command_id;
269 function_out["function_name"] = name; 269 function_out["function_name"] = name;
270 function_out["service_name"] = service_name; 270 function_out["service_name"] = service_name;
diff --git a/src/tests/common/range_map.cpp b/src/tests/common/range_map.cpp
index d301ac5f6..faaefd49f 100644
--- a/src/tests/common/range_map.cpp
+++ b/src/tests/common/range_map.cpp
@@ -21,9 +21,9 @@ TEST_CASE("Range Map: Setup", "[video_core]") {
21 my_map.Map(4000, 4500, MappedEnum::Valid_2); 21 my_map.Map(4000, 4500, MappedEnum::Valid_2);
22 my_map.Map(4200, 4400, MappedEnum::Valid_2); 22 my_map.Map(4200, 4400, MappedEnum::Valid_2);
23 my_map.Map(4200, 4400, MappedEnum::Valid_1); 23 my_map.Map(4200, 4400, MappedEnum::Valid_1);
24 REQUIRE(my_map.GetContinousSizeFrom(4200) == 200); 24 REQUIRE(my_map.GetContinuousSizeFrom(4200) == 200);
25 REQUIRE(my_map.GetContinousSizeFrom(3000) == 200); 25 REQUIRE(my_map.GetContinuousSizeFrom(3000) == 200);
26 REQUIRE(my_map.GetContinousSizeFrom(2900) == 0); 26 REQUIRE(my_map.GetContinuousSizeFrom(2900) == 0);
27 27
28 REQUIRE(my_map.GetValueAt(2900) == MappedEnum::Invalid); 28 REQUIRE(my_map.GetValueAt(2900) == MappedEnum::Invalid);
29 REQUIRE(my_map.GetValueAt(3100) == MappedEnum::Valid_1); 29 REQUIRE(my_map.GetValueAt(3100) == MappedEnum::Valid_1);
@@ -38,20 +38,20 @@ TEST_CASE("Range Map: Setup", "[video_core]") {
38 38
39 my_map.Unmap(0, 6000); 39 my_map.Unmap(0, 6000);
40 for (u64 address = 0; address < 10000; address += 1000) { 40 for (u64 address = 0; address < 10000; address += 1000) {
41 REQUIRE(my_map.GetContinousSizeFrom(address) == 0); 41 REQUIRE(my_map.GetContinuousSizeFrom(address) == 0);
42 } 42 }
43 43
44 my_map.Map(1000, 3000, MappedEnum::Valid_1); 44 my_map.Map(1000, 3000, MappedEnum::Valid_1);
45 my_map.Map(4000, 5000, MappedEnum::Valid_1); 45 my_map.Map(4000, 5000, MappedEnum::Valid_1);
46 my_map.Map(2500, 4100, MappedEnum::Valid_1); 46 my_map.Map(2500, 4100, MappedEnum::Valid_1);
47 REQUIRE(my_map.GetContinousSizeFrom(1000) == 4000); 47 REQUIRE(my_map.GetContinuousSizeFrom(1000) == 4000);
48 48
49 my_map.Map(1000, 3000, MappedEnum::Valid_1); 49 my_map.Map(1000, 3000, MappedEnum::Valid_1);
50 my_map.Map(4000, 5000, MappedEnum::Valid_2); 50 my_map.Map(4000, 5000, MappedEnum::Valid_2);
51 my_map.Map(2500, 4100, MappedEnum::Valid_3); 51 my_map.Map(2500, 4100, MappedEnum::Valid_3);
52 REQUIRE(my_map.GetContinousSizeFrom(1000) == 1500); 52 REQUIRE(my_map.GetContinuousSizeFrom(1000) == 1500);
53 REQUIRE(my_map.GetContinousSizeFrom(2500) == 1600); 53 REQUIRE(my_map.GetContinuousSizeFrom(2500) == 1600);
54 REQUIRE(my_map.GetContinousSizeFrom(4100) == 900); 54 REQUIRE(my_map.GetContinuousSizeFrom(4100) == 900);
55 REQUIRE(my_map.GetValueAt(900) == MappedEnum::Invalid); 55 REQUIRE(my_map.GetValueAt(900) == MappedEnum::Invalid);
56 REQUIRE(my_map.GetValueAt(1000) == MappedEnum::Valid_1); 56 REQUIRE(my_map.GetValueAt(1000) == MappedEnum::Valid_1);
57 REQUIRE(my_map.GetValueAt(2500) == MappedEnum::Valid_3); 57 REQUIRE(my_map.GetValueAt(2500) == MappedEnum::Valid_3);
@@ -59,8 +59,8 @@ TEST_CASE("Range Map: Setup", "[video_core]") {
59 REQUIRE(my_map.GetValueAt(5000) == MappedEnum::Invalid); 59 REQUIRE(my_map.GetValueAt(5000) == MappedEnum::Invalid);
60 60
61 my_map.Map(2000, 6000, MappedEnum::Valid_3); 61 my_map.Map(2000, 6000, MappedEnum::Valid_3);
62 REQUIRE(my_map.GetContinousSizeFrom(1000) == 1000); 62 REQUIRE(my_map.GetContinuousSizeFrom(1000) == 1000);
63 REQUIRE(my_map.GetContinousSizeFrom(3000) == 3000); 63 REQUIRE(my_map.GetContinuousSizeFrom(3000) == 3000);
64 REQUIRE(my_map.GetValueAt(1000) == MappedEnum::Valid_1); 64 REQUIRE(my_map.GetValueAt(1000) == MappedEnum::Valid_1);
65 REQUIRE(my_map.GetValueAt(1999) == MappedEnum::Valid_1); 65 REQUIRE(my_map.GetValueAt(1999) == MappedEnum::Valid_1);
66 REQUIRE(my_map.GetValueAt(1500) == MappedEnum::Valid_1); 66 REQUIRE(my_map.GetValueAt(1500) == MappedEnum::Valid_1);
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 1f656ffa8..abdc593df 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -1442,7 +1442,7 @@ void BufferCache<P>::UpdateVertexBuffer(u32 index) {
1442 } 1442 }
1443 if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end)) { 1443 if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end)) {
1444 address_size = 1444 address_size =
1445 static_cast<u32>(gpu_memory->MaxContinousRange(gpu_addr_begin, address_size)); 1445 static_cast<u32>(gpu_memory->MaxContinuousRange(gpu_addr_begin, address_size));
1446 } 1446 }
1447 const u32 size = address_size; // TODO: Analyze stride and number of vertices 1447 const u32 size = address_size; // TODO: Analyze stride and number of vertices
1448 vertex_buffers[index] = Binding{ 1448 vertex_buffers[index] = Binding{
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index 83924475b..01fb5b546 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -22,7 +22,7 @@ std::atomic<size_t> MemoryManager::unique_identifier_generator{};
22 22
23MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64 big_page_bits_, 23MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64 big_page_bits_,
24 u64 page_bits_) 24 u64 page_bits_)
25 : system{system_}, memory{system.Memory()}, device_memory{system.DeviceMemory()}, 25 : system{system_}, memory{system.ApplicationMemory()}, device_memory{system.DeviceMemory()},
26 address_space_bits{address_space_bits_}, page_bits{page_bits_}, big_page_bits{big_page_bits_}, 26 address_space_bits{address_space_bits_}, page_bits{page_bits_}, big_page_bits{big_page_bits_},
27 entries{}, big_entries{}, page_table{address_space_bits, address_space_bits + page_bits - 38, 27 entries{}, big_entries{}, page_table{address_space_bits, address_space_bits + page_bits - 38,
28 page_bits != big_page_bits ? page_bits : 0}, 28 page_bits != big_page_bits ? page_bits : 0},
@@ -43,7 +43,7 @@ MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64
43 43
44 big_entries.resize(big_page_table_size / 32, 0); 44 big_entries.resize(big_page_table_size / 32, 0);
45 big_page_table_cpu.resize(big_page_table_size); 45 big_page_table_cpu.resize(big_page_table_size);
46 big_page_continous.resize(big_page_table_size / continous_bits, 0); 46 big_page_continuous.resize(big_page_table_size / continuous_bits, 0);
47 entries.resize(page_table_size / 32, 0); 47 entries.resize(page_table_size / 32, 0);
48} 48}
49 49
@@ -85,17 +85,17 @@ PTEKind MemoryManager::GetPageKind(GPUVAddr gpu_addr) const {
85 return kind_map.GetValueAt(gpu_addr); 85 return kind_map.GetValueAt(gpu_addr);
86} 86}
87 87
88inline bool MemoryManager::IsBigPageContinous(size_t big_page_index) const { 88inline bool MemoryManager::IsBigPageContinuous(size_t big_page_index) const {
89 const u64 entry_mask = big_page_continous[big_page_index / continous_bits]; 89 const u64 entry_mask = big_page_continuous[big_page_index / continuous_bits];
90 const size_t sub_index = big_page_index % continous_bits; 90 const size_t sub_index = big_page_index % continuous_bits;
91 return ((entry_mask >> sub_index) & 0x1ULL) != 0; 91 return ((entry_mask >> sub_index) & 0x1ULL) != 0;
92} 92}
93 93
94inline void MemoryManager::SetBigPageContinous(size_t big_page_index, bool value) { 94inline void MemoryManager::SetBigPageContinuous(size_t big_page_index, bool value) {
95 const u64 continous_mask = big_page_continous[big_page_index / continous_bits]; 95 const u64 continuous_mask = big_page_continuous[big_page_index / continuous_bits];
96 const size_t sub_index = big_page_index % continous_bits; 96 const size_t sub_index = big_page_index % continuous_bits;
97 big_page_continous[big_page_index / continous_bits] = 97 big_page_continuous[big_page_index / continuous_bits] =
98 (~(1ULL << sub_index) & continous_mask) | (value ? 1ULL << sub_index : 0); 98 (~(1ULL << sub_index) & continuous_mask) | (value ? 1ULL << sub_index : 0);
99} 99}
100 100
101template <MemoryManager::EntryType entry_type> 101template <MemoryManager::EntryType entry_type>
@@ -140,7 +140,7 @@ GPUVAddr MemoryManager::BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr
140 const auto index = PageEntryIndex<true>(current_gpu_addr); 140 const auto index = PageEntryIndex<true>(current_gpu_addr);
141 const u32 sub_value = static_cast<u32>(current_cpu_addr >> cpu_page_bits); 141 const u32 sub_value = static_cast<u32>(current_cpu_addr >> cpu_page_bits);
142 big_page_table_cpu[index] = sub_value; 142 big_page_table_cpu[index] = sub_value;
143 const bool is_continous = ([&] { 143 const bool is_continuous = ([&] {
144 uintptr_t base_ptr{ 144 uintptr_t base_ptr{
145 reinterpret_cast<uintptr_t>(memory.GetPointerSilent(current_cpu_addr))}; 145 reinterpret_cast<uintptr_t>(memory.GetPointerSilent(current_cpu_addr))};
146 if (base_ptr == 0) { 146 if (base_ptr == 0) {
@@ -156,7 +156,7 @@ GPUVAddr MemoryManager::BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr
156 } 156 }
157 return true; 157 return true;
158 })(); 158 })();
159 SetBigPageContinous(index, is_continous); 159 SetBigPageContinuous(index, is_continuous);
160 } 160 }
161 remaining_size -= big_page_size; 161 remaining_size -= big_page_size;
162 } 162 }
@@ -378,7 +378,7 @@ void MemoryManager::ReadBlockImpl(GPUVAddr gpu_src_addr, void* dest_buffer, std:
378 if constexpr (is_safe) { 378 if constexpr (is_safe) {
379 rasterizer->FlushRegion(cpu_addr_base, copy_amount, which); 379 rasterizer->FlushRegion(cpu_addr_base, copy_amount, which);
380 } 380 }
381 if (!IsBigPageContinous(page_index)) [[unlikely]] { 381 if (!IsBigPageContinuous(page_index)) [[unlikely]] {
382 memory.ReadBlockUnsafe(cpu_addr_base, dest_buffer, copy_amount); 382 memory.ReadBlockUnsafe(cpu_addr_base, dest_buffer, copy_amount);
383 } else { 383 } else {
384 u8* physical = memory.GetPointer(cpu_addr_base); 384 u8* physical = memory.GetPointer(cpu_addr_base);
@@ -427,7 +427,7 @@ void MemoryManager::WriteBlockImpl(GPUVAddr gpu_dest_addr, const void* src_buffe
427 if constexpr (is_safe) { 427 if constexpr (is_safe) {
428 rasterizer->InvalidateRegion(cpu_addr_base, copy_amount, which); 428 rasterizer->InvalidateRegion(cpu_addr_base, copy_amount, which);
429 } 429 }
430 if (!IsBigPageContinous(page_index)) [[unlikely]] { 430 if (!IsBigPageContinuous(page_index)) [[unlikely]] {
431 memory.WriteBlockUnsafe(cpu_addr_base, src_buffer, copy_amount); 431 memory.WriteBlockUnsafe(cpu_addr_base, src_buffer, copy_amount);
432 } else { 432 } else {
433 u8* physical = memory.GetPointer(cpu_addr_base); 433 u8* physical = memory.GetPointer(cpu_addr_base);
@@ -512,7 +512,7 @@ bool MemoryManager::IsMemoryDirty(GPUVAddr gpu_addr, size_t size,
512 return result; 512 return result;
513} 513}
514 514
515size_t MemoryManager::MaxContinousRange(GPUVAddr gpu_addr, size_t size) const { 515size_t MemoryManager::MaxContinuousRange(GPUVAddr gpu_addr, size_t size) const {
516 std::optional<VAddr> old_page_addr{}; 516 std::optional<VAddr> old_page_addr{};
517 size_t range_so_far = 0; 517 size_t range_so_far = 0;
518 bool result{false}; 518 bool result{false};
@@ -553,7 +553,7 @@ size_t MemoryManager::MaxContinousRange(GPUVAddr gpu_addr, size_t size) const {
553} 553}
554 554
555size_t MemoryManager::GetMemoryLayoutSize(GPUVAddr gpu_addr, size_t max_size) const { 555size_t MemoryManager::GetMemoryLayoutSize(GPUVAddr gpu_addr, size_t max_size) const {
556 return kind_map.GetContinousSizeFrom(gpu_addr); 556 return kind_map.GetContinuousSizeFrom(gpu_addr);
557} 557}
558 558
559void MemoryManager::InvalidateRegion(GPUVAddr gpu_addr, size_t size, 559void MemoryManager::InvalidateRegion(GPUVAddr gpu_addr, size_t size,
@@ -594,7 +594,7 @@ void MemoryManager::CopyBlock(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr, std
594bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const { 594bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const {
595 if (GetEntry<true>(gpu_addr) == EntryType::Mapped) [[likely]] { 595 if (GetEntry<true>(gpu_addr) == EntryType::Mapped) [[likely]] {
596 size_t page_index = gpu_addr >> big_page_bits; 596 size_t page_index = gpu_addr >> big_page_bits;
597 if (IsBigPageContinous(page_index)) [[likely]] { 597 if (IsBigPageContinuous(page_index)) [[likely]] {
598 const std::size_t page{(page_index & big_page_mask) + size}; 598 const std::size_t page{(page_index & big_page_mask) + size};
599 return page <= big_page_size; 599 return page <= big_page_size;
600 } 600 }
@@ -608,7 +608,7 @@ bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const {
608 return page <= Core::Memory::YUZU_PAGESIZE; 608 return page <= Core::Memory::YUZU_PAGESIZE;
609} 609}
610 610
611bool MemoryManager::IsContinousRange(GPUVAddr gpu_addr, std::size_t size) const { 611bool MemoryManager::IsContinuousRange(GPUVAddr gpu_addr, std::size_t size) const {
612 std::optional<VAddr> old_page_addr{}; 612 std::optional<VAddr> old_page_addr{};
613 bool result{true}; 613 bool result{true};
614 auto fail = [&]([[maybe_unused]] std::size_t page_index, [[maybe_unused]] std::size_t offset, 614 auto fail = [&]([[maybe_unused]] std::size_t page_index, [[maybe_unused]] std::size_t offset,
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index 51ae2de68..fbbe856c4 100644
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -94,7 +94,7 @@ public:
94 /** 94 /**
95 * Checks if a gpu region is mapped by a single range of cpu addresses. 95 * Checks if a gpu region is mapped by a single range of cpu addresses.
96 */ 96 */
97 [[nodiscard]] bool IsContinousRange(GPUVAddr gpu_addr, std::size_t size) const; 97 [[nodiscard]] bool IsContinuousRange(GPUVAddr gpu_addr, std::size_t size) const;
98 98
99 /** 99 /**
100 * Checks if a gpu region is mapped entirely. 100 * Checks if a gpu region is mapped entirely.
@@ -123,7 +123,7 @@ public:
123 bool IsMemoryDirty(GPUVAddr gpu_addr, size_t size, 123 bool IsMemoryDirty(GPUVAddr gpu_addr, size_t size,
124 VideoCommon::CacheType which = VideoCommon::CacheType::All) const; 124 VideoCommon::CacheType which = VideoCommon::CacheType::All) const;
125 125
126 size_t MaxContinousRange(GPUVAddr gpu_addr, size_t size) const; 126 size_t MaxContinuousRange(GPUVAddr gpu_addr, size_t size) const;
127 127
128 bool IsWithinGPUAddressRange(GPUVAddr gpu_addr) const { 128 bool IsWithinGPUAddressRange(GPUVAddr gpu_addr) const {
129 return gpu_addr < address_space_size; 129 return gpu_addr < address_space_size;
@@ -158,8 +158,8 @@ private:
158 } 158 }
159 } 159 }
160 160
161 inline bool IsBigPageContinous(size_t big_page_index) const; 161 inline bool IsBigPageContinuous(size_t big_page_index) const;
162 inline void SetBigPageContinous(size_t big_page_index, bool value); 162 inline void SetBigPageContinuous(size_t big_page_index, bool value);
163 163
164 template <bool is_gpu_address> 164 template <bool is_gpu_address>
165 void GetSubmappedRangeImpl( 165 void GetSubmappedRangeImpl(
@@ -213,10 +213,10 @@ private:
213 Common::RangeMap<GPUVAddr, PTEKind> kind_map; 213 Common::RangeMap<GPUVAddr, PTEKind> kind_map;
214 Common::VirtualBuffer<u32> big_page_table_cpu; 214 Common::VirtualBuffer<u32> big_page_table_cpu;
215 215
216 std::vector<u64> big_page_continous; 216 std::vector<u64> big_page_continuous;
217 std::vector<std::pair<VAddr, std::size_t>> page_stash{}; 217 std::vector<std::pair<VAddr, std::size_t>> page_stash{};
218 218
219 static constexpr size_t continous_bits = 64; 219 static constexpr size_t continuous_bits = 64;
220 220
221 const size_t unique_identifier; 221 const size_t unique_identifier;
222 std::unique_ptr<VideoCommon::InvalidationAccumulator> accumulator; 222 std::unique_ptr<VideoCommon::InvalidationAccumulator> accumulator;
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 858449af8..63821d496 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -1269,7 +1269,7 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA
1269 const ImageId new_image_id = slot_images.insert(runtime, new_info, gpu_addr, cpu_addr); 1269 const ImageId new_image_id = slot_images.insert(runtime, new_info, gpu_addr, cpu_addr);
1270 Image& new_image = slot_images[new_image_id]; 1270 Image& new_image = slot_images[new_image_id];
1271 1271
1272 if (!gpu_memory->IsContinousRange(new_image.gpu_addr, new_image.guest_size_bytes)) { 1272 if (!gpu_memory->IsContinuousRange(new_image.gpu_addr, new_image.guest_size_bytes)) {
1273 new_image.flags |= ImageFlagBits::Sparse; 1273 new_image.flags |= ImageFlagBits::Sparse;
1274 } 1274 }
1275 1275
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index fedb4a7bb..b42d48416 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -18,7 +18,7 @@ std::unique_ptr<VideoCore::RendererBase> CreateRenderer(
18 Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu, 18 Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu,
19 std::unique_ptr<Core::Frontend::GraphicsContext> context) { 19 std::unique_ptr<Core::Frontend::GraphicsContext> context) {
20 auto& telemetry_session = system.TelemetrySession(); 20 auto& telemetry_session = system.TelemetrySession();
21 auto& cpu_memory = system.Memory(); 21 auto& cpu_memory = system.ApplicationMemory();
22 22
23 switch (Settings::values.renderer_backend.GetValue()) { 23 switch (Settings::values.renderer_backend.GetValue()) {
24 case Settings::RendererBackend::OpenGL: 24 case Settings::RendererBackend::OpenGL:
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp
index 486d4dfaf..336f53700 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.cpp
+++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp
@@ -375,6 +375,8 @@ const char* ToString(VkResult result) noexcept {
375 return "VK_RESULT_MAX_ENUM"; 375 return "VK_RESULT_MAX_ENUM";
376 case VkResult::VK_ERROR_COMPRESSION_EXHAUSTED_EXT: 376 case VkResult::VK_ERROR_COMPRESSION_EXHAUSTED_EXT:
377 return "VK_ERROR_COMPRESSION_EXHAUSTED_EXT"; 377 return "VK_ERROR_COMPRESSION_EXHAUSTED_EXT";
378 case VkResult::VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT:
379 return "VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT";
378 } 380 }
379 return "Unknown"; 381 return "Unknown";
380} 382}
diff --git a/src/yuzu/applets/qt_amiibo_settings.cpp b/src/yuzu/applets/qt_amiibo_settings.cpp
index 93ad4b4f9..4559df5b1 100644
--- a/src/yuzu/applets/qt_amiibo_settings.cpp
+++ b/src/yuzu/applets/qt_amiibo_settings.cpp
@@ -245,12 +245,19 @@ void QtAmiiboSettingsDialog::SetSettingsDescription() {
245QtAmiiboSettings::QtAmiiboSettings(GMainWindow& parent) { 245QtAmiiboSettings::QtAmiiboSettings(GMainWindow& parent) {
246 connect(this, &QtAmiiboSettings::MainWindowShowAmiiboSettings, &parent, 246 connect(this, &QtAmiiboSettings::MainWindowShowAmiiboSettings, &parent,
247 &GMainWindow::AmiiboSettingsShowDialog, Qt::QueuedConnection); 247 &GMainWindow::AmiiboSettingsShowDialog, Qt::QueuedConnection);
248 connect(this, &QtAmiiboSettings::MainWindowRequestExit, &parent,
249 &GMainWindow::AmiiboSettingsRequestExit, Qt::QueuedConnection);
248 connect(&parent, &GMainWindow::AmiiboSettingsFinished, this, 250 connect(&parent, &GMainWindow::AmiiboSettingsFinished, this,
249 &QtAmiiboSettings::MainWindowFinished, Qt::QueuedConnection); 251 &QtAmiiboSettings::MainWindowFinished, Qt::QueuedConnection);
250} 252}
251 253
252QtAmiiboSettings::~QtAmiiboSettings() = default; 254QtAmiiboSettings::~QtAmiiboSettings() = default;
253 255
256void QtAmiiboSettings::Close() const {
257 callback = {};
258 emit MainWindowRequestExit();
259}
260
254void QtAmiiboSettings::ShowCabinetApplet( 261void QtAmiiboSettings::ShowCabinetApplet(
255 const Core::Frontend::CabinetCallback& callback_, 262 const Core::Frontend::CabinetCallback& callback_,
256 const Core::Frontend::CabinetParameters& parameters, 263 const Core::Frontend::CabinetParameters& parameters,
@@ -260,5 +267,7 @@ void QtAmiiboSettings::ShowCabinetApplet(
260} 267}
261 268
262void QtAmiiboSettings::MainWindowFinished(bool is_success, const std::string& name) { 269void QtAmiiboSettings::MainWindowFinished(bool is_success, const std::string& name) {
263 callback(is_success, name); 270 if (callback) {
271 callback(is_success, name);
272 }
264} 273}
diff --git a/src/yuzu/applets/qt_amiibo_settings.h b/src/yuzu/applets/qt_amiibo_settings.h
index 930c96739..bc389a33f 100644
--- a/src/yuzu/applets/qt_amiibo_settings.h
+++ b/src/yuzu/applets/qt_amiibo_settings.h
@@ -68,6 +68,7 @@ public:
68 explicit QtAmiiboSettings(GMainWindow& parent); 68 explicit QtAmiiboSettings(GMainWindow& parent);
69 ~QtAmiiboSettings() override; 69 ~QtAmiiboSettings() override;
70 70
71 void Close() const override;
71 void ShowCabinetApplet(const Core::Frontend::CabinetCallback& callback_, 72 void ShowCabinetApplet(const Core::Frontend::CabinetCallback& callback_,
72 const Core::Frontend::CabinetParameters& parameters, 73 const Core::Frontend::CabinetParameters& parameters,
73 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const override; 74 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const override;
@@ -75,6 +76,7 @@ public:
75signals: 76signals:
76 void MainWindowShowAmiiboSettings(const Core::Frontend::CabinetParameters& parameters, 77 void MainWindowShowAmiiboSettings(const Core::Frontend::CabinetParameters& parameters,
77 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const; 78 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const;
79 void MainWindowRequestExit() const;
78 80
79private: 81private:
80 void MainWindowFinished(bool is_success, const std::string& name); 82 void MainWindowFinished(bool is_success, const std::string& name);
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index c30b54499..00aafb8f8 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -300,7 +300,7 @@ bool QtControllerSelectorDialog::CheckIfParametersMet() {
300 if (num_connected_players < min_supported_players || 300 if (num_connected_players < min_supported_players ||
301 num_connected_players > max_supported_players) { 301 num_connected_players > max_supported_players) {
302 parameters_met = false; 302 parameters_met = false;
303 ui->buttonBox->setEnabled(parameters_met); 303 ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(parameters_met);
304 return parameters_met; 304 return parameters_met;
305 } 305 }
306 306
@@ -327,7 +327,7 @@ bool QtControllerSelectorDialog::CheckIfParametersMet() {
327 }(); 327 }();
328 328
329 parameters_met = all_controllers_compatible; 329 parameters_met = all_controllers_compatible;
330 ui->buttonBox->setEnabled(parameters_met); 330 ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(parameters_met);
331 return parameters_met; 331 return parameters_met;
332} 332}
333 333
@@ -678,18 +678,27 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() {
678QtControllerSelector::QtControllerSelector(GMainWindow& parent) { 678QtControllerSelector::QtControllerSelector(GMainWindow& parent) {
679 connect(this, &QtControllerSelector::MainWindowReconfigureControllers, &parent, 679 connect(this, &QtControllerSelector::MainWindowReconfigureControllers, &parent,
680 &GMainWindow::ControllerSelectorReconfigureControllers, Qt::QueuedConnection); 680 &GMainWindow::ControllerSelectorReconfigureControllers, Qt::QueuedConnection);
681 connect(this, &QtControllerSelector::MainWindowRequestExit, &parent,
682 &GMainWindow::ControllerSelectorRequestExit, Qt::QueuedConnection);
681 connect(&parent, &GMainWindow::ControllerSelectorReconfigureFinished, this, 683 connect(&parent, &GMainWindow::ControllerSelectorReconfigureFinished, this,
682 &QtControllerSelector::MainWindowReconfigureFinished, Qt::QueuedConnection); 684 &QtControllerSelector::MainWindowReconfigureFinished, Qt::QueuedConnection);
683} 685}
684 686
685QtControllerSelector::~QtControllerSelector() = default; 687QtControllerSelector::~QtControllerSelector() = default;
686 688
689void QtControllerSelector::Close() const {
690 callback = {};
691 emit MainWindowRequestExit();
692}
693
687void QtControllerSelector::ReconfigureControllers( 694void QtControllerSelector::ReconfigureControllers(
688 ReconfigureCallback callback_, const Core::Frontend::ControllerParameters& parameters) const { 695 ReconfigureCallback callback_, const Core::Frontend::ControllerParameters& parameters) const {
689 callback = std::move(callback_); 696 callback = std::move(callback_);
690 emit MainWindowReconfigureControllers(parameters); 697 emit MainWindowReconfigureControllers(parameters);
691} 698}
692 699
693void QtControllerSelector::MainWindowReconfigureFinished() { 700void QtControllerSelector::MainWindowReconfigureFinished(bool is_success) {
694 callback(); 701 if (callback) {
702 callback(is_success);
703 }
695} 704}
diff --git a/src/yuzu/applets/qt_controller.h b/src/yuzu/applets/qt_controller.h
index 16e99f507..2fdc35857 100644
--- a/src/yuzu/applets/qt_controller.h
+++ b/src/yuzu/applets/qt_controller.h
@@ -156,6 +156,7 @@ public:
156 explicit QtControllerSelector(GMainWindow& parent); 156 explicit QtControllerSelector(GMainWindow& parent);
157 ~QtControllerSelector() override; 157 ~QtControllerSelector() override;
158 158
159 void Close() const override;
159 void ReconfigureControllers( 160 void ReconfigureControllers(
160 ReconfigureCallback callback_, 161 ReconfigureCallback callback_,
161 const Core::Frontend::ControllerParameters& parameters) const override; 162 const Core::Frontend::ControllerParameters& parameters) const override;
@@ -163,9 +164,10 @@ public:
163signals: 164signals:
164 void MainWindowReconfigureControllers( 165 void MainWindowReconfigureControllers(
165 const Core::Frontend::ControllerParameters& parameters) const; 166 const Core::Frontend::ControllerParameters& parameters) const;
167 void MainWindowRequestExit() const;
166 168
167private: 169private:
168 void MainWindowReconfigureFinished(); 170 void MainWindowReconfigureFinished(bool is_success);
169 171
170 mutable ReconfigureCallback callback; 172 mutable ReconfigureCallback callback;
171}; 173};
diff --git a/src/yuzu/applets/qt_controller.ui b/src/yuzu/applets/qt_controller.ui
index f5eccba70..729e921ee 100644
--- a/src/yuzu/applets/qt_controller.ui
+++ b/src/yuzu/applets/qt_controller.ui
@@ -2629,7 +2629,7 @@
2629 <bool>true</bool> 2629 <bool>true</bool>
2630 </property> 2630 </property>
2631 <property name="standardButtons"> 2631 <property name="standardButtons">
2632 <set>QDialogButtonBox::Ok</set> 2632 <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
2633 </property> 2633 </property>
2634 </widget> 2634 </widget>
2635 </item> 2635 </item>
@@ -2649,5 +2649,11 @@
2649 <receiver>QtControllerSelectorDialog</receiver> 2649 <receiver>QtControllerSelectorDialog</receiver>
2650 <slot>accept()</slot> 2650 <slot>accept()</slot>
2651 </connection> 2651 </connection>
2652 <connection>
2653 <sender>buttonBox</sender>
2654 <signal>rejected()</signal>
2655 <receiver>QtControllerSelectorDialog</receiver>
2656 <slot>reject()</slot>
2657 </connection>
2652 </connections> 2658 </connections>
2653</ui> 2659</ui>
diff --git a/src/yuzu/applets/qt_error.cpp b/src/yuzu/applets/qt_error.cpp
index e0190a979..1dc4f0383 100644
--- a/src/yuzu/applets/qt_error.cpp
+++ b/src/yuzu/applets/qt_error.cpp
@@ -8,12 +8,19 @@
8QtErrorDisplay::QtErrorDisplay(GMainWindow& parent) { 8QtErrorDisplay::QtErrorDisplay(GMainWindow& parent) {
9 connect(this, &QtErrorDisplay::MainWindowDisplayError, &parent, 9 connect(this, &QtErrorDisplay::MainWindowDisplayError, &parent,
10 &GMainWindow::ErrorDisplayDisplayError, Qt::QueuedConnection); 10 &GMainWindow::ErrorDisplayDisplayError, Qt::QueuedConnection);
11 connect(this, &QtErrorDisplay::MainWindowRequestExit, &parent,
12 &GMainWindow::ErrorDisplayRequestExit, Qt::QueuedConnection);
11 connect(&parent, &GMainWindow::ErrorDisplayFinished, this, 13 connect(&parent, &GMainWindow::ErrorDisplayFinished, this,
12 &QtErrorDisplay::MainWindowFinishedError, Qt::DirectConnection); 14 &QtErrorDisplay::MainWindowFinishedError, Qt::DirectConnection);
13} 15}
14 16
15QtErrorDisplay::~QtErrorDisplay() = default; 17QtErrorDisplay::~QtErrorDisplay() = default;
16 18
19void QtErrorDisplay::Close() const {
20 callback = {};
21 emit MainWindowRequestExit();
22}
23
17void QtErrorDisplay::ShowError(Result error, FinishedCallback finished) const { 24void QtErrorDisplay::ShowError(Result error, FinishedCallback finished) const {
18 callback = std::move(finished); 25 callback = std::move(finished);
19 emit MainWindowDisplayError( 26 emit MainWindowDisplayError(
@@ -55,5 +62,7 @@ void QtErrorDisplay::ShowCustomErrorText(Result error, std::string dialog_text,
55} 62}
56 63
57void QtErrorDisplay::MainWindowFinishedError() { 64void QtErrorDisplay::MainWindowFinishedError() {
58 callback(); 65 if (callback) {
66 callback();
67 }
59} 68}
diff --git a/src/yuzu/applets/qt_error.h b/src/yuzu/applets/qt_error.h
index e4e174721..957f170ad 100644
--- a/src/yuzu/applets/qt_error.h
+++ b/src/yuzu/applets/qt_error.h
@@ -16,6 +16,7 @@ public:
16 explicit QtErrorDisplay(GMainWindow& parent); 16 explicit QtErrorDisplay(GMainWindow& parent);
17 ~QtErrorDisplay() override; 17 ~QtErrorDisplay() override;
18 18
19 void Close() const override;
19 void ShowError(Result error, FinishedCallback finished) const override; 20 void ShowError(Result error, FinishedCallback finished) const override;
20 void ShowErrorWithTimestamp(Result error, std::chrono::seconds time, 21 void ShowErrorWithTimestamp(Result error, std::chrono::seconds time,
21 FinishedCallback finished) const override; 22 FinishedCallback finished) const override;
@@ -24,6 +25,7 @@ public:
24 25
25signals: 26signals:
26 void MainWindowDisplayError(QString error_code, QString error_text) const; 27 void MainWindowDisplayError(QString error_code, QString error_text) const;
28 void MainWindowRequestExit() const;
27 29
28private: 30private:
29 void MainWindowFinishedError(); 31 void MainWindowFinishedError();
diff --git a/src/yuzu/applets/qt_profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp
index 4145c5299..2448e46b6 100644
--- a/src/yuzu/applets/qt_profile_select.cpp
+++ b/src/yuzu/applets/qt_profile_select.cpp
@@ -46,11 +46,13 @@ QPixmap GetIcon(Common::UUID uuid) {
46} 46}
47} // Anonymous namespace 47} // Anonymous namespace
48 48
49QtProfileSelectionDialog::QtProfileSelectionDialog(Core::HID::HIDCore& hid_core, QWidget* parent) 49QtProfileSelectionDialog::QtProfileSelectionDialog(
50 Core::HID::HIDCore& hid_core, QWidget* parent,
51 const Core::Frontend::ProfileSelectParameters& parameters)
50 : QDialog(parent), profile_manager(std::make_unique<Service::Account::ProfileManager>()) { 52 : QDialog(parent), profile_manager(std::make_unique<Service::Account::ProfileManager>()) {
51 outer_layout = new QVBoxLayout; 53 outer_layout = new QVBoxLayout;
52 54
53 instruction_label = new QLabel(tr("Select a user:")); 55 instruction_label = new QLabel();
54 56
55 scroll_area = new QScrollArea; 57 scroll_area = new QScrollArea;
56 58
@@ -120,7 +122,8 @@ QtProfileSelectionDialog::QtProfileSelectionDialog(Core::HID::HIDCore& hid_core,
120 item_model->appendRow(item); 122 item_model->appendRow(item);
121 123
122 setLayout(outer_layout); 124 setLayout(outer_layout);
123 setWindowTitle(tr("Profile Selector")); 125 SetWindowTitle(parameters);
126 SetDialogPurpose(parameters);
124 resize(550, 400); 127 resize(550, 400);
125} 128}
126 129
@@ -154,20 +157,101 @@ void QtProfileSelectionDialog::SelectUser(const QModelIndex& index) {
154 user_index = index.row(); 157 user_index = index.row();
155} 158}
156 159
160void QtProfileSelectionDialog::SetWindowTitle(
161 const Core::Frontend::ProfileSelectParameters& parameters) {
162 using Service::AM::Applets::UiMode;
163 switch (parameters.mode) {
164 case UiMode::UserCreator:
165 case UiMode::UserCreatorForStarter:
166 setWindowTitle(tr("Profile Creator"));
167 return;
168 case UiMode::EnsureNetworkServiceAccountAvailable:
169 setWindowTitle(tr("Profile Selector"));
170 return;
171 case UiMode::UserIconEditor:
172 setWindowTitle(tr("Profile Icon Editor"));
173 return;
174 case UiMode::UserNicknameEditor:
175 setWindowTitle(tr("Profile Nickname Editor"));
176 return;
177 case UiMode::NintendoAccountAuthorizationRequestContext:
178 case UiMode::IntroduceExternalNetworkServiceAccount:
179 case UiMode::IntroduceExternalNetworkServiceAccountForRegistration:
180 case UiMode::NintendoAccountNnidLinker:
181 case UiMode::LicenseRequirementsForNetworkService:
182 case UiMode::LicenseRequirementsForNetworkServiceWithUserContextImpl:
183 case UiMode::UserCreatorForImmediateNaLoginTest:
184 case UiMode::UserQualificationPromoter:
185 case UiMode::UserSelector:
186 default:
187 setWindowTitle(tr("Profile Selector"));
188 }
189}
190
191void QtProfileSelectionDialog::SetDialogPurpose(
192 const Core::Frontend::ProfileSelectParameters& parameters) {
193 using Service::AM::Applets::UserSelectionPurpose;
194
195 switch (parameters.purpose) {
196 case UserSelectionPurpose::GameCardRegistration:
197 instruction_label->setText(tr("Who will receive the points?"));
198 return;
199 case UserSelectionPurpose::EShopLaunch:
200 instruction_label->setText(tr("Who is using Nintendo eShop?"));
201 return;
202 case UserSelectionPurpose::EShopItemShow:
203 instruction_label->setText(tr("Who is making this purchase?"));
204 return;
205 case UserSelectionPurpose::PicturePost:
206 instruction_label->setText(tr("Who is posting?"));
207 return;
208 case UserSelectionPurpose::NintendoAccountLinkage:
209 instruction_label->setText(tr("Select a user to link to a Nintendo Account."));
210 return;
211 case UserSelectionPurpose::SettingsUpdate:
212 instruction_label->setText(tr("Change settings for which user?"));
213 return;
214 case UserSelectionPurpose::SaveDataDeletion:
215 instruction_label->setText(tr("Format data for which user?"));
216 return;
217 case UserSelectionPurpose::UserMigration:
218 instruction_label->setText(tr("Which user will be transferred to another console?"));
219 return;
220 case UserSelectionPurpose::SaveDataTransfer:
221 instruction_label->setText(tr("Send save data for which user?"));
222 return;
223 case UserSelectionPurpose::General:
224 default:
225 instruction_label->setText(tr("Select a user:"));
226 return;
227 }
228}
229
157QtProfileSelector::QtProfileSelector(GMainWindow& parent) { 230QtProfileSelector::QtProfileSelector(GMainWindow& parent) {
158 connect(this, &QtProfileSelector::MainWindowSelectProfile, &parent, 231 connect(this, &QtProfileSelector::MainWindowSelectProfile, &parent,
159 &GMainWindow::ProfileSelectorSelectProfile, Qt::QueuedConnection); 232 &GMainWindow::ProfileSelectorSelectProfile, Qt::QueuedConnection);
233 connect(this, &QtProfileSelector::MainWindowRequestExit, &parent,
234 &GMainWindow::ProfileSelectorRequestExit, Qt::QueuedConnection);
160 connect(&parent, &GMainWindow::ProfileSelectorFinishedSelection, this, 235 connect(&parent, &GMainWindow::ProfileSelectorFinishedSelection, this,
161 &QtProfileSelector::MainWindowFinishedSelection, Qt::DirectConnection); 236 &QtProfileSelector::MainWindowFinishedSelection, Qt::DirectConnection);
162} 237}
163 238
164QtProfileSelector::~QtProfileSelector() = default; 239QtProfileSelector::~QtProfileSelector() = default;
165 240
166void QtProfileSelector::SelectProfile(SelectProfileCallback callback_) const { 241void QtProfileSelector::Close() const {
242 callback = {};
243 emit MainWindowRequestExit();
244}
245
246void QtProfileSelector::SelectProfile(
247 SelectProfileCallback callback_,
248 const Core::Frontend::ProfileSelectParameters& parameters) const {
167 callback = std::move(callback_); 249 callback = std::move(callback_);
168 emit MainWindowSelectProfile(); 250 emit MainWindowSelectProfile(parameters);
169} 251}
170 252
171void QtProfileSelector::MainWindowFinishedSelection(std::optional<Common::UUID> uuid) { 253void QtProfileSelector::MainWindowFinishedSelection(std::optional<Common::UUID> uuid) {
172 callback(uuid); 254 if (callback) {
255 callback(uuid);
256 }
173} 257}
diff --git a/src/yuzu/applets/qt_profile_select.h b/src/yuzu/applets/qt_profile_select.h
index 637a3bda2..99056e274 100644
--- a/src/yuzu/applets/qt_profile_select.h
+++ b/src/yuzu/applets/qt_profile_select.h
@@ -28,7 +28,8 @@ class QtProfileSelectionDialog final : public QDialog {
28 Q_OBJECT 28 Q_OBJECT
29 29
30public: 30public:
31 explicit QtProfileSelectionDialog(Core::HID::HIDCore& hid_core, QWidget* parent); 31 explicit QtProfileSelectionDialog(Core::HID::HIDCore& hid_core, QWidget* parent,
32 const Core::Frontend::ProfileSelectParameters& parameters);
32 ~QtProfileSelectionDialog() override; 33 ~QtProfileSelectionDialog() override;
33 34
34 int exec() override; 35 int exec() override;
@@ -40,6 +41,9 @@ public:
40private: 41private:
41 void SelectUser(const QModelIndex& index); 42 void SelectUser(const QModelIndex& index);
42 43
44 void SetWindowTitle(const Core::Frontend::ProfileSelectParameters& parameters);
45 void SetDialogPurpose(const Core::Frontend::ProfileSelectParameters& parameters);
46
43 int user_index = 0; 47 int user_index = 0;
44 48
45 QVBoxLayout* layout; 49 QVBoxLayout* layout;
@@ -65,10 +69,13 @@ public:
65 explicit QtProfileSelector(GMainWindow& parent); 69 explicit QtProfileSelector(GMainWindow& parent);
66 ~QtProfileSelector() override; 70 ~QtProfileSelector() override;
67 71
68 void SelectProfile(SelectProfileCallback callback_) const override; 72 void Close() const override;
73 void SelectProfile(SelectProfileCallback callback_,
74 const Core::Frontend::ProfileSelectParameters& parameters) const override;
69 75
70signals: 76signals:
71 void MainWindowSelectProfile() const; 77 void MainWindowSelectProfile(const Core::Frontend::ProfileSelectParameters& parameters) const;
78 void MainWindowRequestExit() const;
72 79
73private: 80private:
74 void MainWindowFinishedSelection(std::optional<Common::UUID> uuid); 81 void MainWindowFinishedSelection(std::optional<Common::UUID> uuid);
diff --git a/src/yuzu/applets/qt_software_keyboard.h b/src/yuzu/applets/qt_software_keyboard.h
index 30ac8ecf6..ac23ce047 100644
--- a/src/yuzu/applets/qt_software_keyboard.h
+++ b/src/yuzu/applets/qt_software_keyboard.h
@@ -233,6 +233,10 @@ public:
233 explicit QtSoftwareKeyboard(GMainWindow& parent); 233 explicit QtSoftwareKeyboard(GMainWindow& parent);
234 ~QtSoftwareKeyboard() override; 234 ~QtSoftwareKeyboard() override;
235 235
236 void Close() const override {
237 ExitKeyboard();
238 }
239
236 void InitializeKeyboard(bool is_inline, 240 void InitializeKeyboard(bool is_inline,
237 Core::Frontend::KeyboardInitializeParameters initialize_parameters, 241 Core::Frontend::KeyboardInitializeParameters initialize_parameters,
238 SubmitNormalCallback submit_normal_callback_, 242 SubmitNormalCallback submit_normal_callback_,
diff --git a/src/yuzu/applets/qt_web_browser.cpp b/src/yuzu/applets/qt_web_browser.cpp
index 0a5912326..28acc0ff8 100644
--- a/src/yuzu/applets/qt_web_browser.cpp
+++ b/src/yuzu/applets/qt_web_browser.cpp
@@ -393,6 +393,8 @@ void QtNXWebEngineView::FocusFirstLinkElement() {
393QtWebBrowser::QtWebBrowser(GMainWindow& main_window) { 393QtWebBrowser::QtWebBrowser(GMainWindow& main_window) {
394 connect(this, &QtWebBrowser::MainWindowOpenWebPage, &main_window, 394 connect(this, &QtWebBrowser::MainWindowOpenWebPage, &main_window,
395 &GMainWindow::WebBrowserOpenWebPage, Qt::QueuedConnection); 395 &GMainWindow::WebBrowserOpenWebPage, Qt::QueuedConnection);
396 connect(this, &QtWebBrowser::MainWindowRequestExit, &main_window,
397 &GMainWindow::WebBrowserRequestExit, Qt::QueuedConnection);
396 connect(&main_window, &GMainWindow::WebBrowserExtractOfflineRomFS, this, 398 connect(&main_window, &GMainWindow::WebBrowserExtractOfflineRomFS, this,
397 &QtWebBrowser::MainWindowExtractOfflineRomFS, Qt::QueuedConnection); 399 &QtWebBrowser::MainWindowExtractOfflineRomFS, Qt::QueuedConnection);
398 connect(&main_window, &GMainWindow::WebBrowserClosed, this, 400 connect(&main_window, &GMainWindow::WebBrowserClosed, this,
@@ -401,6 +403,11 @@ QtWebBrowser::QtWebBrowser(GMainWindow& main_window) {
401 403
402QtWebBrowser::~QtWebBrowser() = default; 404QtWebBrowser::~QtWebBrowser() = default;
403 405
406void QtWebBrowser::Close() const {
407 callback = {};
408 emit MainWindowRequestExit();
409}
410
404void QtWebBrowser::OpenLocalWebPage(const std::string& local_url, 411void QtWebBrowser::OpenLocalWebPage(const std::string& local_url,
405 ExtractROMFSCallback extract_romfs_callback_, 412 ExtractROMFSCallback extract_romfs_callback_,
406 OpenWebPageCallback callback_) const { 413 OpenWebPageCallback callback_) const {
@@ -436,5 +443,7 @@ void QtWebBrowser::MainWindowExtractOfflineRomFS() {
436 443
437void QtWebBrowser::MainWindowWebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, 444void QtWebBrowser::MainWindowWebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason,
438 std::string last_url) { 445 std::string last_url) {
439 callback(exit_reason, last_url); 446 if (callback) {
447 callback(exit_reason, last_url);
448 }
440} 449}
diff --git a/src/yuzu/applets/qt_web_browser.h b/src/yuzu/applets/qt_web_browser.h
index ceae7926e..1234108ae 100644
--- a/src/yuzu/applets/qt_web_browser.h
+++ b/src/yuzu/applets/qt_web_browser.h
@@ -196,6 +196,7 @@ public:
196 explicit QtWebBrowser(GMainWindow& parent); 196 explicit QtWebBrowser(GMainWindow& parent);
197 ~QtWebBrowser() override; 197 ~QtWebBrowser() override;
198 198
199 void Close() const override;
199 void OpenLocalWebPage(const std::string& local_url, 200 void OpenLocalWebPage(const std::string& local_url,
200 ExtractROMFSCallback extract_romfs_callback_, 201 ExtractROMFSCallback extract_romfs_callback_,
201 OpenWebPageCallback callback_) const override; 202 OpenWebPageCallback callback_) const override;
@@ -206,6 +207,7 @@ public:
206signals: 207signals:
207 void MainWindowOpenWebPage(const std::string& main_url, const std::string& additional_args, 208 void MainWindowOpenWebPage(const std::string& main_url, const std::string& additional_args,
208 bool is_local) const; 209 bool is_local) const;
210 void MainWindowRequestExit() const;
209 211
210private: 212private:
211 void MainWindowExtractOfflineRomFS(); 213 void MainWindowExtractOfflineRomFS();
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index ae14884b5..b79409a68 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -307,6 +307,8 @@ GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan
307 system->Initialize(); 307 system->Initialize();
308 308
309 Common::Log::Initialize(); 309 Common::Log::Initialize();
310 Common::Log::Start();
311
310 LoadTranslation(); 312 LoadTranslation();
311 313
312 setAcceptDrops(true); 314 setAcceptDrops(true);
@@ -449,8 +451,6 @@ GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan
449 451
450 SetupPrepareForSleep(); 452 SetupPrepareForSleep();
451 453
452 Common::Log::Start();
453
454 QStringList args = QApplication::arguments(); 454 QStringList args = QApplication::arguments();
455 455
456 if (args.size() < 2) { 456 if (args.size() < 2) {
@@ -576,6 +576,10 @@ void GMainWindow::RegisterMetaTypes() {
576 // Controller Applet 576 // Controller Applet
577 qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters"); 577 qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters");
578 578
579 // Profile Select Applet
580 qRegisterMetaType<Core::Frontend::ProfileSelectParameters>(
581 "Core::Frontend::ProfileSelectParameters");
582
579 // Software Keyboard Applet 583 // Software Keyboard Applet
580 qRegisterMetaType<Core::Frontend::KeyboardInitializeParameters>( 584 qRegisterMetaType<Core::Frontend::KeyboardInitializeParameters>(
581 "Core::Frontend::KeyboardInitializeParameters"); 585 "Core::Frontend::KeyboardInitializeParameters");
@@ -596,50 +600,81 @@ void GMainWindow::RegisterMetaTypes() {
596 600
597void GMainWindow::AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters, 601void GMainWindow::AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters,
598 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) { 602 std::shared_ptr<Service::NFP::NfpDevice> nfp_device) {
599 QtAmiiboSettingsDialog dialog(this, parameters, input_subsystem.get(), nfp_device); 603 cabinet_applet =
604 new QtAmiiboSettingsDialog(this, parameters, input_subsystem.get(), nfp_device);
605 SCOPE_EXIT({
606 cabinet_applet->deleteLater();
607 cabinet_applet = nullptr;
608 });
600 609
601 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | 610 cabinet_applet->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint |
602 Qt::WindowTitleHint | Qt::WindowSystemMenuHint); 611 Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
603 dialog.setWindowModality(Qt::WindowModal); 612 cabinet_applet->setWindowModality(Qt::WindowModal);
604 if (dialog.exec() == QDialog::Rejected) { 613
614 if (cabinet_applet->exec() == QDialog::Rejected) {
605 emit AmiiboSettingsFinished(false, {}); 615 emit AmiiboSettingsFinished(false, {});
606 return; 616 return;
607 } 617 }
608 618
609 emit AmiiboSettingsFinished(true, dialog.GetName()); 619 emit AmiiboSettingsFinished(true, cabinet_applet->GetName());
620}
621
622void GMainWindow::AmiiboSettingsRequestExit() {
623 if (cabinet_applet) {
624 cabinet_applet->reject();
625 }
610} 626}
611 627
612void GMainWindow::ControllerSelectorReconfigureControllers( 628void GMainWindow::ControllerSelectorReconfigureControllers(
613 const Core::Frontend::ControllerParameters& parameters) { 629 const Core::Frontend::ControllerParameters& parameters) {
614 QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get(), *system); 630 controller_applet =
615 631 new QtControllerSelectorDialog(this, parameters, input_subsystem.get(), *system);
616 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | 632 SCOPE_EXIT({
617 Qt::WindowTitleHint | Qt::WindowSystemMenuHint); 633 controller_applet->deleteLater();
618 dialog.setWindowModality(Qt::WindowModal); 634 controller_applet = nullptr;
619 dialog.exec(); 635 });
620 636
621 emit ControllerSelectorReconfigureFinished(); 637 controller_applet->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint |
638 Qt::WindowStaysOnTopHint | Qt::WindowTitleHint |
639 Qt::WindowSystemMenuHint);
640 controller_applet->setWindowModality(Qt::WindowModal);
641 bool is_success = controller_applet->exec() != QDialog::Rejected;
622 642
623 // Don't forget to apply settings. 643 // Don't forget to apply settings.
644 system->HIDCore().DisableAllControllerConfiguration();
624 system->ApplySettings(); 645 system->ApplySettings();
625 config->Save(); 646 config->Save();
626 647
627 UpdateStatusButtons(); 648 UpdateStatusButtons();
649
650 emit ControllerSelectorReconfigureFinished(is_success);
628} 651}
629 652
630void GMainWindow::ProfileSelectorSelectProfile() { 653void GMainWindow::ControllerSelectorRequestExit() {
631 QtProfileSelectionDialog dialog(system->HIDCore(), this); 654 if (controller_applet) {
632 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | 655 controller_applet->reject();
633 Qt::WindowTitleHint | Qt::WindowSystemMenuHint | 656 }
634 Qt::WindowCloseButtonHint); 657}
635 dialog.setWindowModality(Qt::WindowModal); 658
636 if (dialog.exec() == QDialog::Rejected) { 659void GMainWindow::ProfileSelectorSelectProfile(
660 const Core::Frontend::ProfileSelectParameters& parameters) {
661 profile_select_applet = new QtProfileSelectionDialog(system->HIDCore(), this, parameters);
662 SCOPE_EXIT({
663 profile_select_applet->deleteLater();
664 profile_select_applet = nullptr;
665 });
666
667 profile_select_applet->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint |
668 Qt::WindowStaysOnTopHint | Qt::WindowTitleHint |
669 Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
670 profile_select_applet->setWindowModality(Qt::WindowModal);
671 if (profile_select_applet->exec() == QDialog::Rejected) {
637 emit ProfileSelectorFinishedSelection(std::nullopt); 672 emit ProfileSelectorFinishedSelection(std::nullopt);
638 return; 673 return;
639 } 674 }
640 675
641 const Service::Account::ProfileManager manager; 676 const Service::Account::ProfileManager manager;
642 const auto uuid = manager.GetUser(static_cast<std::size_t>(dialog.GetIndex())); 677 const auto uuid = manager.GetUser(static_cast<std::size_t>(profile_select_applet->GetIndex()));
643 if (!uuid.has_value()) { 678 if (!uuid.has_value()) {
644 emit ProfileSelectorFinishedSelection(std::nullopt); 679 emit ProfileSelectorFinishedSelection(std::nullopt);
645 return; 680 return;
@@ -648,6 +683,12 @@ void GMainWindow::ProfileSelectorSelectProfile() {
648 emit ProfileSelectorFinishedSelection(uuid); 683 emit ProfileSelectorFinishedSelection(uuid);
649} 684}
650 685
686void GMainWindow::ProfileSelectorRequestExit() {
687 if (profile_select_applet) {
688 profile_select_applet->reject();
689 }
690}
691
651void GMainWindow::SoftwareKeyboardInitialize( 692void GMainWindow::SoftwareKeyboardInitialize(
652 bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) { 693 bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) {
653 if (software_keyboard) { 694 if (software_keyboard) {
@@ -772,7 +813,7 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
772 return; 813 return;
773 } 814 }
774 815
775 QtNXWebEngineView web_browser_view(this, *system, input_subsystem.get()); 816 web_applet = new QtNXWebEngineView(this, *system, input_subsystem.get());
776 817
777 ui->action_Pause->setEnabled(false); 818 ui->action_Pause->setEnabled(false);
778 ui->action_Restart->setEnabled(false); 819 ui->action_Restart->setEnabled(false);
@@ -799,9 +840,9 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
799 loading_progress.setValue(1); 840 loading_progress.setValue(1);
800 841
801 if (is_local) { 842 if (is_local) {
802 web_browser_view.LoadLocalWebPage(main_url, additional_args); 843 web_applet->LoadLocalWebPage(main_url, additional_args);
803 } else { 844 } else {
804 web_browser_view.LoadExternalWebPage(main_url, additional_args); 845 web_applet->LoadExternalWebPage(main_url, additional_args);
805 } 846 }
806 847
807 if (render_window->IsLoadingComplete()) { 848 if (render_window->IsLoadingComplete()) {
@@ -810,15 +851,15 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
810 851
811 const auto& layout = render_window->GetFramebufferLayout(); 852 const auto& layout = render_window->GetFramebufferLayout();
812 const auto scale_ratio = devicePixelRatioF(); 853 const auto scale_ratio = devicePixelRatioF();
813 web_browser_view.resize(layout.screen.GetWidth() / scale_ratio, 854 web_applet->resize(layout.screen.GetWidth() / scale_ratio,
814 layout.screen.GetHeight() / scale_ratio); 855 layout.screen.GetHeight() / scale_ratio);
815 web_browser_view.move(layout.screen.left / scale_ratio, 856 web_applet->move(layout.screen.left / scale_ratio,
816 (layout.screen.top / scale_ratio) + menuBar()->height()); 857 (layout.screen.top / scale_ratio) + menuBar()->height());
817 web_browser_view.setZoomFactor(static_cast<qreal>(layout.screen.GetWidth() / scale_ratio) / 858 web_applet->setZoomFactor(static_cast<qreal>(layout.screen.GetWidth() / scale_ratio) /
818 static_cast<qreal>(Layout::ScreenUndocked::Width)); 859 static_cast<qreal>(Layout::ScreenUndocked::Width));
819 860
820 web_browser_view.setFocus(); 861 web_applet->setFocus();
821 web_browser_view.show(); 862 web_applet->show();
822 863
823 loading_progress.setValue(2); 864 loading_progress.setValue(2);
824 865
@@ -831,7 +872,7 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
831 872
832 // TODO (Morph): Remove this 873 // TODO (Morph): Remove this
833 QAction* exit_action = new QAction(tr("Disable Web Applet"), this); 874 QAction* exit_action = new QAction(tr("Disable Web Applet"), this);
834 connect(exit_action, &QAction::triggered, this, [this, &web_browser_view] { 875 connect(exit_action, &QAction::triggered, this, [this] {
835 const auto result = QMessageBox::warning( 876 const auto result = QMessageBox::warning(
836 this, tr("Disable Web Applet"), 877 this, tr("Disable Web Applet"),
837 tr("Disabling the web applet can lead to undefined behavior and should only be used " 878 tr("Disabling the web applet can lead to undefined behavior and should only be used "
@@ -840,21 +881,21 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
840 QMessageBox::Yes | QMessageBox::No); 881 QMessageBox::Yes | QMessageBox::No);
841 if (result == QMessageBox::Yes) { 882 if (result == QMessageBox::Yes) {
842 UISettings::values.disable_web_applet = true; 883 UISettings::values.disable_web_applet = true;
843 web_browser_view.SetFinished(true); 884 web_applet->SetFinished(true);
844 } 885 }
845 }); 886 });
846 ui->menubar->addAction(exit_action); 887 ui->menubar->addAction(exit_action);
847 888
848 while (!web_browser_view.IsFinished()) { 889 while (!web_applet->IsFinished()) {
849 QCoreApplication::processEvents(); 890 QCoreApplication::processEvents();
850 891
851 if (!exit_check) { 892 if (!exit_check) {
852 web_browser_view.page()->runJavaScript( 893 web_applet->page()->runJavaScript(
853 QStringLiteral("end_applet;"), [&](const QVariant& variant) { 894 QStringLiteral("end_applet;"), [&](const QVariant& variant) {
854 exit_check = false; 895 exit_check = false;
855 if (variant.toBool()) { 896 if (variant.toBool()) {
856 web_browser_view.SetFinished(true); 897 web_applet->SetFinished(true);
857 web_browser_view.SetExitReason( 898 web_applet->SetExitReason(
858 Service::AM::Applets::WebExitReason::EndButtonPressed); 899 Service::AM::Applets::WebExitReason::EndButtonPressed);
859 } 900 }
860 }); 901 });
@@ -862,22 +903,22 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
862 exit_check = true; 903 exit_check = true;
863 } 904 }
864 905
865 if (web_browser_view.GetCurrentURL().contains(QStringLiteral("localhost"))) { 906 if (web_applet->GetCurrentURL().contains(QStringLiteral("localhost"))) {
866 if (!web_browser_view.IsFinished()) { 907 if (!web_applet->IsFinished()) {
867 web_browser_view.SetFinished(true); 908 web_applet->SetFinished(true);
868 web_browser_view.SetExitReason(Service::AM::Applets::WebExitReason::CallbackURL); 909 web_applet->SetExitReason(Service::AM::Applets::WebExitReason::CallbackURL);
869 } 910 }
870 911
871 web_browser_view.SetLastURL(web_browser_view.GetCurrentURL().toStdString()); 912 web_applet->SetLastURL(web_applet->GetCurrentURL().toStdString());
872 } 913 }
873 914
874 std::this_thread::sleep_for(std::chrono::milliseconds(1)); 915 std::this_thread::sleep_for(std::chrono::milliseconds(1));
875 } 916 }
876 917
877 const auto exit_reason = web_browser_view.GetExitReason(); 918 const auto exit_reason = web_applet->GetExitReason();
878 const auto last_url = web_browser_view.GetLastURL(); 919 const auto last_url = web_applet->GetLastURL();
879 920
880 web_browser_view.hide(); 921 web_applet->hide();
881 922
882 render_window->setFocus(); 923 render_window->setFocus();
883 924
@@ -903,6 +944,15 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url,
903#endif 944#endif
904} 945}
905 946
947void GMainWindow::WebBrowserRequestExit() {
948#ifdef YUZU_USE_QT_WEB_ENGINE
949 if (web_applet) {
950 web_applet->SetExitReason(Service::AM::Applets::WebExitReason::ExitRequested);
951 web_applet->SetFinished(true);
952 }
953#endif
954}
955
906void GMainWindow::InitializeWidgets() { 956void GMainWindow::InitializeWidgets() {
907#ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING 957#ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING
908 ui->action_Report_Compatibility->setVisible(true); 958 ui->action_Report_Compatibility->setVisible(true);
@@ -1675,8 +1725,9 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p
1675 return true; 1725 return true;
1676} 1726}
1677 1727
1678bool GMainWindow::SelectAndSetCurrentUser() { 1728bool GMainWindow::SelectAndSetCurrentUser(
1679 QtProfileSelectionDialog dialog(system->HIDCore(), this); 1729 const Core::Frontend::ProfileSelectParameters& parameters) {
1730 QtProfileSelectionDialog dialog(system->HIDCore(), this, parameters);
1680 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | 1731 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
1681 Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); 1732 Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
1682 dialog.setWindowModality(Qt::WindowModal); 1733 dialog.setWindowModality(Qt::WindowModal);
@@ -1722,7 +1773,13 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
1722 Settings::LogSettings(); 1773 Settings::LogSettings();
1723 1774
1724 if (UISettings::values.select_user_on_boot) { 1775 if (UISettings::values.select_user_on_boot) {
1725 if (SelectAndSetCurrentUser() == false) { 1776 const Core::Frontend::ProfileSelectParameters parameters{
1777 .mode = Service::AM::Applets::UiMode::UserSelector,
1778 .invalid_uid_list = {},
1779 .display_options = {},
1780 .purpose = Service::AM::Applets::UserSelectionPurpose::General,
1781 };
1782 if (SelectAndSetCurrentUser(parameters) == false) {
1726 return; 1783 return;
1727 } 1784 }
1728 } 1785 }
@@ -2014,7 +2071,13 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
2014 if (has_user_save) { 2071 if (has_user_save) {
2015 // User save data 2072 // User save data
2016 const auto select_profile = [this] { 2073 const auto select_profile = [this] {
2017 QtProfileSelectionDialog dialog(system->HIDCore(), this); 2074 const Core::Frontend::ProfileSelectParameters parameters{
2075 .mode = Service::AM::Applets::UiMode::UserSelector,
2076 .invalid_uid_list = {},
2077 .display_options = {},
2078 .purpose = Service::AM::Applets::UserSelectionPurpose::General,
2079 };
2080 QtProfileSelectionDialog dialog(system->HIDCore(), this, parameters);
2018 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | 2081 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
2019 Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); 2082 Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
2020 dialog.setWindowModality(Qt::WindowModal); 2083 dialog.setWindowModality(Qt::WindowModal);
@@ -3089,13 +3152,23 @@ void GMainWindow::OnSaveConfig() {
3089} 3152}
3090 3153
3091void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) { 3154void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) {
3092 OverlayDialog dialog(render_window, *system, error_code, error_text, QString{}, tr("OK"), 3155 error_applet = new OverlayDialog(render_window, *system, error_code, error_text, QString{},
3093 Qt::AlignLeft | Qt::AlignVCenter); 3156 tr("OK"), Qt::AlignLeft | Qt::AlignVCenter);
3094 dialog.exec(); 3157 SCOPE_EXIT({
3158 error_applet->deleteLater();
3159 error_applet = nullptr;
3160 });
3161 error_applet->exec();
3095 3162
3096 emit ErrorDisplayFinished(); 3163 emit ErrorDisplayFinished();
3097} 3164}
3098 3165
3166void GMainWindow::ErrorDisplayRequestExit() {
3167 if (error_applet) {
3168 error_applet->reject();
3169 }
3170}
3171
3099void GMainWindow::OnMenuReportCompatibility() { 3172void GMainWindow::OnMenuReportCompatibility() {
3100#if defined(ARCHITECTURE_x86_64) && !defined(__APPLE__) 3173#if defined(ARCHITECTURE_x86_64) && !defined(__APPLE__)
3101 const auto& caps = Common::GetCPUCaps(); 3174 const auto& caps = Common::GetCPUCaps();
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index a23b373a5..8b5c1d747 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -47,7 +47,11 @@ enum class DumpRomFSTarget;
47enum class InstalledEntryType; 47enum class InstalledEntryType;
48class GameListPlaceholder; 48class GameListPlaceholder;
49 49
50class QtAmiiboSettingsDialog;
51class QtControllerSelectorDialog;
52class QtProfileSelectionDialog;
50class QtSoftwareKeyboardDialog; 53class QtSoftwareKeyboardDialog;
54class QtNXWebEngineView;
51 55
52enum class StartGameType { 56enum class StartGameType {
53 Normal, // Can use custom configuration 57 Normal, // Can use custom configuration
@@ -65,6 +69,7 @@ struct ControllerParameters;
65struct InlineAppearParameters; 69struct InlineAppearParameters;
66struct InlineTextParameters; 70struct InlineTextParameters;
67struct KeyboardInitializeParameters; 71struct KeyboardInitializeParameters;
72struct ProfileSelectParameters;
68} // namespace Core::Frontend 73} // namespace Core::Frontend
69 74
70namespace DiscordRPC { 75namespace DiscordRPC {
@@ -161,7 +166,7 @@ signals:
161 166
162 void AmiiboSettingsFinished(bool is_success, const std::string& name); 167 void AmiiboSettingsFinished(bool is_success, const std::string& name);
163 168
164 void ControllerSelectorReconfigureFinished(); 169 void ControllerSelectorReconfigureFinished(bool is_success);
165 170
166 void ErrorDisplayFinished(); 171 void ErrorDisplayFinished();
167 172
@@ -184,8 +189,10 @@ public slots:
184 void OnSaveConfig(); 189 void OnSaveConfig();
185 void AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters, 190 void AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters,
186 std::shared_ptr<Service::NFP::NfpDevice> nfp_device); 191 std::shared_ptr<Service::NFP::NfpDevice> nfp_device);
192 void AmiiboSettingsRequestExit();
187 void ControllerSelectorReconfigureControllers( 193 void ControllerSelectorReconfigureControllers(
188 const Core::Frontend::ControllerParameters& parameters); 194 const Core::Frontend::ControllerParameters& parameters);
195 void ControllerSelectorRequestExit();
189 void SoftwareKeyboardInitialize( 196 void SoftwareKeyboardInitialize(
190 bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters); 197 bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters);
191 void SoftwareKeyboardShowNormal(); 198 void SoftwareKeyboardShowNormal();
@@ -196,9 +203,12 @@ public slots:
196 void SoftwareKeyboardInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters); 203 void SoftwareKeyboardInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters);
197 void SoftwareKeyboardExit(); 204 void SoftwareKeyboardExit();
198 void ErrorDisplayDisplayError(QString error_code, QString error_text); 205 void ErrorDisplayDisplayError(QString error_code, QString error_text);
199 void ProfileSelectorSelectProfile(); 206 void ErrorDisplayRequestExit();
207 void ProfileSelectorSelectProfile(const Core::Frontend::ProfileSelectParameters& parameters);
208 void ProfileSelectorRequestExit();
200 void WebBrowserOpenWebPage(const std::string& main_url, const std::string& additional_args, 209 void WebBrowserOpenWebPage(const std::string& main_url, const std::string& additional_args,
201 bool is_local); 210 bool is_local);
211 void WebBrowserRequestExit();
202 void OnAppFocusStateChanged(Qt::ApplicationState state); 212 void OnAppFocusStateChanged(Qt::ApplicationState state);
203 void OnTasStateChanged(); 213 void OnTasStateChanged();
204 214
@@ -233,7 +243,7 @@ private:
233 void SetDiscordEnabled(bool state); 243 void SetDiscordEnabled(bool state);
234 void LoadAmiibo(const QString& filename); 244 void LoadAmiibo(const QString& filename);
235 245
236 bool SelectAndSetCurrentUser(); 246 bool SelectAndSetCurrentUser(const Core::Frontend::ProfileSelectParameters& parameters);
237 247
238 /** 248 /**
239 * Stores the filename in the recently loaded files list. 249 * Stores the filename in the recently loaded files list.
@@ -466,7 +476,12 @@ private:
466 QString last_filename_booted; 476 QString last_filename_booted;
467 477
468 // Applets 478 // Applets
479 QtAmiiboSettingsDialog* cabinet_applet = nullptr;
480 QtControllerSelectorDialog* controller_applet = nullptr;
481 QtProfileSelectionDialog* profile_select_applet = nullptr;
482 QDialog* error_applet = nullptr;
469 QtSoftwareKeyboardDialog* software_keyboard = nullptr; 483 QtSoftwareKeyboardDialog* software_keyboard = nullptr;
484 QtNXWebEngineView* web_applet = nullptr;
470 485
471 // True if amiibo file select is visible 486 // True if amiibo file select is visible
472 bool is_amiibo_file_select_active{}; 487 bool is_amiibo_file_select_active{};