summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/audio_core/delay_line.cpp4
-rw-r--r--src/audio_core/delay_line.h4
-rw-r--r--src/common/host_memory.cpp4
-rw-r--r--src/common/logging/filter.cpp1
-rw-r--r--src/common/logging/types.h1
-rw-r--r--src/common/x64/native_clock.cpp36
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/hid/emulated_controller.cpp45
-rw-r--r--src/core/hid/emulated_controller.h14
-rw-r--r--src/core/hid/hid_core.cpp20
-rw-r--r--src/core/hid/hid_core.h5
-rw-r--r--src/core/hid/hid_types.h2
-rw-r--r--src/core/hle/kernel/init/init_slab_setup.cpp2
-rw-r--r--src/core/hle/kernel/k_class_token.cpp5
-rw-r--r--src/core/hle/kernel/k_code_memory.cpp146
-rw-r--r--src/core/hle/kernel/k_code_memory.h66
-rw-r--r--src/core/hle/kernel/k_memory_block.h20
-rw-r--r--src/core/hle/kernel/k_page_linked_list.h4
-rw-r--r--src/core/hle/kernel/k_page_table.cpp119
-rw-r--r--src/core/hle/kernel/k_page_table.h8
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/core/hle/kernel/svc.cpp214
-rw-r--r--src/core/hle/kernel/svc_wrap.h27
-rw-r--r--src/core/hle/service/glue/glue.cpp4
-rw-r--r--src/core/hle/service/glue/notif.cpp44
-rw-r--r--src/core/hle/service/glue/notif.h25
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp195
-rw-r--r--src/core/hle/service/hid/controllers/npad.h8
-rw-r--r--src/core/hle/service/hid/hid.cpp61
-rw-r--r--src/core/hle/service/hid/hid.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp13
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.h3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.cpp10
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.h3
-rw-r--r--src/core/hle/service/nvdrv/nvdata.h4
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp5
-rw-r--r--src/shader_recompiler/CMakeLists.txt12
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_barriers.cpp22
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp31
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_control_flow.cpp18
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_image.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_logical.cpp26
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp171
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_select.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_special.cpp95
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_undefined.cpp30
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/glasm_emit_context.cpp (renamed from src/shader_recompiler/backend/glasm/emit_context.cpp)2
-rw-r--r--src/shader_recompiler/backend/glasm/glasm_emit_context.h (renamed from src/shader_recompiler/backend/glasm/emit_context.h)0
-rw-r--r--src/shader_recompiler/backend/glasm/reg_alloc.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_barriers.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_control_flow.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_image.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_logical.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_select.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_special.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_undefined.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp2
-rw-r--r--src/shader_recompiler/backend/glsl/glsl_emit_context.cpp (renamed from src/shader_recompiler/backend/glsl/emit_context.cpp)2
-rw-r--r--src/shader_recompiler/backend/glsl/glsl_emit_context.h (renamed from src/shader_recompiler/backend/glsl/emit_context.h)0
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.h4
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_select.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_special.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_undefined.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp1
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.cpp (renamed from src/shader_recompiler/backend/spirv/emit_context.cpp)2
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.h (renamed from src/shader_recompiler/backend/spirv/emit_context.h)0
-rw-r--r--src/shader_recompiler/environment.h4
-rw-r--r--src/video_core/gpu.cpp44
-rw-r--r--src/video_core/gpu.h4
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp2
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp1
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp131
-rw-r--r--src/yuzu/debugger/profiler.cpp2
-rw-r--r--src/yuzu/main.cpp20
112 files changed, 1428 insertions, 418 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 63dd9febf..19d16147d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -24,6 +24,7 @@ if (MSVC)
24 # /W3 - Level 3 warnings 24 # /W3 - Level 3 warnings
25 # /MP - Multi-threaded compilation 25 # /MP - Multi-threaded compilation
26 # /Zi - Output debugging information 26 # /Zi - Output debugging information
27 # /Zm - Specifies the precompiled header memory allocation limit
27 # /Zo - Enhanced debug info for optimized builds 28 # /Zo - Enhanced debug info for optimized builds
28 # /permissive- - Enables stricter C++ standards conformance checks 29 # /permissive- - Enables stricter C++ standards conformance checks
29 # /EHsc - C++-only exception handling semantics 30 # /EHsc - C++-only exception handling semantics
@@ -36,6 +37,7 @@ if (MSVC)
36 add_compile_options( 37 add_compile_options(
37 /MP 38 /MP
38 /Zi 39 /Zi
40 /Zm200
39 /Zo 41 /Zo
40 /permissive- 42 /permissive-
41 /EHsc 43 /EHsc
diff --git a/src/audio_core/delay_line.cpp b/src/audio_core/delay_line.cpp
index f4e4dd8d2..2793ed8db 100644
--- a/src/audio_core/delay_line.cpp
+++ b/src/audio_core/delay_line.cpp
@@ -1,3 +1,7 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
1#include <cstring> 5#include <cstring>
2#include "audio_core/delay_line.h" 6#include "audio_core/delay_line.h"
3 7
diff --git a/src/audio_core/delay_line.h b/src/audio_core/delay_line.h
index cafddd432..84f11bc52 100644
--- a/src/audio_core/delay_line.h
+++ b/src/audio_core/delay_line.h
@@ -1,3 +1,7 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
1#pragma once 5#pragma once
2 6
3#include "common/common_types.h" 7#include "common/common_types.h"
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index b44a44949..28949fe5e 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -1,3 +1,7 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
1#ifdef _WIN32 5#ifdef _WIN32
2 6
3#include <iterator> 7#include <iterator>
diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp
index 42744c994..b898a652c 100644
--- a/src/common/logging/filter.cpp
+++ b/src/common/logging/filter.cpp
@@ -114,6 +114,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
114 SUB(Service, NGCT) \ 114 SUB(Service, NGCT) \
115 SUB(Service, NIFM) \ 115 SUB(Service, NIFM) \
116 SUB(Service, NIM) \ 116 SUB(Service, NIM) \
117 SUB(Service, NOTIF) \
117 SUB(Service, NPNS) \ 118 SUB(Service, NPNS) \
118 SUB(Service, NS) \ 119 SUB(Service, NS) \
119 SUB(Service, NVDRV) \ 120 SUB(Service, NVDRV) \
diff --git a/src/common/logging/types.h b/src/common/logging/types.h
index 2d21fc483..9ed0c7ad6 100644
--- a/src/common/logging/types.h
+++ b/src/common/logging/types.h
@@ -82,6 +82,7 @@ enum class Class : u8 {
82 Service_NGCT, ///< The NGCT (No Good Content for Terra) service 82 Service_NGCT, ///< The NGCT (No Good Content for Terra) service
83 Service_NIFM, ///< The NIFM (Network interface) service 83 Service_NIFM, ///< The NIFM (Network interface) service
84 Service_NIM, ///< The NIM service 84 Service_NIM, ///< The NIM service
85 Service_NOTIF, ///< The NOTIF (Notification) service
85 Service_NPNS, ///< The NPNS service 86 Service_NPNS, ///< The NPNS service
86 Service_NS, ///< The NS services 87 Service_NS, ///< The NS services
87 Service_NVDRV, ///< The NVDRV (Nvidia driver) service 88 Service_NVDRV, ///< The NVDRV (Nvidia driver) service
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp
index 28f834443..82ee2c8a1 100644
--- a/src/common/x64/native_clock.cpp
+++ b/src/common/x64/native_clock.cpp
@@ -15,26 +15,26 @@
15namespace Common { 15namespace Common {
16 16
17u64 EstimateRDTSCFrequency() { 17u64 EstimateRDTSCFrequency() {
18 const auto milli_10 = std::chrono::milliseconds{10}; 18 // Discard the first result measuring the rdtsc.
19 // get current time
20 _mm_mfence(); 19 _mm_mfence();
21 const u64 tscStart = __rdtsc(); 20 __rdtsc();
22 const auto startTime = std::chrono::steady_clock::now(); 21 std::this_thread::sleep_for(std::chrono::milliseconds{1});
23 // wait roughly 3 seconds 22 _mm_mfence();
24 while (true) { 23 __rdtsc();
25 auto milli = std::chrono::duration_cast<std::chrono::milliseconds>( 24
26 std::chrono::steady_clock::now() - startTime); 25 // Get the current time.
27 if (milli.count() >= 3000) 26 const auto start_time = std::chrono::steady_clock::now();
28 break; 27 _mm_mfence();
29 std::this_thread::sleep_for(milli_10); 28 const u64 tsc_start = __rdtsc();
30 } 29 // Wait for 200 milliseconds.
31 const auto endTime = std::chrono::steady_clock::now(); 30 std::this_thread::sleep_for(std::chrono::milliseconds{200});
31 const auto end_time = std::chrono::steady_clock::now();
32 _mm_mfence(); 32 _mm_mfence();
33 const u64 tscEnd = __rdtsc(); 33 const u64 tsc_end = __rdtsc();
34 // calculate difference 34 // Calculate differences.
35 const u64 timer_diff = 35 const u64 timer_diff = static_cast<u64>(
36 std::chrono::duration_cast<std::chrono::nanoseconds>(endTime - startTime).count(); 36 std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count());
37 const u64 tsc_diff = tscEnd - tscStart; 37 const u64 tsc_diff = tsc_end - tsc_start;
38 const u64 tsc_freq = MultiplyAndDivide64(tsc_diff, 1000000000ULL, timer_diff); 38 const u64 tsc_freq = MultiplyAndDivide64(tsc_diff, 1000000000ULL, timer_diff);
39 return tsc_freq; 39 return tsc_freq;
40} 40}
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index eee8e2ccd..506885659 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -179,6 +179,8 @@ add_library(core STATIC
179 hle/kernel/k_client_port.h 179 hle/kernel/k_client_port.h
180 hle/kernel/k_client_session.cpp 180 hle/kernel/k_client_session.cpp
181 hle/kernel/k_client_session.h 181 hle/kernel/k_client_session.h
182 hle/kernel/k_code_memory.cpp
183 hle/kernel/k_code_memory.h
182 hle/kernel/k_condition_variable.cpp 184 hle/kernel/k_condition_variable.cpp
183 hle/kernel/k_condition_variable.h 185 hle/kernel/k_condition_variable.h
184 hle/kernel/k_event.cpp 186 hle/kernel/k_event.cpp
@@ -408,6 +410,8 @@ add_library(core STATIC
408 hle/service/glue/glue.h 410 hle/service/glue/glue.h
409 hle/service/glue/glue_manager.cpp 411 hle/service/glue/glue_manager.cpp
410 hle/service/glue/glue_manager.h 412 hle/service/glue/glue_manager.h
413 hle/service/glue/notif.cpp
414 hle/service/glue/notif.h
411 hle/service/grc/grc.cpp 415 hle/service/grc/grc.cpp
412 hle/service/grc/grc.h 416 hle/service/grc/grc.h
413 hle/service/hid/hid.cpp 417 hle/service/hid/hid.cpp
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 466ff5542..fbb19f230 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -866,7 +866,52 @@ void EmulatedController::SetLedPattern() {
866 } 866 }
867} 867}
868 868
869void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles) {
870 supported_style_tag = supported_styles;
871 if (!is_connected) {
872 return;
873 }
874 if (!IsControllerSupported()) {
875 LOG_ERROR(Service_HID, "Controller type {} is not supported. Disconnecting controller",
876 npad_type);
877 Disconnect();
878 }
879}
880
881bool EmulatedController::IsControllerSupported() const {
882 switch (npad_type) {
883 case NpadStyleIndex::ProController:
884 return supported_style_tag.fullkey;
885 case NpadStyleIndex::Handheld:
886 return supported_style_tag.handheld;
887 case NpadStyleIndex::JoyconDual:
888 return supported_style_tag.joycon_dual;
889 case NpadStyleIndex::JoyconLeft:
890 return supported_style_tag.joycon_left;
891 case NpadStyleIndex::JoyconRight:
892 return supported_style_tag.joycon_right;
893 case NpadStyleIndex::GameCube:
894 return supported_style_tag.gamecube;
895 case NpadStyleIndex::Pokeball:
896 return supported_style_tag.palma;
897 case NpadStyleIndex::NES:
898 return supported_style_tag.lark;
899 case NpadStyleIndex::SNES:
900 return supported_style_tag.lucia;
901 case NpadStyleIndex::N64:
902 return supported_style_tag.lagoon;
903 case NpadStyleIndex::SegaGenesis:
904 return supported_style_tag.lager;
905 default:
906 return false;
907 }
908}
909
869void EmulatedController::Connect() { 910void EmulatedController::Connect() {
911 if (!IsControllerSupported()) {
912 LOG_ERROR(Service_HID, "Controller type {} is not supported", npad_type);
913 return;
914 }
870 { 915 {
871 std::lock_guard lock{mutex}; 916 std::lock_guard lock{mutex};
872 if (is_configuring) { 917 if (is_configuring) {
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 5887e3e38..425b3e7c4 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -160,6 +160,13 @@ public:
160 */ 160 */
161 NpadStyleIndex GetNpadStyleIndex(bool get_temporary_value = false) const; 161 NpadStyleIndex GetNpadStyleIndex(bool get_temporary_value = false) const;
162 162
163 /**
164 * Sets the supported controller types. Disconnects the controller if current type is not
165 * supported
166 * @param supported_styles bitflag with supported types
167 */
168 void SetSupportedNpadStyleTag(NpadStyleTag supported_styles);
169
163 /// Sets the connected status to true 170 /// Sets the connected status to true
164 void Connect(); 171 void Connect();
165 172
@@ -311,6 +318,12 @@ private:
311 void LoadTASParams(); 318 void LoadTASParams();
312 319
313 /** 320 /**
321 * Checks the current controller type against the supported_style_tag
322 * @return true if the controller is supported
323 */
324 bool IsControllerSupported() const;
325
326 /**
314 * Updates the button status of the controller 327 * Updates the button status of the controller
315 * @param callback A CallbackStatus containing the button status 328 * @param callback A CallbackStatus containing the button status
316 * @param index Button ID of the to be updated 329 * @param index Button ID of the to be updated
@@ -354,6 +367,7 @@ private:
354 367
355 NpadIdType npad_id_type; 368 NpadIdType npad_id_type;
356 NpadStyleIndex npad_type{NpadStyleIndex::None}; 369 NpadStyleIndex npad_type{NpadStyleIndex::None};
370 NpadStyleTag supported_style_tag{NpadStyleSet::All};
357 bool is_connected{false}; 371 bool is_connected{false};
358 bool is_configuring{false}; 372 bool is_configuring{false};
359 f32 motion_sensitivity{0.01f}; 373 f32 motion_sensitivity{0.01f};
diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp
index 946adde00..a1c3bbb57 100644
--- a/src/core/hid/hid_core.cpp
+++ b/src/core/hid/hid_core.cpp
@@ -108,6 +108,16 @@ const EmulatedController* HIDCore::GetEmulatedControllerByIndex(std::size_t inde
108 108
109void HIDCore::SetSupportedStyleTag(NpadStyleTag style_tag) { 109void HIDCore::SetSupportedStyleTag(NpadStyleTag style_tag) {
110 supported_style_tag.raw = style_tag.raw; 110 supported_style_tag.raw = style_tag.raw;
111 player_1->SetSupportedNpadStyleTag(supported_style_tag);
112 player_2->SetSupportedNpadStyleTag(supported_style_tag);
113 player_3->SetSupportedNpadStyleTag(supported_style_tag);
114 player_4->SetSupportedNpadStyleTag(supported_style_tag);
115 player_5->SetSupportedNpadStyleTag(supported_style_tag);
116 player_6->SetSupportedNpadStyleTag(supported_style_tag);
117 player_7->SetSupportedNpadStyleTag(supported_style_tag);
118 player_8->SetSupportedNpadStyleTag(supported_style_tag);
119 other->SetSupportedNpadStyleTag(supported_style_tag);
120 handheld->SetSupportedNpadStyleTag(supported_style_tag);
111} 121}
112 122
113NpadStyleTag HIDCore::GetSupportedStyleTag() const { 123NpadStyleTag HIDCore::GetSupportedStyleTag() const {
@@ -135,6 +145,16 @@ NpadIdType HIDCore::GetFirstNpadId() const {
135 return NpadIdType::Player1; 145 return NpadIdType::Player1;
136} 146}
137 147
148NpadIdType HIDCore::GetFirstDisconnectedNpadId() const {
149 for (std::size_t player_index = 0; player_index < available_controllers; ++player_index) {
150 const auto* const controller = GetEmulatedControllerByIndex(player_index);
151 if (!controller->IsConnected()) {
152 return controller->GetNpadIdType();
153 }
154 }
155 return NpadIdType::Player1;
156}
157
138void HIDCore::EnableAllControllerConfiguration() { 158void HIDCore::EnableAllControllerConfiguration() {
139 player_1->EnableConfiguration(); 159 player_1->EnableConfiguration();
140 player_2->EnableConfiguration(); 160 player_2->EnableConfiguration();
diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h
index 140a0e962..837f7de49 100644
--- a/src/core/hid/hid_core.h
+++ b/src/core/hid/hid_core.h
@@ -45,6 +45,9 @@ public:
45 /// Returns the first connected npad id 45 /// Returns the first connected npad id
46 NpadIdType GetFirstNpadId() const; 46 NpadIdType GetFirstNpadId() const;
47 47
48 /// Returns the first disconnected npad id
49 NpadIdType GetFirstDisconnectedNpadId() const;
50
48 /// Sets all emulated controllers into configuring mode. 51 /// Sets all emulated controllers into configuring mode.
49 void EnableAllControllerConfiguration(); 52 void EnableAllControllerConfiguration();
50 53
@@ -73,7 +76,7 @@ private:
73 std::unique_ptr<EmulatedController> handheld; 76 std::unique_ptr<EmulatedController> handheld;
74 std::unique_ptr<EmulatedConsole> console; 77 std::unique_ptr<EmulatedConsole> console;
75 std::unique_ptr<EmulatedDevices> devices; 78 std::unique_ptr<EmulatedDevices> devices;
76 NpadStyleTag supported_style_tag; 79 NpadStyleTag supported_style_tag{NpadStyleSet::All};
77}; 80};
78 81
79} // namespace Core::HID 82} // namespace Core::HID
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index 780659b86..7c12f01fc 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -256,6 +256,8 @@ enum class NpadStyleSet : u32 {
256 Lager = 1U << 11, 256 Lager = 1U << 11,
257 SystemExt = 1U << 29, 257 SystemExt = 1U << 29,
258 System = 1U << 30, 258 System = 1U << 30,
259
260 All = 0xFFFFFFFFU,
259}; 261};
260static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); 262static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
261 263
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp
index 8ff0f695d..36fc0944a 100644
--- a/src/core/hle/kernel/init/init_slab_setup.cpp
+++ b/src/core/hle/kernel/init/init_slab_setup.cpp
@@ -9,6 +9,7 @@
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hardware_properties.h" 10#include "core/hardware_properties.h"
11#include "core/hle/kernel/init/init_slab_setup.h" 11#include "core/hle/kernel/init/init_slab_setup.h"
12#include "core/hle/kernel/k_code_memory.h"
12#include "core/hle/kernel/k_event.h" 13#include "core/hle/kernel/k_event.h"
13#include "core/hle/kernel/k_memory_layout.h" 14#include "core/hle/kernel/k_memory_layout.h"
14#include "core/hle/kernel/k_memory_manager.h" 15#include "core/hle/kernel/k_memory_manager.h"
@@ -32,6 +33,7 @@ namespace Kernel::Init {
32 HANDLER(KPort, (SLAB_COUNT(KPort)), ##__VA_ARGS__) \ 33 HANDLER(KPort, (SLAB_COUNT(KPort)), ##__VA_ARGS__) \
33 HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \ 34 HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \
34 HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \ 35 HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \
36 HANDLER(KCodeMemory, (SLAB_COUNT(KCodeMemory)), ##__VA_ARGS__) \
35 HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) \ 37 HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) \
36 HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ##__VA_ARGS__) 38 HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ##__VA_ARGS__)
37 39
diff --git a/src/core/hle/kernel/k_class_token.cpp b/src/core/hle/kernel/k_class_token.cpp
index 0be0027be..21e2fe494 100644
--- a/src/core/hle/kernel/k_class_token.cpp
+++ b/src/core/hle/kernel/k_class_token.cpp
@@ -6,6 +6,7 @@
6#include "core/hle/kernel/k_class_token.h" 6#include "core/hle/kernel/k_class_token.h"
7#include "core/hle/kernel/k_client_port.h" 7#include "core/hle/kernel/k_client_port.h"
8#include "core/hle/kernel/k_client_session.h" 8#include "core/hle/kernel/k_client_session.h"
9#include "core/hle/kernel/k_code_memory.h"
9#include "core/hle/kernel/k_event.h" 10#include "core/hle/kernel/k_event.h"
10#include "core/hle/kernel/k_port.h" 11#include "core/hle/kernel/k_port.h"
11#include "core/hle/kernel/k_process.h" 12#include "core/hle/kernel/k_process.h"
@@ -48,7 +49,7 @@ static_assert(ClassToken<KWritableEvent> == 0b10001001'00000000);
48static_assert(ClassToken<KTransferMemory> == 0b10010001'00000000); 49static_assert(ClassToken<KTransferMemory> == 0b10010001'00000000);
49// static_assert(ClassToken<KDeviceAddressSpace> == 0b01100001'00000000); 50// static_assert(ClassToken<KDeviceAddressSpace> == 0b01100001'00000000);
50// static_assert(ClassToken<KSessionRequest> == 0b10100001'00000000); 51// static_assert(ClassToken<KSessionRequest> == 0b10100001'00000000);
51// static_assert(ClassToken<KCodeMemory> == 0b11000001'00000000); 52static_assert(ClassToken<KCodeMemory> == 0b11000001'00000000);
52 53
53// Ensure that the token hierarchy is correct. 54// Ensure that the token hierarchy is correct.
54 55
@@ -79,7 +80,7 @@ static_assert(ClassToken<KWritableEvent> == ((0b10001001 << 8) | ClassToken<KAut
79static_assert(ClassToken<KTransferMemory> == ((0b10010001 << 8) | ClassToken<KAutoObject>)); 80static_assert(ClassToken<KTransferMemory> == ((0b10010001 << 8) | ClassToken<KAutoObject>));
80// static_assert(ClassToken<KDeviceAddressSpace> == ((0b01100001 << 8) | ClassToken<KAutoObject>)); 81// static_assert(ClassToken<KDeviceAddressSpace> == ((0b01100001 << 8) | ClassToken<KAutoObject>));
81// static_assert(ClassToken<KSessionRequest> == ((0b10100001 << 8) | ClassToken<KAutoObject>)); 82// static_assert(ClassToken<KSessionRequest> == ((0b10100001 << 8) | ClassToken<KAutoObject>));
82// static_assert(ClassToken<KCodeMemory> == ((0b11000001 << 8) | ClassToken<KAutoObject>)); 83static_assert(ClassToken<KCodeMemory> == ((0b11000001 << 8) | ClassToken<KAutoObject>));
83 84
84// Ensure that the token hierarchy reflects the class hierarchy. 85// Ensure that the token hierarchy reflects the class hierarchy.
85 86
diff --git a/src/core/hle/kernel/k_code_memory.cpp b/src/core/hle/kernel/k_code_memory.cpp
new file mode 100644
index 000000000..d69f7ffb7
--- /dev/null
+++ b/src/core/hle/kernel/k_code_memory.cpp
@@ -0,0 +1,146 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/common_types.h"
6#include "core/device_memory.h"
7#include "core/hle/kernel/k_auto_object.h"
8#include "core/hle/kernel/k_code_memory.h"
9#include "core/hle/kernel/k_light_lock.h"
10#include "core/hle/kernel/k_memory_block.h"
11#include "core/hle/kernel/k_page_linked_list.h"
12#include "core/hle/kernel/k_page_table.h"
13#include "core/hle/kernel/k_process.h"
14#include "core/hle/kernel/slab_helpers.h"
15#include "core/hle/kernel/svc_types.h"
16#include "core/hle/result.h"
17
18namespace Kernel {
19
20KCodeMemory::KCodeMemory(KernelCore& kernel_)
21 : KAutoObjectWithSlabHeapAndContainer{kernel_}, m_lock(kernel_) {}
22
23ResultCode KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr, size_t size) {
24 // Set members.
25 m_owner = kernel.CurrentProcess();
26
27 // Get the owner page table.
28 auto& page_table = m_owner->PageTable();
29
30 // Construct the page group.
31 KMemoryInfo kBlockInfo = page_table.QueryInfo(addr);
32 m_page_group = KPageLinkedList(kBlockInfo.GetAddress(), kBlockInfo.GetNumPages());
33
34 // Lock the memory.
35 R_TRY(page_table.LockForCodeMemory(addr, size))
36
37 // Clear the memory.
38 for (const auto& block : m_page_group.Nodes()) {
39 std::memset(device_memory.GetPointer(block.GetAddress()), 0xFF, block.GetSize());
40 }
41
42 // Set remaining tracking members.
43 m_address = addr;
44 m_is_initialized = true;
45 m_is_owner_mapped = false;
46 m_is_mapped = false;
47
48 // We succeeded.
49 return ResultSuccess;
50}
51
52void KCodeMemory::Finalize() {
53 // Unlock.
54 if (!m_is_mapped && !m_is_owner_mapped) {
55 const size_t size = m_page_group.GetNumPages() * PageSize;
56 m_owner->PageTable().UnlockForCodeMemory(m_address, size);
57 }
58}
59
60ResultCode KCodeMemory::Map(VAddr address, size_t size) {
61 // Validate the size.
62 R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
63
64 // Lock ourselves.
65 KScopedLightLock lk(m_lock);
66
67 // Ensure we're not already mapped.
68 R_UNLESS(!m_is_mapped, ResultInvalidState);
69
70 // Map the memory.
71 R_TRY(kernel.CurrentProcess()->PageTable().MapPages(
72 address, m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite));
73
74 // Mark ourselves as mapped.
75 m_is_mapped = true;
76
77 return ResultSuccess;
78}
79
80ResultCode KCodeMemory::Unmap(VAddr address, size_t size) {
81 // Validate the size.
82 R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
83
84 // Lock ourselves.
85 KScopedLightLock lk(m_lock);
86
87 // Unmap the memory.
88 R_TRY(kernel.CurrentProcess()->PageTable().UnmapPages(address, m_page_group,
89 KMemoryState::CodeOut));
90
91 // Mark ourselves as unmapped.
92 m_is_mapped = false;
93
94 return ResultSuccess;
95}
96
97ResultCode KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm) {
98 // Validate the size.
99 R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
100
101 // Lock ourselves.
102 KScopedLightLock lk(m_lock);
103
104 // Ensure we're not already mapped.
105 R_UNLESS(!m_is_owner_mapped, ResultInvalidState);
106
107 // Convert the memory permission.
108 KMemoryPermission k_perm{};
109 switch (perm) {
110 case Svc::MemoryPermission::Read:
111 k_perm = KMemoryPermission::UserRead;
112 break;
113 case Svc::MemoryPermission::ReadExecute:
114 k_perm = KMemoryPermission::UserReadExecute;
115 break;
116 default:
117 break;
118 }
119
120 // Map the memory.
121 R_TRY(
122 m_owner->PageTable().MapPages(address, m_page_group, KMemoryState::GeneratedCode, k_perm));
123
124 // Mark ourselves as mapped.
125 m_is_owner_mapped = true;
126
127 return ResultSuccess;
128}
129
130ResultCode KCodeMemory::UnmapFromOwner(VAddr address, size_t size) {
131 // Validate the size.
132 R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
133
134 // Lock ourselves.
135 KScopedLightLock lk(m_lock);
136
137 // Unmap the memory.
138 R_TRY(m_owner->PageTable().UnmapPages(address, m_page_group, KMemoryState::GeneratedCode));
139
140 // Mark ourselves as unmapped.
141 m_is_owner_mapped = false;
142
143 return ResultSuccess;
144}
145
146} // namespace Kernel \ No newline at end of file
diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h
new file mode 100644
index 000000000..e0ba19a53
--- /dev/null
+++ b/src/core/hle/kernel/k_code_memory.h
@@ -0,0 +1,66 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8#include "core/device_memory.h"
9#include "core/hle/kernel/k_auto_object.h"
10#include "core/hle/kernel/k_light_lock.h"
11#include "core/hle/kernel/k_page_linked_list.h"
12#include "core/hle/kernel/k_process.h"
13#include "core/hle/kernel/slab_helpers.h"
14#include "core/hle/kernel/svc_types.h"
15#include "core/hle/result.h"
16
17namespace Kernel {
18
19enum class CodeMemoryOperation : u32 {
20 Map = 0,
21 MapToOwner = 1,
22 Unmap = 2,
23 UnmapFromOwner = 3,
24};
25
26class KCodeMemory final
27 : public KAutoObjectWithSlabHeapAndContainer<KCodeMemory, KAutoObjectWithList> {
28 KERNEL_AUTOOBJECT_TRAITS(KCodeMemory, KAutoObject);
29
30public:
31 explicit KCodeMemory(KernelCore& kernel_);
32
33 ResultCode Initialize(Core::DeviceMemory& device_memory, VAddr address, size_t size);
34 void Finalize();
35
36 ResultCode Map(VAddr address, size_t size);
37 ResultCode Unmap(VAddr address, size_t size);
38 ResultCode MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm);
39 ResultCode UnmapFromOwner(VAddr address, size_t size);
40
41 bool IsInitialized() const {
42 return m_is_initialized;
43 }
44 static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
45
46 KProcess* GetOwner() const {
47 return m_owner;
48 }
49 VAddr GetSourceAddress() const {
50 return m_address;
51 }
52 size_t GetSize() const {
53 return m_is_initialized ? m_page_group.GetNumPages() * PageSize : 0;
54 }
55
56private:
57 KPageLinkedList m_page_group{};
58 KProcess* m_owner{};
59 VAddr m_address{};
60 KLightLock m_lock;
61 bool m_is_initialized{};
62 bool m_is_owner_mapped{};
63 bool m_is_mapped{};
64};
65
66} // namespace Kernel
diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h
index a7fdb5fb8..fd491146f 100644
--- a/src/core/hle/kernel/k_memory_block.h
+++ b/src/core/hle/kernel/k_memory_block.h
@@ -131,6 +131,26 @@ enum class KMemoryPermission : u8 {
131 131
132 UserMask = static_cast<u8>(Svc::MemoryPermission::Read | Svc::MemoryPermission::Write | 132 UserMask = static_cast<u8>(Svc::MemoryPermission::Read | Svc::MemoryPermission::Write |
133 Svc::MemoryPermission::Execute), 133 Svc::MemoryPermission::Execute),
134
135 KernelShift = 3,
136
137 KernelRead = Read << KernelShift,
138 KernelWrite = Write << KernelShift,
139 KernelExecute = Execute << KernelShift,
140
141 NotMapped = (1 << (2 * KernelShift)),
142
143 KernelReadWrite = KernelRead | KernelWrite,
144 KernelReadExecute = KernelRead | KernelExecute,
145
146 UserRead = Read | KernelRead,
147 UserWrite = Write | KernelWrite,
148 UserExecute = Execute,
149
150 UserReadWrite = UserRead | UserWrite,
151 UserReadExecute = UserRead | UserExecute,
152
153 IpcLockChangeMask = NotMapped | UserReadWrite
134}; 154};
135DECLARE_ENUM_FLAG_OPERATORS(KMemoryPermission); 155DECLARE_ENUM_FLAG_OPERATORS(KMemoryPermission);
136 156
diff --git a/src/core/hle/kernel/k_page_linked_list.h b/src/core/hle/kernel/k_page_linked_list.h
index 3362fb236..0e2ae582a 100644
--- a/src/core/hle/kernel/k_page_linked_list.h
+++ b/src/core/hle/kernel/k_page_linked_list.h
@@ -27,6 +27,10 @@ public:
27 return num_pages; 27 return num_pages;
28 } 28 }
29 29
30 constexpr std::size_t GetSize() const {
31 return GetNumPages() * PageSize;
32 }
33
30 private: 34 private:
31 u64 addr{}; 35 u64 addr{};
32 std::size_t num_pages{}; 36 std::size_t num_pages{};
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp
index 9bda5c5b2..99982e5a3 100644
--- a/src/core/hle/kernel/k_page_table.cpp
+++ b/src/core/hle/kernel/k_page_table.cpp
@@ -368,6 +368,33 @@ ResultCode KPageTable::UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, st
368 return ResultSuccess; 368 return ResultSuccess;
369} 369}
370 370
371ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size,
372 KPageTable& src_page_table, VAddr src_addr) {
373 std::lock_guard lock{page_table_lock};
374
375 const std::size_t num_pages{size / PageSize};
376
377 // Check that the memory is mapped in the destination process.
378 size_t num_allocator_blocks;
379 R_TRY(CheckMemoryState(&num_allocator_blocks, dst_addr, size, KMemoryState::All,
380 KMemoryState::SharedCode, KMemoryPermission::UserReadWrite,
381 KMemoryPermission::UserReadWrite, KMemoryAttribute::All,
382 KMemoryAttribute::None));
383
384 // Check that the memory is mapped in the source process.
385 R_TRY(src_page_table.CheckMemoryState(src_addr, size, KMemoryState::FlagCanMapProcess,
386 KMemoryState::FlagCanMapProcess, KMemoryPermission::None,
387 KMemoryPermission::None, KMemoryAttribute::All,
388 KMemoryAttribute::None));
389
390 CASCADE_CODE(Operate(dst_addr, num_pages, KMemoryPermission::None, OperationType::Unmap));
391
392 // Apply the memory block update.
393 block_manager->Update(dst_addr, num_pages, KMemoryState::Free, KMemoryPermission::None,
394 KMemoryAttribute::None);
395
396 return ResultSuccess;
397}
371void KPageTable::MapPhysicalMemory(KPageLinkedList& page_linked_list, VAddr start, VAddr end) { 398void KPageTable::MapPhysicalMemory(KPageLinkedList& page_linked_list, VAddr start, VAddr end) {
372 auto node{page_linked_list.Nodes().begin()}; 399 auto node{page_linked_list.Nodes().begin()};
373 PAddr map_addr{node->GetAddress()}; 400 PAddr map_addr{node->GetAddress()};
@@ -942,6 +969,60 @@ ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size)
942 return ResultSuccess; 969 return ResultSuccess;
943} 970}
944 971
972ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) {
973 std::lock_guard lock{page_table_lock};
974
975 KMemoryPermission new_perm = KMemoryPermission::NotMapped | KMemoryPermission::KernelReadWrite;
976
977 KMemoryPermission old_perm{};
978
979 if (const ResultCode result{CheckMemoryState(
980 nullptr, &old_perm, nullptr, addr, size, KMemoryState::FlagCanCodeMemory,
981 KMemoryState::FlagCanCodeMemory, KMemoryPermission::Mask,
982 KMemoryPermission::UserReadWrite, KMemoryAttribute::All, KMemoryAttribute::None)};
983 result.IsError()) {
984 return result;
985 }
986
987 new_perm = (new_perm != KMemoryPermission::None) ? new_perm : old_perm;
988
989 block_manager->UpdateLock(
990 addr, size / PageSize,
991 [](KMemoryBlockManager::iterator block, KMemoryPermission permission) {
992 block->ShareToDevice(permission);
993 },
994 new_perm);
995
996 return ResultSuccess;
997}
998
999ResultCode KPageTable::UnlockForCodeMemory(VAddr addr, std::size_t size) {
1000 std::lock_guard lock{page_table_lock};
1001
1002 KMemoryPermission new_perm = KMemoryPermission::UserReadWrite;
1003
1004 KMemoryPermission old_perm{};
1005
1006 if (const ResultCode result{CheckMemoryState(
1007 nullptr, &old_perm, nullptr, addr, size, KMemoryState::FlagCanCodeMemory,
1008 KMemoryState::FlagCanCodeMemory, KMemoryPermission::None, KMemoryPermission::None,
1009 KMemoryAttribute::All, KMemoryAttribute::Locked)};
1010 result.IsError()) {
1011 return result;
1012 }
1013
1014 new_perm = (new_perm != KMemoryPermission::None) ? new_perm : old_perm;
1015
1016 block_manager->UpdateLock(
1017 addr, size / PageSize,
1018 [](KMemoryBlockManager::iterator block, KMemoryPermission permission) {
1019 block->UnshareToDevice(permission);
1020 },
1021 new_perm);
1022
1023 return ResultSuccess;
1024}
1025
945ResultCode KPageTable::InitializeMemoryLayout(VAddr start, VAddr end) { 1026ResultCode KPageTable::InitializeMemoryLayout(VAddr start, VAddr end) {
946 block_manager = std::make_unique<KMemoryBlockManager>(start, end); 1027 block_manager = std::make_unique<KMemoryBlockManager>(start, end);
947 1028
@@ -1231,4 +1312,42 @@ ResultCode KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermissi
1231 return ResultSuccess; 1312 return ResultSuccess;
1232} 1313}
1233 1314
1315ResultCode KPageTable::CheckMemoryState(size_t* out_blocks_needed, VAddr addr, size_t size,
1316 KMemoryState state_mask, KMemoryState state,
1317 KMemoryPermission perm_mask, KMemoryPermission perm,
1318 KMemoryAttribute attr_mask, KMemoryAttribute attr) const {
1319 // Get information about the first block.
1320 const VAddr last_addr = addr + size - 1;
1321 KMemoryBlockManager::const_iterator it{block_manager->FindIterator(addr)};
1322 KMemoryInfo info = it->GetMemoryInfo();
1323
1324 // If the start address isn't aligned, we need a block.
1325 const size_t blocks_for_start_align =
1326 (Common::AlignDown(addr, PageSize) != info.GetAddress()) ? 1 : 0;
1327
1328 while (true) {
1329 // Validate against the provided masks.
1330 R_TRY(CheckMemoryState(info, state_mask, state, perm_mask, perm, attr_mask, attr));
1331
1332 // Break once we're done.
1333 if (last_addr <= info.GetLastAddress()) {
1334 break;
1335 }
1336
1337 // Advance our iterator.
1338 it++;
1339 info = it->GetMemoryInfo();
1340 }
1341
1342 // If the end address isn't aligned, we need a block.
1343 const size_t blocks_for_end_align =
1344 (Common::AlignUp(addr + size, PageSize) != info.GetEndAddress()) ? 1 : 0;
1345
1346 if (out_blocks_needed != nullptr) {
1347 *out_blocks_needed = blocks_for_start_align + blocks_for_end_align;
1348 }
1349
1350 return ResultSuccess;
1351}
1352
1234} // namespace Kernel 1353} // namespace Kernel
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h
index b7ec38f06..d784aa67e 100644
--- a/src/core/hle/kernel/k_page_table.h
+++ b/src/core/hle/kernel/k_page_table.h
@@ -33,6 +33,8 @@ public:
33 KMemoryPermission perm); 33 KMemoryPermission perm);
34 ResultCode MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size); 34 ResultCode MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size);
35 ResultCode UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size); 35 ResultCode UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size);
36 ResultCode UnmapProcessMemory(VAddr dst_addr, std::size_t size, KPageTable& src_page_table,
37 VAddr src_addr);
36 ResultCode MapPhysicalMemory(VAddr addr, std::size_t size); 38 ResultCode MapPhysicalMemory(VAddr addr, std::size_t size);
37 ResultCode UnmapPhysicalMemory(VAddr addr, std::size_t size); 39 ResultCode UnmapPhysicalMemory(VAddr addr, std::size_t size);
38 ResultCode UnmapMemory(VAddr addr, std::size_t size); 40 ResultCode UnmapMemory(VAddr addr, std::size_t size);
@@ -55,6 +57,8 @@ public:
55 KMemoryPermission perm, PAddr map_addr = 0); 57 KMemoryPermission perm, PAddr map_addr = 0);
56 ResultCode LockForDeviceAddressSpace(VAddr addr, std::size_t size); 58 ResultCode LockForDeviceAddressSpace(VAddr addr, std::size_t size);
57 ResultCode UnlockForDeviceAddressSpace(VAddr addr, std::size_t size); 59 ResultCode UnlockForDeviceAddressSpace(VAddr addr, std::size_t size);
60 ResultCode LockForCodeMemory(VAddr addr, std::size_t size);
61 ResultCode UnlockForCodeMemory(VAddr addr, std::size_t size);
58 62
59 Common::PageTable& PageTableImpl() { 63 Common::PageTable& PageTableImpl() {
60 return page_table_impl; 64 return page_table_impl;
@@ -115,6 +119,10 @@ private:
115 return CheckMemoryState(nullptr, nullptr, nullptr, addr, size, state_mask, state, perm_mask, 119 return CheckMemoryState(nullptr, nullptr, nullptr, addr, size, state_mask, state, perm_mask,
116 perm, attr_mask, attr, ignore_attr); 120 perm, attr_mask, attr, ignore_attr);
117 } 121 }
122 ResultCode CheckMemoryState(size_t* out_blocks_needed, VAddr addr, size_t size,
123 KMemoryState state_mask, KMemoryState state,
124 KMemoryPermission perm_mask, KMemoryPermission perm,
125 KMemoryAttribute attr_mask, KMemoryAttribute attr) const;
118 126
119 std::recursive_mutex page_table_lock; 127 std::recursive_mutex page_table_lock;
120 std::unique_ptr<KMemoryBlockManager> block_manager; 128 std::unique_ptr<KMemoryBlockManager> block_manager;
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index d2ceae950..d847fd0c5 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -53,6 +53,7 @@ class KSharedMemoryInfo;
53class KThread; 53class KThread;
54class KTransferMemory; 54class KTransferMemory;
55class KWritableEvent; 55class KWritableEvent;
56class KCodeMemory;
56class PhysicalCore; 57class PhysicalCore;
57class ServiceThread; 58class ServiceThread;
58class Synchronization; 59class Synchronization;
@@ -326,6 +327,8 @@ public:
326 return slab_heap_container->transfer_memory; 327 return slab_heap_container->transfer_memory;
327 } else if constexpr (std::is_same_v<T, KWritableEvent>) { 328 } else if constexpr (std::is_same_v<T, KWritableEvent>) {
328 return slab_heap_container->writeable_event; 329 return slab_heap_container->writeable_event;
330 } else if constexpr (std::is_same_v<T, KCodeMemory>) {
331 return slab_heap_container->code_memory;
329 } 332 }
330 } 333 }
331 334
@@ -377,6 +380,7 @@ private:
377 KSlabHeap<KThread> thread; 380 KSlabHeap<KThread> thread;
378 KSlabHeap<KTransferMemory> transfer_memory; 381 KSlabHeap<KTransferMemory> transfer_memory;
379 KSlabHeap<KWritableEvent> writeable_event; 382 KSlabHeap<KWritableEvent> writeable_event;
383 KSlabHeap<KCodeMemory> code_memory;
380 }; 384 };
381 385
382 std::unique_ptr<SlabHeapContainer> slab_heap_container; 386 std::unique_ptr<SlabHeapContainer> slab_heap_container;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index f0cd8471e..b37db918e 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -18,6 +18,7 @@
18#include "core/core_timing.h" 18#include "core/core_timing.h"
19#include "core/hle/kernel/k_client_port.h" 19#include "core/hle/kernel/k_client_port.h"
20#include "core/hle/kernel/k_client_session.h" 20#include "core/hle/kernel/k_client_session.h"
21#include "core/hle/kernel/k_code_memory.h"
21#include "core/hle/kernel/k_event.h" 22#include "core/hle/kernel/k_event.h"
22#include "core/hle/kernel/k_handle_table.h" 23#include "core/hle/kernel/k_handle_table.h"
23#include "core/hle/kernel/k_memory_block.h" 24#include "core/hle/kernel/k_memory_block.h"
@@ -1197,6 +1198,22 @@ constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) {
1197 } 1198 }
1198} 1199}
1199 1200
1201constexpr bool IsValidMapCodeMemoryPermission(Svc::MemoryPermission perm) {
1202 return perm == Svc::MemoryPermission::ReadWrite;
1203}
1204
1205constexpr bool IsValidMapToOwnerCodeMemoryPermission(Svc::MemoryPermission perm) {
1206 return perm == Svc::MemoryPermission::Read || perm == Svc::MemoryPermission::ReadExecute;
1207}
1208
1209constexpr bool IsValidUnmapCodeMemoryPermission(Svc::MemoryPermission perm) {
1210 return perm == Svc::MemoryPermission::None;
1211}
1212
1213constexpr bool IsValidUnmapFromOwnerCodeMemoryPermission(Svc::MemoryPermission perm) {
1214 return perm == Svc::MemoryPermission::None;
1215}
1216
1200} // Anonymous namespace 1217} // Anonymous namespace
1201 1218
1202static ResultCode MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, 1219static ResultCode MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address,
@@ -1306,6 +1323,195 @@ static ResultCode SetProcessMemoryPermission(Core::System& system, Handle proces
1306 return page_table.SetProcessMemoryPermission(address, size, ConvertToKMemoryPermission(perm)); 1323 return page_table.SetProcessMemoryPermission(address, size, ConvertToKMemoryPermission(perm));
1307} 1324}
1308 1325
1326static ResultCode MapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle,
1327 VAddr src_address, u64 size) {
1328 LOG_TRACE(Kernel_SVC,
1329 "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}",
1330 dst_address, process_handle, src_address, size);
1331
1332 // Validate the address/size.
1333 R_UNLESS(Common::IsAligned(dst_address, PageSize), ResultInvalidAddress);
1334 R_UNLESS(Common::IsAligned(src_address, PageSize), ResultInvalidAddress);
1335 R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
1336 R_UNLESS(size > 0, ResultInvalidSize);
1337 R_UNLESS((dst_address < dst_address + size), ResultInvalidCurrentMemory);
1338 R_UNLESS((src_address < src_address + size), ResultInvalidCurrentMemory);
1339
1340 // Get the processes.
1341 KProcess* dst_process = system.CurrentProcess();
1342 KScopedAutoObject src_process =
1343 dst_process->GetHandleTable().GetObjectWithoutPseudoHandle<KProcess>(process_handle);
1344 R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);
1345
1346 // Get the page tables.
1347 auto& dst_pt = dst_process->PageTable();
1348 auto& src_pt = src_process->PageTable();
1349
1350 // Validate that the mapping is in range.
1351 R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory);
1352 R_UNLESS(dst_pt.CanContain(dst_address, size, KMemoryState::SharedCode),
1353 ResultInvalidMemoryRegion);
1354
1355 // Create a new page group.
1356 KMemoryInfo kBlockInfo = dst_pt.QueryInfo(dst_address);
1357 KPageLinkedList pg(kBlockInfo.GetAddress(), kBlockInfo.GetNumPages());
1358
1359 // Map the group.
1360 R_TRY(dst_pt.MapPages(dst_address, pg, KMemoryState::SharedCode,
1361 KMemoryPermission::UserReadWrite));
1362
1363 return ResultSuccess;
1364}
1365
1366static ResultCode UnmapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle,
1367 VAddr src_address, u64 size) {
1368 LOG_TRACE(Kernel_SVC,
1369 "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}",
1370 dst_address, process_handle, src_address, size);
1371
1372 // Validate the address/size.
1373 R_UNLESS(Common::IsAligned(dst_address, PageSize), ResultInvalidAddress);
1374 R_UNLESS(Common::IsAligned(src_address, PageSize), ResultInvalidAddress);
1375 R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
1376 R_UNLESS(size > 0, ResultInvalidSize);
1377 R_UNLESS((dst_address < dst_address + size), ResultInvalidCurrentMemory);
1378 R_UNLESS((src_address < src_address + size), ResultInvalidCurrentMemory);
1379
1380 // Get the processes.
1381 KProcess* dst_process = system.CurrentProcess();
1382 KScopedAutoObject src_process =
1383 dst_process->GetHandleTable().GetObjectWithoutPseudoHandle<KProcess>(process_handle);
1384 R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);
1385
1386 // Get the page tables.
1387 auto& dst_pt = dst_process->PageTable();
1388 auto& src_pt = src_process->PageTable();
1389
1390 // Validate that the mapping is in range.
1391 R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory);
1392 R_UNLESS(dst_pt.CanContain(dst_address, size, KMemoryState::SharedCode),
1393 ResultInvalidMemoryRegion);
1394
1395 // Unmap the memory.
1396 R_TRY(dst_pt.UnmapProcessMemory(dst_address, size, src_pt, src_address));
1397
1398 return ResultSuccess;
1399}
1400
1401static ResultCode CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t size) {
1402 LOG_TRACE(Kernel_SVC, "called, handle_out=0x{:X}, address=0x{:X}, size=0x{:X}",
1403 static_cast<void*>(out), address, size);
1404 // Get kernel instance.
1405 auto& kernel = system.Kernel();
1406
1407 // Validate address / size.
1408 R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
1409 R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
1410 R_UNLESS(size > 0, ResultInvalidSize);
1411 R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
1412
1413 // Create the code memory.
1414
1415 KCodeMemory* code_mem = KCodeMemory::Create(kernel);
1416 R_UNLESS(code_mem != nullptr, ResultOutOfResource);
1417
1418 // Verify that the region is in range.
1419 R_UNLESS(system.CurrentProcess()->PageTable().Contains(address, size),
1420 ResultInvalidCurrentMemory);
1421
1422 // Initialize the code memory.
1423 R_TRY(code_mem->Initialize(system.DeviceMemory(), address, size));
1424
1425 // Register the code memory.
1426 KCodeMemory::Register(kernel, code_mem);
1427
1428 // Add the code memory to the handle table.
1429 R_TRY(system.CurrentProcess()->GetHandleTable().Add(out, code_mem));
1430
1431 code_mem->Close();
1432
1433 return ResultSuccess;
1434}
1435
1436static ResultCode ControlCodeMemory(Core::System& system, Handle code_memory_handle, u32 operation,
1437 VAddr address, size_t size, Svc::MemoryPermission perm) {
1438
1439 LOG_TRACE(Kernel_SVC,
1440 "called, code_memory_handle=0x{:X}, operation=0x{:X}, address=0x{:X}, size=0x{:X}, "
1441 "permission=0x{:X}",
1442 code_memory_handle, operation, address, size, perm);
1443
1444 // Validate the address / size.
1445 R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
1446 R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
1447 R_UNLESS(size > 0, ResultInvalidSize);
1448 R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
1449
1450 // Get the code memory from its handle.
1451 KScopedAutoObject code_mem =
1452 system.CurrentProcess()->GetHandleTable().GetObject<KCodeMemory>(code_memory_handle);
1453 R_UNLESS(code_mem.IsNotNull(), ResultInvalidHandle);
1454
1455 // NOTE: Here, Atmosphere extends the SVC to allow code memory operations on one's own process.
1456 // This enables homebrew usage of these SVCs for JIT.
1457
1458 // Perform the operation.
1459 switch (static_cast<CodeMemoryOperation>(operation)) {
1460 case CodeMemoryOperation::Map: {
1461 // Check that the region is in range.
1462 R_UNLESS(
1463 system.CurrentProcess()->PageTable().CanContain(address, size, KMemoryState::CodeOut),
1464 ResultInvalidMemoryRegion);
1465
1466 // Check the memory permission.
1467 R_UNLESS(IsValidMapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission);
1468
1469 // Map the memory.
1470 R_TRY(code_mem->Map(address, size));
1471 } break;
1472 case CodeMemoryOperation::Unmap: {
1473 // Check that the region is in range.
1474 R_UNLESS(
1475 system.CurrentProcess()->PageTable().CanContain(address, size, KMemoryState::CodeOut),
1476 ResultInvalidMemoryRegion);
1477
1478 // Check the memory permission.
1479 R_UNLESS(IsValidUnmapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission);
1480
1481 // Unmap the memory.
1482 R_TRY(code_mem->Unmap(address, size));
1483 } break;
1484 case CodeMemoryOperation::MapToOwner: {
1485 // Check that the region is in range.
1486 R_UNLESS(code_mem->GetOwner()->PageTable().CanContain(address, size,
1487 KMemoryState::GeneratedCode),
1488 ResultInvalidMemoryRegion);
1489
1490 // Check the memory permission.
1491 R_UNLESS(IsValidMapToOwnerCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission);
1492
1493 // Map the memory to its owner.
1494 R_TRY(code_mem->MapToOwner(address, size, perm));
1495 } break;
1496 case CodeMemoryOperation::UnmapFromOwner: {
1497 // Check that the region is in range.
1498 R_UNLESS(code_mem->GetOwner()->PageTable().CanContain(address, size,
1499 KMemoryState::GeneratedCode),
1500 ResultInvalidMemoryRegion);
1501
1502 // Check the memory permission.
1503 R_UNLESS(IsValidUnmapFromOwnerCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission);
1504
1505 // Unmap the memory from its owner.
1506 R_TRY(code_mem->UnmapFromOwner(address, size));
1507 } break;
1508 default:
1509 return ResultInvalidEnumValue;
1510 }
1511
1512 return ResultSuccess;
1513}
1514
1309static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, 1515static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address,
1310 VAddr page_info_address, Handle process_handle, 1516 VAddr page_info_address, Handle process_handle,
1311 VAddr address) { 1517 VAddr address) {
@@ -2600,8 +2806,8 @@ static const FunctionDef SVC_Table_64[] = {
2600 {0x48, nullptr, "MapPhysicalMemoryUnsafe"}, 2806 {0x48, nullptr, "MapPhysicalMemoryUnsafe"},
2601 {0x49, nullptr, "UnmapPhysicalMemoryUnsafe"}, 2807 {0x49, nullptr, "UnmapPhysicalMemoryUnsafe"},
2602 {0x4A, nullptr, "SetUnsafeLimit"}, 2808 {0x4A, nullptr, "SetUnsafeLimit"},
2603 {0x4B, nullptr, "CreateCodeMemory"}, 2809 {0x4B, SvcWrap64<CreateCodeMemory>, "CreateCodeMemory"},
2604 {0x4C, nullptr, "ControlCodeMemory"}, 2810 {0x4C, SvcWrap64<ControlCodeMemory>, "ControlCodeMemory"},
2605 {0x4D, nullptr, "SleepSystem"}, 2811 {0x4D, nullptr, "SleepSystem"},
2606 {0x4E, nullptr, "ReadWriteRegister"}, 2812 {0x4E, nullptr, "ReadWriteRegister"},
2607 {0x4F, nullptr, "SetProcessActivity"}, 2813 {0x4F, nullptr, "SetProcessActivity"},
@@ -2641,8 +2847,8 @@ static const FunctionDef SVC_Table_64[] = {
2641 {0x71, nullptr, "ManageNamedPort"}, 2847 {0x71, nullptr, "ManageNamedPort"},
2642 {0x72, nullptr, "ConnectToPort"}, 2848 {0x72, nullptr, "ConnectToPort"},
2643 {0x73, SvcWrap64<SetProcessMemoryPermission>, "SetProcessMemoryPermission"}, 2849 {0x73, SvcWrap64<SetProcessMemoryPermission>, "SetProcessMemoryPermission"},
2644 {0x74, nullptr, "MapProcessMemory"}, 2850 {0x74, SvcWrap64<MapProcessMemory>, "MapProcessMemory"},
2645 {0x75, nullptr, "UnmapProcessMemory"}, 2851 {0x75, SvcWrap64<UnmapProcessMemory>, "UnmapProcessMemory"},
2646 {0x76, SvcWrap64<QueryProcessMemory>, "QueryProcessMemory"}, 2852 {0x76, SvcWrap64<QueryProcessMemory>, "QueryProcessMemory"},
2647 {0x77, SvcWrap64<MapProcessCodeMemory>, "MapProcessCodeMemory"}, 2853 {0x77, SvcWrap64<MapProcessCodeMemory>, "MapProcessCodeMemory"},
2648 {0x78, SvcWrap64<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"}, 2854 {0x78, SvcWrap64<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"},
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index 6e62e656f..86255fe6d 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -73,6 +73,23 @@ void SvcWrap64(Core::System& system) {
73 .raw); 73 .raw);
74} 74}
75 75
76// Used by MapProcessMemory and UnmapProcessMemory
77template <ResultCode func(Core::System&, u64, u32, u64, u64)>
78void SvcWrap64(Core::System& system) {
79 FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)),
80 Param(system, 2), Param(system, 3))
81 .raw);
82}
83
84// Used by ControlCodeMemory
85template <ResultCode func(Core::System&, Handle, u32, u64, u64, Svc::MemoryPermission)>
86void SvcWrap64(Core::System& system) {
87 FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)),
88 static_cast<u32>(Param(system, 1)), Param(system, 2), Param(system, 3),
89 static_cast<Svc::MemoryPermission>(Param(system, 4)))
90 .raw);
91}
92
76template <ResultCode func(Core::System&, u32*)> 93template <ResultCode func(Core::System&, u32*)>
77void SvcWrap64(Core::System& system) { 94void SvcWrap64(Core::System& system) {
78 u32 param = 0; 95 u32 param = 0;
@@ -301,6 +318,16 @@ void SvcWrap64(Core::System& system) {
301 FuncReturn(system, retval); 318 FuncReturn(system, retval);
302} 319}
303 320
321// Used by CreateCodeMemory
322template <ResultCode func(Core::System&, Handle*, u64, u64)>
323void SvcWrap64(Core::System& system) {
324 u32 param_1 = 0;
325 const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2)).raw;
326
327 system.CurrentArmInterface().SetReg(1, param_1);
328 FuncReturn(system, retval);
329}
330
304template <ResultCode func(Core::System&, Handle*, u64, u32, u32)> 331template <ResultCode func(Core::System&, Handle*, u64, u32, u32)>
305void SvcWrap64(Core::System& system) { 332void SvcWrap64(Core::System& system) {
306 u32 param_1 = 0; 333 u32 param_1 = 0;
diff --git a/src/core/hle/service/glue/glue.cpp b/src/core/hle/service/glue/glue.cpp
index a08dc9758..b24d469cf 100644
--- a/src/core/hle/service/glue/glue.cpp
+++ b/src/core/hle/service/glue/glue.cpp
@@ -8,6 +8,7 @@
8#include "core/hle/service/glue/bgtc.h" 8#include "core/hle/service/glue/bgtc.h"
9#include "core/hle/service/glue/ectx.h" 9#include "core/hle/service/glue/ectx.h"
10#include "core/hle/service/glue/glue.h" 10#include "core/hle/service/glue/glue.h"
11#include "core/hle/service/glue/notif.h"
11 12
12namespace Service::Glue { 13namespace Service::Glue {
13 14
@@ -24,6 +25,9 @@ void InstallInterfaces(Core::System& system) {
24 25
25 // Error Context 26 // Error Context
26 std::make_shared<ECTX_AW>(system)->InstallAsService(system.ServiceManager()); 27 std::make_shared<ECTX_AW>(system)->InstallAsService(system.ServiceManager());
28
29 // Notification Services for application
30 std::make_shared<NOTIF_A>(system)->InstallAsService(system.ServiceManager());
27} 31}
28 32
29} // namespace Service::Glue 33} // namespace Service::Glue
diff --git a/src/core/hle/service/glue/notif.cpp b/src/core/hle/service/glue/notif.cpp
new file mode 100644
index 000000000..c559ec9df
--- /dev/null
+++ b/src/core/hle/service/glue/notif.cpp
@@ -0,0 +1,44 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/ipc_helpers.h"
6#include "core/hle/service/glue/notif.h"
7
8namespace Service::Glue {
9
10NOTIF_A::NOTIF_A(Core::System& system_) : ServiceFramework{system_, "notif:a"} {
11 // clang-format off
12 static const FunctionInfo functions[] = {
13 {500, nullptr, "RegisterAlarmSetting"},
14 {510, nullptr, "UpdateAlarmSetting"},
15 {520, &NOTIF_A::ListAlarmSettings, "ListAlarmSettings"},
16 {530, nullptr, "LoadApplicationParameter"},
17 {540, nullptr, "DeleteAlarmSetting"},
18 {1000, &NOTIF_A::Initialize, "Initialize"},
19 };
20 // clang-format on
21
22 RegisterHandlers(functions);
23}
24
25NOTIF_A::~NOTIF_A() = default;
26
27void NOTIF_A::ListAlarmSettings(Kernel::HLERequestContext& ctx) {
28 // Returns an array of AlarmSetting
29 constexpr s32 alarm_count = 0;
30
31 LOG_WARNING(Service_NOTIF, "(STUBBED) called");
32
33 IPC::ResponseBuilder rb{ctx, 3};
34 rb.Push(ResultSuccess);
35 rb.Push(alarm_count);
36}
37
38void NOTIF_A::Initialize(Kernel::HLERequestContext& ctx) {
39 LOG_WARNING(Service_NOTIF, "(STUBBED) called");
40 IPC::ResponseBuilder rb{ctx, 2};
41 rb.Push(ResultSuccess);
42}
43
44} // namespace Service::Glue
diff --git a/src/core/hle/service/glue/notif.h b/src/core/hle/service/glue/notif.h
new file mode 100644
index 000000000..6ecf2015c
--- /dev/null
+++ b/src/core/hle/service/glue/notif.h
@@ -0,0 +1,25 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9namespace Core {
10class System;
11}
12
13namespace Service::Glue {
14
15class NOTIF_A final : public ServiceFramework<NOTIF_A> {
16public:
17 explicit NOTIF_A(Core::System& system_);
18 ~NOTIF_A() override;
19
20private:
21 void ListAlarmSettings(Kernel::HLERequestContext& ctx);
22 void Initialize(Kernel::HLERequestContext& ctx);
23};
24
25} // namespace Service::Glue
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 6916930f7..2705e9dcb 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -110,7 +110,7 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
110 UpdateControllerAt(npad_type, npad_id, is_connected); 110 UpdateControllerAt(npad_type, npad_id, is_connected);
111 break; 111 break;
112 case Core::HID::ControllerTriggerType::Battery: { 112 case Core::HID::ControllerTriggerType::Battery: {
113 if (!controller.is_connected) { 113 if (!controller.device->IsConnected()) {
114 return; 114 return;
115 } 115 }
116 auto& shared_memory = controller.shared_memory_entry; 116 auto& shared_memory = controller.shared_memory_entry;
@@ -126,8 +126,11 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
126} 126}
127 127
128void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) { 128void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
129 LOG_DEBUG(Service_HID, "Npad connected {}", npad_id);
130 auto& controller = GetControllerFromNpadIdType(npad_id); 129 auto& controller = GetControllerFromNpadIdType(npad_id);
130 if (!IsControllerSupported(controller.device->GetNpadStyleIndex())) {
131 return;
132 }
133 LOG_DEBUG(Service_HID, "Npad connected {}", npad_id);
131 const auto controller_type = controller.device->GetNpadStyleIndex(); 134 const auto controller_type = controller.device->GetNpadStyleIndex();
132 auto& shared_memory = controller.shared_memory_entry; 135 auto& shared_memory = controller.shared_memory_entry;
133 if (controller_type == Core::HID::NpadStyleIndex::None) { 136 if (controller_type == Core::HID::NpadStyleIndex::None) {
@@ -147,7 +150,6 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
147 shared_memory.system_properties.is_vertical.Assign(1); 150 shared_memory.system_properties.is_vertical.Assign(1);
148 shared_memory.system_properties.use_plus.Assign(1); 151 shared_memory.system_properties.use_plus.Assign(1);
149 shared_memory.system_properties.use_minus.Assign(1); 152 shared_memory.system_properties.use_minus.Assign(1);
150 shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
151 shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController; 153 shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController;
152 break; 154 break;
153 case Core::HID::NpadStyleIndex::Handheld: 155 case Core::HID::NpadStyleIndex::Handheld:
@@ -163,21 +165,30 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
163 break; 165 break;
164 case Core::HID::NpadStyleIndex::JoyconDual: 166 case Core::HID::NpadStyleIndex::JoyconDual:
165 shared_memory.style_tag.joycon_dual.Assign(1); 167 shared_memory.style_tag.joycon_dual.Assign(1);
166 shared_memory.device_type.joycon_left.Assign(1); 168 if (controller.is_dual_left_connected) {
167 shared_memory.device_type.joycon_right.Assign(1); 169 shared_memory.device_type.joycon_left.Assign(1);
168 shared_memory.system_properties.is_vertical.Assign(1); 170 shared_memory.system_properties.use_minus.Assign(1);
169 shared_memory.system_properties.use_plus.Assign(1); 171 }
170 shared_memory.system_properties.use_minus.Assign(1); 172 if (controller.is_dual_right_connected) {
173 shared_memory.device_type.joycon_right.Assign(1);
174 shared_memory.system_properties.use_plus.Assign(1);
175 }
171 shared_memory.system_properties.use_directional_buttons.Assign(1); 176 shared_memory.system_properties.use_directional_buttons.Assign(1);
177 shared_memory.system_properties.is_vertical.Assign(1);
172 shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; 178 shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
173 shared_memory.applet_footer.type = AppletFooterUiType::JoyDual; 179 if (controller.is_dual_left_connected && controller.is_dual_right_connected) {
180 shared_memory.applet_footer.type = AppletFooterUiType::JoyDual;
181 } else if (controller.is_dual_left_connected) {
182 shared_memory.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly;
183 } else {
184 shared_memory.applet_footer.type = AppletFooterUiType::JoyDualRightOnly;
185 }
174 break; 186 break;
175 case Core::HID::NpadStyleIndex::JoyconLeft: 187 case Core::HID::NpadStyleIndex::JoyconLeft:
176 shared_memory.style_tag.joycon_left.Assign(1); 188 shared_memory.style_tag.joycon_left.Assign(1);
177 shared_memory.device_type.joycon_left.Assign(1); 189 shared_memory.device_type.joycon_left.Assign(1);
178 shared_memory.system_properties.is_horizontal.Assign(1); 190 shared_memory.system_properties.is_horizontal.Assign(1);
179 shared_memory.system_properties.use_minus.Assign(1); 191 shared_memory.system_properties.use_minus.Assign(1);
180 shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
181 shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal; 192 shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
182 break; 193 break;
183 case Core::HID::NpadStyleIndex::JoyconRight: 194 case Core::HID::NpadStyleIndex::JoyconRight:
@@ -185,7 +196,6 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
185 shared_memory.device_type.joycon_right.Assign(1); 196 shared_memory.device_type.joycon_right.Assign(1);
186 shared_memory.system_properties.is_horizontal.Assign(1); 197 shared_memory.system_properties.is_horizontal.Assign(1);
187 shared_memory.system_properties.use_plus.Assign(1); 198 shared_memory.system_properties.use_plus.Assign(1);
188 shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
189 shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal; 199 shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
190 break; 200 break;
191 case Core::HID::NpadStyleIndex::GameCube: 201 case Core::HID::NpadStyleIndex::GameCube:
@@ -197,7 +207,6 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
197 case Core::HID::NpadStyleIndex::Pokeball: 207 case Core::HID::NpadStyleIndex::Pokeball:
198 shared_memory.style_tag.palma.Assign(1); 208 shared_memory.style_tag.palma.Assign(1);
199 shared_memory.device_type.palma.Assign(1); 209 shared_memory.device_type.palma.Assign(1);
200 shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
201 break; 210 break;
202 case Core::HID::NpadStyleIndex::NES: 211 case Core::HID::NpadStyleIndex::NES:
203 shared_memory.style_tag.lark.Assign(1); 212 shared_memory.style_tag.lark.Assign(1);
@@ -255,19 +264,7 @@ void Controller_NPad::OnInit() {
255 264
256 if (hid_core.GetSupportedStyleTag().raw == Core::HID::NpadStyleSet::None) { 265 if (hid_core.GetSupportedStyleTag().raw == Core::HID::NpadStyleSet::None) {
257 // We want to support all controllers 266 // We want to support all controllers
258 Core::HID::NpadStyleTag style{}; 267 hid_core.SetSupportedStyleTag({Core::HID::NpadStyleSet::All});
259 style.handheld.Assign(1);
260 style.joycon_left.Assign(1);
261 style.joycon_right.Assign(1);
262 style.joycon_dual.Assign(1);
263 style.fullkey.Assign(1);
264 style.gamecube.Assign(1);
265 style.palma.Assign(1);
266 style.lark.Assign(1);
267 style.lucia.Assign(1);
268 style.lagoon.Assign(1);
269 style.lager.Assign(1);
270 hid_core.SetSupportedStyleTag(style);
271 } 268 }
272 269
273 supported_npad_id_types.resize(npad_id_list.size()); 270 supported_npad_id_types.resize(npad_id_list.size());
@@ -452,11 +449,15 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
452 case Core::HID::NpadStyleIndex::JoyconDual: 449 case Core::HID::NpadStyleIndex::JoyconDual:
453 pad_state.connection_status.raw = 0; 450 pad_state.connection_status.raw = 0;
454 pad_state.connection_status.is_connected.Assign(1); 451 pad_state.connection_status.is_connected.Assign(1);
455 pad_state.connection_status.is_left_connected.Assign(1); 452 if (controller.is_dual_left_connected) {
456 pad_state.connection_status.is_right_connected.Assign(1); 453 pad_state.connection_status.is_left_connected.Assign(1);
454 libnx_state.connection_status.is_left_connected.Assign(1);
455 }
456 if (controller.is_dual_right_connected) {
457 pad_state.connection_status.is_right_connected.Assign(1);
458 libnx_state.connection_status.is_right_connected.Assign(1);
459 }
457 460
458 libnx_state.connection_status.is_left_connected.Assign(1);
459 libnx_state.connection_status.is_right_connected.Assign(1);
460 pad_state.sampling_number = 461 pad_state.sampling_number =
461 npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1; 462 npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1;
462 npad.joy_dual_lifo.WriteNextEntry(pad_state); 463 npad.joy_dual_lifo.WriteNextEntry(pad_state);
@@ -696,7 +697,7 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode
696 return communication_mode; 697 return communication_mode;
697} 698}
698 699
699void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, 700void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type,
700 NpadJoyAssignmentMode assignment_mode) { 701 NpadJoyAssignmentMode assignment_mode) {
701 if (!IsNpadIdValid(npad_id)) { 702 if (!IsNpadIdValid(npad_id)) {
702 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 703 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
@@ -707,6 +708,62 @@ void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id,
707 if (controller.shared_memory_entry.assignment_mode != assignment_mode) { 708 if (controller.shared_memory_entry.assignment_mode != assignment_mode) {
708 controller.shared_memory_entry.assignment_mode = assignment_mode; 709 controller.shared_memory_entry.assignment_mode = assignment_mode;
709 } 710 }
711
712 if (!controller.device->IsConnected()) {
713 return;
714 }
715
716 if (assignment_mode == NpadJoyAssignmentMode::Dual) {
717 if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft) {
718 DisconnectNpad(npad_id);
719 controller.is_dual_left_connected = true;
720 controller.is_dual_right_connected = false;
721 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
722 return;
723 }
724 if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) {
725 DisconnectNpad(npad_id);
726 controller.is_dual_left_connected = false;
727 controller.is_dual_right_connected = true;
728 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
729 return;
730 }
731 return;
732 }
733
734 // This is for NpadJoyAssignmentMode::Single
735
736 // Only JoyconDual get affected by this function
737 if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) {
738 return;
739 }
740
741 if (controller.is_dual_left_connected && !controller.is_dual_right_connected) {
742 DisconnectNpad(npad_id);
743 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true);
744 return;
745 }
746 if (!controller.is_dual_left_connected && controller.is_dual_right_connected) {
747 DisconnectNpad(npad_id);
748 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true);
749 return;
750 }
751
752 // We have two controllers connected to the same npad_id we need to split them
753 const auto npad_id_2 = hid_core.GetFirstDisconnectedNpadId();
754 auto& controller_2 = GetControllerFromNpadIdType(npad_id_2);
755 DisconnectNpad(npad_id);
756 if (npad_device_type == NpadJoyDeviceType::Left) {
757 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true);
758 controller_2.is_dual_left_connected = false;
759 controller_2.is_dual_right_connected = true;
760 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true);
761 } else {
762 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true);
763 controller_2.is_dual_left_connected = true;
764 controller_2.is_dual_right_connected = false;
765 UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true);
766 }
710} 767}
711 768
712bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, 769bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
@@ -916,6 +973,7 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
916 } 973 }
917 974
918 auto& shared_memory_entry = controller.shared_memory_entry; 975 auto& shared_memory_entry = controller.shared_memory_entry;
976 // Don't reset shared_memory_entry.assignment_mode this value is persistent
919 shared_memory_entry.style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out 977 shared_memory_entry.style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out
920 shared_memory_entry.device_type.raw = 0; 978 shared_memory_entry.device_type.raw = 0;
921 shared_memory_entry.system_properties.raw = 0; 979 shared_memory_entry.system_properties.raw = 0;
@@ -932,9 +990,10 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
932 .left = {}, 990 .left = {},
933 .right = {}, 991 .right = {},
934 }; 992 };
935 shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual;
936 shared_memory_entry.applet_footer.type = AppletFooterUiType::None; 993 shared_memory_entry.applet_footer.type = AppletFooterUiType::None;
937 994
995 controller.is_dual_left_connected = true;
996 controller.is_dual_right_connected = true;
938 controller.is_connected = false; 997 controller.is_connected = false;
939 controller.device->Disconnect(); 998 controller.device->Disconnect();
940 SignalStyleSetChangedEvent(npad_id); 999 SignalStyleSetChangedEvent(npad_id);
@@ -1031,19 +1090,70 @@ void Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
1031 npad_id_2); 1090 npad_id_2);
1032 return; 1091 return;
1033 } 1092 }
1034 auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device; 1093 auto& controller_1 = GetControllerFromNpadIdType(npad_id_1);
1035 auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device; 1094 auto& controller_2 = GetControllerFromNpadIdType(npad_id_2);
1095 const auto controller_style_1 = controller_1.device->GetNpadStyleIndex();
1096 const auto controller_style_2 = controller_2.device->GetNpadStyleIndex();
1097 bool merge_controllers = false;
1036 1098
1037 // If the controllers at both npad indices form a pair of left and right joycons, merge them. 1099 // If the controllers at both npad indices form a pair of left and right joycons, merge them.
1038 // Otherwise, do nothing. 1100 // Otherwise, do nothing.
1039 if ((controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && 1101 if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft &&
1040 controller_2->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) || 1102 controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) {
1041 (controller_2->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && 1103 merge_controllers = true;
1042 controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight)) { 1104 }
1105 if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft &&
1106 controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight) {
1107 merge_controllers = true;
1108 }
1109 if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
1110 controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight &&
1111 controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) {
1112 merge_controllers = true;
1113 }
1114 if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
1115 controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft &&
1116 !controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) {
1117 merge_controllers = true;
1118 }
1119 if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
1120 controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight &&
1121 controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) {
1122 merge_controllers = true;
1123 }
1124 if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
1125 controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft &&
1126 !controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) {
1127 merge_controllers = true;
1128 }
1129 if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
1130 controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
1131 controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected &&
1132 !controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) {
1133 merge_controllers = true;
1134 }
1135 if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
1136 controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
1137 !controller_1.is_dual_left_connected && controller_1.is_dual_right_connected &&
1138 controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) {
1139 merge_controllers = true;
1140 }
1141
1142 if (merge_controllers) {
1043 // Disconnect the joycon at the second id and connect the dual joycon at the first index. 1143 // Disconnect the joycon at the second id and connect the dual joycon at the first index.
1044 DisconnectNpad(npad_id_2); 1144 DisconnectNpad(npad_id_2);
1145 controller_1.is_dual_left_connected = true;
1146 controller_1.is_dual_right_connected = true;
1045 AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); 1147 AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1);
1148 return;
1046 } 1149 }
1150 LOG_WARNING(Service_HID,
1151 "Controllers can't be merged npad_id_1:{}, npad_id_2:{}, type_1:{}, type_2:{}, "
1152 "dual_1(left/right):{}/{}, dual_2(left/right):{}/{}",
1153 npad_id_1, npad_id_2, controller_1.device->GetNpadStyleIndex(),
1154 controller_2.device->GetNpadStyleIndex(), controller_1.is_dual_left_connected,
1155 controller_1.is_dual_right_connected, controller_2.is_dual_left_connected,
1156 controller_2.is_dual_right_connected);
1047} 1157}
1048 1158
1049void Controller_NPad::StartLRAssignmentMode() { 1159void Controller_NPad::StartLRAssignmentMode() {
@@ -1072,13 +1182,18 @@ bool Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
1072 const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device; 1182 const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device;
1073 const auto type_index_1 = controller_1->GetNpadStyleIndex(); 1183 const auto type_index_1 = controller_1->GetNpadStyleIndex();
1074 const auto type_index_2 = controller_2->GetNpadStyleIndex(); 1184 const auto type_index_2 = controller_2->GetNpadStyleIndex();
1185 const auto is_connected_1 = controller_1->IsConnected();
1186 const auto is_connected_2 = controller_2->IsConnected();
1075 1187
1076 if (!IsControllerSupported(type_index_1) || !IsControllerSupported(type_index_2)) { 1188 if (!IsControllerSupported(type_index_1) && is_connected_1) {
1189 return false;
1190 }
1191 if (!IsControllerSupported(type_index_2) && is_connected_2) {
1077 return false; 1192 return false;
1078 } 1193 }
1079 1194
1080 AddNewControllerAt(type_index_2, npad_id_1); 1195 UpdateControllerAt(type_index_2, npad_id_1, is_connected_2);
1081 AddNewControllerAt(type_index_1, npad_id_2); 1196 UpdateControllerAt(type_index_1, npad_id_2, is_connected_1);
1082 1197
1083 return true; 1198 return true;
1084} 1199}
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index de5fa5a64..63281cb35 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -113,7 +113,8 @@ public:
113 void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); 113 void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_);
114 NpadCommunicationMode GetNpadCommunicationMode() const; 114 NpadCommunicationMode GetNpadCommunicationMode() const;
115 115
116 void SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyAssignmentMode assignment_mode); 116 void SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type,
117 NpadJoyAssignmentMode assignment_mode);
117 118
118 bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index, 119 bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index,
119 const Core::HID::VibrationValue& vibration_value); 120 const Core::HID::VibrationValue& vibration_value);
@@ -464,7 +465,10 @@ private:
464 std::array<VibrationData, 2> vibration{}; 465 std::array<VibrationData, 2> vibration{};
465 bool unintended_home_button_input_protection{}; 466 bool unintended_home_button_input_protection{};
466 bool is_connected{}; 467 bool is_connected{};
467 Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None}; 468
469 // Dual joycons can have only one side connected
470 bool is_dual_left_connected{true};
471 bool is_dual_right_connected{true};
468 472
469 // Motion parameters 473 // Motion parameters
470 bool sixaxis_at_rest{true}; 474 bool sixaxis_at_rest{true};
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index b36689552..7163e1a4e 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -293,8 +293,8 @@ Hid::Hid(Core::System& system_)
293 {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"}, 293 {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"},
294 {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"}, 294 {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"},
295 {134, &Hid::SetNpadAnalogStickUseCenterClamp, "SetNpadAnalogStickUseCenterClamp"}, 295 {134, &Hid::SetNpadAnalogStickUseCenterClamp, "SetNpadAnalogStickUseCenterClamp"},
296 {135, nullptr, "SetNpadCaptureButtonAssignment"}, 296 {135, &Hid::SetNpadCaptureButtonAssignment, "SetNpadCaptureButtonAssignment"},
297 {136, nullptr, "ClearNpadCaptureButtonAssignment"}, 297 {136, &Hid::ClearNpadCaptureButtonAssignment, "ClearNpadCaptureButtonAssignment"},
298 {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"}, 298 {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
299 {201, &Hid::SendVibrationValue, "SendVibrationValue"}, 299 {201, &Hid::SendVibrationValue, "SendVibrationValue"},
300 {202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"}, 300 {202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"},
@@ -975,35 +975,35 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx
975 const auto parameters{rp.PopRaw<Parameters>()}; 975 const auto parameters{rp.PopRaw<Parameters>()};
976 976
977 applet_resource->GetController<Controller_NPad>(HidController::NPad) 977 applet_resource->GetController<Controller_NPad>(HidController::NPad)
978 .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Single); 978 .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyDeviceType::Left,
979 Controller_NPad::NpadJoyAssignmentMode::Single);
979 980
980 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", 981 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
981 parameters.npad_id, parameters.applet_resource_user_id); 982 parameters.applet_resource_user_id);
982 983
983 IPC::ResponseBuilder rb{ctx, 2}; 984 IPC::ResponseBuilder rb{ctx, 2};
984 rb.Push(ResultSuccess); 985 rb.Push(ResultSuccess);
985} 986}
986 987
987void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { 988void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
988 // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault
989 IPC::RequestParser rp{ctx}; 989 IPC::RequestParser rp{ctx};
990 struct Parameters { 990 struct Parameters {
991 Core::HID::NpadIdType npad_id; 991 Core::HID::NpadIdType npad_id;
992 INSERT_PADDING_WORDS_NOINIT(1); 992 INSERT_PADDING_WORDS_NOINIT(1);
993 u64 applet_resource_user_id; 993 u64 applet_resource_user_id;
994 u64 npad_joy_device_type; 994 Controller_NPad::NpadJoyDeviceType npad_joy_device_type;
995 }; 995 };
996 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); 996 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
997 997
998 const auto parameters{rp.PopRaw<Parameters>()}; 998 const auto parameters{rp.PopRaw<Parameters>()};
999 999
1000 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1000 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1001 .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Single); 1001 .SetNpadMode(parameters.npad_id, parameters.npad_joy_device_type,
1002 Controller_NPad::NpadJoyAssignmentMode::Single);
1002 1003
1003 LOG_WARNING(Service_HID, 1004 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
1004 "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", 1005 parameters.npad_id, parameters.applet_resource_user_id,
1005 parameters.npad_id, parameters.applet_resource_user_id, 1006 parameters.npad_joy_device_type);
1006 parameters.npad_joy_device_type);
1007 1007
1008 IPC::ResponseBuilder rb{ctx, 2}; 1008 IPC::ResponseBuilder rb{ctx, 2};
1009 rb.Push(ResultSuccess); 1009 rb.Push(ResultSuccess);
@@ -1021,10 +1021,10 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
1021 const auto parameters{rp.PopRaw<Parameters>()}; 1021 const auto parameters{rp.PopRaw<Parameters>()};
1022 1022
1023 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1023 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1024 .SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Dual); 1024 .SetNpadMode(parameters.npad_id, {}, Controller_NPad::NpadJoyAssignmentMode::Dual);
1025 1025
1026 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", 1026 LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
1027 parameters.npad_id, parameters.applet_resource_user_id); 1027 parameters.applet_resource_user_id);
1028 1028
1029 IPC::ResponseBuilder rb{ctx, 2}; 1029 IPC::ResponseBuilder rb{ctx, 2};
1030 rb.Push(ResultSuccess); 1030 rb.Push(ResultSuccess);
@@ -1186,6 +1186,37 @@ void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) {
1186 rb.Push(ResultSuccess); 1186 rb.Push(ResultSuccess);
1187} 1187}
1188 1188
1189void Hid::SetNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx) {
1190 IPC::RequestParser rp{ctx};
1191 struct Parameters {
1192 Core::HID::NpadStyleSet npad_styleset;
1193 INSERT_PADDING_WORDS_NOINIT(1);
1194 u64 applet_resource_user_id;
1195 Core::HID::NpadButton button;
1196 };
1197 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1198
1199 const auto parameters{rp.PopRaw<Parameters>()};
1200
1201 LOG_WARNING(Service_HID,
1202 "(STUBBED) called, npad_styleset={}, applet_resource_user_id={}, button={}",
1203 parameters.npad_styleset, parameters.applet_resource_user_id, parameters.button);
1204
1205 IPC::ResponseBuilder rb{ctx, 2};
1206 rb.Push(ResultSuccess);
1207}
1208
1209void Hid::ClearNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx) {
1210 IPC::RequestParser rp{ctx};
1211 const auto applet_resource_user_id{rp.Pop<u64>()};
1212
1213 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
1214 applet_resource_user_id);
1215
1216 IPC::ResponseBuilder rb{ctx, 2};
1217 rb.Push(ResultSuccess);
1218}
1219
1189void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { 1220void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
1190 IPC::RequestParser rp{ctx}; 1221 IPC::RequestParser rp{ctx};
1191 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; 1222 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index ab0084118..d290df161 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -136,6 +136,8 @@ private:
136 void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx); 136 void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx);
137 void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx); 137 void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx);
138 void SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx); 138 void SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx);
139 void SetNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx);
140 void ClearNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx);
139 void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); 141 void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx);
140 void SendVibrationValue(Kernel::HLERequestContext& ctx); 142 void SendVibrationValue(Kernel::HLERequestContext& ctx);
141 void GetActualVibrationValue(Kernel::HLERequestContext& ctx); 143 void GetActualVibrationValue(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
index 0d7d4ad03..8314d1ec2 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
@@ -20,8 +20,12 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>&
20 switch (command.group) { 20 switch (command.group) {
21 case 0x0: 21 case 0x0:
22 switch (command.cmd) { 22 switch (command.cmd) {
23 case 0x1: 23 case 0x1: {
24 return Submit(input, output); 24 if (!fd_to_id.contains(fd)) {
25 fd_to_id[fd] = next_id++;
26 }
27 return Submit(fd, input, output);
28 }
25 case 0x2: 29 case 0x2:
26 return GetSyncpoint(input, output); 30 return GetSyncpoint(input, output);
27 case 0x3: 31 case 0x3:
@@ -66,7 +70,10 @@ void nvhost_nvdec::OnOpen(DeviceFD fd) {}
66 70
67void nvhost_nvdec::OnClose(DeviceFD fd) { 71void nvhost_nvdec::OnClose(DeviceFD fd) {
68 LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); 72 LOG_INFO(Service_NVDRV, "NVDEC video stream ended");
69 system.GPU().ClearCdmaInstance(); 73 const auto iter = fd_to_id.find(fd);
74 if (iter != fd_to_id.end()) {
75 system.GPU().ClearCdmaInstance(iter->second);
76 }
70} 77}
71 78
72} // namespace Service::Nvidia::Devices 79} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
index 523d96e3a..a507c4d0a 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
@@ -24,6 +24,9 @@ public:
24 24
25 void OnOpen(DeviceFD fd) override; 25 void OnOpen(DeviceFD fd) override;
26 void OnClose(DeviceFD fd) override; 26 void OnClose(DeviceFD fd) override;
27
28private:
29 u32 next_id{};
27}; 30};
28 31
29} // namespace Service::Nvidia::Devices 32} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
index e61261f98..8a05f0668 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
@@ -59,7 +59,8 @@ NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) {
59 return NvResult::Success; 59 return NvResult::Success;
60} 60}
61 61
62NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u8>& output) { 62NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector<u8>& input,
63 std::vector<u8>& output) {
63 IoctlSubmit params{}; 64 IoctlSubmit params{};
64 std::memcpy(&params, input.data(), sizeof(IoctlSubmit)); 65 std::memcpy(&params, input.data(), sizeof(IoctlSubmit));
65 LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); 66 LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count);
@@ -93,7 +94,7 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u
93 Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); 94 Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count);
94 system.Memory().ReadBlock(object->addr + cmd_buffer.offset, cmdlist.data(), 95 system.Memory().ReadBlock(object->addr + cmd_buffer.offset, cmdlist.data(),
95 cmdlist.size() * sizeof(u32)); 96 cmdlist.size() * sizeof(u32));
96 gpu.PushCommandBuffer(cmdlist); 97 gpu.PushCommandBuffer(fd_to_id[fd], cmdlist);
97 } 98 }
98 std::memcpy(output.data(), &params, sizeof(IoctlSubmit)); 99 std::memcpy(output.data(), &params, sizeof(IoctlSubmit));
99 // Some games expect command_buffers to be written back 100 // Some games expect command_buffers to be written back
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
index 351625c17..e28c54df6 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
@@ -104,13 +104,14 @@ protected:
104 104
105 /// Ioctl command implementations 105 /// Ioctl command implementations
106 NvResult SetNVMAPfd(const std::vector<u8>& input); 106 NvResult SetNVMAPfd(const std::vector<u8>& input);
107 NvResult Submit(const std::vector<u8>& input, std::vector<u8>& output); 107 NvResult Submit(DeviceFD fd, const std::vector<u8>& input, std::vector<u8>& output);
108 NvResult GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output); 108 NvResult GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output);
109 NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); 109 NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
110 NvResult MapBuffer(const std::vector<u8>& input, std::vector<u8>& output); 110 NvResult MapBuffer(const std::vector<u8>& input, std::vector<u8>& output);
111 NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); 111 NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output);
112 NvResult SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output); 112 NvResult SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output);
113 113
114 std::unordered_map<DeviceFD, u32> fd_to_id{};
114 s32_le nvmap_fd{}; 115 s32_le nvmap_fd{};
115 u32_le submit_timeout{}; 116 u32_le submit_timeout{};
116 std::shared_ptr<nvmap> nvmap_dev; 117 std::shared_ptr<nvmap> nvmap_dev;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
index eac4dd530..76b39806f 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
@@ -21,7 +21,10 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& i
21 case 0x0: 21 case 0x0:
22 switch (command.cmd) { 22 switch (command.cmd) {
23 case 0x1: 23 case 0x1:
24 return Submit(input, output); 24 if (!fd_to_id.contains(fd)) {
25 fd_to_id[fd] = next_id++;
26 }
27 return Submit(fd, input, output);
25 case 0x2: 28 case 0x2:
26 return GetSyncpoint(input, output); 29 return GetSyncpoint(input, output);
27 case 0x3: 30 case 0x3:
@@ -65,7 +68,10 @@ NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& i
65void nvhost_vic::OnOpen(DeviceFD fd) {} 68void nvhost_vic::OnOpen(DeviceFD fd) {}
66 69
67void nvhost_vic::OnClose(DeviceFD fd) { 70void nvhost_vic::OnClose(DeviceFD fd) {
68 system.GPU().ClearCdmaInstance(); 71 const auto iter = fd_to_id.find(fd);
72 if (iter != fd_to_id.end()) {
73 system.GPU().ClearCdmaInstance(iter->second);
74 }
69} 75}
70 76
71} // namespace Service::Nvidia::Devices 77} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
index 6d7fda9d1..c9732c037 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
@@ -23,5 +23,8 @@ public:
23 23
24 void OnOpen(DeviceFD fd) override; 24 void OnOpen(DeviceFD fd) override;
25 void OnClose(DeviceFD fd) override; 25 void OnClose(DeviceFD fd) override;
26
27private:
28 u32 next_id{};
26}; 29};
27} // namespace Service::Nvidia::Devices 30} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/nvdata.h b/src/core/hle/service/nvdrv/nvdata.h
index 3294bc0e7..5ab221fc1 100644
--- a/src/core/hle/service/nvdrv/nvdata.h
+++ b/src/core/hle/service/nvdrv/nvdata.h
@@ -1,3 +1,7 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
1#pragma once 5#pragma once
2 6
3#include <array> 7#include <array>
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 1b5aca65d..b47e3bf69 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -125,8 +125,9 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
125 } 125 }
126 metadata.Print(); 126 metadata.Print();
127 127
128 const auto static_modules = {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3", 128 const auto static_modules = {"rtld", "main", "subsdk0", "subsdk1", "subsdk2",
129 "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}; 129 "subsdk3", "subsdk4", "subsdk5", "subsdk6", "subsdk7",
130 "subsdk8", "subsdk9", "sdk"};
130 131
131 // Use the NSO module loader to figure out the code layout 132 // Use the NSO module loader to figure out the code layout
132 std::size_t code_size{}; 133 std::size_t code_size{};
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt
index bc3df80c8..4c76ce1ea 100644
--- a/src/shader_recompiler/CMakeLists.txt
+++ b/src/shader_recompiler/CMakeLists.txt
@@ -1,7 +1,5 @@
1add_library(shader_recompiler STATIC 1add_library(shader_recompiler STATIC
2 backend/bindings.h 2 backend/bindings.h
3 backend/glasm/emit_context.cpp
4 backend/glasm/emit_context.h
5 backend/glasm/emit_glasm.cpp 3 backend/glasm/emit_glasm.cpp
6 backend/glasm/emit_glasm.h 4 backend/glasm/emit_glasm.h
7 backend/glasm/emit_glasm_barriers.cpp 5 backend/glasm/emit_glasm_barriers.cpp
@@ -22,10 +20,10 @@ add_library(shader_recompiler STATIC
22 backend/glasm/emit_glasm_special.cpp 20 backend/glasm/emit_glasm_special.cpp
23 backend/glasm/emit_glasm_undefined.cpp 21 backend/glasm/emit_glasm_undefined.cpp
24 backend/glasm/emit_glasm_warp.cpp 22 backend/glasm/emit_glasm_warp.cpp
23 backend/glasm/glasm_emit_context.cpp
24 backend/glasm/glasm_emit_context.h
25 backend/glasm/reg_alloc.cpp 25 backend/glasm/reg_alloc.cpp
26 backend/glasm/reg_alloc.h 26 backend/glasm/reg_alloc.h
27 backend/glsl/emit_context.cpp
28 backend/glsl/emit_context.h
29 backend/glsl/emit_glsl.cpp 27 backend/glsl/emit_glsl.cpp
30 backend/glsl/emit_glsl.h 28 backend/glsl/emit_glsl.h
31 backend/glsl/emit_glsl_atomic.cpp 29 backend/glsl/emit_glsl_atomic.cpp
@@ -47,10 +45,10 @@ add_library(shader_recompiler STATIC
47 backend/glsl/emit_glsl_special.cpp 45 backend/glsl/emit_glsl_special.cpp
48 backend/glsl/emit_glsl_undefined.cpp 46 backend/glsl/emit_glsl_undefined.cpp
49 backend/glsl/emit_glsl_warp.cpp 47 backend/glsl/emit_glsl_warp.cpp
48 backend/glsl/glsl_emit_context.cpp
49 backend/glsl/glsl_emit_context.h
50 backend/glsl/var_alloc.cpp 50 backend/glsl/var_alloc.cpp
51 backend/glsl/var_alloc.h 51 backend/glsl/var_alloc.h
52 backend/spirv/emit_context.cpp
53 backend/spirv/emit_context.h
54 backend/spirv/emit_spirv.cpp 52 backend/spirv/emit_spirv.cpp
55 backend/spirv/emit_spirv.h 53 backend/spirv/emit_spirv.h
56 backend/spirv/emit_spirv_atomic.cpp 54 backend/spirv/emit_spirv_atomic.cpp
@@ -72,6 +70,8 @@ add_library(shader_recompiler STATIC
72 backend/spirv/emit_spirv_special.cpp 70 backend/spirv/emit_spirv_special.cpp
73 backend/spirv/emit_spirv_undefined.cpp 71 backend/spirv/emit_spirv_undefined.cpp
74 backend/spirv/emit_spirv_warp.cpp 72 backend/spirv/emit_spirv_warp.cpp
73 backend/spirv/spirv_emit_context.cpp
74 backend/spirv/spirv_emit_context.h
75 environment.h 75 environment.h
76 exception.h 76 exception.h
77 frontend/ir/abstract_syntax_list.h 77 frontend/ir/abstract_syntax_list.h
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
index 004658546..42eff443f 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
@@ -9,9 +9,9 @@
9#include "common/div_ceil.h" 9#include "common/div_ceil.h"
10#include "common/settings.h" 10#include "common/settings.h"
11#include "shader_recompiler/backend/bindings.h" 11#include "shader_recompiler/backend/bindings.h"
12#include "shader_recompiler/backend/glasm/emit_context.h"
13#include "shader_recompiler/backend/glasm/emit_glasm.h" 12#include "shader_recompiler/backend/glasm/emit_glasm.h"
14#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 13#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
14#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
15#include "shader_recompiler/frontend/ir/ir_emitter.h" 15#include "shader_recompiler/frontend/ir/ir_emitter.h"
16#include "shader_recompiler/frontend/ir/program.h" 16#include "shader_recompiler/frontend/ir/program.h"
17#include "shader_recompiler/profile.h" 17#include "shader_recompiler/profile.h"
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_barriers.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_barriers.cpp
index e69de29bb..c0b97683e 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_barriers.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_barriers.cpp
@@ -0,0 +1,22 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
6#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
7
8namespace Shader::Backend::GLASM {
9
10void EmitBarrier(EmitContext& ctx) {
11 ctx.Add("BAR;");
12}
13
14void EmitWorkgroupMemoryBarrier(EmitContext& ctx) {
15 ctx.Add("MEMBAR.CTA;");
16}
17
18void EmitDeviceMemoryBarrier(EmitContext& ctx) {
19 ctx.Add("MEMBAR;");
20}
21
22} // namespace Shader::Backend::GLASM
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp
index 9201ccd39..3bfcbbe65 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp
@@ -2,8 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/glasm/emit_context.h"
6#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 5#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
6#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
7#include "shader_recompiler/frontend/ir/value.h" 7#include "shader_recompiler/frontend/ir/value.h"
8 8
9namespace Shader::Backend::GLASM { 9namespace Shader::Backend::GLASM {
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp
index bff0b7c1c..babbe6654 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp
@@ -2,8 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/glasm/emit_context.h"
6#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 5#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
6#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
7#include "shader_recompiler/frontend/ir/value.h" 7#include "shader_recompiler/frontend/ir/value.h"
8 8
9namespace Shader::Backend::GLASM { 9namespace Shader::Backend::GLASM {
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
index 02c9dc6d7..081b2c8e0 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glasm/emit_context.h"
8#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 7#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
8#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
10#include "shader_recompiler/profile.h" 10#include "shader_recompiler/profile.h"
11#include "shader_recompiler/shader_info.h" 11#include "shader_recompiler/shader_info.h"
@@ -335,6 +335,35 @@ void EmitSetFragDepth(EmitContext& ctx, ScalarF32 value) {
335 ctx.Add("MOV.F result.depth.z,{};", value); 335 ctx.Add("MOV.F result.depth.z,{};", value);
336} 336}
337 337
338void EmitWorkgroupId(EmitContext& ctx, IR::Inst& inst) {
339 ctx.Add("MOV.S {},invocation.groupid;", inst);
340}
341
342void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst) {
343 ctx.Add("MOV.S {},invocation.localid;", inst);
344}
345
346void EmitInvocationId(EmitContext& ctx, IR::Inst& inst) {
347 ctx.Add("MOV.S {}.x,primitive_invocation.x;", inst);
348}
349
350void EmitSampleId(EmitContext& ctx, IR::Inst& inst) {
351 ctx.Add("MOV.S {}.x,fragment.sampleid.x;", inst);
352}
353
354void EmitIsHelperInvocation(EmitContext& ctx, IR::Inst& inst) {
355 ctx.Add("MOV.S {}.x,fragment.helperthread.x;", inst);
356}
357
358void EmitYDirection(EmitContext& ctx, IR::Inst& inst) {
359 ctx.uses_y_direction = true;
360 ctx.Add("MOV.F {}.x,y_direction[0].w;", inst);
361}
362
363void EmitResolutionDownFactor(EmitContext& ctx, IR::Inst& inst) {
364 ctx.Add("MOV.F {}.x,scaling[0].z;", inst);
365}
366
338void EmitLoadLocal(EmitContext& ctx, IR::Inst& inst, ScalarU32 word_offset) { 367void EmitLoadLocal(EmitContext& ctx, IR::Inst& inst, ScalarU32 word_offset) {
339 ctx.Add("MOV.U {},lmem[{}].x;", inst, word_offset); 368 ctx.Add("MOV.U {},lmem[{}].x;", inst, word_offset);
340} 369}
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_control_flow.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_control_flow.cpp
index e69de29bb..8a14fc8d9 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_control_flow.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_control_flow.cpp
@@ -0,0 +1,18 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
6#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
7
8namespace Shader::Backend::GLASM {
9
10void EmitJoin(EmitContext&) {
11 throw NotImplementedException("Join shouldn't be emitted");
12}
13
14void EmitDemoteToHelperInvocation(EmitContext& ctx) {
15 ctx.Add("KIL TR.x;");
16}
17
18} // namespace Shader::Backend::GLASM
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp
index ccdf1cbc8..4cff70fe4 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_convert.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glasm/emit_context.h"
8#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 7#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
8#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
9#include "shader_recompiler/frontend/ir/modifiers.h" 9#include "shader_recompiler/frontend/ir/modifiers.h"
10#include "shader_recompiler/frontend/ir/value.h" 10#include "shader_recompiler/frontend/ir/value.h"
11 11
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp
index 4ed58619d..356640471 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_floating_point.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glasm/emit_context.h"
8#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 7#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
8#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
9#include "shader_recompiler/frontend/ir/modifiers.h" 9#include "shader_recompiler/frontend/ir/modifiers.h"
10#include "shader_recompiler/frontend/ir/value.h" 10#include "shader_recompiler/frontend/ir/value.h"
11 11
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
index d325d31c7..237a5af3f 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
@@ -4,8 +4,8 @@
4 4
5#include <utility> 5#include <utility>
6 6
7#include "shader_recompiler/backend/glasm/emit_context.h"
8#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 7#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
8#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
9#include "shader_recompiler/frontend/ir/modifiers.h" 9#include "shader_recompiler/frontend/ir/modifiers.h"
10#include "shader_recompiler/frontend/ir/value.h" 10#include "shader_recompiler/frontend/ir/value.h"
11 11
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp
index 8aa494a4d..f698b8b9b 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp
@@ -2,8 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/glasm/emit_context.h"
6#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 5#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
6#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
7#include "shader_recompiler/frontend/ir/value.h" 7#include "shader_recompiler/frontend/ir/value.h"
8 8
9namespace Shader::Backend::GLASM { 9namespace Shader::Backend::GLASM {
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_logical.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_logical.cpp
index e69de29bb..eed7bfec2 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_logical.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_logical.cpp
@@ -0,0 +1,26 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
6#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
7
8namespace Shader::Backend::GLASM {
9
10void EmitLogicalOr(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) {
11 ctx.Add("OR.S {},{},{};", inst, a, b);
12}
13
14void EmitLogicalAnd(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) {
15 ctx.Add("AND.S {},{},{};", inst, a, b);
16}
17
18void EmitLogicalXor(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) {
19 ctx.Add("XOR.S {},{},{};", inst, a, b);
20}
21
22void EmitLogicalNot(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) {
23 ctx.Add("SEQ.S {},{},0;", inst, value);
24}
25
26} // namespace Shader::Backend::GLASM
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp
index af9fac7c1..f135b67f5 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glasm/emit_context.h"
8#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 7#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
8#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
9#include "shader_recompiler/frontend/ir/program.h" 9#include "shader_recompiler/frontend/ir/program.h"
10#include "shader_recompiler/frontend/ir/value.h" 10#include "shader_recompiler/frontend/ir/value.h"
11#include "shader_recompiler/runtime_info.h" 11#include "shader_recompiler/runtime_info.h"
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
index 681aeda8d..86287ee3f 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glasm/emit_context.h"
8#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 7#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
8#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
9#include "shader_recompiler/frontend/ir/program.h" 9#include "shader_recompiler/frontend/ir/program.h"
10#include "shader_recompiler/frontend/ir/value.h" 10#include "shader_recompiler/frontend/ir/value.h"
11 11
@@ -17,110 +17,6 @@ namespace Shader::Backend::GLASM {
17 17
18#define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__) 18#define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__)
19 19
20static void DefinePhi(EmitContext& ctx, IR::Inst& phi) {
21 switch (phi.Type()) {
22 case IR::Type::U1:
23 case IR::Type::U32:
24 case IR::Type::F32:
25 ctx.reg_alloc.Define(phi);
26 break;
27 case IR::Type::U64:
28 case IR::Type::F64:
29 ctx.reg_alloc.LongDefine(phi);
30 break;
31 default:
32 throw NotImplementedException("Phi node type {}", phi.Type());
33 }
34}
35
36void EmitPhi(EmitContext& ctx, IR::Inst& phi) {
37 const size_t num_args{phi.NumArgs()};
38 for (size_t i = 0; i < num_args; ++i) {
39 ctx.reg_alloc.Consume(phi.Arg(i));
40 }
41 if (!phi.Definition<Id>().is_valid) {
42 // The phi node wasn't forward defined
43 DefinePhi(ctx, phi);
44 }
45}
46
47void EmitVoid(EmitContext&) {}
48
49void EmitReference(EmitContext& ctx, const IR::Value& value) {
50 ctx.reg_alloc.Consume(value);
51}
52
53void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& value) {
54 IR::Inst& phi{RegAlloc::AliasInst(*phi_value.Inst())};
55 if (!phi.Definition<Id>().is_valid) {
56 // The phi node wasn't forward defined
57 DefinePhi(ctx, phi);
58 }
59 const Register phi_reg{ctx.reg_alloc.Consume(IR::Value{&phi})};
60 const Value eval_value{ctx.reg_alloc.Consume(value)};
61
62 if (phi_reg == eval_value) {
63 return;
64 }
65 switch (phi.Flags<IR::Type>()) {
66 case IR::Type::U1:
67 case IR::Type::U32:
68 case IR::Type::F32:
69 ctx.Add("MOV.S {}.x,{};", phi_reg, ScalarS32{eval_value});
70 break;
71 case IR::Type::U64:
72 case IR::Type::F64:
73 ctx.Add("MOV.U64 {}.x,{};", phi_reg, ScalarRegister{eval_value});
74 break;
75 default:
76 throw NotImplementedException("Phi node type {}", phi.Type());
77 }
78}
79
80void EmitJoin(EmitContext& ctx) {
81 NotImplemented();
82}
83
84void EmitDemoteToHelperInvocation(EmitContext& ctx) {
85 ctx.Add("KIL TR.x;");
86}
87
88void EmitBarrier(EmitContext& ctx) {
89 ctx.Add("BAR;");
90}
91
92void EmitWorkgroupMemoryBarrier(EmitContext& ctx) {
93 ctx.Add("MEMBAR.CTA;");
94}
95
96void EmitDeviceMemoryBarrier(EmitContext& ctx) {
97 ctx.Add("MEMBAR;");
98}
99
100void EmitPrologue(EmitContext& ctx) {
101 // TODO
102}
103
104void EmitEpilogue(EmitContext& ctx) {
105 // TODO
106}
107
108void EmitEmitVertex(EmitContext& ctx, ScalarS32 stream) {
109 if (stream.type == Type::U32 && stream.imm_u32 == 0) {
110 ctx.Add("EMIT;");
111 } else {
112 ctx.Add("EMITS {};", stream);
113 }
114}
115
116void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) {
117 if (!stream.IsImmediate()) {
118 LOG_WARNING(Shader_GLASM, "Stream is not immediate");
119 }
120 ctx.reg_alloc.Consume(stream);
121 ctx.Add("ENDPRIM;");
122}
123
124void EmitGetRegister(EmitContext& ctx) { 20void EmitGetRegister(EmitContext& ctx) {
125 NotImplemented(); 21 NotImplemented();
126} 22}
@@ -185,55 +81,6 @@ void EmitSetOFlag(EmitContext& ctx) {
185 NotImplemented(); 81 NotImplemented();
186} 82}
187 83
188void EmitWorkgroupId(EmitContext& ctx, IR::Inst& inst) {
189 ctx.Add("MOV.S {},invocation.groupid;", inst);
190}
191
192void EmitLocalInvocationId(EmitContext& ctx, IR::Inst& inst) {
193 ctx.Add("MOV.S {},invocation.localid;", inst);
194}
195
196void EmitInvocationId(EmitContext& ctx, IR::Inst& inst) {
197 ctx.Add("MOV.S {}.x,primitive_invocation.x;", inst);
198}
199
200void EmitSampleId(EmitContext& ctx, IR::Inst& inst) {
201 ctx.Add("MOV.S {}.x,fragment.sampleid.x;", inst);
202}
203
204void EmitIsHelperInvocation(EmitContext& ctx, IR::Inst& inst) {
205 ctx.Add("MOV.S {}.x,fragment.helperthread.x;", inst);
206}
207
208void EmitYDirection(EmitContext& ctx, IR::Inst& inst) {
209 ctx.uses_y_direction = true;
210 ctx.Add("MOV.F {}.x,y_direction[0].w;", inst);
211}
212
213void EmitResolutionDownFactor(EmitContext& ctx, IR::Inst& inst) {
214 ctx.Add("MOV.F {}.x,scaling[0].z;", inst);
215}
216
217void EmitUndefU1(EmitContext& ctx, IR::Inst& inst) {
218 ctx.Add("MOV.S {}.x,0;", inst);
219}
220
221void EmitUndefU8(EmitContext& ctx, IR::Inst& inst) {
222 ctx.Add("MOV.S {}.x,0;", inst);
223}
224
225void EmitUndefU16(EmitContext& ctx, IR::Inst& inst) {
226 ctx.Add("MOV.S {}.x,0;", inst);
227}
228
229void EmitUndefU32(EmitContext& ctx, IR::Inst& inst) {
230 ctx.Add("MOV.S {}.x,0;", inst);
231}
232
233void EmitUndefU64(EmitContext& ctx, IR::Inst& inst) {
234 ctx.LongAdd("MOV.S64 {}.x,0;", inst);
235}
236
237void EmitGetZeroFromOp(EmitContext& ctx) { 84void EmitGetZeroFromOp(EmitContext& ctx) {
238 NotImplemented(); 85 NotImplemented();
239} 86}
@@ -258,20 +105,4 @@ void EmitGetInBoundsFromOp(EmitContext& ctx) {
258 NotImplemented(); 105 NotImplemented();
259} 106}
260 107
261void EmitLogicalOr(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) {
262 ctx.Add("OR.S {},{},{};", inst, a, b);
263}
264
265void EmitLogicalAnd(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) {
266 ctx.Add("AND.S {},{},{};", inst, a, b);
267}
268
269void EmitLogicalXor(EmitContext& ctx, IR::Inst& inst, ScalarS32 a, ScalarS32 b) {
270 ctx.Add("XOR.S {},{},{};", inst, a, b);
271}
272
273void EmitLogicalNot(EmitContext& ctx, IR::Inst& inst, ScalarS32 value) {
274 ctx.Add("SEQ.S {},{},0;", inst, value);
275}
276
277} // namespace Shader::Backend::GLASM 108} // namespace Shader::Backend::GLASM
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp
index 68fff613c..dc441c56d 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_select.cpp
@@ -3,8 +3,8 @@
3// Licensed under GPLv2 or any later version 3// Licensed under GPLv2 or any later version
4// Refer to the license.txt file included. 4// Refer to the license.txt file included.
5 5
6#include "shader_recompiler/backend/glasm/emit_context.h"
7#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 6#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
7#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
8#include "shader_recompiler/frontend/ir/value.h" 8#include "shader_recompiler/frontend/ir/value.h"
9 9
10namespace Shader::Backend::GLASM { 10namespace Shader::Backend::GLASM {
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp
index c1498f449..39e1c6c3a 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_shared_memory.cpp
@@ -3,8 +3,8 @@
3// Licensed under GPLv2 or any later version 3// Licensed under GPLv2 or any later version
4// Refer to the license.txt file included. 4// Refer to the license.txt file included.
5 5
6#include "shader_recompiler/backend/glasm/emit_context.h"
7#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 6#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
7#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
8#include "shader_recompiler/frontend/ir/value.h" 8#include "shader_recompiler/frontend/ir/value.h"
9 9
10namespace Shader::Backend::GLASM { 10namespace Shader::Backend::GLASM {
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_special.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_special.cpp
index e69de29bb..e7a5fb13a 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_special.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_special.cpp
@@ -0,0 +1,95 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
6#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
7#include "shader_recompiler/frontend/ir/value.h"
8
9namespace Shader::Backend::GLASM {
10
11static void DefinePhi(EmitContext& ctx, IR::Inst& phi) {
12 switch (phi.Type()) {
13 case IR::Type::U1:
14 case IR::Type::U32:
15 case IR::Type::F32:
16 ctx.reg_alloc.Define(phi);
17 break;
18 case IR::Type::U64:
19 case IR::Type::F64:
20 ctx.reg_alloc.LongDefine(phi);
21 break;
22 default:
23 throw NotImplementedException("Phi node type {}", phi.Type());
24 }
25}
26
27void EmitPhi(EmitContext& ctx, IR::Inst& phi) {
28 const size_t num_args{phi.NumArgs()};
29 for (size_t i = 0; i < num_args; ++i) {
30 ctx.reg_alloc.Consume(phi.Arg(i));
31 }
32 if (!phi.Definition<Id>().is_valid) {
33 // The phi node wasn't forward defined
34 DefinePhi(ctx, phi);
35 }
36}
37
38void EmitVoid(EmitContext&) {}
39
40void EmitReference(EmitContext& ctx, const IR::Value& value) {
41 ctx.reg_alloc.Consume(value);
42}
43
44void EmitPhiMove(EmitContext& ctx, const IR::Value& phi_value, const IR::Value& value) {
45 IR::Inst& phi{RegAlloc::AliasInst(*phi_value.Inst())};
46 if (!phi.Definition<Id>().is_valid) {
47 // The phi node wasn't forward defined
48 DefinePhi(ctx, phi);
49 }
50 const Register phi_reg{ctx.reg_alloc.Consume(IR::Value{&phi})};
51 const Value eval_value{ctx.reg_alloc.Consume(value)};
52
53 if (phi_reg == eval_value) {
54 return;
55 }
56 switch (phi.Flags<IR::Type>()) {
57 case IR::Type::U1:
58 case IR::Type::U32:
59 case IR::Type::F32:
60 ctx.Add("MOV.S {}.x,{};", phi_reg, ScalarS32{eval_value});
61 break;
62 case IR::Type::U64:
63 case IR::Type::F64:
64 ctx.Add("MOV.U64 {}.x,{};", phi_reg, ScalarRegister{eval_value});
65 break;
66 default:
67 throw NotImplementedException("Phi node type {}", phi.Type());
68 }
69}
70
71void EmitPrologue(EmitContext&) {
72 // TODO
73}
74
75void EmitEpilogue(EmitContext&) {
76 // TODO
77}
78
79void EmitEmitVertex(EmitContext& ctx, ScalarS32 stream) {
80 if (stream.type == Type::U32 && stream.imm_u32 == 0) {
81 ctx.Add("EMIT;");
82 } else {
83 ctx.Add("EMITS {};", stream);
84 }
85}
86
87void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) {
88 if (!stream.IsImmediate()) {
89 LOG_WARNING(Shader_GLASM, "Stream is not immediate");
90 }
91 ctx.reg_alloc.Consume(stream);
92 ctx.Add("ENDPRIM;");
93}
94
95} // namespace Shader::Backend::GLASM
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_undefined.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_undefined.cpp
index e69de29bb..875e9d991 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_undefined.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_undefined.cpp
@@ -0,0 +1,30 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
6#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
7
8namespace Shader::Backend::GLASM {
9
10void EmitUndefU1(EmitContext& ctx, IR::Inst& inst) {
11 ctx.Add("MOV.S {}.x,0;", inst);
12}
13
14void EmitUndefU8(EmitContext& ctx, IR::Inst& inst) {
15 ctx.Add("MOV.S {}.x,0;", inst);
16}
17
18void EmitUndefU16(EmitContext& ctx, IR::Inst& inst) {
19 ctx.Add("MOV.S {}.x,0;", inst);
20}
21
22void EmitUndefU32(EmitContext& ctx, IR::Inst& inst) {
23 ctx.Add("MOV.S {}.x,0;", inst);
24}
25
26void EmitUndefU64(EmitContext& ctx, IR::Inst& inst) {
27 ctx.LongAdd("MOV.S64 {}.x,0;", inst);
28}
29
30} // namespace Shader::Backend::GLASM
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp
index 544d475b4..32e0dd923 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp
@@ -2,8 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/glasm/emit_context.h"
6#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 5#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
6#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
7#include "shader_recompiler/frontend/ir/value.h" 7#include "shader_recompiler/frontend/ir/value.h"
8#include "shader_recompiler/profile.h" 8#include "shader_recompiler/profile.h"
9 9
diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/glasm_emit_context.cpp
index 8fd459dfe..0401953f7 100644
--- a/src/shader_recompiler/backend/glasm/emit_context.cpp
+++ b/src/shader_recompiler/backend/glasm/glasm_emit_context.cpp
@@ -5,8 +5,8 @@
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/bindings.h" 7#include "shader_recompiler/backend/bindings.h"
8#include "shader_recompiler/backend/glasm/emit_context.h"
9#include "shader_recompiler/backend/glasm/emit_glasm.h" 8#include "shader_recompiler/backend/glasm/emit_glasm.h"
9#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
10#include "shader_recompiler/frontend/ir/program.h" 10#include "shader_recompiler/frontend/ir/program.h"
11#include "shader_recompiler/profile.h" 11#include "shader_recompiler/profile.h"
12#include "shader_recompiler/runtime_info.h" 12#include "shader_recompiler/runtime_info.h"
diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/glasm_emit_context.h
index 8433e5c00..8433e5c00 100644
--- a/src/shader_recompiler/backend/glasm/emit_context.h
+++ b/src/shader_recompiler/backend/glasm/glasm_emit_context.h
diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp
index 4c046db6e..201e428c1 100644
--- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp
+++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp
@@ -6,7 +6,7 @@
6 6
7#include <fmt/format.h> 7#include <fmt/format.h>
8 8
9#include "shader_recompiler/backend/glasm/emit_context.h" 9#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
10#include "shader_recompiler/backend/glasm/reg_alloc.h" 10#include "shader_recompiler/backend/glasm/reg_alloc.h"
11#include "shader_recompiler/exception.h" 11#include "shader_recompiler/exception.h"
12#include "shader_recompiler/frontend/ir/value.h" 12#include "shader_recompiler/frontend/ir/value.h"
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl.cpp b/src/shader_recompiler/backend/glsl/emit_glsl.cpp
index 8a430d573..78b2eeaa2 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl.cpp
@@ -9,9 +9,9 @@
9 9
10#include "common/div_ceil.h" 10#include "common/div_ceil.h"
11#include "common/settings.h" 11#include "common/settings.h"
12#include "shader_recompiler/backend/glsl/emit_context.h"
13#include "shader_recompiler/backend/glsl/emit_glsl.h" 12#include "shader_recompiler/backend/glsl/emit_glsl.h"
14#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 13#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
14#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
15#include "shader_recompiler/frontend/ir/ir_emitter.h" 15#include "shader_recompiler/frontend/ir/ir_emitter.h"
16 16
17namespace Shader::Backend::GLSL { 17namespace Shader::Backend::GLSL {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
index 772acc5a4..dc377b053 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_atomic.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
10 10
11namespace Shader::Backend::GLSL { 11namespace Shader::Backend::GLSL {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_barriers.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_barriers.cpp
index e1d1b558e..8a9faa394 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_barriers.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_barriers.cpp
@@ -2,8 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/glsl/emit_context.h"
6#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 5#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
6#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
7#include "shader_recompiler/frontend/ir/value.h" 7#include "shader_recompiler/frontend/ir/value.h"
8 8
9namespace Shader::Backend::GLSL { 9namespace Shader::Backend::GLSL {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
index 3c1714e89..0f2668d9e 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
10 10
11namespace Shader::Backend::GLSL { 11namespace Shader::Backend::GLSL {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
index 49a66e3ec..98cc57e58 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_composite.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
10 10
11namespace Shader::Backend::GLSL { 11namespace Shader::Backend::GLSL {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
index 4c26f3829..1920047f4 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_context_get_set.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
10#include "shader_recompiler/profile.h" 10#include "shader_recompiler/profile.h"
11#include "shader_recompiler/runtime_info.h" 11#include "shader_recompiler/runtime_info.h"
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_control_flow.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_control_flow.cpp
index 53f8896be..c86465e8b 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_control_flow.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_control_flow.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/exception.h" 9#include "shader_recompiler/exception.h"
10 10
11namespace Shader::Backend::GLSL { 11namespace Shader::Backend::GLSL {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp
index eeae6562c..ce6ea1bb7 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_convert.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
10 10
11namespace Shader::Backend::GLSL { 11namespace Shader::Backend::GLSL {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
index d423bfb1b..b765a251b 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/modifiers.h" 9#include "shader_recompiler/frontend/ir/modifiers.h"
10#include "shader_recompiler/frontend/ir/value.h" 10#include "shader_recompiler/frontend/ir/value.h"
11 11
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
index 2f78d0267..fae2e397a 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/modifiers.h" 9#include "shader_recompiler/frontend/ir/modifiers.h"
10#include "shader_recompiler/frontend/ir/value.h" 10#include "shader_recompiler/frontend/ir/value.h"
11#include "shader_recompiler/profile.h" 11#include "shader_recompiler/profile.h"
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
index 88c1d4c5e..44060df33 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
10 10
11namespace Shader::Backend::GLSL { 11namespace Shader::Backend::GLSL {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_logical.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_logical.cpp
index 338ff4bd6..742fec9cf 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_logical.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_logical.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
10 10
11namespace Shader::Backend::GLSL { 11namespace Shader::Backend::GLSL {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp
index e3957491f..9fd41b4fd 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_memory.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
10#include "shader_recompiler/profile.h" 10#include "shader_recompiler/profile.h"
11 11
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
index f420fe388..4ebdfb3bc 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
10 10
11#ifdef _MSC_VER 11#ifdef _MSC_VER
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp
index 49fba9073..b1e486e5f 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_select.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
10 10
11namespace Shader::Backend::GLSL { 11namespace Shader::Backend::GLSL {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
index 518b78f06..74ae345e5 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_shared_memory.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
10 10
11namespace Shader::Backend::GLSL { 11namespace Shader::Backend::GLSL {
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp
index 67f9dad68..b8ddafe48 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_special.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/program.h" 9#include "shader_recompiler/frontend/ir/program.h"
10#include "shader_recompiler/frontend/ir/value.h" 10#include "shader_recompiler/frontend/ir/value.h"
11#include "shader_recompiler/profile.h" 11#include "shader_recompiler/profile.h"
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_undefined.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_undefined.cpp
index 15bf02dd6..cace1db85 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_undefined.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_undefined.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9 9
10namespace Shader::Backend::GLSL { 10namespace Shader::Backend::GLSL {
11 11
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp
index cd285e2c8..6e01979b4 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp
@@ -4,8 +4,8 @@
4 4
5#include <string_view> 5#include <string_view>
6 6
7#include "shader_recompiler/backend/glsl/emit_context.h"
8#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h" 7#include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
8#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
9#include "shader_recompiler/frontend/ir/value.h" 9#include "shader_recompiler/frontend/ir/value.h"
10#include "shader_recompiler/profile.h" 10#include "shader_recompiler/profile.h"
11 11
diff --git a/src/shader_recompiler/backend/glsl/emit_context.cpp b/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp
index 97bd59302..1de017e76 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp
@@ -3,7 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "shader_recompiler/backend/bindings.h" 5#include "shader_recompiler/backend/bindings.h"
6#include "shader_recompiler/backend/glsl/emit_context.h" 6#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
7#include "shader_recompiler/frontend/ir/program.h" 7#include "shader_recompiler/frontend/ir/program.h"
8#include "shader_recompiler/profile.h" 8#include "shader_recompiler/profile.h"
9#include "shader_recompiler/runtime_info.h" 9#include "shader_recompiler/runtime_info.h"
diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/glsl_emit_context.h
index d9b639d29..d9b639d29 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.h
+++ b/src/shader_recompiler/backend/glsl/glsl_emit_context.h
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
index d7a86e270..6ce7ed12a 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
@@ -11,6 +11,7 @@
11#include "common/settings.h" 11#include "common/settings.h"
12#include "shader_recompiler/backend/spirv/emit_spirv.h" 12#include "shader_recompiler/backend/spirv/emit_spirv.h"
13#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 13#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
14#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
14#include "shader_recompiler/frontend/ir/basic_block.h" 15#include "shader_recompiler/frontend/ir/basic_block.h"
15#include "shader_recompiler/frontend/ir/program.h" 16#include "shader_recompiler/frontend/ir/program.h"
16 17
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h
index 4b25534ce..b412957c7 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.h
@@ -6,13 +6,11 @@
6 6
7#include <vector> 7#include <vector>
8 8
9#include <sirit/sirit.h>
10
11#include "common/common_types.h" 9#include "common/common_types.h"
12#include "shader_recompiler/backend/bindings.h" 10#include "shader_recompiler/backend/bindings.h"
13#include "shader_recompiler/backend/spirv/emit_context.h"
14#include "shader_recompiler/frontend/ir/program.h" 11#include "shader_recompiler/frontend/ir/program.h"
15#include "shader_recompiler/profile.h" 12#include "shader_recompiler/profile.h"
13#include "shader_recompiler/runtime_info.h"
16 14
17namespace Shader::Backend::SPIRV { 15namespace Shader::Backend::SPIRV {
18 16
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp
index 9af8bb9e1..0d37b405c 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7 8
8namespace Shader::Backend::SPIRV { 9namespace Shader::Backend::SPIRV {
9namespace { 10namespace {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp
index e0b52a001..9ce95a41b 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_barriers.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7#include "shader_recompiler/frontend/ir/modifiers.h" 8#include "shader_recompiler/frontend/ir/modifiers.h"
8 9
9namespace Shader::Backend::SPIRV { 10namespace Shader::Backend::SPIRV {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp
index bb11f4f4e..02d1e63f7 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7 8
8namespace Shader::Backend::SPIRV { 9namespace Shader::Backend::SPIRV {
9 10
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp
index 10ff4ecab..5c3e1ee2b 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_composite.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7#include "shader_recompiler/frontend/ir/modifiers.h" 8#include "shader_recompiler/frontend/ir/modifiers.h"
8 9
9namespace Shader::Backend::SPIRV { 10namespace Shader::Backend::SPIRV {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
index bac683ae1..ad84966b5 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
@@ -7,6 +7,7 @@
7 7
8#include "shader_recompiler/backend/spirv/emit_spirv.h" 8#include "shader_recompiler/backend/spirv/emit_spirv.h"
9#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 9#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
10#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
10 11
11namespace Shader::Backend::SPIRV { 12namespace Shader::Backend::SPIRV {
12namespace { 13namespace {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp
index d33486f28..1eca3aa85 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7 8
8namespace Shader::Backend::SPIRV { 9namespace Shader::Backend::SPIRV {
9 10
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp
index fd42b7a16..832de2452 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7 8
8namespace Shader::Backend::SPIRV { 9namespace Shader::Backend::SPIRV {
9namespace { 10namespace {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp
index 61cf25f9c..0cdc46495 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7#include "shader_recompiler/frontend/ir/modifiers.h" 8#include "shader_recompiler/frontend/ir/modifiers.h"
8 9
9namespace Shader::Backend::SPIRV { 10namespace Shader::Backend::SPIRV {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
index 4d168a96d..d18d5f1d5 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -6,6 +6,7 @@
6 6
7#include "shader_recompiler/backend/spirv/emit_spirv.h" 7#include "shader_recompiler/backend/spirv/emit_spirv.h"
8#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 8#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
9#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
9#include "shader_recompiler/frontend/ir/modifiers.h" 10#include "shader_recompiler/frontend/ir/modifiers.h"
10 11
11namespace Shader::Backend::SPIRV { 12namespace Shader::Backend::SPIRV {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp
index d7f1a365a..a96190bc6 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7#include "shader_recompiler/frontend/ir/modifiers.h" 8#include "shader_recompiler/frontend/ir/modifiers.h"
8 9
9namespace Shader::Backend::SPIRV { 10namespace Shader::Backend::SPIRV {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
index 50277eec3..44521f539 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7 8
8namespace Shader::Backend::SPIRV { 9namespace Shader::Backend::SPIRV {
9namespace { 10namespace {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp
index b9a9500fc..47745f7ee 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7 8
8namespace Shader::Backend::SPIRV { 9namespace Shader::Backend::SPIRV {
9 10
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp
index 679ee2684..175f4be19 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_memory.cpp
@@ -6,6 +6,7 @@
6 6
7#include "shader_recompiler/backend/spirv/emit_spirv.h" 7#include "shader_recompiler/backend/spirv/emit_spirv.h"
8#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 8#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
9#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
9 10
10namespace Shader::Backend::SPIRV { 11namespace Shader::Backend::SPIRV {
11namespace { 12namespace {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp
index c5b4f4720..48caf1ffc 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_select.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7 8
8namespace Shader::Backend::SPIRV { 9namespace Shader::Backend::SPIRV {
9 10
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp
index 9a79fc7a2..330c9052c 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7 8
8namespace Shader::Backend::SPIRV { 9namespace Shader::Backend::SPIRV {
9namespace { 10namespace {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp
index 9e7eb3cb1..d96a17583 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7 8
8namespace Shader::Backend::SPIRV { 9namespace Shader::Backend::SPIRV {
9namespace { 10namespace {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_undefined.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_undefined.cpp
index c9f469e90..b5766fc52 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_undefined.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_undefined.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7 8
8namespace Shader::Backend::SPIRV { 9namespace Shader::Backend::SPIRV {
9 10
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp
index cef52c56e..7034228bf 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp
@@ -4,6 +4,7 @@
4 4
5#include "shader_recompiler/backend/spirv/emit_spirv.h" 5#include "shader_recompiler/backend/spirv/emit_spirv.h"
6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" 6#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
7#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
7 8
8namespace Shader::Backend::SPIRV { 9namespace Shader::Backend::SPIRV {
9namespace { 10namespace {
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
index 723455462..4b6f792bf 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
@@ -13,8 +13,8 @@
13 13
14#include "common/common_types.h" 14#include "common/common_types.h"
15#include "common/div_ceil.h" 15#include "common/div_ceil.h"
16#include "shader_recompiler/backend/spirv/emit_context.h"
17#include "shader_recompiler/backend/spirv/emit_spirv.h" 16#include "shader_recompiler/backend/spirv/emit_spirv.h"
17#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
18 18
19namespace Shader::Backend::SPIRV { 19namespace Shader::Backend::SPIRV {
20namespace { 20namespace {
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
index 63f8185d9..63f8185d9 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.h
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
diff --git a/src/shader_recompiler/environment.h b/src/shader_recompiler/environment.h
index 8369d0d84..b4df73e8a 100644
--- a/src/shader_recompiler/environment.h
+++ b/src/shader_recompiler/environment.h
@@ -1,3 +1,7 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
1#pragma once 5#pragma once
2 6
3#include <array> 7#include <array>
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index ab7c21a49..8788f5148 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -185,16 +185,6 @@ struct GPU::Impl {
185 return *dma_pusher; 185 return *dma_pusher;
186 } 186 }
187 187
188 /// Returns a reference to the GPU CDMA pusher.
189 [[nodiscard]] Tegra::CDmaPusher& CDmaPusher() {
190 return *cdma_pusher;
191 }
192
193 /// Returns a const reference to the GPU CDMA pusher.
194 [[nodiscard]] const Tegra::CDmaPusher& CDmaPusher() const {
195 return *cdma_pusher;
196 }
197
198 /// Returns a reference to the underlying renderer. 188 /// Returns a reference to the underlying renderer.
199 [[nodiscard]] VideoCore::RendererBase& Renderer() { 189 [[nodiscard]] VideoCore::RendererBase& Renderer() {
200 return *renderer; 190 return *renderer;
@@ -338,25 +328,27 @@ struct GPU::Impl {
338 } 328 }
339 329
340 /// Push GPU command buffer entries to be processed 330 /// Push GPU command buffer entries to be processed
341 void PushCommandBuffer(Tegra::ChCommandHeaderList& entries) { 331 void PushCommandBuffer(u32 id, Tegra::ChCommandHeaderList& entries) {
342 if (!use_nvdec) { 332 if (!use_nvdec) {
343 return; 333 return;
344 } 334 }
345 335
346 if (!cdma_pusher) { 336 if (!cdma_pushers.contains(id)) {
347 cdma_pusher = std::make_unique<Tegra::CDmaPusher>(gpu); 337 cdma_pushers.insert_or_assign(id, std::make_unique<Tegra::CDmaPusher>(gpu));
348 } 338 }
349 339
350 // SubmitCommandBuffer would make the nvdec operations async, this is not currently working 340 // SubmitCommandBuffer would make the nvdec operations async, this is not currently working
351 // TODO(ameerj): RE proper async nvdec operation 341 // TODO(ameerj): RE proper async nvdec operation
352 // gpu_thread.SubmitCommandBuffer(std::move(entries)); 342 // gpu_thread.SubmitCommandBuffer(std::move(entries));
353 343 cdma_pushers[id]->ProcessEntries(std::move(entries));
354 cdma_pusher->ProcessEntries(std::move(entries));
355 } 344 }
356 345
357 /// Frees the CDMAPusher instance to free up resources 346 /// Frees the CDMAPusher instance to free up resources
358 void ClearCdmaInstance() { 347 void ClearCdmaInstance(u32 id) {
359 cdma_pusher.reset(); 348 const auto iter = cdma_pushers.find(id);
349 if (iter != cdma_pushers.end()) {
350 cdma_pushers.erase(iter);
351 }
360 } 352 }
361 353
362 /// Swap buffers (render frame) 354 /// Swap buffers (render frame)
@@ -659,7 +651,7 @@ struct GPU::Impl {
659 Core::System& system; 651 Core::System& system;
660 std::unique_ptr<Tegra::MemoryManager> memory_manager; 652 std::unique_ptr<Tegra::MemoryManager> memory_manager;
661 std::unique_ptr<Tegra::DmaPusher> dma_pusher; 653 std::unique_ptr<Tegra::DmaPusher> dma_pusher;
662 std::unique_ptr<Tegra::CDmaPusher> cdma_pusher; 654 std::map<u32, std::unique_ptr<Tegra::CDmaPusher>> cdma_pushers;
663 std::unique_ptr<VideoCore::RendererBase> renderer; 655 std::unique_ptr<VideoCore::RendererBase> renderer;
664 VideoCore::RasterizerInterface* rasterizer = nullptr; 656 VideoCore::RasterizerInterface* rasterizer = nullptr;
665 const bool use_nvdec; 657 const bool use_nvdec;
@@ -811,14 +803,6 @@ const Tegra::DmaPusher& GPU::DmaPusher() const {
811 return impl->DmaPusher(); 803 return impl->DmaPusher();
812} 804}
813 805
814Tegra::CDmaPusher& GPU::CDmaPusher() {
815 return impl->CDmaPusher();
816}
817
818const Tegra::CDmaPusher& GPU::CDmaPusher() const {
819 return impl->CDmaPusher();
820}
821
822VideoCore::RendererBase& GPU::Renderer() { 806VideoCore::RendererBase& GPU::Renderer() {
823 return impl->Renderer(); 807 return impl->Renderer();
824} 808}
@@ -887,12 +871,12 @@ void GPU::PushGPUEntries(Tegra::CommandList&& entries) {
887 impl->PushGPUEntries(std::move(entries)); 871 impl->PushGPUEntries(std::move(entries));
888} 872}
889 873
890void GPU::PushCommandBuffer(Tegra::ChCommandHeaderList& entries) { 874void GPU::PushCommandBuffer(u32 id, Tegra::ChCommandHeaderList& entries) {
891 impl->PushCommandBuffer(entries); 875 impl->PushCommandBuffer(id, entries);
892} 876}
893 877
894void GPU::ClearCdmaInstance() { 878void GPU::ClearCdmaInstance(u32 id) {
895 impl->ClearCdmaInstance(); 879 impl->ClearCdmaInstance(id);
896} 880}
897 881
898void GPU::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { 882void GPU::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index c89a5d693..500411176 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -242,10 +242,10 @@ public:
242 void PushGPUEntries(Tegra::CommandList&& entries); 242 void PushGPUEntries(Tegra::CommandList&& entries);
243 243
244 /// Push GPU command buffer entries to be processed 244 /// Push GPU command buffer entries to be processed
245 void PushCommandBuffer(Tegra::ChCommandHeaderList& entries); 245 void PushCommandBuffer(u32 id, Tegra::ChCommandHeaderList& entries);
246 246
247 /// Frees the CDMAPusher instance to free up resources 247 /// Frees the CDMAPusher instance to free up resources
248 void ClearCdmaInstance(); 248 void ClearCdmaInstance(u32 id);
249 249
250 /// Swap buffers (render frame) 250 /// Swap buffers (render frame)
251 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer); 251 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer);
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
index 31adada56..e38cfbc6c 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
@@ -162,7 +162,7 @@ struct FormatTuple {
162 {VK_FORMAT_UNDEFINED}, // R16_SINT 162 {VK_FORMAT_UNDEFINED}, // R16_SINT
163 {VK_FORMAT_R16G16_UNORM, Attachable | Storage}, // R16G16_UNORM 163 {VK_FORMAT_R16G16_UNORM, Attachable | Storage}, // R16G16_UNORM
164 {VK_FORMAT_R16G16_SFLOAT, Attachable | Storage}, // R16G16_FLOAT 164 {VK_FORMAT_R16G16_SFLOAT, Attachable | Storage}, // R16G16_FLOAT
165 {VK_FORMAT_UNDEFINED}, // R16G16_UINT 165 {VK_FORMAT_R16G16_UINT, Attachable | Storage}, // R16G16_UINT
166 {VK_FORMAT_R16G16_SINT, Attachable | Storage}, // R16G16_SINT 166 {VK_FORMAT_R16G16_SINT, Attachable | Storage}, // R16G16_SINT
167 {VK_FORMAT_R16G16_SNORM, Attachable | Storage}, // R16G16_SNORM 167 {VK_FORMAT_R16G16_SNORM, Attachable | Storage}, // R16G16_SNORM
168 {VK_FORMAT_UNDEFINED}, // R32G32B32_FLOAT 168 {VK_FORMAT_UNDEFINED}, // R32G32B32_FLOAT
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 70c52aaac..7bf5b6578 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -130,6 +130,7 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(vk::Physica
130 VK_FORMAT_R16G16_UNORM, 130 VK_FORMAT_R16G16_UNORM,
131 VK_FORMAT_R16G16_SNORM, 131 VK_FORMAT_R16G16_SNORM,
132 VK_FORMAT_R16G16_SFLOAT, 132 VK_FORMAT_R16G16_SFLOAT,
133 VK_FORMAT_R16G16_UINT,
133 VK_FORMAT_R16G16_SINT, 134 VK_FORMAT_R16G16_SINT,
134 VK_FORMAT_R16_UNORM, 135 VK_FORMAT_R16_UNORM,
135 VK_FORMAT_R16_SNORM, 136 VK_FORMAT_R16_SNORM,
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 34099bc83..8a8be8e40 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -907,88 +907,79 @@ void ConfigureInputPlayer::UpdateUI() {
907} 907}
908 908
909void ConfigureInputPlayer::SetConnectableControllers() { 909void ConfigureInputPlayer::SetConnectableControllers() {
910 const auto add_controllers = [this](bool enable_all, 910 Core::HID::NpadStyleTag npad_style_set = hid_core.GetSupportedStyleTag();
911 Core::HID::NpadStyleTag npad_style_set = {}) { 911 index_controller_type_pairs.clear();
912 index_controller_type_pairs.clear(); 912 ui->comboControllerType->clear();
913 ui->comboControllerType->clear();
914
915 if (enable_all || npad_style_set.fullkey == 1) {
916 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
917 Core::HID::NpadStyleIndex::ProController);
918 ui->comboControllerType->addItem(tr("Pro Controller"));
919 }
920
921 if (enable_all || npad_style_set.joycon_dual == 1) {
922 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
923 Core::HID::NpadStyleIndex::JoyconDual);
924 ui->comboControllerType->addItem(tr("Dual Joycons"));
925 }
926 913
927 if (enable_all || npad_style_set.joycon_left == 1) { 914 if (npad_style_set.fullkey == 1) {
928 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 915 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
929 Core::HID::NpadStyleIndex::JoyconLeft); 916 Core::HID::NpadStyleIndex::ProController);
930 ui->comboControllerType->addItem(tr("Left Joycon")); 917 ui->comboControllerType->addItem(tr("Pro Controller"));
931 } 918 }
932 919
933 if (enable_all || npad_style_set.joycon_right == 1) { 920 if (npad_style_set.joycon_dual == 1) {
934 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 921 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
935 Core::HID::NpadStyleIndex::JoyconRight); 922 Core::HID::NpadStyleIndex::JoyconDual);
936 ui->comboControllerType->addItem(tr("Right Joycon")); 923 ui->comboControllerType->addItem(tr("Dual Joycons"));
937 } 924 }
938 925
939 if (player_index == 0 && (enable_all || npad_style_set.handheld == 1)) { 926 if (npad_style_set.joycon_left == 1) {
940 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 927 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
941 Core::HID::NpadStyleIndex::Handheld); 928 Core::HID::NpadStyleIndex::JoyconLeft);
942 ui->comboControllerType->addItem(tr("Handheld")); 929 ui->comboControllerType->addItem(tr("Left Joycon"));
943 } 930 }
944 931
945 if (enable_all || npad_style_set.gamecube == 1) { 932 if (npad_style_set.joycon_right == 1) {
946 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 933 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
947 Core::HID::NpadStyleIndex::GameCube); 934 Core::HID::NpadStyleIndex::JoyconRight);
948 ui->comboControllerType->addItem(tr("GameCube Controller")); 935 ui->comboControllerType->addItem(tr("Right Joycon"));
949 } 936 }
950 937
951 // Disable all unsupported controllers 938 if (player_index == 0 && npad_style_set.handheld == 1) {
952 if (!Settings::values.enable_all_controllers) { 939 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
953 return; 940 Core::HID::NpadStyleIndex::Handheld);
954 } 941 ui->comboControllerType->addItem(tr("Handheld"));
955 if (enable_all || npad_style_set.palma == 1) { 942 }
956 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
957 Core::HID::NpadStyleIndex::Pokeball);
958 ui->comboControllerType->addItem(tr("Poke Ball Plus"));
959 }
960 943
961 if (enable_all || npad_style_set.lark == 1) { 944 if (npad_style_set.gamecube == 1) {
962 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 945 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
963 Core::HID::NpadStyleIndex::NES); 946 Core::HID::NpadStyleIndex::GameCube);
964 ui->comboControllerType->addItem(tr("NES Controller")); 947 ui->comboControllerType->addItem(tr("GameCube Controller"));
965 } 948 }
966 949
967 if (enable_all || npad_style_set.lucia == 1) { 950 // Disable all unsupported controllers
968 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 951 if (!Settings::values.enable_all_controllers) {
969 Core::HID::NpadStyleIndex::SNES); 952 return;
970 ui->comboControllerType->addItem(tr("SNES Controller")); 953 }
971 } 954 if (npad_style_set.palma == 1) {
955 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
956 Core::HID::NpadStyleIndex::Pokeball);
957 ui->comboControllerType->addItem(tr("Poke Ball Plus"));
958 }
972 959
973 if (enable_all || npad_style_set.lagoon == 1) { 960 if (npad_style_set.lark == 1) {
974 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 961 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
975 Core::HID::NpadStyleIndex::N64); 962 Core::HID::NpadStyleIndex::NES);
976 ui->comboControllerType->addItem(tr("N64 Controller")); 963 ui->comboControllerType->addItem(tr("NES Controller"));
977 } 964 }
978 965
979 if (enable_all || npad_style_set.lager == 1) { 966 if (npad_style_set.lucia == 1) {
980 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 967 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
981 Core::HID::NpadStyleIndex::SegaGenesis); 968 Core::HID::NpadStyleIndex::SNES);
982 ui->comboControllerType->addItem(tr("Sega Genesis")); 969 ui->comboControllerType->addItem(tr("SNES Controller"));
983 } 970 }
984 };
985 971
986 if (!is_powered_on) { 972 if (npad_style_set.lagoon == 1) {
987 add_controllers(true); 973 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
988 return; 974 Core::HID::NpadStyleIndex::N64);
975 ui->comboControllerType->addItem(tr("N64 Controller"));
989 } 976 }
990 977
991 add_controllers(false, hid_core.GetSupportedStyleTag()); 978 if (npad_style_set.lager == 1) {
979 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
980 Core::HID::NpadStyleIndex::SegaGenesis);
981 ui->comboControllerType->addItem(tr("Sega Genesis"));
982 }
992} 983}
993 984
994Core::HID::NpadStyleIndex ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const { 985Core::HID::NpadStyleIndex ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const {
diff --git a/src/yuzu/debugger/profiler.cpp b/src/yuzu/debugger/profiler.cpp
index a8b254199..33110685a 100644
--- a/src/yuzu/debugger/profiler.cpp
+++ b/src/yuzu/debugger/profiler.cpp
@@ -163,7 +163,7 @@ void MicroProfileWidget::mouseReleaseEvent(QMouseEvent* ev) {
163} 163}
164 164
165void MicroProfileWidget::wheelEvent(QWheelEvent* ev) { 165void MicroProfileWidget::wheelEvent(QWheelEvent* ev) {
166 const auto wheel_position = ev->pos(); 166 const auto wheel_position = ev->position().toPoint();
167 MicroProfileMousePosition(wheel_position.x() / x_scale, wheel_position.y() / y_scale, 167 MicroProfileMousePosition(wheel_position.x() / x_scale, wheel_position.y() / y_scale,
168 ev->angleDelta().y() / 120); 168 ev->angleDelta().y() / 120);
169 ev->accept(); 169 ev->accept();
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index f266fd963..cc84ea11c 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1082,14 +1082,15 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
1082 state != Qt::ApplicationActive) { 1082 state != Qt::ApplicationActive) {
1083 LOG_DEBUG(Frontend, "ApplicationState unusual flag: {} ", state); 1083 LOG_DEBUG(Frontend, "ApplicationState unusual flag: {} ", state);
1084 } 1084 }
1085 if (ui->action_Pause->isEnabled() && 1085 if (emulation_running) {
1086 (state & (Qt::ApplicationHidden | Qt::ApplicationInactive))) { 1086 if (emu_thread->IsRunning() &&
1087 auto_paused = true; 1087 (state & (Qt::ApplicationHidden | Qt::ApplicationInactive))) {
1088 OnPauseGame(); 1088 auto_paused = true;
1089 } else if (emulation_running && !emu_thread->IsRunning() && auto_paused && 1089 OnPauseGame();
1090 state == Qt::ApplicationActive) { 1090 } else if (!emu_thread->IsRunning() && auto_paused && state == Qt::ApplicationActive) {
1091 auto_paused = false; 1091 auto_paused = false;
1092 OnStartGame(); 1092 OnStartGame();
1093 }
1093 } 1094 }
1094} 1095}
1095 1096
@@ -1516,6 +1517,9 @@ void GMainWindow::ShutdownGame() {
1516 input_subsystem->GetTas()->Stop(); 1517 input_subsystem->GetTas()->Stop();
1517 OnTasStateChanged(); 1518 OnTasStateChanged();
1518 1519
1520 // Enable all controllers
1521 system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All});
1522
1519 render_window->removeEventFilter(render_window); 1523 render_window->removeEventFilter(render_window);
1520 render_window->setAttribute(Qt::WA_Hover, false); 1524 render_window->setAttribute(Qt::WA_Hover, false);
1521 1525