summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/CMakeLists.txt10
-rw-r--r--src/common/CMakeLists.txt14
-rw-r--r--src/common/settings.h1
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/arm/arm_interface.cpp8
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp21
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp21
-rw-r--r--src/core/frontend/applets/controller.cpp2
-rw-r--r--src/core/frontend/applets/controller.h6
-rw-r--r--src/core/frontend/applets/error.cpp6
-rw-r--r--src/core/frontend/applets/error.h14
-rw-r--r--src/core/frontend/applets/mii_edit.cpp2
-rw-r--r--src/core/frontend/applets/mii_edit.h6
-rw-r--r--src/core/frontend/applets/profile_select.cpp3
-rw-r--r--src/core/frontend/applets/profile_select.h6
-rw-r--r--src/core/frontend/applets/software_keyboard.cpp5
-rw-r--r--src/core/frontend/applets/software_keyboard.h32
-rw-r--r--src/core/frontend/applets/web_browser.cpp11
-rw-r--r--src/core/frontend/applets/web_browser.h24
-rw-r--r--src/core/hid/emulated_console.cpp10
-rw-r--r--src/core/hid/emulated_controller.cpp15
-rw-r--r--src/core/hid/emulated_controller.h2
-rw-r--r--src/core/hle/kernel/k_memory_block.h33
-rw-r--r--src/core/hle/kernel/k_memory_block_manager.h9
-rw-r--r--src/core/hle/kernel/k_shared_memory.h2
-rw-r--r--src/core/hle/kernel/k_thread.h4
-rw-r--r--src/core/hle/kernel/kernel.cpp2
-rw-r--r--src/core/hle/kernel/physical_core.h2
-rw-r--r--src/core/hle/service/nfc/mifare_user.cpp400
-rw-r--r--src/core/hle/service/nfc/mifare_user.h52
-rw-r--r--src/core/hle/service/nfc/nfc.cpp27
-rw-r--r--src/core/hle/service/nfc/nfc_device.cpp84
-rw-r--r--src/core/hle/service/nfc/nfc_device.h13
-rw-r--r--src/core/hle/service/nfc/nfc_result.h8
-rw-r--r--src/core/hle/service/nfc/nfc_user.cpp4
-rw-r--r--src/core/hle/service/nfp/nfp_types.h46
-rw-r--r--src/core/reporter.cpp35
-rw-r--r--src/core/reporter.h16
-rw-r--r--src/input_common/CMakeLists.txt10
-rw-r--r--src/input_common/drivers/virtual_amiibo.cpp38
-rw-r--r--src/input_common/drivers/virtual_amiibo.h7
-rw-r--r--src/network/CMakeLists.txt2
-rw-r--r--src/video_core/CMakeLists.txt7
-rw-r--r--src/video_core/engines/maxwell_3d.cpp68
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp2
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp4
-rw-r--r--src/video_core/vulkan_common/vulkan_debug_callback.cpp2
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp4
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.cpp8
-rw-r--r--src/web_service/CMakeLists.txt2
-rw-r--r--src/yuzu/CMakeLists.txt12
-rw-r--r--src/yuzu/applets/qt_controller.cpp2
-rw-r--r--src/yuzu/applets/qt_controller.h4
-rw-r--r--src/yuzu/applets/qt_error.cpp6
-rw-r--r--src/yuzu/applets/qt_error.h8
-rw-r--r--src/yuzu/applets/qt_profile_select.cpp3
-rw-r--r--src/yuzu/applets/qt_profile_select.h4
-rw-r--r--src/yuzu/applets/qt_software_keyboard.cpp5
-rw-r--r--src/yuzu/applets/qt_software_keyboard.h16
-rw-r--r--src/yuzu/applets/qt_web_browser.cpp11
-rw-r--r--src/yuzu/applets/qt_web_browser.h13
-rw-r--r--src/yuzu/configuration/config.cpp2
-rw-r--r--src/yuzu/configuration/configure_cpu_debug.cpp4
-rw-r--r--src/yuzu/configuration/configure_cpu_debug.ui13
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp2
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp3
-rw-r--r--src/yuzu_cmd/CMakeLists.txt10
-rw-r--r--src/yuzu_cmd/config.cpp3
-rw-r--r--src/yuzu_cmd/default_ini.h4
70 files changed, 930 insertions, 311 deletions
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index 0a9d9ec29..420ba62e0 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -219,19 +219,15 @@ endif()
219 219
220target_link_libraries(audio_core PUBLIC common core) 220target_link_libraries(audio_core PUBLIC common core)
221if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) 221if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
222 target_link_libraries(audio_core PRIVATE dynarmic) 222 target_link_libraries(audio_core PRIVATE dynarmic::dynarmic)
223endif() 223endif()
224 224
225if(ENABLE_CUBEB) 225if(ENABLE_CUBEB)
226 target_link_libraries(audio_core PRIVATE cubeb) 226 target_link_libraries(audio_core PRIVATE cubeb::cubeb)
227 target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1) 227 target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1)
228endif() 228endif()
229if(ENABLE_SDL2) 229if(ENABLE_SDL2)
230 if (YUZU_USE_EXTERNAL_SDL2) 230 target_link_libraries(audio_core PRIVATE SDL2::SDL2)
231 target_link_libraries(audio_core PRIVATE SDL2-static)
232 else()
233 target_link_libraries(audio_core PRIVATE SDL2)
234 endif()
235 target_compile_definitions(audio_core PRIVATE HAVE_SDL2) 231 target_compile_definitions(audio_core PRIVATE HAVE_SDL2)
236endif() 232endif()
237 233
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index a12edc584..6bdffcb7a 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -149,7 +149,7 @@ if(ARCHITECTURE_x86_64)
149 x64/xbyak_abi.h 149 x64/xbyak_abi.h
150 x64/xbyak_util.h 150 x64/xbyak_util.h
151 ) 151 )
152 target_link_libraries(common PRIVATE xbyak) 152 target_link_libraries(common PRIVATE xbyak::xbyak)
153endif() 153endif()
154 154
155if (MSVC) 155if (MSVC)
@@ -174,17 +174,7 @@ endif()
174create_target_directory_groups(common) 174create_target_directory_groups(common)
175 175
176target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile Threads::Threads) 176target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile Threads::Threads)
177if (TARGET lz4::lz4) 177target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd)
178 target_link_libraries(common PRIVATE lz4::lz4)
179else()
180 target_link_libraries(common PRIVATE LZ4::lz4_shared)
181endif()
182if (TARGET zstd::zstd)
183 target_link_libraries(common PRIVATE zstd::zstd)
184else()
185 target_link_libraries(common PRIVATE
186 $<IF:$<TARGET_EXISTS:zstd::libzstd_shared>,zstd::libzstd_shared,zstd::libzstd_static>)
187endif()
188 178
189if (YUZU_USE_PRECOMPILED_HEADERS) 179if (YUZU_USE_PRECOMPILED_HEADERS)
190 target_precompile_headers(common PRIVATE precompiled_headers.h) 180 target_precompile_headers(common PRIVATE precompiled_headers.h)
diff --git a/src/common/settings.h b/src/common/settings.h
index c0620066c..29b730cff 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -400,6 +400,7 @@ struct Values {
400 Setting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"}; 400 Setting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"};
401 Setting<bool> cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"}; 401 Setting<bool> cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"};
402 Setting<bool> cpuopt_recompile_exclusives{true, "cpuopt_recompile_exclusives"}; 402 Setting<bool> cpuopt_recompile_exclusives{true, "cpuopt_recompile_exclusives"};
403 Setting<bool> cpuopt_ignore_memory_aborts{true, "cpuopt_ignore_memory_aborts"};
403 404
404 SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"}; 405 SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"};
405 SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"}; 406 SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"};
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 6530d3c60..c6b5ac196 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -528,6 +528,8 @@ add_library(core STATIC
528 hle/service/mnpp/mnpp_app.h 528 hle/service/mnpp/mnpp_app.h
529 hle/service/ncm/ncm.cpp 529 hle/service/ncm/ncm.cpp
530 hle/service/ncm/ncm.h 530 hle/service/ncm/ncm.h
531 hle/service/nfc/mifare_user.cpp
532 hle/service/nfc/mifare_user.h
531 hle/service/nfc/nfc.cpp 533 hle/service/nfc/nfc.cpp
532 hle/service/nfc/nfc.h 534 hle/service/nfc/nfc.h
533 hle/service/nfc/nfc_device.cpp 535 hle/service/nfc/nfc_device.cpp
@@ -824,7 +826,7 @@ if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
824 hle/service/jit/jit.cpp 826 hle/service/jit/jit.cpp
825 hle/service/jit/jit.h 827 hle/service/jit/jit.h
826 ) 828 )
827 target_link_libraries(core PRIVATE dynarmic) 829 target_link_libraries(core PRIVATE dynarmic::dynarmic)
828endif() 830endif()
829 831
830if (YUZU_USE_PRECOMPILED_HEADERS) 832if (YUZU_USE_PRECOMPILED_HEADERS)
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index 29ba562dc..2df7b0ee8 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -145,11 +145,15 @@ void ARM_Interface::Run() {
145 // Notify the debugger and go to sleep if a breakpoint was hit, 145 // Notify the debugger and go to sleep if a breakpoint was hit,
146 // or if the thread is unable to continue for any reason. 146 // or if the thread is unable to continue for any reason.
147 if (Has(hr, breakpoint) || Has(hr, no_execute)) { 147 if (Has(hr, breakpoint) || Has(hr, no_execute)) {
148 RewindBreakpointInstruction(); 148 if (!Has(hr, no_execute)) {
149 RewindBreakpointInstruction();
150 }
149 if (system.DebuggerEnabled()) { 151 if (system.DebuggerEnabled()) {
150 system.GetDebugger().NotifyThreadStopped(current_thread); 152 system.GetDebugger().NotifyThreadStopped(current_thread);
153 } else {
154 LogBacktrace();
151 } 155 }
152 current_thread->RequestSuspend(Kernel::SuspendType::Debug); 156 current_thread->RequestSuspend(SuspendType::Debug);
153 break; 157 break;
154 } 158 }
155 159
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 227e06ea1..947747d36 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -29,7 +29,9 @@ class 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_},
32 memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()} {} 32 memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()},
33 check_memory_access{debugger_enabled ||
34 !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
33 35
34 u8 MemoryRead8(u32 vaddr) override { 36 u8 MemoryRead8(u32 vaddr) override {
35 CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); 37 CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
@@ -154,6 +156,17 @@ public:
154 } 156 }
155 157
156 bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) { 158 bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) {
159 if (!check_memory_access) {
160 return true;
161 }
162
163 if (!memory.IsValidVirtualAddressRange(addr, size)) {
164 LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}",
165 addr);
166 parent.jit.load()->HaltExecution(ARM_Interface::no_execute);
167 return false;
168 }
169
157 if (!debugger_enabled) { 170 if (!debugger_enabled) {
158 return true; 171 return true;
159 } 172 }
@@ -181,7 +194,8 @@ public:
181 ARM_Dynarmic_32& parent; 194 ARM_Dynarmic_32& parent;
182 Core::Memory::Memory& memory; 195 Core::Memory::Memory& memory;
183 std::size_t num_interpreted_instructions{}; 196 std::size_t num_interpreted_instructions{};
184 bool debugger_enabled{}; 197 const bool debugger_enabled{};
198 const bool check_memory_access{};
185 static constexpr u64 minimum_run_cycles = 10000U; 199 static constexpr u64 minimum_run_cycles = 10000U;
186}; 200};
187 201
@@ -264,6 +278,9 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
264 if (!Settings::values.cpuopt_recompile_exclusives) { 278 if (!Settings::values.cpuopt_recompile_exclusives) {
265 config.recompile_on_exclusive_fastmem_failure = false; 279 config.recompile_on_exclusive_fastmem_failure = false;
266 } 280 }
281 if (!Settings::values.cpuopt_ignore_memory_aborts) {
282 config.check_halt_on_memory_access = true;
283 }
267 } else { 284 } else {
268 // Unsafe optimizations 285 // Unsafe optimizations
269 if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { 286 if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) {
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index cb53d64ba..3df943df7 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -29,7 +29,9 @@ class 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_},
32 memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()} {} 32 memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()},
33 check_memory_access{debugger_enabled ||
34 !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
33 35
34 u8 MemoryRead8(u64 vaddr) override { 36 u8 MemoryRead8(u64 vaddr) override {
35 CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); 37 CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
@@ -198,6 +200,17 @@ public:
198 } 200 }
199 201
200 bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) { 202 bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) {
203 if (!check_memory_access) {
204 return true;
205 }
206
207 if (!memory.IsValidVirtualAddressRange(addr, size)) {
208 LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}",
209 addr);
210 parent.jit.load()->HaltExecution(ARM_Interface::no_execute);
211 return false;
212 }
213
201 if (!debugger_enabled) { 214 if (!debugger_enabled) {
202 return true; 215 return true;
203 } 216 }
@@ -226,7 +239,8 @@ public:
226 Core::Memory::Memory& memory; 239 Core::Memory::Memory& memory;
227 u64 tpidrro_el0 = 0; 240 u64 tpidrro_el0 = 0;
228 u64 tpidr_el0 = 0; 241 u64 tpidr_el0 = 0;
229 bool debugger_enabled{}; 242 const bool debugger_enabled{};
243 const bool check_memory_access{};
230 static constexpr u64 minimum_run_cycles = 10000U; 244 static constexpr u64 minimum_run_cycles = 10000U;
231}; 245};
232 246
@@ -323,6 +337,9 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
323 if (!Settings::values.cpuopt_recompile_exclusives) { 337 if (!Settings::values.cpuopt_recompile_exclusives) {
324 config.recompile_on_exclusive_fastmem_failure = false; 338 config.recompile_on_exclusive_fastmem_failure = false;
325 } 339 }
340 if (!Settings::values.cpuopt_ignore_memory_aborts) {
341 config.check_halt_on_memory_access = true;
342 }
326 } else { 343 } else {
327 // Unsafe optimizations 344 // Unsafe optimizations
328 if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { 345 if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) {
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp
index 6c230f619..52919484e 100644
--- a/src/core/frontend/applets/controller.cpp
+++ b/src/core/frontend/applets/controller.cpp
@@ -16,7 +16,7 @@ DefaultControllerApplet::DefaultControllerApplet(HID::HIDCore& hid_core_) : hid_
16 16
17DefaultControllerApplet::~DefaultControllerApplet() = default; 17DefaultControllerApplet::~DefaultControllerApplet() = default;
18 18
19void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callback, 19void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callback,
20 const ControllerParameters& parameters) const { 20 const ControllerParameters& parameters) const {
21 LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!"); 21 LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!");
22 22
diff --git a/src/core/frontend/applets/controller.h b/src/core/frontend/applets/controller.h
index 71698df74..adb2feefd 100644
--- a/src/core/frontend/applets/controller.h
+++ b/src/core/frontend/applets/controller.h
@@ -36,9 +36,11 @@ struct ControllerParameters {
36 36
37class ControllerApplet { 37class ControllerApplet {
38public: 38public:
39 using ReconfigureCallback = std::function<void()>;
40
39 virtual ~ControllerApplet(); 41 virtual ~ControllerApplet();
40 42
41 virtual void ReconfigureControllers(std::function<void()> callback, 43 virtual void ReconfigureControllers(ReconfigureCallback callback,
42 const ControllerParameters& parameters) const = 0; 44 const ControllerParameters& parameters) const = 0;
43}; 45};
44 46
@@ -47,7 +49,7 @@ public:
47 explicit DefaultControllerApplet(HID::HIDCore& hid_core_); 49 explicit DefaultControllerApplet(HID::HIDCore& hid_core_);
48 ~DefaultControllerApplet() override; 50 ~DefaultControllerApplet() override;
49 51
50 void ReconfigureControllers(std::function<void()> callback, 52 void ReconfigureControllers(ReconfigureCallback callback,
51 const ControllerParameters& parameters) const override; 53 const ControllerParameters& parameters) const override;
52 54
53private: 55private:
diff --git a/src/core/frontend/applets/error.cpp b/src/core/frontend/applets/error.cpp
index f8b961098..69c2b2b4d 100644
--- a/src/core/frontend/applets/error.cpp
+++ b/src/core/frontend/applets/error.cpp
@@ -8,13 +8,13 @@ namespace Core::Frontend {
8 8
9ErrorApplet::~ErrorApplet() = default; 9ErrorApplet::~ErrorApplet() = default;
10 10
11void DefaultErrorApplet::ShowError(Result error, std::function<void()> finished) const { 11void DefaultErrorApplet::ShowError(Result error, FinishedCallback finished) const {
12 LOG_CRITICAL(Service_Fatal, "Application requested error display: {:04}-{:04} (raw={:08X})", 12 LOG_CRITICAL(Service_Fatal, "Application requested error display: {:04}-{:04} (raw={:08X})",
13 error.module.Value(), error.description.Value(), error.raw); 13 error.module.Value(), error.description.Value(), error.raw);
14} 14}
15 15
16void DefaultErrorApplet::ShowErrorWithTimestamp(Result error, std::chrono::seconds time, 16void DefaultErrorApplet::ShowErrorWithTimestamp(Result error, std::chrono::seconds time,
17 std::function<void()> finished) const { 17 FinishedCallback finished) const {
18 LOG_CRITICAL( 18 LOG_CRITICAL(
19 Service_Fatal, 19 Service_Fatal,
20 "Application requested error display: {:04X}-{:04X} (raw={:08X}) with timestamp={:016X}", 20 "Application requested error display: {:04X}-{:04X} (raw={:08X}) with timestamp={:016X}",
@@ -23,7 +23,7 @@ void DefaultErrorApplet::ShowErrorWithTimestamp(Result error, std::chrono::secon
23 23
24void DefaultErrorApplet::ShowCustomErrorText(Result error, std::string main_text, 24void DefaultErrorApplet::ShowCustomErrorText(Result error, std::string main_text,
25 std::string detail_text, 25 std::string detail_text,
26 std::function<void()> finished) const { 26 FinishedCallback finished) const {
27 LOG_CRITICAL(Service_Fatal, 27 LOG_CRITICAL(Service_Fatal,
28 "Application requested custom error with error_code={:04X}-{:04X} (raw={:08X})", 28 "Application requested custom error with error_code={:04X}-{:04X} (raw={:08X})",
29 error.module.Value(), error.description.Value(), error.raw); 29 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 f378f8805..884f2f653 100644
--- a/src/core/frontend/applets/error.h
+++ b/src/core/frontend/applets/error.h
@@ -12,25 +12,27 @@ namespace Core::Frontend {
12 12
13class ErrorApplet { 13class ErrorApplet {
14public: 14public:
15 using FinishedCallback = std::function<void()>;
16
15 virtual ~ErrorApplet(); 17 virtual ~ErrorApplet();
16 18
17 virtual void ShowError(Result error, std::function<void()> finished) const = 0; 19 virtual void ShowError(Result error, FinishedCallback finished) const = 0;
18 20
19 virtual void ShowErrorWithTimestamp(Result error, std::chrono::seconds time, 21 virtual void ShowErrorWithTimestamp(Result error, std::chrono::seconds time,
20 std::function<void()> finished) const = 0; 22 FinishedCallback finished) const = 0;
21 23
22 virtual void ShowCustomErrorText(Result error, std::string dialog_text, 24 virtual void ShowCustomErrorText(Result error, std::string dialog_text,
23 std::string fullscreen_text, 25 std::string fullscreen_text,
24 std::function<void()> finished) const = 0; 26 FinishedCallback finished) const = 0;
25}; 27};
26 28
27class DefaultErrorApplet final : public ErrorApplet { 29class DefaultErrorApplet final : public ErrorApplet {
28public: 30public:
29 void ShowError(Result error, std::function<void()> finished) const override; 31 void ShowError(Result error, FinishedCallback finished) const override;
30 void ShowErrorWithTimestamp(Result error, std::chrono::seconds time, 32 void ShowErrorWithTimestamp(Result error, std::chrono::seconds time,
31 std::function<void()> finished) const override; 33 FinishedCallback finished) const override;
32 void ShowCustomErrorText(Result error, std::string main_text, std::string detail_text, 34 void ShowCustomErrorText(Result error, std::string main_text, std::string detail_text,
33 std::function<void()> finished) const override; 35 FinishedCallback finished) const override;
34}; 36};
35 37
36} // namespace Core::Frontend 38} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/mii_edit.cpp b/src/core/frontend/applets/mii_edit.cpp
index d37b5368a..bc8c57067 100644
--- a/src/core/frontend/applets/mii_edit.cpp
+++ b/src/core/frontend/applets/mii_edit.cpp
@@ -8,7 +8,7 @@ namespace Core::Frontend {
8 8
9MiiEditApplet::~MiiEditApplet() = default; 9MiiEditApplet::~MiiEditApplet() = default;
10 10
11void DefaultMiiEditApplet::ShowMiiEdit(const std::function<void()>& callback) const { 11void DefaultMiiEditApplet::ShowMiiEdit(const MiiEditCallback& callback) const {
12 LOG_WARNING(Service_AM, "(STUBBED) called"); 12 LOG_WARNING(Service_AM, "(STUBBED) called");
13 13
14 callback(); 14 callback();
diff --git a/src/core/frontend/applets/mii_edit.h b/src/core/frontend/applets/mii_edit.h
index 58fa2039b..d828f06ec 100644
--- a/src/core/frontend/applets/mii_edit.h
+++ b/src/core/frontend/applets/mii_edit.h
@@ -9,14 +9,16 @@ namespace Core::Frontend {
9 9
10class MiiEditApplet { 10class MiiEditApplet {
11public: 11public:
12 using MiiEditCallback = std::function<void()>;
13
12 virtual ~MiiEditApplet(); 14 virtual ~MiiEditApplet();
13 15
14 virtual void ShowMiiEdit(const std::function<void()>& callback) const = 0; 16 virtual void ShowMiiEdit(const MiiEditCallback& callback) const = 0;
15}; 17};
16 18
17class DefaultMiiEditApplet final : public MiiEditApplet { 19class DefaultMiiEditApplet final : public MiiEditApplet {
18public: 20public:
19 void ShowMiiEdit(const std::function<void()>& callback) const override; 21 void ShowMiiEdit(const MiiEditCallback& callback) const override;
20}; 22};
21 23
22} // namespace Core::Frontend 24} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/profile_select.cpp b/src/core/frontend/applets/profile_select.cpp
index d11fbce0a..da4cfbf87 100644
--- a/src/core/frontend/applets/profile_select.cpp
+++ b/src/core/frontend/applets/profile_select.cpp
@@ -9,8 +9,7 @@ namespace Core::Frontend {
9 9
10ProfileSelectApplet::~ProfileSelectApplet() = default; 10ProfileSelectApplet::~ProfileSelectApplet() = default;
11 11
12void DefaultProfileSelectApplet::SelectProfile( 12void DefaultProfileSelectApplet::SelectProfile(SelectProfileCallback callback) const {
13 std::function<void(std::optional<Common::UUID>)> callback) const {
14 Service::Account::ProfileManager manager; 13 Service::Account::ProfileManager manager;
15 callback(manager.GetUser(Settings::values.current_user.GetValue()).value_or(Common::UUID{})); 14 callback(manager.GetUser(Settings::values.current_user.GetValue()).value_or(Common::UUID{}));
16 LOG_INFO(Service_ACC, "called, selecting current user instead of prompting..."); 15 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 8d6ee5279..138429533 100644
--- a/src/core/frontend/applets/profile_select.h
+++ b/src/core/frontend/applets/profile_select.h
@@ -11,14 +11,16 @@ namespace Core::Frontend {
11 11
12class ProfileSelectApplet { 12class ProfileSelectApplet {
13public: 13public:
14 using SelectProfileCallback = std::function<void(std::optional<Common::UUID>)>;
15
14 virtual ~ProfileSelectApplet(); 16 virtual ~ProfileSelectApplet();
15 17
16 virtual void SelectProfile(std::function<void(std::optional<Common::UUID>)> callback) const = 0; 18 virtual void SelectProfile(SelectProfileCallback callback) const = 0;
17}; 19};
18 20
19class DefaultProfileSelectApplet final : public ProfileSelectApplet { 21class DefaultProfileSelectApplet final : public ProfileSelectApplet {
20public: 22public:
21 void SelectProfile(std::function<void(std::optional<Common::UUID>)> callback) const override; 23 void SelectProfile(SelectProfileCallback callback) const override;
22}; 24};
23 25
24} // namespace Core::Frontend 26} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp
index 020c7fa5e..a3720f4d7 100644
--- a/src/core/frontend/applets/software_keyboard.cpp
+++ b/src/core/frontend/applets/software_keyboard.cpp
@@ -15,10 +15,7 @@ DefaultSoftwareKeyboardApplet::~DefaultSoftwareKeyboardApplet() = default;
15 15
16void DefaultSoftwareKeyboardApplet::InitializeKeyboard( 16void DefaultSoftwareKeyboardApplet::InitializeKeyboard(
17 bool is_inline, KeyboardInitializeParameters initialize_parameters, 17 bool is_inline, KeyboardInitializeParameters initialize_parameters,
18 std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)> 18 SubmitNormalCallback submit_normal_callback_, SubmitInlineCallback submit_inline_callback_) {
19 submit_normal_callback_,
20 std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
21 submit_inline_callback_) {
22 if (is_inline) { 19 if (is_inline) {
23 LOG_WARNING( 20 LOG_WARNING(
24 Service_AM, 21 Service_AM,
diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h
index 094d1e713..8aef103d3 100644
--- a/src/core/frontend/applets/software_keyboard.h
+++ b/src/core/frontend/applets/software_keyboard.h
@@ -54,14 +54,17 @@ struct InlineTextParameters {
54 54
55class SoftwareKeyboardApplet { 55class SoftwareKeyboardApplet {
56public: 56public:
57 using SubmitInlineCallback =
58 std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>;
59 using SubmitNormalCallback =
60 std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)>;
61
57 virtual ~SoftwareKeyboardApplet(); 62 virtual ~SoftwareKeyboardApplet();
58 63
59 virtual void InitializeKeyboard( 64 virtual void InitializeKeyboard(bool is_inline,
60 bool is_inline, KeyboardInitializeParameters initialize_parameters, 65 KeyboardInitializeParameters initialize_parameters,
61 std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)> 66 SubmitNormalCallback submit_normal_callback_,
62 submit_normal_callback_, 67 SubmitInlineCallback submit_inline_callback_) = 0;
63 std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
64 submit_inline_callback_) = 0;
65 68
66 virtual void ShowNormalKeyboard() const = 0; 69 virtual void ShowNormalKeyboard() const = 0;
67 70
@@ -81,12 +84,9 @@ class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet {
81public: 84public:
82 ~DefaultSoftwareKeyboardApplet() override; 85 ~DefaultSoftwareKeyboardApplet() override;
83 86
84 void InitializeKeyboard( 87 void InitializeKeyboard(bool is_inline, KeyboardInitializeParameters initialize_parameters,
85 bool is_inline, KeyboardInitializeParameters initialize_parameters, 88 SubmitNormalCallback submit_normal_callback_,
86 std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)> 89 SubmitInlineCallback submit_inline_callback_) override;
87 submit_normal_callback_,
88 std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
89 submit_inline_callback_) override;
90 90
91 void ShowNormalKeyboard() const override; 91 void ShowNormalKeyboard() const override;
92 92
@@ -105,12 +105,10 @@ private:
105 void SubmitNormalText(std::u16string text) const; 105 void SubmitNormalText(std::u16string text) const;
106 void SubmitInlineText(std::u16string_view text) const; 106 void SubmitInlineText(std::u16string_view text) const;
107 107
108 KeyboardInitializeParameters parameters; 108 KeyboardInitializeParameters parameters{};
109 109
110 mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)> 110 mutable SubmitNormalCallback submit_normal_callback;
111 submit_normal_callback; 111 mutable SubmitInlineCallback submit_inline_callback;
112 mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
113 submit_inline_callback;
114}; 112};
115 113
116} // namespace Core::Frontend 114} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/web_browser.cpp b/src/core/frontend/applets/web_browser.cpp
index 27c7086be..b09cb7102 100644
--- a/src/core/frontend/applets/web_browser.cpp
+++ b/src/core/frontend/applets/web_browser.cpp
@@ -10,18 +10,17 @@ WebBrowserApplet::~WebBrowserApplet() = default;
10 10
11DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default; 11DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default;
12 12
13void DefaultWebBrowserApplet::OpenLocalWebPage( 13void DefaultWebBrowserApplet::OpenLocalWebPage(const std::string& local_url,
14 const std::string& local_url, std::function<void()> extract_romfs_callback, 14 ExtractROMFSCallback extract_romfs_callback,
15 std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const { 15 OpenWebPageCallback callback) const {
16 LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open local web page at {}", 16 LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open local web page at {}",
17 local_url); 17 local_url);
18 18
19 callback(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/"); 19 callback(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/");
20} 20}
21 21
22void DefaultWebBrowserApplet::OpenExternalWebPage( 22void DefaultWebBrowserApplet::OpenExternalWebPage(const std::string& external_url,
23 const std::string& external_url, 23 OpenWebPageCallback callback) const {
24 std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const {
25 LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open external web page at {}", 24 LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open external web page at {}",
26 external_url); 25 external_url);
27 26
diff --git a/src/core/frontend/applets/web_browser.h b/src/core/frontend/applets/web_browser.h
index 1411274f8..4f72284ad 100644
--- a/src/core/frontend/applets/web_browser.h
+++ b/src/core/frontend/applets/web_browser.h
@@ -11,29 +11,29 @@ namespace Core::Frontend {
11 11
12class WebBrowserApplet { 12class WebBrowserApplet {
13public: 13public:
14 using ExtractROMFSCallback = std::function<void()>;
15 using OpenWebPageCallback =
16 std::function<void(Service::AM::Applets::WebExitReason, std::string)>;
17
14 virtual ~WebBrowserApplet(); 18 virtual ~WebBrowserApplet();
15 19
16 virtual void OpenLocalWebPage( 20 virtual void OpenLocalWebPage(const std::string& local_url,
17 const std::string& local_url, std::function<void()> extract_romfs_callback, 21 ExtractROMFSCallback extract_romfs_callback,
18 std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0; 22 OpenWebPageCallback callback) const = 0;
19 23
20 virtual void OpenExternalWebPage( 24 virtual void OpenExternalWebPage(const std::string& external_url,
21 const std::string& external_url, 25 OpenWebPageCallback callback) const = 0;
22 std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0;
23}; 26};
24 27
25class DefaultWebBrowserApplet final : public WebBrowserApplet { 28class DefaultWebBrowserApplet final : public WebBrowserApplet {
26public: 29public:
27 ~DefaultWebBrowserApplet() override; 30 ~DefaultWebBrowserApplet() override;
28 31
29 void OpenLocalWebPage(const std::string& local_url, 32 void OpenLocalWebPage(const std::string& local_url, ExtractROMFSCallback extract_romfs_callback,
30 std::function<void()> extract_romfs_callback, 33 OpenWebPageCallback callback) const override;
31 std::function<void(Service::AM::Applets::WebExitReason, std::string)>
32 callback) const override;
33 34
34 void OpenExternalWebPage(const std::string& external_url, 35 void OpenExternalWebPage(const std::string& external_url,
35 std::function<void(Service::AM::Applets::WebExitReason, std::string)> 36 OpenWebPageCallback callback) const override;
36 callback) const override;
37}; 37};
38 38
39} // namespace Core::Frontend 39} // namespace Core::Frontend
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index b6c8cc58d..30c2e9d17 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -37,7 +37,7 @@ void EmulatedConsole::SetTouchParams() {
37 touchscreen_param.Set("axis_x", i * 2); 37 touchscreen_param.Set("axis_x", i * 2);
38 touchscreen_param.Set("axis_y", (i * 2) + 1); 38 touchscreen_param.Set("axis_y", (i * 2) + 1);
39 touchscreen_param.Set("button", i); 39 touchscreen_param.Set("button", i);
40 touch_params[index++] = touchscreen_param; 40 touch_params[index++] = std::move(touchscreen_param);
41 } 41 }
42 42
43 const auto button_index = 43 const auto button_index =
@@ -59,7 +59,7 @@ void EmulatedConsole::SetTouchParams() {
59 touch_button_params.Set("button", params.Serialize()); 59 touch_button_params.Set("button", params.Serialize());
60 touch_button_params.Set("x", x); 60 touch_button_params.Set("x", x);
61 touch_button_params.Set("y", y); 61 touch_button_params.Set("y", y);
62 touch_params[index] = touch_button_params; 62 touch_params[index] = std::move(touch_button_params);
63 index++; 63 index++;
64 } 64 }
65} 65}
@@ -131,7 +131,7 @@ Common::ParamPackage EmulatedConsole::GetMotionParam() const {
131} 131}
132 132
133void EmulatedConsole::SetMotionParam(Common::ParamPackage param) { 133void EmulatedConsole::SetMotionParam(Common::ParamPackage param) {
134 motion_params = param; 134 motion_params = std::move(param);
135 ReloadInput(); 135 ReloadInput();
136} 136}
137 137
@@ -199,7 +199,7 @@ void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, st
199 199
200 if (is_new_input) { 200 if (is_new_input) {
201 touch_value.pressed.value = true; 201 touch_value.pressed.value = true;
202 touch_value.id = static_cast<u32>(index); 202 touch_value.id = static_cast<int>(index);
203 } 203 }
204 204
205 touch_value.x = touch_input.x; 205 touch_value.x = touch_input.x;
@@ -284,7 +284,7 @@ void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) {
284 284
285int EmulatedConsole::SetCallback(ConsoleUpdateCallback update_callback) { 285int EmulatedConsole::SetCallback(ConsoleUpdateCallback update_callback) {
286 std::scoped_lock lock{callback_mutex}; 286 std::scoped_lock lock{callback_mutex};
287 callback_list.insert_or_assign(last_callback_key, update_callback); 287 callback_list.insert_or_assign(last_callback_key, std::move(update_callback));
288 return last_callback_key++; 288 return last_callback_key++;
289} 289}
290 290
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 74c877728..67969e938 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -424,15 +424,14 @@ void EmulatedController::RestoreConfig() {
424 ReloadFromSettings(); 424 ReloadFromSettings();
425} 425}
426 426
427std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices( 427std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices() const {
428 EmulatedDeviceIndex device_index) const {
429 std::vector<Common::ParamPackage> devices; 428 std::vector<Common::ParamPackage> devices;
430 for (const auto& param : button_params) { 429 for (const auto& param : button_params) {
431 if (!param.Has("engine")) { 430 if (!param.Has("engine")) {
432 continue; 431 continue;
433 } 432 }
434 const auto devices_it = std::find_if( 433 const auto devices_it = std::find_if(
435 devices.begin(), devices.end(), [param](const Common::ParamPackage param_) { 434 devices.begin(), devices.end(), [&param](const Common::ParamPackage& param_) {
436 return param.Get("engine", "") == param_.Get("engine", "") && 435 return param.Get("engine", "") == param_.Get("engine", "") &&
437 param.Get("guid", "") == param_.Get("guid", "") && 436 param.Get("guid", "") == param_.Get("guid", "") &&
438 param.Get("port", 0) == param_.Get("port", 0) && 437 param.Get("port", 0) == param_.Get("port", 0) &&
@@ -441,12 +440,12 @@ std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices(
441 if (devices_it != devices.end()) { 440 if (devices_it != devices.end()) {
442 continue; 441 continue;
443 } 442 }
444 Common::ParamPackage device{}; 443
444 auto& device = devices.emplace_back();
445 device.Set("engine", param.Get("engine", "")); 445 device.Set("engine", param.Get("engine", ""));
446 device.Set("guid", param.Get("guid", "")); 446 device.Set("guid", param.Get("guid", ""));
447 device.Set("port", param.Get("port", 0)); 447 device.Set("port", param.Get("port", 0));
448 device.Set("pad", param.Get("pad", 0)); 448 device.Set("pad", param.Get("pad", 0));
449 devices.push_back(device);
450 } 449 }
451 450
452 for (const auto& param : stick_params) { 451 for (const auto& param : stick_params) {
@@ -457,7 +456,7 @@ std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices(
457 continue; 456 continue;
458 } 457 }
459 const auto devices_it = std::find_if( 458 const auto devices_it = std::find_if(
460 devices.begin(), devices.end(), [param](const Common::ParamPackage param_) { 459 devices.begin(), devices.end(), [&param](const Common::ParamPackage& param_) {
461 return param.Get("engine", "") == param_.Get("engine", "") && 460 return param.Get("engine", "") == param_.Get("engine", "") &&
462 param.Get("guid", "") == param_.Get("guid", "") && 461 param.Get("guid", "") == param_.Get("guid", "") &&
463 param.Get("port", 0) == param_.Get("port", 0) && 462 param.Get("port", 0) == param_.Get("port", 0) &&
@@ -466,12 +465,12 @@ std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices(
466 if (devices_it != devices.end()) { 465 if (devices_it != devices.end()) {
467 continue; 466 continue;
468 } 467 }
469 Common::ParamPackage device{}; 468
469 auto& device = devices.emplace_back();
470 device.Set("engine", param.Get("engine", "")); 470 device.Set("engine", param.Get("engine", ""));
471 device.Set("guid", param.Get("guid", "")); 471 device.Set("guid", param.Get("guid", ""));
472 device.Set("port", param.Get("port", 0)); 472 device.Set("port", param.Get("port", 0));
473 device.Set("pad", param.Get("pad", 0)); 473 device.Set("pad", param.Get("pad", 0));
474 devices.push_back(device);
475 } 474 }
476 return devices; 475 return devices;
477} 476}
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 3f83108d3..fa7a34278 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -244,7 +244,7 @@ public:
244 void RestoreConfig(); 244 void RestoreConfig();
245 245
246 /// Returns a vector of mapped devices from the mapped button and stick parameters 246 /// Returns a vector of mapped devices from the mapped button and stick parameters
247 std::vector<Common::ParamPackage> GetMappedDevices(EmulatedDeviceIndex device_index) const; 247 std::vector<Common::ParamPackage> GetMappedDevices() const;
248 248
249 // Returns the current mapped button device 249 // Returns the current mapped button device
250 Common::ParamPackage GetButtonParam(std::size_t index) const; 250 Common::ParamPackage GetButtonParam(std::size_t index) const;
diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h
index 3b6e7baff..87ca65592 100644
--- a/src/core/hle/kernel/k_memory_block.h
+++ b/src/core/hle/kernel/k_memory_block.h
@@ -280,18 +280,19 @@ struct KMemoryInfo {
280 280
281class KMemoryBlock : public Common::IntrusiveRedBlackTreeBaseNode<KMemoryBlock> { 281class KMemoryBlock : public Common::IntrusiveRedBlackTreeBaseNode<KMemoryBlock> {
282private: 282private:
283 u16 m_device_disable_merge_left_count; 283 u16 m_device_disable_merge_left_count{};
284 u16 m_device_disable_merge_right_count; 284 u16 m_device_disable_merge_right_count{};
285 VAddr m_address; 285 VAddr m_address{};
286 size_t m_num_pages; 286 size_t m_num_pages{};
287 KMemoryState m_memory_state; 287 KMemoryState m_memory_state{KMemoryState::None};
288 u16 m_ipc_lock_count; 288 u16 m_ipc_lock_count{};
289 u16 m_device_use_count; 289 u16 m_device_use_count{};
290 u16 m_ipc_disable_merge_count; 290 u16 m_ipc_disable_merge_count{};
291 KMemoryPermission m_permission; 291 KMemoryPermission m_permission{KMemoryPermission::None};
292 KMemoryPermission m_original_permission; 292 KMemoryPermission m_original_permission{KMemoryPermission::None};
293 KMemoryAttribute m_attribute; 293 KMemoryAttribute m_attribute{KMemoryAttribute::None};
294 KMemoryBlockDisableMergeAttribute m_disable_merge_attribute; 294 KMemoryBlockDisableMergeAttribute m_disable_merge_attribute{
295 KMemoryBlockDisableMergeAttribute::None};
295 296
296public: 297public:
297 static constexpr int Compare(const KMemoryBlock& lhs, const KMemoryBlock& rhs) { 298 static constexpr int Compare(const KMemoryBlock& lhs, const KMemoryBlock& rhs) {
@@ -367,12 +368,8 @@ public:
367 368
368 constexpr KMemoryBlock(VAddr addr, size_t np, KMemoryState ms, KMemoryPermission p, 369 constexpr KMemoryBlock(VAddr addr, size_t np, KMemoryState ms, KMemoryPermission p,
369 KMemoryAttribute attr) 370 KMemoryAttribute attr)
370 : Common::IntrusiveRedBlackTreeBaseNode<KMemoryBlock>(), 371 : Common::IntrusiveRedBlackTreeBaseNode<KMemoryBlock>(), m_address(addr), m_num_pages(np),
371 m_device_disable_merge_left_count(), m_device_disable_merge_right_count(), 372 m_memory_state(ms), m_permission(p), m_attribute(attr) {}
372 m_address(addr), m_num_pages(np), m_memory_state(ms), m_ipc_lock_count(0),
373 m_device_use_count(0), m_ipc_disable_merge_count(), m_permission(p),
374 m_original_permission(KMemoryPermission::None), m_attribute(attr),
375 m_disable_merge_attribute() {}
376 373
377 constexpr void Initialize(VAddr addr, size_t np, KMemoryState ms, KMemoryPermission p, 374 constexpr void Initialize(VAddr addr, size_t np, KMemoryState ms, KMemoryPermission p,
378 KMemoryAttribute attr) { 375 KMemoryAttribute attr) {
diff --git a/src/core/hle/kernel/k_memory_block_manager.h b/src/core/hle/kernel/k_memory_block_manager.h
index 9b5873883..d382722a6 100644
--- a/src/core/hle/kernel/k_memory_block_manager.h
+++ b/src/core/hle/kernel/k_memory_block_manager.h
@@ -3,6 +3,7 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <array>
6#include <functional> 7#include <functional>
7 8
8#include "common/common_funcs.h" 9#include "common/common_funcs.h"
@@ -17,9 +18,9 @@ public:
17 static constexpr size_t MaxBlocks = 2; 18 static constexpr size_t MaxBlocks = 2;
18 19
19private: 20private:
20 KMemoryBlock* m_blocks[MaxBlocks]; 21 std::array<KMemoryBlock*, MaxBlocks> m_blocks{};
21 size_t m_index; 22 size_t m_index{MaxBlocks};
22 KMemoryBlockSlabManager* m_slab_manager; 23 KMemoryBlockSlabManager* m_slab_manager{};
23 24
24private: 25private:
25 Result Initialize(size_t num_blocks) { 26 Result Initialize(size_t num_blocks) {
@@ -41,7 +42,7 @@ private:
41public: 42public:
42 KMemoryBlockManagerUpdateAllocator(Result* out_result, KMemoryBlockSlabManager* sm, 43 KMemoryBlockManagerUpdateAllocator(Result* out_result, KMemoryBlockSlabManager* sm,
43 size_t num_blocks = MaxBlocks) 44 size_t num_blocks = MaxBlocks)
44 : m_blocks(), m_index(MaxBlocks), m_slab_manager(sm) { 45 : m_slab_manager(sm) {
45 *out_result = this->Initialize(num_blocks); 46 *out_result = this->Initialize(num_blocks);
46 } 47 }
47 48
diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h
index 5620c3660..a96c55a3e 100644
--- a/src/core/hle/kernel/k_shared_memory.h
+++ b/src/core/hle/kernel/k_shared_memory.h
@@ -74,7 +74,7 @@ public:
74 static void PostDestroy([[maybe_unused]] uintptr_t arg) {} 74 static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
75 75
76private: 76private:
77 Core::DeviceMemory* device_memory; 77 Core::DeviceMemory* device_memory{};
78 KProcess* owner_process{}; 78 KProcess* owner_process{};
79 KPageGroup page_list; 79 KPageGroup page_list;
80 Svc::MemoryPermission owner_permission{}; 80 Svc::MemoryPermission owner_permission{};
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index f38c92bff..dc52b4ed3 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -784,8 +784,8 @@ private:
784 std::vector<KSynchronizationObject*> wait_objects_for_debugging; 784 std::vector<KSynchronizationObject*> wait_objects_for_debugging;
785 VAddr mutex_wait_address_for_debugging{}; 785 VAddr mutex_wait_address_for_debugging{};
786 ThreadWaitReasonForDebugging wait_reason_for_debugging{}; 786 ThreadWaitReasonForDebugging wait_reason_for_debugging{};
787 uintptr_t argument; 787 uintptr_t argument{};
788 VAddr stack_top; 788 VAddr stack_top{};
789 789
790public: 790public:
791 using ConditionVariableThreadTreeType = ConditionVariableThreadTree; 791 using ConditionVariableThreadTreeType = ConditionVariableThreadTree;
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index b77723503..288f97df5 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -891,7 +891,7 @@ struct KernelCore::Impl {
891 Common::ThreadWorker service_threads_manager; 891 Common::ThreadWorker service_threads_manager;
892 Common::Barrier service_thread_barrier; 892 Common::Barrier service_thread_barrier;
893 893
894 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads; 894 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads{};
895 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; 895 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
896 896
897 bool is_multicore{}; 897 bool is_multicore{};
diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h
index 2fc8d4be2..fb2ba4c6b 100644
--- a/src/core/hle/kernel/physical_core.h
+++ b/src/core/hle/kernel/physical_core.h
@@ -85,7 +85,7 @@ private:
85 std::mutex guard; 85 std::mutex guard;
86 std::condition_variable on_interrupt; 86 std::condition_variable on_interrupt;
87 std::unique_ptr<Core::ARM_Interface> arm_interface; 87 std::unique_ptr<Core::ARM_Interface> arm_interface;
88 bool is_interrupted; 88 bool is_interrupted{};
89}; 89};
90 90
91} // namespace Kernel 91} // namespace Kernel
diff --git a/src/core/hle/service/nfc/mifare_user.cpp b/src/core/hle/service/nfc/mifare_user.cpp
new file mode 100644
index 000000000..51523a3ae
--- /dev/null
+++ b/src/core/hle/service/nfc/mifare_user.cpp
@@ -0,0 +1,400 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/logging/log.h"
5#include "core/core.h"
6#include "core/hid/hid_types.h"
7#include "core/hle/ipc_helpers.h"
8#include "core/hle/kernel/k_event.h"
9#include "core/hle/service/nfc/mifare_user.h"
10#include "core/hle/service/nfc/nfc_device.h"
11#include "core/hle/service/nfc/nfc_result.h"
12
13namespace Service::NFC {
14
15MFIUser::MFIUser(Core::System& system_)
16 : ServiceFramework{system_, "NFC::MFIUser"}, service_context{system_, service_name} {
17 static const FunctionInfo functions[] = {
18 {0, &MFIUser::Initialize, "Initialize"},
19 {1, &MFIUser::Finalize, "Finalize"},
20 {2, &MFIUser::ListDevices, "ListDevices"},
21 {3, &MFIUser::StartDetection, "StartDetection"},
22 {4, &MFIUser::StopDetection, "StopDetection"},
23 {5, &MFIUser::Read, "Read"},
24 {6, &MFIUser::Write, "Write"},
25 {7, &MFIUser::GetTagInfo, "GetTagInfo"},
26 {8, &MFIUser::GetActivateEventHandle, "GetActivateEventHandle"},
27 {9, &MFIUser::GetDeactivateEventHandle, "GetDeactivateEventHandle"},
28 {10, &MFIUser::GetState, "GetState"},
29 {11, &MFIUser::GetDeviceState, "GetDeviceState"},
30 {12, &MFIUser::GetNpadId, "GetNpadId"},
31 {13, &MFIUser::GetAvailabilityChangeEventHandle, "GetAvailabilityChangeEventHandle"},
32 };
33 RegisterHandlers(functions);
34
35 availability_change_event = service_context.CreateEvent("MFIUser:AvailabilityChangeEvent");
36
37 for (u32 device_index = 0; device_index < 10; device_index++) {
38 devices[device_index] =
39 std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system,
40 service_context, availability_change_event);
41 }
42}
43
44MFIUser ::~MFIUser() {
45 availability_change_event->Close();
46}
47
48void MFIUser::Initialize(Kernel::HLERequestContext& ctx) {
49 LOG_INFO(Service_NFC, "called");
50
51 state = State::Initialized;
52
53 for (auto& device : devices) {
54 device->Initialize();
55 }
56
57 IPC::ResponseBuilder rb{ctx, 2, 0};
58 rb.Push(ResultSuccess);
59}
60
61void MFIUser::Finalize(Kernel::HLERequestContext& ctx) {
62 LOG_INFO(Service_NFC, "called");
63
64 state = State::NonInitialized;
65
66 for (auto& device : devices) {
67 device->Finalize();
68 }
69
70 IPC::ResponseBuilder rb{ctx, 2};
71 rb.Push(ResultSuccess);
72}
73
74void MFIUser::ListDevices(Kernel::HLERequestContext& ctx) {
75 LOG_DEBUG(Service_NFC, "called");
76
77 if (state == State::NonInitialized) {
78 IPC::ResponseBuilder rb{ctx, 2};
79 rb.Push(MifareNfcDisabled);
80 return;
81 }
82
83 if (!ctx.CanWriteBuffer()) {
84 IPC::ResponseBuilder rb{ctx, 2};
85 rb.Push(MifareInvalidArgument);
86 return;
87 }
88
89 if (ctx.GetWriteBufferSize() == 0) {
90 IPC::ResponseBuilder rb{ctx, 2};
91 rb.Push(MifareInvalidArgument);
92 return;
93 }
94
95 std::vector<u64> nfp_devices;
96 const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>();
97
98 for (const auto& device : devices) {
99 if (nfp_devices.size() >= max_allowed_devices) {
100 continue;
101 }
102 if (device->GetCurrentState() != NFP::DeviceState::Unavailable) {
103 nfp_devices.push_back(device->GetHandle());
104 }
105 }
106
107 if (nfp_devices.empty()) {
108 IPC::ResponseBuilder rb{ctx, 2};
109 rb.Push(MifareDeviceNotFound);
110 return;
111 }
112
113 ctx.WriteBuffer(nfp_devices);
114
115 IPC::ResponseBuilder rb{ctx, 3};
116 rb.Push(ResultSuccess);
117 rb.Push(static_cast<s32>(nfp_devices.size()));
118}
119
120void MFIUser::StartDetection(Kernel::HLERequestContext& ctx) {
121 IPC::RequestParser rp{ctx};
122 const auto device_handle{rp.Pop<u64>()};
123 LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
124
125 if (state == State::NonInitialized) {
126 IPC::ResponseBuilder rb{ctx, 2};
127 rb.Push(MifareNfcDisabled);
128 return;
129 }
130
131 auto device = GetNfcDevice(device_handle);
132
133 if (!device.has_value()) {
134 IPC::ResponseBuilder rb{ctx, 2};
135 rb.Push(MifareDeviceNotFound);
136 return;
137 }
138
139 const auto result = device.value()->StartDetection(NFP::TagProtocol::All);
140 IPC::ResponseBuilder rb{ctx, 2};
141 rb.Push(result);
142}
143
144void MFIUser::StopDetection(Kernel::HLERequestContext& ctx) {
145 IPC::RequestParser rp{ctx};
146 const auto device_handle{rp.Pop<u64>()};
147 LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
148
149 if (state == State::NonInitialized) {
150 IPC::ResponseBuilder rb{ctx, 2};
151 rb.Push(MifareNfcDisabled);
152 return;
153 }
154
155 auto device = GetNfcDevice(device_handle);
156
157 if (!device.has_value()) {
158 IPC::ResponseBuilder rb{ctx, 2};
159 rb.Push(MifareDeviceNotFound);
160 return;
161 }
162
163 const auto result = device.value()->StopDetection();
164 IPC::ResponseBuilder rb{ctx, 2};
165 rb.Push(result);
166}
167
168void MFIUser::Read(Kernel::HLERequestContext& ctx) {
169 IPC::RequestParser rp{ctx};
170 const auto device_handle{rp.Pop<u64>()};
171 const auto buffer{ctx.ReadBuffer()};
172 const auto number_of_commands{ctx.GetReadBufferNumElements<NFP::MifareReadBlockParameter>()};
173 std::vector<NFP::MifareReadBlockParameter> read_commands(number_of_commands);
174
175 memcpy(read_commands.data(), buffer.data(),
176 number_of_commands * sizeof(NFP::MifareReadBlockParameter));
177
178 LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, read_commands_size={}",
179 device_handle, number_of_commands);
180
181 if (state == State::NonInitialized) {
182 IPC::ResponseBuilder rb{ctx, 2};
183 rb.Push(MifareNfcDisabled);
184 return;
185 }
186
187 auto device = GetNfcDevice(device_handle);
188
189 if (!device.has_value()) {
190 IPC::ResponseBuilder rb{ctx, 2};
191 rb.Push(MifareDeviceNotFound);
192 return;
193 }
194
195 Result result = ResultSuccess;
196 std::vector<NFP::MifareReadBlockData> out_data(number_of_commands);
197 for (std::size_t i = 0; i < number_of_commands; i++) {
198 result = device.value()->MifareRead(read_commands[i], out_data[i]);
199 if (result.IsError()) {
200 break;
201 }
202 }
203
204 ctx.WriteBuffer(out_data);
205 IPC::ResponseBuilder rb{ctx, 2};
206 rb.Push(result);
207}
208
209void MFIUser::Write(Kernel::HLERequestContext& ctx) {
210 IPC::RequestParser rp{ctx};
211 const auto device_handle{rp.Pop<u64>()};
212 const auto buffer{ctx.ReadBuffer()};
213 const auto number_of_commands{ctx.GetReadBufferNumElements<NFP::MifareWriteBlockParameter>()};
214 std::vector<NFP::MifareWriteBlockParameter> write_commands(number_of_commands);
215
216 memcpy(write_commands.data(), buffer.data(),
217 number_of_commands * sizeof(NFP::MifareWriteBlockParameter));
218
219 LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, write_commands_size={}",
220 device_handle, number_of_commands);
221
222 if (state == State::NonInitialized) {
223 IPC::ResponseBuilder rb{ctx, 2};
224 rb.Push(MifareNfcDisabled);
225 return;
226 }
227
228 auto device = GetNfcDevice(device_handle);
229
230 if (!device.has_value()) {
231 IPC::ResponseBuilder rb{ctx, 2};
232 rb.Push(MifareDeviceNotFound);
233 return;
234 }
235
236 Result result = ResultSuccess;
237 std::vector<NFP::MifareReadBlockData> out_data(number_of_commands);
238 for (std::size_t i = 0; i < number_of_commands; i++) {
239 result = device.value()->MifareWrite(write_commands[i]);
240 if (result.IsError()) {
241 break;
242 }
243 }
244
245 if (result.IsSuccess()) {
246 result = device.value()->Flush();
247 }
248
249 IPC::ResponseBuilder rb{ctx, 2};
250 rb.Push(result);
251}
252
253void MFIUser::GetTagInfo(Kernel::HLERequestContext& ctx) {
254 IPC::RequestParser rp{ctx};
255 const auto device_handle{rp.Pop<u64>()};
256 LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
257
258 if (state == State::NonInitialized) {
259 IPC::ResponseBuilder rb{ctx, 2};
260 rb.Push(MifareNfcDisabled);
261 return;
262 }
263
264 auto device = GetNfcDevice(device_handle);
265
266 if (!device.has_value()) {
267 IPC::ResponseBuilder rb{ctx, 2};
268 rb.Push(MifareDeviceNotFound);
269 return;
270 }
271
272 NFP::TagInfo tag_info{};
273 const auto result = device.value()->GetTagInfo(tag_info, true);
274 ctx.WriteBuffer(tag_info);
275 IPC::ResponseBuilder rb{ctx, 2};
276 rb.Push(result);
277}
278
279void MFIUser::GetActivateEventHandle(Kernel::HLERequestContext& ctx) {
280 IPC::RequestParser rp{ctx};
281 const auto device_handle{rp.Pop<u64>()};
282 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
283
284 if (state == State::NonInitialized) {
285 IPC::ResponseBuilder rb{ctx, 2};
286 rb.Push(MifareNfcDisabled);
287 return;
288 }
289
290 auto device = GetNfcDevice(device_handle);
291
292 if (!device.has_value()) {
293 IPC::ResponseBuilder rb{ctx, 2};
294 rb.Push(MifareDeviceNotFound);
295 return;
296 }
297
298 IPC::ResponseBuilder rb{ctx, 2, 1};
299 rb.Push(ResultSuccess);
300 rb.PushCopyObjects(device.value()->GetActivateEvent());
301}
302
303void MFIUser::GetDeactivateEventHandle(Kernel::HLERequestContext& ctx) {
304 IPC::RequestParser rp{ctx};
305 const auto device_handle{rp.Pop<u64>()};
306 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
307
308 if (state == State::NonInitialized) {
309 IPC::ResponseBuilder rb{ctx, 2};
310 rb.Push(MifareNfcDisabled);
311 return;
312 }
313
314 auto device = GetNfcDevice(device_handle);
315
316 if (!device.has_value()) {
317 IPC::ResponseBuilder rb{ctx, 2};
318 rb.Push(MifareDeviceNotFound);
319 return;
320 }
321
322 IPC::ResponseBuilder rb{ctx, 2, 1};
323 rb.Push(ResultSuccess);
324 rb.PushCopyObjects(device.value()->GetDeactivateEvent());
325}
326
327void MFIUser::GetState(Kernel::HLERequestContext& ctx) {
328 LOG_DEBUG(Service_NFC, "called");
329
330 IPC::ResponseBuilder rb{ctx, 3};
331 rb.Push(ResultSuccess);
332 rb.PushEnum(state);
333}
334
335void MFIUser::GetDeviceState(Kernel::HLERequestContext& ctx) {
336 IPC::RequestParser rp{ctx};
337 const auto device_handle{rp.Pop<u64>()};
338 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
339
340 auto device = GetNfcDevice(device_handle);
341
342 if (!device.has_value()) {
343 IPC::ResponseBuilder rb{ctx, 2};
344 rb.Push(MifareDeviceNotFound);
345 return;
346 }
347
348 IPC::ResponseBuilder rb{ctx, 3};
349 rb.Push(ResultSuccess);
350 rb.PushEnum(device.value()->GetCurrentState());
351}
352
353void MFIUser::GetNpadId(Kernel::HLERequestContext& ctx) {
354 IPC::RequestParser rp{ctx};
355 const auto device_handle{rp.Pop<u64>()};
356 LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
357
358 if (state == State::NonInitialized) {
359 IPC::ResponseBuilder rb{ctx, 2};
360 rb.Push(MifareNfcDisabled);
361 return;
362 }
363
364 auto device = GetNfcDevice(device_handle);
365
366 if (!device.has_value()) {
367 IPC::ResponseBuilder rb{ctx, 2};
368 rb.Push(MifareDeviceNotFound);
369 return;
370 }
371
372 IPC::ResponseBuilder rb{ctx, 3};
373 rb.Push(ResultSuccess);
374 rb.PushEnum(device.value()->GetNpadId());
375}
376
377void MFIUser::GetAvailabilityChangeEventHandle(Kernel::HLERequestContext& ctx) {
378 LOG_INFO(Service_NFC, "called");
379
380 if (state == State::NonInitialized) {
381 IPC::ResponseBuilder rb{ctx, 2};
382 rb.Push(MifareNfcDisabled);
383 return;
384 }
385
386 IPC::ResponseBuilder rb{ctx, 2, 1};
387 rb.Push(ResultSuccess);
388 rb.PushCopyObjects(availability_change_event->GetReadableEvent());
389}
390
391std::optional<std::shared_ptr<NfcDevice>> MFIUser::GetNfcDevice(u64 handle) {
392 for (auto& device : devices) {
393 if (device->GetHandle() == handle) {
394 return device;
395 }
396 }
397 return std::nullopt;
398}
399
400} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/mifare_user.h b/src/core/hle/service/nfc/mifare_user.h
new file mode 100644
index 000000000..0e0638cb6
--- /dev/null
+++ b/src/core/hle/service/nfc/mifare_user.h
@@ -0,0 +1,52 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <array>
7#include <memory>
8#include <optional>
9
10#include "core/hle/service/kernel_helpers.h"
11#include "core/hle/service/service.h"
12
13namespace Service::NFC {
14class NfcDevice;
15
16class MFIUser final : public ServiceFramework<MFIUser> {
17public:
18 explicit MFIUser(Core::System& system_);
19 ~MFIUser();
20
21private:
22 enum class State : u32 {
23 NonInitialized,
24 Initialized,
25 };
26
27 void Initialize(Kernel::HLERequestContext& ctx);
28 void Finalize(Kernel::HLERequestContext& ctx);
29 void ListDevices(Kernel::HLERequestContext& ctx);
30 void StartDetection(Kernel::HLERequestContext& ctx);
31 void StopDetection(Kernel::HLERequestContext& ctx);
32 void Read(Kernel::HLERequestContext& ctx);
33 void Write(Kernel::HLERequestContext& ctx);
34 void GetTagInfo(Kernel::HLERequestContext& ctx);
35 void GetActivateEventHandle(Kernel::HLERequestContext& ctx);
36 void GetDeactivateEventHandle(Kernel::HLERequestContext& ctx);
37 void GetState(Kernel::HLERequestContext& ctx);
38 void GetDeviceState(Kernel::HLERequestContext& ctx);
39 void GetNpadId(Kernel::HLERequestContext& ctx);
40 void GetAvailabilityChangeEventHandle(Kernel::HLERequestContext& ctx);
41
42 std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle);
43
44 KernelHelpers::ServiceContext service_context;
45
46 std::array<std::shared_ptr<NfcDevice>, 10> devices{};
47
48 State state{State::NonInitialized};
49 Kernel::KEvent* availability_change_event;
50};
51
52} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp
index 2f4bacb3b..b17b18ab9 100644
--- a/src/core/hle/service/nfc/nfc.cpp
+++ b/src/core/hle/service/nfc/nfc.cpp
@@ -6,6 +6,7 @@
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "common/settings.h" 7#include "common/settings.h"
8#include "core/hle/ipc_helpers.h" 8#include "core/hle/ipc_helpers.h"
9#include "core/hle/service/nfc/mifare_user.h"
9#include "core/hle/service/nfc/nfc.h" 10#include "core/hle/service/nfc/nfc.h"
10#include "core/hle/service/nfc/nfc_user.h" 11#include "core/hle/service/nfc/nfc_user.h"
11#include "core/hle/service/service.h" 12#include "core/hle/service/service.h"
@@ -50,32 +51,6 @@ private:
50 } 51 }
51}; 52};
52 53
53class MFIUser final : public ServiceFramework<MFIUser> {
54public:
55 explicit MFIUser(Core::System& system_) : ServiceFramework{system_, "NFC::MFIUser"} {
56 // clang-format off
57 static const FunctionInfo functions[] = {
58 {0, nullptr, "Initialize"},
59 {1, nullptr, "Finalize"},
60 {2, nullptr, "ListDevices"},
61 {3, nullptr, "StartDetection"},
62 {4, nullptr, "StopDetection"},
63 {5, nullptr, "Read"},
64 {6, nullptr, "Write"},
65 {7, nullptr, "GetTagInfo"},
66 {8, nullptr, "GetActivateEventHandle"},
67 {9, nullptr, "GetDeactivateEventHandle"},
68 {10, nullptr, "GetState"},
69 {11, nullptr, "GetDeviceState"},
70 {12, nullptr, "GetNpadId"},
71 {13, nullptr, "GetAvailabilityChangeEventHandle"},
72 };
73 // clang-format on
74
75 RegisterHandlers(functions);
76 }
77};
78
79class NFC_MF_U final : public ServiceFramework<NFC_MF_U> { 54class NFC_MF_U final : public ServiceFramework<NFC_MF_U> {
80public: 55public:
81 explicit NFC_MF_U(Core::System& system_) : ServiceFramework{system_, "nfc:mf:u"} { 56 explicit NFC_MF_U(Core::System& system_) : ServiceFramework{system_, "nfc:mf:u"} {
diff --git a/src/core/hle/service/nfc/nfc_device.cpp b/src/core/hle/service/nfc/nfc_device.cpp
index 4d514cf5f..78578f723 100644
--- a/src/core/hle/service/nfc/nfc_device.cpp
+++ b/src/core/hle/service/nfc/nfc_device.cpp
@@ -77,11 +77,13 @@ bool NfcDevice::LoadNfcTag(std::span<const u8> data) {
77 return false; 77 return false;
78 } 78 }
79 79
80 if (data.size() != sizeof(NFP::EncryptedNTAG215File)) { 80 if (data.size() < sizeof(NFP::EncryptedNTAG215File)) {
81 LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size()); 81 LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size());
82 return false; 82 return false;
83 } 83 }
84 84
85 tag_data.resize(data.size());
86 memcpy(tag_data.data(), data.data(), data.size());
85 memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); 87 memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));
86 88
87 device_state = NFP::DeviceState::TagFound; 89 device_state = NFP::DeviceState::TagFound;
@@ -121,7 +123,7 @@ void NfcDevice::Finalize() {
121 device_state = NFP::DeviceState::Unavailable; 123 device_state = NFP::DeviceState::Unavailable;
122} 124}
123 125
124Result NfcDevice::StartDetection(s32 protocol_) { 126Result NfcDevice::StartDetection(NFP::TagProtocol allowed_protocol) {
125 if (device_state != NFP::DeviceState::Initialized && 127 if (device_state != NFP::DeviceState::Initialized &&
126 device_state != NFP::DeviceState::TagRemoved) { 128 device_state != NFP::DeviceState::TagRemoved) {
127 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); 129 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
@@ -134,7 +136,7 @@ Result NfcDevice::StartDetection(s32 protocol_) {
134 } 136 }
135 137
136 device_state = NFP::DeviceState::SearchingForTag; 138 device_state = NFP::DeviceState::SearchingForTag;
137 protocol = protocol_; 139 allowed_protocols = allowed_protocol;
138 return ResultSuccess; 140 return ResultSuccess;
139} 141}
140 142
@@ -160,7 +162,7 @@ Result NfcDevice::StopDetection() {
160 return WrongDeviceState; 162 return WrongDeviceState;
161} 163}
162 164
163Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info) const { 165Result NfcDevice::Flush() {
164 if (device_state != NFP::DeviceState::TagFound && 166 if (device_state != NFP::DeviceState::TagFound &&
165 device_state != NFP::DeviceState::TagMounted) { 167 device_state != NFP::DeviceState::TagMounted) {
166 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); 168 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
@@ -170,6 +172,34 @@ Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info) const {
170 return WrongDeviceState; 172 return WrongDeviceState;
171 } 173 }
172 174
175 if (!npad_device->WriteNfc(tag_data)) {
176 LOG_ERROR(Service_NFP, "Error writing to file");
177 return MifareReadError;
178 }
179
180 return ResultSuccess;
181}
182
183Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const {
184 if (device_state != NFP::DeviceState::TagFound &&
185 device_state != NFP::DeviceState::TagMounted) {
186 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
187 if (device_state == NFP::DeviceState::TagRemoved) {
188 return TagRemoved;
189 }
190 return WrongDeviceState;
191 }
192
193 if (is_mifare) {
194 tag_info = {
195 .uuid = encrypted_tag_data.uuid.uid,
196 .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()),
197 .protocol = NFP::TagProtocol::TypeA,
198 .tag_type = NFP::TagType::Type4,
199 };
200 return ResultSuccess;
201 }
202
173 // Protocol and tag type may change here 203 // Protocol and tag type may change here
174 tag_info = { 204 tag_info = {
175 .uuid = encrypted_tag_data.uuid.uid, 205 .uuid = encrypted_tag_data.uuid.uid,
@@ -181,6 +211,52 @@ Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info) const {
181 return ResultSuccess; 211 return ResultSuccess;
182} 212}
183 213
214Result NfcDevice::MifareRead(const NFP::MifareReadBlockParameter& parameter,
215 NFP::MifareReadBlockData& read_block_data) {
216 const std::size_t sector_index = parameter.sector_number * sizeof(NFP::DataBlock);
217 read_block_data.sector_number = parameter.sector_number;
218
219 if (device_state != NFP::DeviceState::TagFound &&
220 device_state != NFP::DeviceState::TagMounted) {
221 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
222 if (device_state == NFP::DeviceState::TagRemoved) {
223 return TagRemoved;
224 }
225 return WrongDeviceState;
226 }
227
228 if (tag_data.size() < sector_index + sizeof(NFP::DataBlock)) {
229 return MifareReadError;
230 }
231
232 // TODO: Use parameter.sector_key to read encrypted data
233 memcpy(read_block_data.data.data(), tag_data.data() + sector_index, sizeof(NFP::DataBlock));
234
235 return ResultSuccess;
236}
237
238Result NfcDevice::MifareWrite(const NFP::MifareWriteBlockParameter& parameter) {
239 const std::size_t sector_index = parameter.sector_number * sizeof(NFP::DataBlock);
240
241 if (device_state != NFP::DeviceState::TagFound &&
242 device_state != NFP::DeviceState::TagMounted) {
243 LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
244 if (device_state == NFP::DeviceState::TagRemoved) {
245 return TagRemoved;
246 }
247 return WrongDeviceState;
248 }
249
250 if (tag_data.size() < sector_index + sizeof(NFP::DataBlock)) {
251 return MifareReadError;
252 }
253
254 // TODO: Use parameter.sector_key to encrypt the data
255 memcpy(tag_data.data() + sector_index, parameter.data.data(), sizeof(NFP::DataBlock));
256
257 return ResultSuccess;
258}
259
184u64 NfcDevice::GetHandle() const { 260u64 NfcDevice::GetHandle() const {
185 // Generate a handle based of the npad id 261 // Generate a handle based of the npad id
186 return static_cast<u64>(npad_id); 262 return static_cast<u64>(npad_id);
diff --git a/src/core/hle/service/nfc/nfc_device.h b/src/core/hle/service/nfc/nfc_device.h
index fa1348f1a..a6e114d36 100644
--- a/src/core/hle/service/nfc/nfc_device.h
+++ b/src/core/hle/service/nfc/nfc_device.h
@@ -34,10 +34,16 @@ public:
34 void Initialize(); 34 void Initialize();
35 void Finalize(); 35 void Finalize();
36 36
37 Result StartDetection(s32 protocol_); 37 Result StartDetection(NFP::TagProtocol allowed_protocol);
38 Result StopDetection(); 38 Result StopDetection();
39 Result Flush();
39 40
40 Result GetTagInfo(NFP::TagInfo& tag_info) const; 41 Result GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const;
42
43 Result MifareRead(const NFP::MifareReadBlockParameter& parameter,
44 NFP::MifareReadBlockData& read_block_data);
45
46 Result MifareWrite(const NFP::MifareWriteBlockParameter& parameter);
41 47
42 u64 GetHandle() const; 48 u64 GetHandle() const;
43 NFP::DeviceState GetCurrentState() const; 49 NFP::DeviceState GetCurrentState() const;
@@ -61,10 +67,11 @@ private:
61 Kernel::KEvent* deactivate_event = nullptr; 67 Kernel::KEvent* deactivate_event = nullptr;
62 Kernel::KEvent* availability_change_event = nullptr; 68 Kernel::KEvent* availability_change_event = nullptr;
63 69
64 s32 protocol{}; 70 NFP::TagProtocol allowed_protocols{};
65 NFP::DeviceState device_state{NFP::DeviceState::Unavailable}; 71 NFP::DeviceState device_state{NFP::DeviceState::Unavailable};
66 72
67 NFP::EncryptedNTAG215File encrypted_tag_data{}; 73 NFP::EncryptedNTAG215File encrypted_tag_data{};
74 std::vector<u8> tag_data{};
68}; 75};
69 76
70} // namespace Service::NFC 77} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/nfc_result.h b/src/core/hle/service/nfc/nfc_result.h
index 537dc15f4..146b8ba61 100644
--- a/src/core/hle/service/nfc/nfc_result.h
+++ b/src/core/hle/service/nfc/nfc_result.h
@@ -12,6 +12,12 @@ constexpr Result InvalidArgument(ErrorModule::NFC, 65);
12constexpr Result WrongDeviceState(ErrorModule::NFC, 73); 12constexpr Result WrongDeviceState(ErrorModule::NFC, 73);
13constexpr Result NfcDisabled(ErrorModule::NFC, 80); 13constexpr Result NfcDisabled(ErrorModule::NFC, 80);
14constexpr Result TagRemoved(ErrorModule::NFC, 97); 14constexpr Result TagRemoved(ErrorModule::NFC, 97);
15constexpr Result CorruptedData(ErrorModule::NFC, 144); 15
16constexpr Result MifareDeviceNotFound(ErrorModule::NFCMifare, 64);
17constexpr Result MifareInvalidArgument(ErrorModule::NFCMifare, 65);
18constexpr Result MifareWrongDeviceState(ErrorModule::NFCMifare, 73);
19constexpr Result MifareNfcDisabled(ErrorModule::NFCMifare, 80);
20constexpr Result MifareTagRemoved(ErrorModule::NFCMifare, 97);
21constexpr Result MifareReadError(ErrorModule::NFCMifare, 288);
16 22
17} // namespace Service::NFC 23} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/nfc_user.cpp b/src/core/hle/service/nfc/nfc_user.cpp
index ced2d560b..4615697e2 100644
--- a/src/core/hle/service/nfc/nfc_user.cpp
+++ b/src/core/hle/service/nfc/nfc_user.cpp
@@ -201,7 +201,7 @@ void IUser::AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) {
201void IUser::StartDetection(Kernel::HLERequestContext& ctx) { 201void IUser::StartDetection(Kernel::HLERequestContext& ctx) {
202 IPC::RequestParser rp{ctx}; 202 IPC::RequestParser rp{ctx};
203 const auto device_handle{rp.Pop<u64>()}; 203 const auto device_handle{rp.Pop<u64>()};
204 const auto nfp_protocol{rp.Pop<s32>()}; 204 const auto nfp_protocol{rp.PopEnum<NFP::TagProtocol>()};
205 LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol); 205 LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol);
206 206
207 if (state == State::NonInitialized) { 207 if (state == State::NonInitialized) {
@@ -267,7 +267,7 @@ void IUser::GetTagInfo(Kernel::HLERequestContext& ctx) {
267 } 267 }
268 268
269 NFP::TagInfo tag_info{}; 269 NFP::TagInfo tag_info{};
270 const auto result = device.value()->GetTagInfo(tag_info); 270 const auto result = device.value()->GetTagInfo(tag_info, false);
271 ctx.WriteBuffer(tag_info); 271 ctx.WriteBuffer(tag_info);
272 IPC::ResponseBuilder rb{ctx, 2}; 272 IPC::ResponseBuilder rb{ctx, 2};
273 rb.Push(result); 273 rb.Push(result);
diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h
index 69858096a..fc228c2b2 100644
--- a/src/core/hle/service/nfp/nfp_types.h
+++ b/src/core/hle/service/nfp/nfp_types.h
@@ -106,11 +106,24 @@ enum class CabinetMode : u8 {
106 StartFormatter, 106 StartFormatter,
107}; 107};
108 108
109enum class MifareCmd : u8 {
110 AuthA = 0x60,
111 AuthB = 0x61,
112 Read = 0x30,
113 Write = 0xA0,
114 Transfer = 0xB0,
115 Decrement = 0xC0,
116 Increment = 0xC1,
117 Store = 0xC2
118};
119
109using UniqueSerialNumber = std::array<u8, 7>; 120using UniqueSerialNumber = std::array<u8, 7>;
110using LockBytes = std::array<u8, 2>; 121using LockBytes = std::array<u8, 2>;
111using HashData = std::array<u8, 0x20>; 122using HashData = std::array<u8, 0x20>;
112using ApplicationArea = std::array<u8, 0xD8>; 123using ApplicationArea = std::array<u8, 0xD8>;
113using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>; 124using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>;
125using DataBlock = std::array<u8, 0x10>;
126using KeyData = std::array<u8, 0x6>;
114 127
115struct TagUuid { 128struct TagUuid {
116 UniqueSerialNumber uid; 129 UniqueSerialNumber uid;
@@ -323,4 +336,37 @@ struct RegisterInfo {
323}; 336};
324static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size"); 337static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size");
325 338
339struct SectorKey {
340 MifareCmd command;
341 u8 unknown; // Usually 1
342 INSERT_PADDING_BYTES(0x6);
343 KeyData sector_key;
344 INSERT_PADDING_BYTES(0x2);
345};
346static_assert(sizeof(SectorKey) == 0x10, "SectorKey is an invalid size");
347
348struct MifareReadBlockParameter {
349 u8 sector_number;
350 INSERT_PADDING_BYTES(0x7);
351 SectorKey sector_key;
352};
353static_assert(sizeof(MifareReadBlockParameter) == 0x18,
354 "MifareReadBlockParameter is an invalid size");
355
356struct MifareReadBlockData {
357 DataBlock data;
358 u8 sector_number;
359 INSERT_PADDING_BYTES(0x7);
360};
361static_assert(sizeof(MifareReadBlockData) == 0x18, "MifareReadBlockData is an invalid size");
362
363struct MifareWriteBlockParameter {
364 DataBlock data;
365 u8 sector_number;
366 INSERT_PADDING_BYTES(0x7);
367 SectorKey sector_key;
368};
369static_assert(sizeof(MifareWriteBlockParameter) == 0x28,
370 "MifareWriteBlockParameter is an invalid size");
371
326} // namespace Service::NFP 372} // namespace Service::NFP
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp
index 6e21296f6..77821e047 100644
--- a/src/core/reporter.cpp
+++ b/src/core/reporter.cpp
@@ -38,7 +38,7 @@ std::string GetTimestamp() {
38 38
39using namespace nlohmann; 39using namespace nlohmann;
40 40
41void SaveToFile(json json, const std::filesystem::path& filename) { 41void SaveToFile(const json& json, const std::filesystem::path& filename) {
42 if (!Common::FS::CreateParentDirs(filename)) { 42 if (!Common::FS::CreateParentDirs(filename)) {
43 LOG_ERROR(Core, "Failed to create path for '{}' to save report!", 43 LOG_ERROR(Core, "Failed to create path for '{}' to save report!",
44 Common::FS::PathToUTF8String(filename)); 44 Common::FS::PathToUTF8String(filename));
@@ -81,8 +81,8 @@ json GetReportCommonData(u64 title_id, Result result, const std::string& timesta
81} 81}
82 82
83json GetProcessorStateData(const std::string& architecture, u64 entry_point, u64 sp, u64 pc, 83json GetProcessorStateData(const std::string& architecture, u64 entry_point, u64 sp, u64 pc,
84 u64 pstate, std::array<u64, 31> registers, 84 u64 pstate, const std::array<u64, 31>& registers,
85 std::optional<std::array<u64, 32>> backtrace = {}) { 85 const std::optional<std::array<u64, 32>>& backtrace = {}) {
86 auto out = json{ 86 auto out = json{
87 {"entry_point", fmt::format("{:016X}", entry_point)}, 87 {"entry_point", fmt::format("{:016X}", entry_point)},
88 {"sp", fmt::format("{:016X}", sp)}, 88 {"sp", fmt::format("{:016X}", sp)},
@@ -224,11 +224,11 @@ void Reporter::SaveCrashReport(u64 title_id, Result result, u64 set_flags, u64 e
224 224
225 out["processor_state"] = std::move(proc_out); 225 out["processor_state"] = std::move(proc_out);
226 226
227 SaveToFile(std::move(out), GetPath("crash_report", title_id, timestamp)); 227 SaveToFile(out, GetPath("crash_report", title_id, timestamp));
228} 228}
229 229
230void Reporter::SaveSvcBreakReport(u32 type, bool signal_debugger, u64 info1, u64 info2, 230void Reporter::SaveSvcBreakReport(u32 type, bool signal_debugger, u64 info1, u64 info2,
231 std::optional<std::vector<u8>> resolved_buffer) const { 231 const std::optional<std::vector<u8>>& resolved_buffer) const {
232 if (!IsReportingEnabled()) { 232 if (!IsReportingEnabled()) {
233 return; 233 return;
234 } 234 }
@@ -250,7 +250,7 @@ void Reporter::SaveSvcBreakReport(u32 type, bool signal_debugger, u64 info1, u64
250 250
251 out["svc_break"] = std::move(break_out); 251 out["svc_break"] = std::move(break_out);
252 252
253 SaveToFile(std::move(out), GetPath("svc_break_report", title_id, timestamp)); 253 SaveToFile(out, GetPath("svc_break_report", title_id, timestamp));
254} 254}
255 255
256void Reporter::SaveUnimplementedFunctionReport(Kernel::HLERequestContext& ctx, u32 command_id, 256void Reporter::SaveUnimplementedFunctionReport(Kernel::HLERequestContext& ctx, u32 command_id,
@@ -271,13 +271,13 @@ void Reporter::SaveUnimplementedFunctionReport(Kernel::HLERequestContext& ctx, u
271 271
272 out["function"] = std::move(function_out); 272 out["function"] = std::move(function_out);
273 273
274 SaveToFile(std::move(out), GetPath("unimpl_func_report", title_id, timestamp)); 274 SaveToFile(out, GetPath("unimpl_func_report", title_id, timestamp));
275} 275}
276 276
277void Reporter::SaveUnimplementedAppletReport( 277void Reporter::SaveUnimplementedAppletReport(
278 u32 applet_id, u32 common_args_version, u32 library_version, u32 theme_color, 278 u32 applet_id, u32 common_args_version, u32 library_version, u32 theme_color,
279 bool startup_sound, u64 system_tick, std::vector<std::vector<u8>> normal_channel, 279 bool startup_sound, u64 system_tick, const std::vector<std::vector<u8>>& normal_channel,
280 std::vector<std::vector<u8>> interactive_channel) const { 280 const std::vector<std::vector<u8>>& interactive_channel) const {
281 if (!IsReportingEnabled()) { 281 if (!IsReportingEnabled()) {
282 return; 282 return;
283 } 283 }
@@ -308,10 +308,11 @@ void Reporter::SaveUnimplementedAppletReport(
308 out["applet_normal_data"] = std::move(normal_out); 308 out["applet_normal_data"] = std::move(normal_out);
309 out["applet_interactive_data"] = std::move(interactive_out); 309 out["applet_interactive_data"] = std::move(interactive_out);
310 310
311 SaveToFile(std::move(out), GetPath("unimpl_applet_report", title_id, timestamp)); 311 SaveToFile(out, GetPath("unimpl_applet_report", title_id, timestamp));
312} 312}
313 313
314void Reporter::SavePlayReport(PlayReportType type, u64 title_id, std::vector<std::vector<u8>> data, 314void Reporter::SavePlayReport(PlayReportType type, u64 title_id,
315 const std::vector<std::vector<u8>>& data,
315 std::optional<u64> process_id, std::optional<u128> user_id) const { 316 std::optional<u64> process_id, std::optional<u128> user_id) const {
316 if (!IsReportingEnabled()) { 317 if (!IsReportingEnabled()) {
317 return; 318 return;
@@ -335,12 +336,12 @@ void Reporter::SavePlayReport(PlayReportType type, u64 title_id, std::vector<std
335 out["play_report_type"] = fmt::format("{:02}", static_cast<u8>(type)); 336 out["play_report_type"] = fmt::format("{:02}", static_cast<u8>(type));
336 out["play_report_data"] = std::move(data_out); 337 out["play_report_data"] = std::move(data_out);
337 338
338 SaveToFile(std::move(out), GetPath("play_report", title_id, timestamp)); 339 SaveToFile(out, GetPath("play_report", title_id, timestamp));
339} 340}
340 341
341void Reporter::SaveErrorReport(u64 title_id, Result result, 342void Reporter::SaveErrorReport(u64 title_id, Result result,
342 std::optional<std::string> custom_text_main, 343 const std::optional<std::string>& custom_text_main,
343 std::optional<std::string> custom_text_detail) const { 344 const std::optional<std::string>& custom_text_detail) const {
344 if (!IsReportingEnabled()) { 345 if (!IsReportingEnabled()) {
345 return; 346 return;
346 } 347 }
@@ -354,11 +355,11 @@ void Reporter::SaveErrorReport(u64 title_id, Result result,
354 out["backtrace"] = GetBacktraceData(system); 355 out["backtrace"] = GetBacktraceData(system);
355 356
356 out["error_custom_text"] = { 357 out["error_custom_text"] = {
357 {"main", *custom_text_main}, 358 {"main", custom_text_main.value_or("")},
358 {"detail", *custom_text_detail}, 359 {"detail", custom_text_detail.value_or("")},
359 }; 360 };
360 361
361 SaveToFile(std::move(out), GetPath("error_report", title_id, timestamp)); 362 SaveToFile(out, GetPath("error_report", title_id, timestamp));
362} 363}
363 364
364void Reporter::SaveFSAccessLog(std::string_view log_message) const { 365void Reporter::SaveFSAccessLog(std::string_view log_message) const {
diff --git a/src/core/reporter.h b/src/core/reporter.h
index 68755cbde..9fdb9d6c1 100644
--- a/src/core/reporter.h
+++ b/src/core/reporter.h
@@ -36,7 +36,7 @@ public:
36 36
37 // Used by syscall svcBreak 37 // Used by syscall svcBreak
38 void SaveSvcBreakReport(u32 type, bool signal_debugger, u64 info1, u64 info2, 38 void SaveSvcBreakReport(u32 type, bool signal_debugger, u64 info1, u64 info2,
39 std::optional<std::vector<u8>> resolved_buffer = {}) const; 39 const std::optional<std::vector<u8>>& resolved_buffer = {}) const;
40 40
41 // Used by HLE service handler 41 // Used by HLE service handler
42 void SaveUnimplementedFunctionReport(Kernel::HLERequestContext& ctx, u32 command_id, 42 void SaveUnimplementedFunctionReport(Kernel::HLERequestContext& ctx, u32 command_id,
@@ -44,10 +44,10 @@ public:
44 const std::string& service_name) const; 44 const std::string& service_name) const;
45 45
46 // Used by stub applet implementation 46 // Used by stub applet implementation
47 void SaveUnimplementedAppletReport(u32 applet_id, u32 common_args_version, u32 library_version, 47 void SaveUnimplementedAppletReport(
48 u32 theme_color, bool startup_sound, u64 system_tick, 48 u32 applet_id, u32 common_args_version, u32 library_version, u32 theme_color,
49 std::vector<std::vector<u8>> normal_channel, 49 bool startup_sound, u64 system_tick, const std::vector<std::vector<u8>>& normal_channel,
50 std::vector<std::vector<u8>> interactive_channel) const; 50 const std::vector<std::vector<u8>>& interactive_channel) const;
51 51
52 enum class PlayReportType { 52 enum class PlayReportType {
53 Old, 53 Old,
@@ -56,13 +56,13 @@ public:
56 System, 56 System,
57 }; 57 };
58 58
59 void SavePlayReport(PlayReportType type, u64 title_id, std::vector<std::vector<u8>> data, 59 void SavePlayReport(PlayReportType type, u64 title_id, const std::vector<std::vector<u8>>& data,
60 std::optional<u64> process_id = {}, std::optional<u128> user_id = {}) const; 60 std::optional<u64> process_id = {}, std::optional<u128> user_id = {}) const;
61 61
62 // Used by error applet 62 // Used by error applet
63 void SaveErrorReport(u64 title_id, Result result, 63 void SaveErrorReport(u64 title_id, Result result,
64 std::optional<std::string> custom_text_main = {}, 64 const std::optional<std::string>& custom_text_main = {},
65 std::optional<std::string> custom_text_detail = {}) const; 65 const std::optional<std::string>& custom_text_detail = {}) const;
66 66
67 void SaveFSAccessLog(std::string_view log_message) const; 67 void SaveFSAccessLog(std::string_view log_message) const;
68 68
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index e41da2726..7932aaab0 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -56,18 +56,12 @@ if (ENABLE_SDL2)
56 drivers/sdl_driver.cpp 56 drivers/sdl_driver.cpp
57 drivers/sdl_driver.h 57 drivers/sdl_driver.h
58 ) 58 )
59 if (YUZU_USE_EXTERNAL_SDL2) 59 target_link_libraries(input_common PRIVATE SDL2::SDL2)
60 target_link_libraries(input_common PRIVATE SDL2-static)
61 else()
62 target_link_libraries(input_common PRIVATE SDL2)
63 endif()
64 target_compile_definitions(input_common PRIVATE HAVE_SDL2) 60 target_compile_definitions(input_common PRIVATE HAVE_SDL2)
65endif() 61endif()
66 62
67target_link_libraries(input_common PRIVATE usb)
68
69create_target_directory_groups(input_common) 63create_target_directory_groups(input_common)
70target_link_libraries(input_common PUBLIC core PRIVATE common Boost::boost) 64target_link_libraries(input_common PUBLIC core PRIVATE common Boost::boost libusb::usb)
71 65
72if (YUZU_USE_PRECOMPILED_HEADERS) 66if (YUZU_USE_PRECOMPILED_HEADERS)
73 target_precompile_headers(input_common PRIVATE precompiled_headers.h) 67 target_precompile_headers(input_common PRIVATE precompiled_headers.h)
diff --git a/src/input_common/drivers/virtual_amiibo.cpp b/src/input_common/drivers/virtual_amiibo.cpp
index 564a188e5..63ffaca67 100644
--- a/src/input_common/drivers/virtual_amiibo.cpp
+++ b/src/input_common/drivers/virtual_amiibo.cpp
@@ -47,20 +47,20 @@ Common::Input::NfcState VirtualAmiibo::SupportsNfc(
47 47
48Common::Input::NfcState VirtualAmiibo::WriteNfcData( 48Common::Input::NfcState VirtualAmiibo::WriteNfcData(
49 [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) { 49 [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) {
50 const Common::FS::IOFile amiibo_file{file_path, Common::FS::FileAccessMode::ReadWrite, 50 const Common::FS::IOFile nfc_file{file_path, Common::FS::FileAccessMode::ReadWrite,
51 Common::FS::FileType::BinaryFile}; 51 Common::FS::FileType::BinaryFile};
52 52
53 if (!amiibo_file.IsOpen()) { 53 if (!nfc_file.IsOpen()) {
54 LOG_ERROR(Core, "Amiibo is already on use"); 54 LOG_ERROR(Core, "Amiibo is already on use");
55 return Common::Input::NfcState::WriteFailed; 55 return Common::Input::NfcState::WriteFailed;
56 } 56 }
57 57
58 if (!amiibo_file.Write(data)) { 58 if (!nfc_file.Write(data)) {
59 LOG_ERROR(Service_NFP, "Error writting to file"); 59 LOG_ERROR(Service_NFP, "Error writting to file");
60 return Common::Input::NfcState::WriteFailed; 60 return Common::Input::NfcState::WriteFailed;
61 } 61 }
62 62
63 amiibo_data = data; 63 nfc_data = data;
64 64
65 return Common::Input::NfcState::Success; 65 return Common::Input::NfcState::Success;
66} 66}
@@ -70,32 +70,44 @@ VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const {
70} 70}
71 71
72VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) { 72VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) {
73 const Common::FS::IOFile amiibo_file{filename, Common::FS::FileAccessMode::Read, 73 const Common::FS::IOFile nfc_file{filename, Common::FS::FileAccessMode::Read,
74 Common::FS::FileType::BinaryFile}; 74 Common::FS::FileType::BinaryFile};
75 75
76 if (state != State::WaitingForAmiibo) { 76 if (state != State::WaitingForAmiibo) {
77 return Info::WrongDeviceState; 77 return Info::WrongDeviceState;
78 } 78 }
79 79
80 if (!amiibo_file.IsOpen()) { 80 if (!nfc_file.IsOpen()) {
81 return Info::UnableToLoad; 81 return Info::UnableToLoad;
82 } 82 }
83 83
84 amiibo_data.resize(amiibo_size); 84 switch (nfc_file.GetSize()) {
85 85 case AmiiboSize:
86 if (amiibo_file.Read(amiibo_data) < amiibo_size_without_password) { 86 case AmiiboSizeWithoutPassword:
87 nfc_data.resize(AmiiboSize);
88 if (nfc_file.Read(nfc_data) < AmiiboSizeWithoutPassword) {
89 return Info::NotAnAmiibo;
90 }
91 break;
92 case MifareSize:
93 nfc_data.resize(MifareSize);
94 if (nfc_file.Read(nfc_data) < MifareSize) {
95 return Info::NotAnAmiibo;
96 }
97 break;
98 default:
87 return Info::NotAnAmiibo; 99 return Info::NotAnAmiibo;
88 } 100 }
89 101
90 file_path = filename; 102 file_path = filename;
91 state = State::AmiiboIsOpen; 103 state = State::AmiiboIsOpen;
92 SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, amiibo_data}); 104 SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, nfc_data});
93 return Info::Success; 105 return Info::Success;
94} 106}
95 107
96VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() { 108VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() {
97 if (state == State::AmiiboIsOpen) { 109 if (state == State::AmiiboIsOpen) {
98 SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, amiibo_data}); 110 SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, nfc_data});
99 return Info::Success; 111 return Info::Success;
100 } 112 }
101 113
diff --git a/src/input_common/drivers/virtual_amiibo.h b/src/input_common/drivers/virtual_amiibo.h
index 9baeb3997..0f9dad333 100644
--- a/src/input_common/drivers/virtual_amiibo.h
+++ b/src/input_common/drivers/virtual_amiibo.h
@@ -53,12 +53,13 @@ public:
53 std::string GetLastFilePath() const; 53 std::string GetLastFilePath() const;
54 54
55private: 55private:
56 static constexpr std::size_t amiibo_size = 0x21C; 56 static constexpr std::size_t AmiiboSize = 0x21C;
57 static constexpr std::size_t amiibo_size_without_password = amiibo_size - 0x8; 57 static constexpr std::size_t AmiiboSizeWithoutPassword = AmiiboSize - 0x8;
58 static constexpr std::size_t MifareSize = 0x400;
58 59
59 std::string file_path{}; 60 std::string file_path{};
60 State state{State::Initialized}; 61 State state{State::Initialized};
61 std::vector<u8> amiibo_data; 62 std::vector<u8> nfc_data;
62 Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Pasive}; 63 Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Pasive};
63}; 64};
64} // namespace InputCommon 65} // namespace InputCommon
diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt
index c85c308de..1ab52da59 100644
--- a/src/network/CMakeLists.txt
+++ b/src/network/CMakeLists.txt
@@ -19,7 +19,7 @@ add_library(network STATIC
19 19
20create_target_directory_groups(network) 20create_target_directory_groups(network)
21 21
22target_link_libraries(network PRIVATE common enet Boost::boost) 22target_link_libraries(network PRIVATE common enet::enet Boost::boost)
23if (ENABLE_WEB_SERVICE) 23if (ENABLE_WEB_SERVICE)
24 target_compile_definitions(network PRIVATE -DENABLE_WEB_SERVICE) 24 target_compile_definitions(network PRIVATE -DENABLE_WEB_SERVICE)
25 target_link_libraries(network PRIVATE web_service) 25 target_link_libraries(network PRIVATE web_service)
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 33bdae748..06e44d5b5 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -266,8 +266,7 @@ target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS})
266 266
267add_dependencies(video_core host_shaders) 267add_dependencies(video_core host_shaders)
268target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) 268target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE})
269target_include_directories(video_core PRIVATE sirit ../../externals/Vulkan-Headers/include) 269target_link_libraries(video_core PRIVATE sirit Vulkan::Headers)
270target_link_libraries(video_core PRIVATE sirit)
271 270
272if (ENABLE_NSIGHT_AFTERMATH) 271if (ENABLE_NSIGHT_AFTERMATH)
273 if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK}) 272 if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK})
@@ -307,11 +306,11 @@ if (ARCHITECTURE_x86_64)
307 macro/macro_jit_x64.cpp 306 macro/macro_jit_x64.cpp
308 macro/macro_jit_x64.h 307 macro/macro_jit_x64.h
309 ) 308 )
310 target_link_libraries(video_core PUBLIC xbyak) 309 target_link_libraries(video_core PUBLIC xbyak::xbyak)
311endif() 310endif()
312 311
313if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) 312if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
314 target_link_libraries(video_core PRIVATE dynarmic) 313 target_link_libraries(video_core PRIVATE dynarmic::dynarmic)
315endif() 314endif()
316 315
317if (YUZU_USE_PRECOMPILED_HEADERS) 316if (YUZU_USE_PRECOMPILED_HEADERS)
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index d4ef8d7c5..9b182b653 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -382,41 +382,51 @@ void Maxwell3D::ProcessQueryGet() {
382 382
383void Maxwell3D::ProcessQueryCondition() { 383void Maxwell3D::ProcessQueryCondition() {
384 const GPUVAddr condition_address{regs.render_enable.Address()}; 384 const GPUVAddr condition_address{regs.render_enable.Address()};
385 switch (regs.render_enable.mode) { 385 switch (regs.render_enable_override) {
386 case Regs::RenderEnable::Mode::True: { 386 case Regs::RenderEnable::Override::AlwaysRender:
387 execute_on = true; 387 execute_on = true;
388 break; 388 break;
389 } 389 case Regs::RenderEnable::Override::NeverRender:
390 case Regs::RenderEnable::Mode::False: {
391 execute_on = false; 390 execute_on = false;
392 break; 391 break;
393 } 392 case Regs::RenderEnable::Override::UseRenderEnable:
394 case Regs::RenderEnable::Mode::Conditional: { 393 switch (regs.render_enable.mode) {
395 Regs::ReportSemaphore::Compare cmp; 394 case Regs::RenderEnable::Mode::True: {
396 memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp)); 395 execute_on = true;
397 execute_on = cmp.initial_sequence != 0U && cmp.initial_mode != 0U; 396 break;
398 break; 397 }
399 } 398 case Regs::RenderEnable::Mode::False: {
400 case Regs::RenderEnable::Mode::IfEqual: { 399 execute_on = false;
401 Regs::ReportSemaphore::Compare cmp; 400 break;
402 memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp)); 401 }
403 execute_on = 402 case Regs::RenderEnable::Mode::Conditional: {
404 cmp.initial_sequence == cmp.current_sequence && cmp.initial_mode == cmp.current_mode; 403 Regs::ReportSemaphore::Compare cmp;
405 break; 404 memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
406 } 405 execute_on = cmp.initial_sequence != 0U && cmp.initial_mode != 0U;
407 case Regs::RenderEnable::Mode::IfNotEqual: { 406 break;
408 Regs::ReportSemaphore::Compare cmp; 407 }
409 memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp)); 408 case Regs::RenderEnable::Mode::IfEqual: {
410 execute_on = 409 Regs::ReportSemaphore::Compare cmp;
411 cmp.initial_sequence != cmp.current_sequence || cmp.initial_mode != cmp.current_mode; 410 memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
412 break; 411 execute_on = cmp.initial_sequence == cmp.current_sequence &&
413 } 412 cmp.initial_mode == cmp.current_mode;
414 default: { 413 break;
415 UNIMPLEMENTED_MSG("Uninplemented Condition Mode!"); 414 }
416 execute_on = true; 415 case Regs::RenderEnable::Mode::IfNotEqual: {
416 Regs::ReportSemaphore::Compare cmp;
417 memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp));
418 execute_on = cmp.initial_sequence != cmp.current_sequence ||
419 cmp.initial_mode != cmp.current_mode;
420 break;
421 }
422 default: {
423 UNIMPLEMENTED_MSG("Uninplemented Condition Mode!");
424 execute_on = true;
425 break;
426 }
427 }
417 break; 428 break;
418 } 429 }
419 }
420} 430}
421 431
422void Maxwell3D::ProcessCounterReset() { 432void Maxwell3D::ProcessCounterReset() {
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
index 24529c80f..e62b36822 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
@@ -95,6 +95,8 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d,
95 provoking_vertex_last.Assign(regs.provoking_vertex == Maxwell::ProvokingVertex::Last ? 1 : 0); 95 provoking_vertex_last.Assign(regs.provoking_vertex == Maxwell::ProvokingVertex::Last ? 1 : 0);
96 conservative_raster_enable.Assign(regs.conservative_raster_enable != 0 ? 1 : 0); 96 conservative_raster_enable.Assign(regs.conservative_raster_enable != 0 ? 1 : 0);
97 smooth_lines.Assign(regs.line_anti_alias_enable != 0 ? 1 : 0); 97 smooth_lines.Assign(regs.line_anti_alias_enable != 0 ? 1 : 0);
98 alpha_to_coverage_enabled.Assign(regs.anti_alias_alpha_control.alpha_to_coverage != 0 ? 1 : 0);
99 alpha_to_one_enabled.Assign(regs.anti_alias_alpha_control.alpha_to_one != 0 ? 1 : 0);
98 100
99 for (size_t i = 0; i < regs.rt.size(); ++i) { 101 for (size_t i = 0; i < regs.rt.size(); ++i) {
100 color_formats[i] = static_cast<u8>(regs.rt[i].format); 102 color_formats[i] = static_cast<u8>(regs.rt[i].format);
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
index 1afdef329..ab79fb8f3 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
@@ -195,6 +195,8 @@ struct FixedPipelineState {
195 BitField<12, 1, u32> provoking_vertex_last; 195 BitField<12, 1, u32> provoking_vertex_last;
196 BitField<13, 1, u32> conservative_raster_enable; 196 BitField<13, 1, u32> conservative_raster_enable;
197 BitField<14, 1, u32> smooth_lines; 197 BitField<14, 1, u32> smooth_lines;
198 BitField<15, 1, u32> alpha_to_coverage_enabled;
199 BitField<16, 1, u32> alpha_to_one_enabled;
198 }; 200 };
199 std::array<u8, Maxwell::NumRenderTargets> color_formats; 201 std::array<u8, Maxwell::NumRenderTargets> color_formats;
200 202
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index e77a57a4a..006128638 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -714,8 +714,8 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
714 .sampleShadingEnable = VK_FALSE, 714 .sampleShadingEnable = VK_FALSE,
715 .minSampleShading = 0.0f, 715 .minSampleShading = 0.0f,
716 .pSampleMask = nullptr, 716 .pSampleMask = nullptr,
717 .alphaToCoverageEnable = VK_FALSE, 717 .alphaToCoverageEnable = key.state.alpha_to_coverage_enabled != 0 ? VK_TRUE : VK_FALSE,
718 .alphaToOneEnable = VK_FALSE, 718 .alphaToOneEnable = key.state.alpha_to_one_enabled != 0 ? VK_TRUE : VK_FALSE,
719 }; 719 };
720 const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{ 720 const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{
721 .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, 721 .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
diff --git a/src/video_core/vulkan_common/vulkan_debug_callback.cpp b/src/video_core/vulkan_common/vulkan_debug_callback.cpp
index 736474009..10a001b8f 100644
--- a/src/video_core/vulkan_common/vulkan_debug_callback.cpp
+++ b/src/video_core/vulkan_common/vulkan_debug_callback.cpp
@@ -16,6 +16,8 @@ VkBool32 Callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
16 case 0x682a878au: // VUID-vkCmdBindVertexBuffers2EXT-pBuffers-parameter 16 case 0x682a878au: // VUID-vkCmdBindVertexBuffers2EXT-pBuffers-parameter
17 case 0x99fb7dfdu: // UNASSIGNED-RequiredParameter (vkCmdBindVertexBuffers2EXT pBuffers[0]) 17 case 0x99fb7dfdu: // UNASSIGNED-RequiredParameter (vkCmdBindVertexBuffers2EXT pBuffers[0])
18 case 0xe8616bf2u: // Bound VkDescriptorSet 0x0[] was destroyed. Likely push_descriptor related 18 case 0xe8616bf2u: // Bound VkDescriptorSet 0x0[] was destroyed. Likely push_descriptor related
19 case 0x1608dec0u: // Image layout in vkUpdateDescriptorSet doesn't match descriptor use
20 case 0x55362756u: // Descriptor binding and framebuffer attachment overlap
19 return VK_FALSE; 21 return VK_FALSE;
20 default: 22 default:
21 break; 23 break;
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 33856fe59..6a2ad4b1d 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -86,6 +86,8 @@ constexpr std::array REQUIRED_EXTENSIONS{
86}; 86};
87 87
88constexpr std::array REQUIRED_EXTENSIONS_BEFORE_1_2{ 88constexpr std::array REQUIRED_EXTENSIONS_BEFORE_1_2{
89 VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME,
90 VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME,
89 VK_KHR_8BIT_STORAGE_EXTENSION_NAME, 91 VK_KHR_8BIT_STORAGE_EXTENSION_NAME,
90 VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, 92 VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME,
91 VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, 93 VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME,
@@ -1117,7 +1119,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
1117 test(has_ext_transform_feedback, VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, false); 1119 test(has_ext_transform_feedback, VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, false);
1118 test(has_ext_custom_border_color, VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME, false); 1120 test(has_ext_custom_border_color, VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME, false);
1119 test(has_ext_extended_dynamic_state, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, false); 1121 test(has_ext_extended_dynamic_state, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, false);
1120 test(has_ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false); 1122 test(has_ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, true);
1121 test(has_ext_provoking_vertex, VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, false); 1123 test(has_ext_provoking_vertex, VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, false);
1122 test(has_ext_vertex_input_dynamic_state, VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME, 1124 test(has_ext_vertex_input_dynamic_state, VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME,
1123 false); 1125 false);
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp
index e4a07813f..bda10ee2f 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.cpp
+++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp
@@ -454,6 +454,12 @@ VkResult Free(VkDevice device, VkCommandPool handle, Span<VkCommandBuffer> buffe
454 454
455Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char*> extensions, 455Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char*> extensions,
456 InstanceDispatch& dispatch) { 456 InstanceDispatch& dispatch) {
457#ifdef __APPLE__
458 constexpr VkFlags ci_flags{VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR};
459#else
460 constexpr VkFlags ci_flags{};
461#endif
462
457 const VkApplicationInfo application_info{ 463 const VkApplicationInfo application_info{
458 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, 464 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
459 .pNext = nullptr, 465 .pNext = nullptr,
@@ -466,7 +472,7 @@ Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char
466 const VkInstanceCreateInfo ci{ 472 const VkInstanceCreateInfo ci{
467 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 473 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
468 .pNext = nullptr, 474 .pNext = nullptr,
469 .flags = 0, 475 .flags = ci_flags,
470 .pApplicationInfo = &application_info, 476 .pApplicationInfo = &application_info,
471 .enabledLayerCount = layers.size(), 477 .enabledLayerCount = layers.size(),
472 .ppEnabledLayerNames = layers.data(), 478 .ppEnabledLayerNames = layers.data(),
diff --git a/src/web_service/CMakeLists.txt b/src/web_service/CMakeLists.txt
index 19534b9e4..02582aa04 100644
--- a/src/web_service/CMakeLists.txt
+++ b/src/web_service/CMakeLists.txt
@@ -17,7 +17,7 @@ add_library(web_service STATIC
17) 17)
18 18
19create_target_directory_groups(web_service) 19create_target_directory_groups(web_service)
20target_link_libraries(web_service PRIVATE common network nlohmann_json::nlohmann_json httplib cpp-jwt) 20target_link_libraries(web_service PRIVATE common network nlohmann_json::nlohmann_json httplib::httplib cpp-jwt::cpp-jwt)
21 21
22if (YUZU_USE_PRECOMPILED_HEADERS) 22if (YUZU_USE_PRECOMPILED_HEADERS)
23 target_precompile_headers(web_service PRIVATE precompiled_headers.h) 23 target_precompile_headers(web_service PRIVATE precompiled_headers.h)
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index f192d6329..d23eb2907 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -318,7 +318,7 @@ target_link_libraries(yuzu PRIVATE common core input_common network video_core)
318target_link_libraries(yuzu PRIVATE Boost::boost glad Qt${QT_MAJOR_VERSION}::Widgets) 318target_link_libraries(yuzu PRIVATE Boost::boost glad Qt${QT_MAJOR_VERSION}::Widgets)
319target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) 319target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
320 320
321target_include_directories(yuzu PRIVATE ../../externals/Vulkan-Headers/include) 321target_link_libraries(yuzu PRIVATE Vulkan::Headers)
322if (NOT WIN32) 322if (NOT WIN32)
323 target_include_directories(yuzu PRIVATE ${Qt${QT_MAJOR_VERSION}Gui_PRIVATE_INCLUDE_DIRS}) 323 target_include_directories(yuzu PRIVATE ${Qt${QT_MAJOR_VERSION}Gui_PRIVATE_INCLUDE_DIRS})
324endif() 324endif()
@@ -354,7 +354,7 @@ if (USE_DISCORD_PRESENCE)
354 discord_impl.cpp 354 discord_impl.cpp
355 discord_impl.h 355 discord_impl.h
356 ) 356 )
357 target_link_libraries(yuzu PRIVATE discord-rpc) 357 target_link_libraries(yuzu PRIVATE DiscordRPC::discord-rpc)
358 target_compile_definitions(yuzu PRIVATE -DUSE_DISCORD_PRESENCE) 358 target_compile_definitions(yuzu PRIVATE -DUSE_DISCORD_PRESENCE)
359endif() 359endif()
360 360
@@ -391,11 +391,7 @@ if (YUZU_USE_BUNDLED_QT AND QT_VERSION VERSION_LESS 6)
391endif() 391endif()
392 392
393if (ENABLE_SDL2) 393if (ENABLE_SDL2)
394 if (YUZU_USE_EXTERNAL_SDL2) 394 target_link_libraries(yuzu PRIVATE SDL2::SDL2)
395 target_link_libraries(yuzu PRIVATE SDL2-static)
396 else()
397 target_link_libraries(yuzu PRIVATE SDL2)
398 endif()
399 target_compile_definitions(yuzu PRIVATE HAVE_SDL2) 395 target_compile_definitions(yuzu PRIVATE HAVE_SDL2)
400endif() 396endif()
401 397
@@ -411,7 +407,7 @@ if (NOT APPLE)
411endif() 407endif()
412 408
413if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) 409if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
414 target_link_libraries(yuzu PRIVATE dynarmic) 410 target_link_libraries(yuzu PRIVATE dynarmic::dynarmic)
415endif() 411endif()
416 412
417if (YUZU_USE_PRECOMPILED_HEADERS) 413if (YUZU_USE_PRECOMPILED_HEADERS)
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index 12efdc216..c30b54499 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -685,7 +685,7 @@ QtControllerSelector::QtControllerSelector(GMainWindow& parent) {
685QtControllerSelector::~QtControllerSelector() = default; 685QtControllerSelector::~QtControllerSelector() = default;
686 686
687void QtControllerSelector::ReconfigureControllers( 687void QtControllerSelector::ReconfigureControllers(
688 std::function<void()> callback_, const Core::Frontend::ControllerParameters& parameters) const { 688 ReconfigureCallback callback_, const Core::Frontend::ControllerParameters& parameters) const {
689 callback = std::move(callback_); 689 callback = std::move(callback_);
690 emit MainWindowReconfigureControllers(parameters); 690 emit MainWindowReconfigureControllers(parameters);
691} 691}
diff --git a/src/yuzu/applets/qt_controller.h b/src/yuzu/applets/qt_controller.h
index cf948d2b5..16e99f507 100644
--- a/src/yuzu/applets/qt_controller.h
+++ b/src/yuzu/applets/qt_controller.h
@@ -157,7 +157,7 @@ public:
157 ~QtControllerSelector() override; 157 ~QtControllerSelector() override;
158 158
159 void ReconfigureControllers( 159 void ReconfigureControllers(
160 std::function<void()> callback_, 160 ReconfigureCallback callback_,
161 const Core::Frontend::ControllerParameters& parameters) const override; 161 const Core::Frontend::ControllerParameters& parameters) const override;
162 162
163signals: 163signals:
@@ -167,5 +167,5 @@ signals:
167private: 167private:
168 void MainWindowReconfigureFinished(); 168 void MainWindowReconfigureFinished();
169 169
170 mutable std::function<void()> callback; 170 mutable ReconfigureCallback callback;
171}; 171};
diff --git a/src/yuzu/applets/qt_error.cpp b/src/yuzu/applets/qt_error.cpp
index 367d5352d..e0190a979 100644
--- a/src/yuzu/applets/qt_error.cpp
+++ b/src/yuzu/applets/qt_error.cpp
@@ -14,7 +14,7 @@ QtErrorDisplay::QtErrorDisplay(GMainWindow& parent) {
14 14
15QtErrorDisplay::~QtErrorDisplay() = default; 15QtErrorDisplay::~QtErrorDisplay() = default;
16 16
17void QtErrorDisplay::ShowError(Result error, std::function<void()> finished) const { 17void QtErrorDisplay::ShowError(Result error, FinishedCallback finished) const {
18 callback = std::move(finished); 18 callback = std::move(finished);
19 emit MainWindowDisplayError( 19 emit MainWindowDisplayError(
20 tr("Error Code: %1-%2 (0x%3)") 20 tr("Error Code: %1-%2 (0x%3)")
@@ -25,7 +25,7 @@ void QtErrorDisplay::ShowError(Result error, std::function<void()> finished) con
25} 25}
26 26
27void QtErrorDisplay::ShowErrorWithTimestamp(Result error, std::chrono::seconds time, 27void QtErrorDisplay::ShowErrorWithTimestamp(Result error, std::chrono::seconds time,
28 std::function<void()> finished) const { 28 FinishedCallback finished) const {
29 callback = std::move(finished); 29 callback = std::move(finished);
30 30
31 const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count()); 31 const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count());
@@ -42,7 +42,7 @@ void QtErrorDisplay::ShowErrorWithTimestamp(Result error, std::chrono::seconds t
42 42
43void QtErrorDisplay::ShowCustomErrorText(Result error, std::string dialog_text, 43void QtErrorDisplay::ShowCustomErrorText(Result error, std::string dialog_text,
44 std::string fullscreen_text, 44 std::string fullscreen_text,
45 std::function<void()> finished) const { 45 FinishedCallback finished) const {
46 callback = std::move(finished); 46 callback = std::move(finished);
47 emit MainWindowDisplayError( 47 emit MainWindowDisplayError(
48 tr("Error Code: %1-%2 (0x%3)") 48 tr("Error Code: %1-%2 (0x%3)")
diff --git a/src/yuzu/applets/qt_error.h b/src/yuzu/applets/qt_error.h
index eb4107c7e..e4e174721 100644
--- a/src/yuzu/applets/qt_error.h
+++ b/src/yuzu/applets/qt_error.h
@@ -16,11 +16,11 @@ public:
16 explicit QtErrorDisplay(GMainWindow& parent); 16 explicit QtErrorDisplay(GMainWindow& parent);
17 ~QtErrorDisplay() override; 17 ~QtErrorDisplay() override;
18 18
19 void ShowError(Result error, std::function<void()> finished) const override; 19 void ShowError(Result error, FinishedCallback finished) const override;
20 void ShowErrorWithTimestamp(Result error, std::chrono::seconds time, 20 void ShowErrorWithTimestamp(Result error, std::chrono::seconds time,
21 std::function<void()> finished) const override; 21 FinishedCallback finished) const override;
22 void ShowCustomErrorText(Result error, std::string dialog_text, std::string fullscreen_text, 22 void ShowCustomErrorText(Result error, std::string dialog_text, std::string fullscreen_text,
23 std::function<void()> finished) const override; 23 FinishedCallback finished) const override;
24 24
25signals: 25signals:
26 void MainWindowDisplayError(QString error_code, QString error_text) const; 26 void MainWindowDisplayError(QString error_code, QString error_text) const;
@@ -28,5 +28,5 @@ signals:
28private: 28private:
29 void MainWindowFinishedError(); 29 void MainWindowFinishedError();
30 30
31 mutable std::function<void()> callback; 31 mutable FinishedCallback callback;
32}; 32};
diff --git a/src/yuzu/applets/qt_profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp
index c8bcfb223..4145c5299 100644
--- a/src/yuzu/applets/qt_profile_select.cpp
+++ b/src/yuzu/applets/qt_profile_select.cpp
@@ -163,8 +163,7 @@ QtProfileSelector::QtProfileSelector(GMainWindow& parent) {
163 163
164QtProfileSelector::~QtProfileSelector() = default; 164QtProfileSelector::~QtProfileSelector() = default;
165 165
166void QtProfileSelector::SelectProfile( 166void QtProfileSelector::SelectProfile(SelectProfileCallback callback_) const {
167 std::function<void(std::optional<Common::UUID>)> callback_) const {
168 callback = std::move(callback_); 167 callback = std::move(callback_);
169 emit MainWindowSelectProfile(); 168 emit MainWindowSelectProfile();
170} 169}
diff --git a/src/yuzu/applets/qt_profile_select.h b/src/yuzu/applets/qt_profile_select.h
index 124f2cdbd..637a3bda2 100644
--- a/src/yuzu/applets/qt_profile_select.h
+++ b/src/yuzu/applets/qt_profile_select.h
@@ -65,7 +65,7 @@ public:
65 explicit QtProfileSelector(GMainWindow& parent); 65 explicit QtProfileSelector(GMainWindow& parent);
66 ~QtProfileSelector() override; 66 ~QtProfileSelector() override;
67 67
68 void SelectProfile(std::function<void(std::optional<Common::UUID>)> callback_) const override; 68 void SelectProfile(SelectProfileCallback callback_) const override;
69 69
70signals: 70signals:
71 void MainWindowSelectProfile() const; 71 void MainWindowSelectProfile() const;
@@ -73,5 +73,5 @@ signals:
73private: 73private:
74 void MainWindowFinishedSelection(std::optional<Common::UUID> uuid); 74 void MainWindowFinishedSelection(std::optional<Common::UUID> uuid);
75 75
76 mutable std::function<void(std::optional<Common::UUID>)> callback; 76 mutable SelectProfileCallback callback;
77}; 77};
diff --git a/src/yuzu/applets/qt_software_keyboard.cpp b/src/yuzu/applets/qt_software_keyboard.cpp
index e60506197..734b0ea40 100644
--- a/src/yuzu/applets/qt_software_keyboard.cpp
+++ b/src/yuzu/applets/qt_software_keyboard.cpp
@@ -1566,10 +1566,7 @@ QtSoftwareKeyboard::~QtSoftwareKeyboard() = default;
1566 1566
1567void QtSoftwareKeyboard::InitializeKeyboard( 1567void QtSoftwareKeyboard::InitializeKeyboard(
1568 bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, 1568 bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters,
1569 std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)> 1569 SubmitNormalCallback submit_normal_callback_, SubmitInlineCallback submit_inline_callback_) {
1570 submit_normal_callback_,
1571 std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
1572 submit_inline_callback_) {
1573 if (is_inline) { 1570 if (is_inline) {
1574 submit_inline_callback = std::move(submit_inline_callback_); 1571 submit_inline_callback = std::move(submit_inline_callback_);
1575 } else { 1572 } else {
diff --git a/src/yuzu/applets/qt_software_keyboard.h b/src/yuzu/applets/qt_software_keyboard.h
index 35d4ee2ef..30ac8ecf6 100644
--- a/src/yuzu/applets/qt_software_keyboard.h
+++ b/src/yuzu/applets/qt_software_keyboard.h
@@ -233,12 +233,10 @@ public:
233 explicit QtSoftwareKeyboard(GMainWindow& parent); 233 explicit QtSoftwareKeyboard(GMainWindow& parent);
234 ~QtSoftwareKeyboard() override; 234 ~QtSoftwareKeyboard() override;
235 235
236 void InitializeKeyboard( 236 void InitializeKeyboard(bool is_inline,
237 bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, 237 Core::Frontend::KeyboardInitializeParameters initialize_parameters,
238 std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)> 238 SubmitNormalCallback submit_normal_callback_,
239 submit_normal_callback_, 239 SubmitInlineCallback submit_inline_callback_) override;
240 std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
241 submit_inline_callback_) override;
242 240
243 void ShowNormalKeyboard() const override; 241 void ShowNormalKeyboard() const override;
244 242
@@ -279,8 +277,6 @@ private:
279 void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, 277 void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
280 std::u16string submitted_text, s32 cursor_position) const; 278 std::u16string submitted_text, s32 cursor_position) const;
281 279
282 mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)> 280 mutable SubmitNormalCallback submit_normal_callback;
283 submit_normal_callback; 281 mutable SubmitInlineCallback submit_inline_callback;
284 mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
285 submit_inline_callback;
286}; 282};
diff --git a/src/yuzu/applets/qt_web_browser.cpp b/src/yuzu/applets/qt_web_browser.cpp
index 89bd482e0..0a5912326 100644
--- a/src/yuzu/applets/qt_web_browser.cpp
+++ b/src/yuzu/applets/qt_web_browser.cpp
@@ -401,9 +401,9 @@ QtWebBrowser::QtWebBrowser(GMainWindow& main_window) {
401 401
402QtWebBrowser::~QtWebBrowser() = default; 402QtWebBrowser::~QtWebBrowser() = default;
403 403
404void QtWebBrowser::OpenLocalWebPage( 404void QtWebBrowser::OpenLocalWebPage(const std::string& local_url,
405 const std::string& local_url, std::function<void()> extract_romfs_callback_, 405 ExtractROMFSCallback extract_romfs_callback_,
406 std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const { 406 OpenWebPageCallback callback_) const {
407 extract_romfs_callback = std::move(extract_romfs_callback_); 407 extract_romfs_callback = std::move(extract_romfs_callback_);
408 callback = std::move(callback_); 408 callback = std::move(callback_);
409 409
@@ -416,9 +416,8 @@ void QtWebBrowser::OpenLocalWebPage(
416 } 416 }
417} 417}
418 418
419void QtWebBrowser::OpenExternalWebPage( 419void QtWebBrowser::OpenExternalWebPage(const std::string& external_url,
420 const std::string& external_url, 420 OpenWebPageCallback callback_) const {
421 std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const {
422 callback = std::move(callback_); 421 callback = std::move(callback_);
423 422
424 const auto index = external_url.find('?'); 423 const auto index = external_url.find('?');
diff --git a/src/yuzu/applets/qt_web_browser.h b/src/yuzu/applets/qt_web_browser.h
index 043800853..e8fe511ed 100644
--- a/src/yuzu/applets/qt_web_browser.h
+++ b/src/yuzu/applets/qt_web_browser.h
@@ -197,13 +197,11 @@ public:
197 ~QtWebBrowser() override; 197 ~QtWebBrowser() override;
198 198
199 void OpenLocalWebPage(const std::string& local_url, 199 void OpenLocalWebPage(const std::string& local_url,
200 std::function<void()> extract_romfs_callback_, 200 ExtractROMFSCallback extract_romfs_callback_,
201 std::function<void(Service::AM::Applets::WebExitReason, std::string)> 201 OpenWebPageCallback callback_) const override;
202 callback_) const override;
203 202
204 void OpenExternalWebPage(const std::string& external_url, 203 void OpenExternalWebPage(const std::string& external_url,
205 std::function<void(Service::AM::Applets::WebExitReason, std::string)> 204 OpenWebPageCallback callback_) const override;
206 callback_) const override;
207 205
208signals: 206signals:
209 void MainWindowOpenWebPage(const std::string& main_url, const std::string& additional_args, 207 void MainWindowOpenWebPage(const std::string& main_url, const std::string& additional_args,
@@ -215,7 +213,6 @@ private:
215 void MainWindowWebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, 213 void MainWindowWebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason,
216 std::string last_url); 214 std::string last_url);
217 215
218 mutable std::function<void()> extract_romfs_callback; 216 mutable ExtractROMFSCallback extract_romfs_callback;
219 217 mutable OpenWebPageCallback callback;
220 mutable std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback;
221}; 218};
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index c11d1c8b3..722fc708e 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -679,6 +679,7 @@ void Config::ReadCpuValues() {
679 ReadBasicSetting(Settings::values.cpuopt_fastmem); 679 ReadBasicSetting(Settings::values.cpuopt_fastmem);
680 ReadBasicSetting(Settings::values.cpuopt_fastmem_exclusives); 680 ReadBasicSetting(Settings::values.cpuopt_fastmem_exclusives);
681 ReadBasicSetting(Settings::values.cpuopt_recompile_exclusives); 681 ReadBasicSetting(Settings::values.cpuopt_recompile_exclusives);
682 ReadBasicSetting(Settings::values.cpuopt_ignore_memory_aborts);
682 } 683 }
683 684
684 qt_config->endGroup(); 685 qt_config->endGroup();
@@ -1291,6 +1292,7 @@ void Config::SaveCpuValues() {
1291 WriteBasicSetting(Settings::values.cpuopt_fastmem); 1292 WriteBasicSetting(Settings::values.cpuopt_fastmem);
1292 WriteBasicSetting(Settings::values.cpuopt_fastmem_exclusives); 1293 WriteBasicSetting(Settings::values.cpuopt_fastmem_exclusives);
1293 WriteBasicSetting(Settings::values.cpuopt_recompile_exclusives); 1294 WriteBasicSetting(Settings::values.cpuopt_recompile_exclusives);
1295 WriteBasicSetting(Settings::values.cpuopt_ignore_memory_aborts);
1294 } 1296 }
1295 1297
1296 qt_config->endGroup(); 1298 qt_config->endGroup();
diff --git a/src/yuzu/configuration/configure_cpu_debug.cpp b/src/yuzu/configuration/configure_cpu_debug.cpp
index 3c302ec16..8cfef0cc1 100644
--- a/src/yuzu/configuration/configure_cpu_debug.cpp
+++ b/src/yuzu/configuration/configure_cpu_debug.cpp
@@ -45,6 +45,9 @@ void ConfigureCpuDebug::SetConfiguration() {
45 ui->cpuopt_recompile_exclusives->setEnabled(runtime_lock); 45 ui->cpuopt_recompile_exclusives->setEnabled(runtime_lock);
46 ui->cpuopt_recompile_exclusives->setChecked( 46 ui->cpuopt_recompile_exclusives->setChecked(
47 Settings::values.cpuopt_recompile_exclusives.GetValue()); 47 Settings::values.cpuopt_recompile_exclusives.GetValue());
48 ui->cpuopt_ignore_memory_aborts->setEnabled(runtime_lock);
49 ui->cpuopt_ignore_memory_aborts->setChecked(
50 Settings::values.cpuopt_ignore_memory_aborts.GetValue());
48} 51}
49 52
50void ConfigureCpuDebug::ApplyConfiguration() { 53void ConfigureCpuDebug::ApplyConfiguration() {
@@ -59,6 +62,7 @@ void ConfigureCpuDebug::ApplyConfiguration() {
59 Settings::values.cpuopt_fastmem = ui->cpuopt_fastmem->isChecked(); 62 Settings::values.cpuopt_fastmem = ui->cpuopt_fastmem->isChecked();
60 Settings::values.cpuopt_fastmem_exclusives = ui->cpuopt_fastmem_exclusives->isChecked(); 63 Settings::values.cpuopt_fastmem_exclusives = ui->cpuopt_fastmem_exclusives->isChecked();
61 Settings::values.cpuopt_recompile_exclusives = ui->cpuopt_recompile_exclusives->isChecked(); 64 Settings::values.cpuopt_recompile_exclusives = ui->cpuopt_recompile_exclusives->isChecked();
65 Settings::values.cpuopt_ignore_memory_aborts = ui->cpuopt_ignore_memory_aborts->isChecked();
62} 66}
63 67
64void ConfigureCpuDebug::changeEvent(QEvent* event) { 68void ConfigureCpuDebug::changeEvent(QEvent* event) {
diff --git a/src/yuzu/configuration/configure_cpu_debug.ui b/src/yuzu/configuration/configure_cpu_debug.ui
index 2bc268810..3010f7fad 100644
--- a/src/yuzu/configuration/configure_cpu_debug.ui
+++ b/src/yuzu/configuration/configure_cpu_debug.ui
@@ -175,6 +175,19 @@
175 </property> 175 </property>
176 </widget> 176 </widget>
177 </item> 177 </item>
178 <item>
179 <widget class="QCheckBox" name="cpuopt_ignore_memory_aborts">
180 <property name="toolTip">
181 <string>
182 &lt;div style=&quot;white-space: nowrap&quot;&gt;This optimization speeds up memory accesses by allowing invalid memory accesses to succeed.&lt;/div&gt;
183 &lt;div style=&quot;white-space: nowrap&quot;&gt;Enabling it reduces the overhead of all memory accesses and has no impact on programs that don't access invalid memory.&lt;/div&gt;
184 </string>
185 </property>
186 <property name="text">
187 <string>Enable fallbacks for invalid memory accesses</string>
188 </property>
189 </widget>
190 </item>
178 </layout> 191 </layout>
179 </widget> 192 </widget>
180 </item> 193 </item>
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 8ca683966..e9388daad 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -31,7 +31,7 @@ ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* paren
31 31
32 ui->backend->addItem(QStringLiteral("GLSL")); 32 ui->backend->addItem(QStringLiteral("GLSL"));
33 ui->backend->addItem(tr("GLASM (Assembly Shaders, NVIDIA Only)")); 33 ui->backend->addItem(tr("GLASM (Assembly Shaders, NVIDIA Only)"));
34 ui->backend->addItem(QStringLiteral("SPIR-V (Experimental, Mesa Only)")); 34 ui->backend->addItem(tr("SPIR-V (Experimental, Mesa Only)"));
35 35
36 SetupPerGameUI(); 36 SetupPerGameUI();
37 37
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index ed21f4b92..b1575b0d3 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -855,8 +855,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
855 return; 855 return;
856 } 856 }
857 857
858 const auto devices = 858 const auto devices = emulated_controller->GetMappedDevices();
859 emulated_controller->GetMappedDevices(Core::HID::EmulatedDeviceIndex::AllDevices);
860 UpdateInputDevices(); 859 UpdateInputDevices();
861 860
862 if (devices.empty()) { 861 if (devices.empty()) {
diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt
index 1c0c1a9fe..f6eeb9d8d 100644
--- a/src/yuzu_cmd/CMakeLists.txt
+++ b/src/yuzu_cmd/CMakeLists.txt
@@ -34,7 +34,7 @@ add_executable(yuzu-cmd
34create_target_directory_groups(yuzu-cmd) 34create_target_directory_groups(yuzu-cmd)
35 35
36target_link_libraries(yuzu-cmd PRIVATE common core input_common) 36target_link_libraries(yuzu-cmd PRIVATE common core input_common)
37target_link_libraries(yuzu-cmd PRIVATE inih glad) 37target_link_libraries(yuzu-cmd PRIVATE inih::INIReader glad)
38if (MSVC) 38if (MSVC)
39 target_link_libraries(yuzu-cmd PRIVATE getopt) 39 target_link_libraries(yuzu-cmd PRIVATE getopt)
40endif() 40endif()
@@ -43,13 +43,7 @@ target_link_libraries(yuzu-cmd PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
43create_resource("../../dist/yuzu.bmp" "yuzu_cmd/yuzu_icon.h" "yuzu_icon") 43create_resource("../../dist/yuzu.bmp" "yuzu_cmd/yuzu_icon.h" "yuzu_icon")
44target_include_directories(yuzu-cmd PRIVATE ${RESOURCES_DIR}) 44target_include_directories(yuzu-cmd PRIVATE ${RESOURCES_DIR})
45 45
46target_include_directories(yuzu-cmd PRIVATE ../../externals/Vulkan-Headers/include) 46target_link_libraries(yuzu-cmd PRIVATE SDL2::SDL2 Vulkan::Headers)
47
48if (YUZU_USE_EXTERNAL_SDL2)
49 target_link_libraries(yuzu-cmd PRIVATE SDL2-static)
50else()
51 target_link_libraries(yuzu-cmd PRIVATE SDL2)
52endif()
53 47
54if(UNIX AND NOT APPLE) 48if(UNIX AND NOT APPLE)
55 install(TARGETS yuzu-cmd) 49 install(TARGETS yuzu-cmd)
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 59f9c8e09..de9b220da 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -15,7 +15,7 @@
15#pragma clang diagnostic pop 15#pragma clang diagnostic pop
16#endif 16#endif
17 17
18#include <inih/cpp/INIReader.h> 18#include <INIReader.h>
19#include "common/fs/file.h" 19#include "common/fs/file.h"
20#include "common/fs/fs.h" 20#include "common/fs/fs.h"
21#include "common/fs/path_util.h" 21#include "common/fs/path_util.h"
@@ -286,6 +286,7 @@ void Config::ReadValues() {
286 ReadSetting("Cpu", Settings::values.cpuopt_fastmem); 286 ReadSetting("Cpu", Settings::values.cpuopt_fastmem);
287 ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives); 287 ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives);
288 ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives); 288 ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives);
289 ReadSetting("Cpu", Settings::values.cpuopt_ignore_memory_aborts);
289 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma); 290 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma);
290 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error); 291 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error);
291 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr); 292 ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr);
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index 5bbc3f532..6fcf04e1b 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -208,6 +208,10 @@ cpuopt_fastmem_exclusives =
208# 0: Disabled, 1 (default): Enabled 208# 0: Disabled, 1 (default): Enabled
209cpuopt_recompile_exclusives = 209cpuopt_recompile_exclusives =
210 210
211# Enable optimization to ignore invalid memory accesses (faster guest memory access)
212# 0: Disabled, 1 (default): Enabled
213cpuopt_ignore_memory_aborts =
214
211# Enable unfuse FMA (improve performance on CPUs without FMA) 215# Enable unfuse FMA (improve performance on CPUs without FMA)
212# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. 216# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select.
213# 0: Disabled, 1 (default): Enabled 217# 0: Disabled, 1 (default): Enabled