summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--dist/icons/controller/controller.qrc21
-rw-r--r--dist/icons/controller/dual_joycon.pngbin36466 -> 0 bytes
-rw-r--r--dist/icons/controller/dual_joycon_dark.pngbin36261 -> 0 bytes
-rw-r--r--dist/icons/controller/dual_joycon_midnight.pngbin34667 -> 0 bytes
-rw-r--r--dist/icons/controller/handheld.pngbin14108 -> 0 bytes
-rw-r--r--dist/icons/controller/handheld_dark.pngbin13731 -> 0 bytes
-rw-r--r--dist/icons/controller/handheld_midnight.pngbin13366 -> 0 bytes
-rw-r--r--dist/icons/controller/pro_controller.pngbin36710 -> 0 bytes
-rw-r--r--dist/icons/controller/pro_controller_dark.pngbin34897 -> 0 bytes
-rw-r--r--dist/icons/controller/pro_controller_midnight.pngbin35893 -> 0 bytes
-rw-r--r--dist/icons/controller/single_joycon_left.pngbin25565 -> 0 bytes
-rw-r--r--dist/icons/controller/single_joycon_left_dark.pngbin25682 -> 0 bytes
-rw-r--r--dist/icons/controller/single_joycon_left_midnight.pngbin24405 -> 0 bytes
-rw-r--r--dist/icons/controller/single_joycon_left_vertical.pngbin24764 -> 0 bytes
-rw-r--r--dist/icons/controller/single_joycon_left_vertical_dark.pngbin24938 -> 0 bytes
-rw-r--r--dist/icons/controller/single_joycon_left_vertical_midnight.pngbin23681 -> 0 bytes
-rw-r--r--dist/icons/controller/single_joycon_right.pngbin28320 -> 0 bytes
-rw-r--r--dist/icons/controller/single_joycon_right_dark.pngbin28157 -> 0 bytes
-rw-r--r--dist/icons/controller/single_joycon_right_midnight.pngbin27006 -> 0 bytes
-rw-r--r--dist/icons/controller/single_joycon_right_vertical.pngbin27655 -> 0 bytes
-rw-r--r--dist/icons/controller/single_joycon_right_vertical_dark.pngbin27729 -> 0 bytes
-rw-r--r--dist/icons/controller/single_joycon_right_vertical_midnight.pngbin26354 -> 0 bytes
-rw-r--r--src/audio_core/stream.cpp9
-rw-r--r--src/common/ring_buffer.h21
-rw-r--r--src/common/scope_exit.h6
-rw-r--r--src/common/string_util.cpp14
-rw-r--r--src/core/CMakeLists.txt10
-rw-r--r--src/core/frontend/input.h11
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp4
-rw-r--r--src/core/hle/kernel/hle_ipc.h4
-rw-r--r--src/core/hle/kernel/k_address_arbiter.cpp90
-rw-r--r--src/core/hle/kernel/k_event.cpp32
-rw-r--r--src/core/hle/kernel/k_event.h57
-rw-r--r--src/core/hle/kernel/k_priority_queue.h18
-rw-r--r--src/core/hle/kernel/k_readable_event.cpp57
-rw-r--r--src/core/hle/kernel/k_readable_event.h51
-rw-r--r--src/core/hle/kernel/k_synchronization_object.cpp3
-rw-r--r--src/core/hle/kernel/k_synchronization_object.h1
-rw-r--r--src/core/hle/kernel/k_writable_event.cpp27
-rw-r--r--src/core/hle/kernel/k_writable_event.h44
-rw-r--r--src/core/hle/kernel/object.cpp6
-rw-r--r--src/core/hle/kernel/object.h7
-rw-r--r--src/core/hle/kernel/process.cpp19
-rw-r--r--src/core/hle/kernel/process.h2
-rw-r--r--src/core/hle/kernel/readable_event.cpp52
-rw-r--r--src/core/hle/kernel/readable_event.h59
-rw-r--r--src/core/hle/kernel/svc.cpp381
-rw-r--r--src/core/hle/kernel/svc_results.h1
-rw-r--r--src/core/hle/kernel/writable_event.cpp41
-rw-r--r--src/core/hle/kernel/writable_event.h60
-rw-r--r--src/core/hle/service/am/am.cpp80
-rw-r--r--src/core/hle/service/am/am.h23
-rw-r--r--src/core/hle/service/am/applets/applets.cpp40
-rw-r--r--src/core/hle/service/am/applets/applets.h18
-rw-r--r--src/core/hle/service/am/applets/controller.cpp2
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp20
-rw-r--r--src/core/hle/service/aoc/aoc_u.h4
-rw-r--r--src/core/hle/service/audio/audout_u.cpp15
-rw-r--r--src/core/hle/service/audio/audren_u.cpp43
-rw-r--r--src/core/hle/service/bcat/backend/backend.cpp16
-rw-r--r--src/core/hle/service/bcat/backend/backend.h10
-rw-r--r--src/core/hle/service/bcat/module.cpp8
-rw-r--r--src/core/hle/service/btdrv/btdrv.cpp11
-rw-r--r--src/core/hle/service/btm/btm.cpp34
-rw-r--r--src/core/hle/service/friend/friend.cpp14
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.cpp17
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.h21
-rw-r--r--src/core/hle/service/hid/controllers/mouse.cpp11
-rw-r--r--src/core/hle/service/hid/controllers/mouse.h26
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp227
-rw-r--r--src/core/hle/service/hid/controllers/npad.h199
-rw-r--r--src/core/hle/service/hid/controllers/xpad.h70
-rw-r--r--src/core/hle/service/hid/hid.cpp25
-rw-r--r--src/core/hle/service/hid/hid.h10
-rw-r--r--src/core/hle/service/lm/lm.cpp16
-rw-r--r--src/core/hle/service/nfp/nfp.cpp31
-rw-r--r--src/core/hle/service/nfp/nfp.h11
-rw-r--r--src/core/hle/service/nifm/nifm.cpp15
-rw-r--r--src/core/hle/service/nim/nim.cpp18
-rw-r--r--src/core/hle/service/ns/pl_u.cpp9
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp10
-rw-r--r--src/core/hle/service/nvdrv/interface.cpp4
-rw-r--r--src/core/hle/service/nvdrv/interface.h2
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp18
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h12
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp23
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h12
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp4
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h6
-rw-r--r--src/core/hle/service/olsc/olsc.cpp13
-rw-r--r--src/core/hle/service/ptm/psm.cpp20
-rw-r--r--src/core/hle/service/time/standard_user_system_clock_core.cpp8
-rw-r--r--src/core/hle/service/time/standard_user_system_clock_core.h7
-rw-r--r--src/core/hle/service/time/system_clock_context_update_callback.cpp4
-rw-r--r--src/core/hle/service/time/system_clock_context_update_callback.h6
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp14
-rw-r--r--src/core/hle/service/vi/display/vi_display.h9
-rw-r--r--src/core/hle/service/vi/vi.cpp4
-rwxr-xr-xsrc/input_common/analog_from_button.cpp4
-rw-r--r--src/input_common/gcadapter/gc_poller.cpp10
-rw-r--r--src/input_common/mouse/mouse_poller.cpp10
-rw-r--r--src/input_common/sdl/sdl_impl.cpp10
-rw-r--r--src/tests/common/ring_buffer.cpp10
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/morton.cpp0
-rw-r--r--src/video_core/morton.h0
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp2
-rw-r--r--src/yuzu/CMakeLists.txt4
-rw-r--r--src/yuzu/bootmanager.cpp31
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp103
-rw-r--r--src/yuzu/configuration/configure_input_player.h2
-rw-r--r--src/yuzu/configuration/configure_input_player.ui74
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.cpp2694
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.h192
-rw-r--r--src/yuzu/debugger/controller.cpp66
-rw-r--r--src/yuzu/debugger/controller.h31
-rw-r--r--src/yuzu/debugger/wait_tree.cpp6
-rw-r--r--src/yuzu/debugger/wait_tree.h4
-rw-r--r--src/yuzu/main.cpp7
-rw-r--r--src/yuzu/main.h2
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp26
122 files changed, 4588 insertions, 1032 deletions
diff --git a/README.md b/README.md
index fbf62eb7c..cb1a64d8c 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,7 @@ If you want to contribute to the user interface translation, please check out th
33 33
34 34
35### Support 35### Support
36We happily accept monetary donations or donated games and hardware. Please see our [donations page](https://yuzu-emu.org/donate/) for more information on how you can contribute to yuzu. Any donations received will go towards things like: 36We happily accept monetary donations, or donated games and hardware. Please see our [donations page](https://yuzu-emu.org/donate/) for more information on how you can contribute to yuzu. Any donations received will go towards things like:
37* Switch consoles to explore and reverse-engineer the hardware 37* Switch consoles to explore and reverse-engineer the hardware
38* Switch games for testing, reverse-engineering, and implementing new features 38* Switch games for testing, reverse-engineering, and implementing new features
39* Web hosting and infrastructure setup 39* Web hosting and infrastructure setup
diff --git a/dist/icons/controller/controller.qrc b/dist/icons/controller/controller.qrc
index 1c4e960c0..78eae461c 100644
--- a/dist/icons/controller/controller.qrc
+++ b/dist/icons/controller/controller.qrc
@@ -1,26 +1,5 @@
1<RCC> 1<RCC>
2 <qresource prefix="controller"> 2 <qresource prefix="controller">
3 <file alias="dual_joycon">dual_joycon.png</file>
4 <file alias="dual_joycon_dark">dual_joycon_dark.png</file>
5 <file alias="dual_joycon_midnight">dual_joycon_midnight.png</file>
6 <file alias="handheld">handheld.png</file>
7 <file alias="handheld_dark">handheld_dark.png</file>
8 <file alias="handheld_midnight">handheld_midnight.png</file>
9 <file alias="pro_controller">pro_controller.png</file>
10 <file alias="pro_controller_dark">pro_controller_dark.png</file>
11 <file alias="pro_controller_midnight">pro_controller_midnight.png</file>
12 <file alias="single_joycon_left">single_joycon_left.png</file>
13 <file alias="single_joycon_left_dark">single_joycon_left_dark.png</file>
14 <file alias="single_joycon_left_midnight">single_joycon_left_midnight.png</file>
15 <file alias="single_joycon_right">single_joycon_right.png</file>
16 <file alias="single_joycon_right_dark">single_joycon_right_dark.png</file>
17 <file alias="single_joycon_right_midnight">single_joycon_right_midnight.png</file>
18 <file alias="single_joycon_left_vertical">single_joycon_left_vertical.png</file>
19 <file alias="single_joycon_left_vertical_dark">single_joycon_left_vertical_dark.png</file>
20 <file alias="single_joycon_left_vertical_midnight">single_joycon_left_vertical_midnight.png</file>
21 <file alias="single_joycon_right_vertical">single_joycon_right_vertical.png</file>
22 <file alias="single_joycon_right_vertical_dark">single_joycon_right_vertical_dark.png</file>
23 <file alias="single_joycon_right_vertical_midnight">single_joycon_right_vertical_midnight.png</file>
24 <file alias="applet_dual_joycon">applet_dual_joycon.png</file> 3 <file alias="applet_dual_joycon">applet_dual_joycon.png</file>
25 <file alias="applet_dual_joycon_dark">applet_dual_joycon_dark.png</file> 4 <file alias="applet_dual_joycon_dark">applet_dual_joycon_dark.png</file>
26 <file alias="applet_dual_joycon_midnight">applet_dual_joycon_midnight.png</file> 5 <file alias="applet_dual_joycon_midnight">applet_dual_joycon_midnight.png</file>
diff --git a/dist/icons/controller/dual_joycon.png b/dist/icons/controller/dual_joycon.png
deleted file mode 100644
index 4230f5f7b..000000000
--- a/dist/icons/controller/dual_joycon.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/dual_joycon_dark.png b/dist/icons/controller/dual_joycon_dark.png
deleted file mode 100644
index 4445db489..000000000
--- a/dist/icons/controller/dual_joycon_dark.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/dual_joycon_midnight.png b/dist/icons/controller/dual_joycon_midnight.png
deleted file mode 100644
index aac8e5321..000000000
--- a/dist/icons/controller/dual_joycon_midnight.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/handheld.png b/dist/icons/controller/handheld.png
deleted file mode 100644
index d009b4a47..000000000
--- a/dist/icons/controller/handheld.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/handheld_dark.png b/dist/icons/controller/handheld_dark.png
deleted file mode 100644
index c80ca9259..000000000
--- a/dist/icons/controller/handheld_dark.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/handheld_midnight.png b/dist/icons/controller/handheld_midnight.png
deleted file mode 100644
index 19de4629b..000000000
--- a/dist/icons/controller/handheld_midnight.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/pro_controller.png b/dist/icons/controller/pro_controller.png
deleted file mode 100644
index 07d65e94a..000000000
--- a/dist/icons/controller/pro_controller.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/pro_controller_dark.png b/dist/icons/controller/pro_controller_dark.png
deleted file mode 100644
index 73efe18f4..000000000
--- a/dist/icons/controller/pro_controller_dark.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/pro_controller_midnight.png b/dist/icons/controller/pro_controller_midnight.png
deleted file mode 100644
index 8d7e63f0d..000000000
--- a/dist/icons/controller/pro_controller_midnight.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/single_joycon_left.png b/dist/icons/controller/single_joycon_left.png
deleted file mode 100644
index 547153034..000000000
--- a/dist/icons/controller/single_joycon_left.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/single_joycon_left_dark.png b/dist/icons/controller/single_joycon_left_dark.png
deleted file mode 100644
index b6ee073cb..000000000
--- a/dist/icons/controller/single_joycon_left_dark.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/single_joycon_left_midnight.png b/dist/icons/controller/single_joycon_left_midnight.png
deleted file mode 100644
index 34a485c81..000000000
--- a/dist/icons/controller/single_joycon_left_midnight.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/single_joycon_left_vertical.png b/dist/icons/controller/single_joycon_left_vertical.png
deleted file mode 100644
index 1e6282ad8..000000000
--- a/dist/icons/controller/single_joycon_left_vertical.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/single_joycon_left_vertical_dark.png b/dist/icons/controller/single_joycon_left_vertical_dark.png
deleted file mode 100644
index a615d995d..000000000
--- a/dist/icons/controller/single_joycon_left_vertical_dark.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/single_joycon_left_vertical_midnight.png b/dist/icons/controller/single_joycon_left_vertical_midnight.png
deleted file mode 100644
index 4cc578216..000000000
--- a/dist/icons/controller/single_joycon_left_vertical_midnight.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/single_joycon_right.png b/dist/icons/controller/single_joycon_right.png
deleted file mode 100644
index 8d29173f6..000000000
--- a/dist/icons/controller/single_joycon_right.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/single_joycon_right_dark.png b/dist/icons/controller/single_joycon_right_dark.png
deleted file mode 100644
index ead2c44e0..000000000
--- a/dist/icons/controller/single_joycon_right_dark.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/single_joycon_right_midnight.png b/dist/icons/controller/single_joycon_right_midnight.png
deleted file mode 100644
index 89afe022d..000000000
--- a/dist/icons/controller/single_joycon_right_midnight.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/single_joycon_right_vertical.png b/dist/icons/controller/single_joycon_right_vertical.png
deleted file mode 100644
index 4d7d06547..000000000
--- a/dist/icons/controller/single_joycon_right_vertical.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/single_joycon_right_vertical_dark.png b/dist/icons/controller/single_joycon_right_vertical_dark.png
deleted file mode 100644
index 9a6eb3013..000000000
--- a/dist/icons/controller/single_joycon_right_vertical_dark.png
+++ /dev/null
Binary files differ
diff --git a/dist/icons/controller/single_joycon_right_vertical_midnight.png b/dist/icons/controller/single_joycon_right_vertical_midnight.png
deleted file mode 100644
index 685249b68..000000000
--- a/dist/icons/controller/single_joycon_right_vertical_midnight.png
+++ /dev/null
Binary files differ
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp
index 5b0b285cd..b0f6f0c34 100644
--- a/src/audio_core/stream.cpp
+++ b/src/audio_core/stream.cpp
@@ -111,7 +111,14 @@ void Stream::PlayNextBuffer(std::chrono::nanoseconds ns_late) {
111 111
112 sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples()); 112 sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples());
113 113
114 core_timing.ScheduleEvent(GetBufferReleaseNS(*active_buffer) - ns_late, release_event, {}); 114 const auto buffer_release_ns = GetBufferReleaseNS(*active_buffer);
115
116 // If ns_late is higher than the update rate ignore the delay
117 if (ns_late > buffer_release_ns) {
118 ns_late = {};
119 }
120
121 core_timing.ScheduleEvent(buffer_release_ns - ns_late, release_event, {});
115} 122}
116 123
117void Stream::ReleaseActiveBuffer(std::chrono::nanoseconds ns_late) { 124void Stream::ReleaseActiveBuffer(std::chrono::nanoseconds ns_late) {
diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h
index 138fa0131..4a8d09806 100644
--- a/src/common/ring_buffer.h
+++ b/src/common/ring_buffer.h
@@ -19,15 +19,14 @@ namespace Common {
19/// SPSC ring buffer 19/// SPSC ring buffer
20/// @tparam T Element type 20/// @tparam T Element type
21/// @tparam capacity Number of slots in ring buffer 21/// @tparam capacity Number of slots in ring buffer
22/// @tparam granularity Slot size in terms of number of elements 22template <typename T, std::size_t capacity>
23template <typename T, std::size_t capacity, std::size_t granularity = 1>
24class RingBuffer { 23class RingBuffer {
25 /// A "slot" is made of `granularity` elements of `T`. 24 /// A "slot" is made of a single `T`.
26 static constexpr std::size_t slot_size = granularity * sizeof(T); 25 static constexpr std::size_t slot_size = sizeof(T);
27 // T must be safely memcpy-able and have a trivial default constructor. 26 // T must be safely memcpy-able and have a trivial default constructor.
28 static_assert(std::is_trivial_v<T>); 27 static_assert(std::is_trivial_v<T>);
29 // Ensure capacity is sensible. 28 // Ensure capacity is sensible.
30 static_assert(capacity < std::numeric_limits<std::size_t>::max() / 2 / granularity); 29 static_assert(capacity < std::numeric_limits<std::size_t>::max() / 2);
31 static_assert((capacity & (capacity - 1)) == 0, "capacity must be a power of two"); 30 static_assert((capacity & (capacity - 1)) == 0, "capacity must be a power of two");
32 // Ensure lock-free. 31 // Ensure lock-free.
33 static_assert(std::atomic_size_t::is_always_lock_free); 32 static_assert(std::atomic_size_t::is_always_lock_free);
@@ -47,7 +46,7 @@ public:
47 const std::size_t second_copy = push_count - first_copy; 46 const std::size_t second_copy = push_count - first_copy;
48 47
49 const char* in = static_cast<const char*>(new_slots); 48 const char* in = static_cast<const char*>(new_slots);
50 std::memcpy(m_data.data() + pos * granularity, in, first_copy * slot_size); 49 std::memcpy(m_data.data() + pos, in, first_copy * slot_size);
51 in += first_copy * slot_size; 50 in += first_copy * slot_size;
52 std::memcpy(m_data.data(), in, second_copy * slot_size); 51 std::memcpy(m_data.data(), in, second_copy * slot_size);
53 52
@@ -74,7 +73,7 @@ public:
74 const std::size_t second_copy = pop_count - first_copy; 73 const std::size_t second_copy = pop_count - first_copy;
75 74
76 char* out = static_cast<char*>(output); 75 char* out = static_cast<char*>(output);
77 std::memcpy(out, m_data.data() + pos * granularity, first_copy * slot_size); 76 std::memcpy(out, m_data.data() + pos, first_copy * slot_size);
78 out += first_copy * slot_size; 77 out += first_copy * slot_size;
79 std::memcpy(out, m_data.data(), second_copy * slot_size); 78 std::memcpy(out, m_data.data(), second_copy * slot_size);
80 79
@@ -84,9 +83,9 @@ public:
84 } 83 }
85 84
86 std::vector<T> Pop(std::size_t max_slots = ~std::size_t(0)) { 85 std::vector<T> Pop(std::size_t max_slots = ~std::size_t(0)) {
87 std::vector<T> out(std::min(max_slots, capacity) * granularity); 86 std::vector<T> out(std::min(max_slots, capacity));
88 const std::size_t count = Pop(out.data(), out.size() / granularity); 87 const std::size_t count = Pop(out.data(), out.size());
89 out.resize(count * granularity); 88 out.resize(count);
90 return out; 89 return out;
91 } 90 }
92 91
@@ -113,7 +112,7 @@ private:
113 alignas(128) std::atomic_size_t m_write_index{0}; 112 alignas(128) std::atomic_size_t m_write_index{0};
114#endif 113#endif
115 114
116 std::array<T, granularity * capacity> m_data; 115 std::array<T, capacity> m_data;
117}; 116};
118 117
119} // namespace Common 118} // namespace Common
diff --git a/src/common/scope_exit.h b/src/common/scope_exit.h
index fa46cb394..35dac3a8f 100644
--- a/src/common/scope_exit.h
+++ b/src/common/scope_exit.h
@@ -49,3 +49,9 @@ ScopeExitHelper<Func> ScopeExit(Func&& func) {
49 * \endcode 49 * \endcode
50 */ 50 */
51#define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body) 51#define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body)
52
53/**
54 * This macro is similar to SCOPE_EXIT, except the object is caller managed. This is intended to be
55 * used when the caller might want to cancel the ScopeExit.
56 */
57#define SCOPE_GUARD(body) detail::ScopeExit([&]() body)
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index 4cba2aaa4..7b614ad89 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -141,27 +141,13 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
141} 141}
142 142
143std::string UTF16ToUTF8(const std::u16string& input) { 143std::string UTF16ToUTF8(const std::u16string& input) {
144#ifdef _MSC_VER
145 // Workaround for missing char16_t/char32_t instantiations in MSVC2017
146 std::wstring_convert<std::codecvt_utf8_utf16<__int16>, __int16> convert;
147 std::basic_string<__int16> tmp_buffer(input.cbegin(), input.cend());
148 return convert.to_bytes(tmp_buffer);
149#else
150 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; 144 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
151 return convert.to_bytes(input); 145 return convert.to_bytes(input);
152#endif
153} 146}
154 147
155std::u16string UTF8ToUTF16(const std::string& input) { 148std::u16string UTF8ToUTF16(const std::string& input) {
156#ifdef _MSC_VER
157 // Workaround for missing char16_t/char32_t instantiations in MSVC2017
158 std::wstring_convert<std::codecvt_utf8_utf16<__int16>, __int16> convert;
159 auto tmp_buffer = convert.from_bytes(input);
160 return std::u16string(tmp_buffer.cbegin(), tmp_buffer.cend());
161#else
162 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; 149 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
163 return convert.from_bytes(input); 150 return convert.from_bytes(input);
164#endif
165} 151}
166 152
167#ifdef _WIN32 153#ifdef _WIN32
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 0ee02c81d..386d7bddf 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -160,10 +160,14 @@ add_library(core STATIC
160 hle/kernel/k_affinity_mask.h 160 hle/kernel/k_affinity_mask.h
161 hle/kernel/k_condition_variable.cpp 161 hle/kernel/k_condition_variable.cpp
162 hle/kernel/k_condition_variable.h 162 hle/kernel/k_condition_variable.h
163 hle/kernel/k_event.cpp
164 hle/kernel/k_event.h
163 hle/kernel/k_light_condition_variable.h 165 hle/kernel/k_light_condition_variable.h
164 hle/kernel/k_light_lock.cpp 166 hle/kernel/k_light_lock.cpp
165 hle/kernel/k_light_lock.h 167 hle/kernel/k_light_lock.h
166 hle/kernel/k_priority_queue.h 168 hle/kernel/k_priority_queue.h
169 hle/kernel/k_readable_event.cpp
170 hle/kernel/k_readable_event.h
167 hle/kernel/k_resource_limit.cpp 171 hle/kernel/k_resource_limit.cpp
168 hle/kernel/k_resource_limit.h 172 hle/kernel/k_resource_limit.h
169 hle/kernel/k_scheduler.cpp 173 hle/kernel/k_scheduler.cpp
@@ -176,6 +180,8 @@ add_library(core STATIC
176 hle/kernel/k_thread.cpp 180 hle/kernel/k_thread.cpp
177 hle/kernel/k_thread.h 181 hle/kernel/k_thread.h
178 hle/kernel/k_thread_queue.h 182 hle/kernel/k_thread_queue.h
183 hle/kernel/k_writable_event.cpp
184 hle/kernel/k_writable_event.h
179 hle/kernel/kernel.cpp 185 hle/kernel/kernel.cpp
180 hle/kernel/kernel.h 186 hle/kernel/kernel.h
181 hle/kernel/memory/address_space_info.cpp 187 hle/kernel/memory/address_space_info.cpp
@@ -204,8 +210,6 @@ add_library(core STATIC
204 hle/kernel/process.h 210 hle/kernel/process.h
205 hle/kernel/process_capability.cpp 211 hle/kernel/process_capability.cpp
206 hle/kernel/process_capability.h 212 hle/kernel/process_capability.h
207 hle/kernel/readable_event.cpp
208 hle/kernel/readable_event.h
209 hle/kernel/server_port.cpp 213 hle/kernel/server_port.cpp
210 hle/kernel/server_port.h 214 hle/kernel/server_port.h
211 hle/kernel/server_session.cpp 215 hle/kernel/server_session.cpp
@@ -226,8 +230,6 @@ add_library(core STATIC
226 hle/kernel/time_manager.h 230 hle/kernel/time_manager.h
227 hle/kernel/transfer_memory.cpp 231 hle/kernel/transfer_memory.cpp
228 hle/kernel/transfer_memory.h 232 hle/kernel/transfer_memory.h
229 hle/kernel/writable_event.cpp
230 hle/kernel/writable_event.h
231 hle/lock.cpp 233 hle/lock.cpp
232 hle/lock.h 234 hle/lock.h
233 hle/result.h 235 hle/result.h
diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h
index f014dfea3..88ebc6497 100644
--- a/src/core/frontend/input.h
+++ b/src/core/frontend/input.h
@@ -21,6 +21,11 @@ enum class AnalogDirection : u8 {
21 UP, 21 UP,
22 DOWN, 22 DOWN,
23}; 23};
24struct AnalogProperties {
25 float deadzone;
26 float range;
27 float threshold;
28};
24 29
25/// An abstract class template for an input device (a button, an analog input, etc.). 30/// An abstract class template for an input device (a button, an analog input, etc.).
26template <typename StatusType> 31template <typename StatusType>
@@ -30,6 +35,12 @@ public:
30 virtual StatusType GetStatus() const { 35 virtual StatusType GetStatus() const {
31 return {}; 36 return {};
32 } 37 }
38 virtual StatusType GetRawStatus() const {
39 return GetStatus();
40 }
41 virtual AnalogProperties GetAnalogProperties() const {
42 return {};
43 }
33 virtual bool GetAnalogDirectionStatus([[maybe_unused]] AnalogDirection direction) const { 44 virtual bool GetAnalogDirectionStatus([[maybe_unused]] AnalogDirection direction) const {
34 return {}; 45 return {};
35 } 46 }
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index c7b10ca7a..7ec62cf18 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -17,16 +17,16 @@
17#include "core/hle/kernel/errors.h" 17#include "core/hle/kernel/errors.h"
18#include "core/hle/kernel/handle_table.h" 18#include "core/hle/kernel/handle_table.h"
19#include "core/hle/kernel/hle_ipc.h" 19#include "core/hle/kernel/hle_ipc.h"
20#include "core/hle/kernel/k_readable_event.h"
20#include "core/hle/kernel/k_scheduler.h" 21#include "core/hle/kernel/k_scheduler.h"
21#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" 22#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
22#include "core/hle/kernel/k_thread.h" 23#include "core/hle/kernel/k_thread.h"
24#include "core/hle/kernel/k_writable_event.h"
23#include "core/hle/kernel/kernel.h" 25#include "core/hle/kernel/kernel.h"
24#include "core/hle/kernel/object.h" 26#include "core/hle/kernel/object.h"
25#include "core/hle/kernel/process.h" 27#include "core/hle/kernel/process.h"
26#include "core/hle/kernel/readable_event.h"
27#include "core/hle/kernel/server_session.h" 28#include "core/hle/kernel/server_session.h"
28#include "core/hle/kernel/time_manager.h" 29#include "core/hle/kernel/time_manager.h"
29#include "core/hle/kernel/writable_event.h"
30#include "core/memory.h" 30#include "core/memory.h"
31 31
32namespace Kernel { 32namespace Kernel {
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 9f764c79a..9a769781b 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -41,8 +41,8 @@ class KernelCore;
41class Process; 41class Process;
42class ServerSession; 42class ServerSession;
43class KThread; 43class KThread;
44class ReadableEvent; 44class KReadableEvent;
45class WritableEvent; 45class KWritableEvent;
46 46
47enum class ThreadWakeupReason; 47enum class ThreadWakeupReason;
48 48
diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp
index 1685d25bb..d0e90fd60 100644
--- a/src/core/hle/kernel/k_address_arbiter.cpp
+++ b/src/core/hle/kernel/k_address_arbiter.cpp
@@ -118,9 +118,13 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32
118 118
119 // Check the userspace value. 119 // Check the userspace value.
120 s32 user_value{}; 120 s32 user_value{};
121 R_UNLESS(UpdateIfEqual(system, std::addressof(user_value), addr, value, value + 1), 121 if (!UpdateIfEqual(system, &user_value, addr, value, value + 1)) {
122 Svc::ResultInvalidCurrentMemory); 122 LOG_ERROR(Kernel, "Invalid current memory!");
123 R_UNLESS(user_value == value, Svc::ResultInvalidState); 123 return Svc::ResultInvalidCurrentMemory;
124 }
125 if (user_value != value) {
126 return Svc::ResultInvalidState;
127 }
124 128
125 auto it = thread_tree.nfind_light({addr, -1}); 129 auto it = thread_tree.nfind_light({addr, -1});
126 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && 130 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) &&
@@ -143,61 +147,34 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
143 // Perform signaling. 147 // Perform signaling.
144 s32 num_waiters{}; 148 s32 num_waiters{};
145 { 149 {
146 KScopedSchedulerLock sl(kernel); 150 [[maybe_unused]] const KScopedSchedulerLock sl(kernel);
147 151
148 auto it = thread_tree.nfind_light({addr, -1}); 152 auto it = thread_tree.nfind_light({addr, -1});
149 // Determine the updated value. 153 // Determine the updated value.
150 s32 new_value{}; 154 s32 new_value{};
151 if (/*GetTargetFirmware() >= TargetFirmware_7_0_0*/ true) { 155 if (count <= 0) {
152 if (count <= 0) { 156 if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) {
153 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { 157 new_value = value - 2;
154 new_value = value - 2;
155 } else {
156 new_value = value + 1;
157 }
158 } else { 158 } else {
159 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { 159 new_value = value + 1;
160 auto tmp_it = it;
161 s32 tmp_num_waiters{};
162 while ((++tmp_it != thread_tree.end()) &&
163 (tmp_it->GetAddressArbiterKey() == addr)) {
164 if ((tmp_num_waiters++) >= count) {
165 break;
166 }
167 }
168
169 if (tmp_num_waiters < count) {
170 new_value = value - 1;
171 } else {
172 new_value = value;
173 }
174 } else {
175 new_value = value + 1;
176 }
177 } 160 }
178 } else { 161 } else {
179 if (count <= 0) { 162 if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) {
180 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
181 new_value = value - 1;
182 } else {
183 new_value = value + 1;
184 }
185 } else {
186 auto tmp_it = it; 163 auto tmp_it = it;
187 s32 tmp_num_waiters{}; 164 s32 tmp_num_waiters{};
188 while ((tmp_it != thread_tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && 165 while (++tmp_it != thread_tree.end() && tmp_it->GetAddressArbiterKey() == addr) {
189 (tmp_num_waiters < count + 1)) { 166 if (tmp_num_waiters++ >= count) {
190 ++tmp_num_waiters; 167 break;
191 ++tmp_it; 168 }
192 } 169 }
193 170
194 if (tmp_num_waiters == 0) { 171 if (tmp_num_waiters < count) {
195 new_value = value + 1;
196 } else if (tmp_num_waiters <= count) {
197 new_value = value - 1; 172 new_value = value - 1;
198 } else { 173 } else {
199 new_value = value; 174 new_value = value;
200 } 175 }
176 } else {
177 new_value = value + 1;
201 } 178 }
202 } 179 }
203 180
@@ -205,13 +182,18 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
205 s32 user_value{}; 182 s32 user_value{};
206 bool succeeded{}; 183 bool succeeded{};
207 if (value != new_value) { 184 if (value != new_value) {
208 succeeded = UpdateIfEqual(system, std::addressof(user_value), addr, value, new_value); 185 succeeded = UpdateIfEqual(system, &user_value, addr, value, new_value);
209 } else { 186 } else {
210 succeeded = ReadFromUser(system, std::addressof(user_value), addr); 187 succeeded = ReadFromUser(system, &user_value, addr);
211 } 188 }
212 189
213 R_UNLESS(succeeded, Svc::ResultInvalidCurrentMemory); 190 if (!succeeded) {
214 R_UNLESS(user_value == value, Svc::ResultInvalidState); 191 LOG_ERROR(Kernel, "Invalid current memory!");
192 return Svc::ResultInvalidCurrentMemory;
193 }
194 if (user_value != value) {
195 return Svc::ResultInvalidState;
196 }
215 197
216 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && 198 while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) &&
217 (it->GetAddressArbiterKey() == addr)) { 199 (it->GetAddressArbiterKey() == addr)) {
@@ -249,9 +231,9 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
249 s32 user_value{}; 231 s32 user_value{};
250 bool succeeded{}; 232 bool succeeded{};
251 if (decrement) { 233 if (decrement) {
252 succeeded = DecrementIfLessThan(system, std::addressof(user_value), addr, value); 234 succeeded = DecrementIfLessThan(system, &user_value, addr, value);
253 } else { 235 } else {
254 succeeded = ReadFromUser(system, std::addressof(user_value), addr); 236 succeeded = ReadFromUser(system, &user_value, addr);
255 } 237 }
256 238
257 if (!succeeded) { 239 if (!succeeded) {
@@ -272,7 +254,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
272 } 254 }
273 255
274 // Set the arbiter. 256 // Set the arbiter.
275 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); 257 cur_thread->SetAddressArbiter(&thread_tree, addr);
276 thread_tree.insert(*cur_thread); 258 thread_tree.insert(*cur_thread);
277 cur_thread->SetState(ThreadState::Waiting); 259 cur_thread->SetState(ThreadState::Waiting);
278 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); 260 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
@@ -293,7 +275,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
293 275
294 // Get the result. 276 // Get the result.
295 KSynchronizationObject* dummy{}; 277 KSynchronizationObject* dummy{};
296 return cur_thread->GetWaitResult(std::addressof(dummy)); 278 return cur_thread->GetWaitResult(&dummy);
297} 279}
298 280
299ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { 281ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
@@ -314,7 +296,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
314 296
315 // Read the value from userspace. 297 // Read the value from userspace.
316 s32 user_value{}; 298 s32 user_value{};
317 if (!ReadFromUser(system, std::addressof(user_value), addr)) { 299 if (!ReadFromUser(system, &user_value, addr)) {
318 slp.CancelSleep(); 300 slp.CancelSleep();
319 return Svc::ResultInvalidCurrentMemory; 301 return Svc::ResultInvalidCurrentMemory;
320 } 302 }
@@ -332,7 +314,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
332 } 314 }
333 315
334 // Set the arbiter. 316 // Set the arbiter.
335 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); 317 cur_thread->SetAddressArbiter(&thread_tree, addr);
336 thread_tree.insert(*cur_thread); 318 thread_tree.insert(*cur_thread);
337 cur_thread->SetState(ThreadState::Waiting); 319 cur_thread->SetState(ThreadState::Waiting);
338 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); 320 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
@@ -353,7 +335,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
353 335
354 // Get the result. 336 // Get the result.
355 KSynchronizationObject* dummy{}; 337 KSynchronizationObject* dummy{};
356 return cur_thread->GetWaitResult(std::addressof(dummy)); 338 return cur_thread->GetWaitResult(&dummy);
357} 339}
358 340
359} // namespace Kernel 341} // namespace Kernel
diff --git a/src/core/hle/kernel/k_event.cpp b/src/core/hle/kernel/k_event.cpp
new file mode 100644
index 000000000..bb2fa4ad5
--- /dev/null
+++ b/src/core/hle/kernel/k_event.cpp
@@ -0,0 +1,32 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/k_event.h"
6#include "core/hle/kernel/k_readable_event.h"
7#include "core/hle/kernel/k_writable_event.h"
8
9namespace Kernel {
10
11KEvent::KEvent(KernelCore& kernel, std::string&& name) : Object{kernel, std::move(name)} {}
12
13KEvent::~KEvent() = default;
14
15std::shared_ptr<KEvent> KEvent::Create(KernelCore& kernel, std::string&& name) {
16 return std::make_shared<KEvent>(kernel, std::move(name));
17}
18
19void KEvent::Initialize() {
20 // Create our sub events.
21 readable_event = std::make_shared<KReadableEvent>(kernel, GetName() + ":Readable");
22 writable_event = std::make_shared<KWritableEvent>(kernel, GetName() + ":Writable");
23
24 // Initialize our sub sessions.
25 readable_event->Initialize(this);
26 writable_event->Initialize(this);
27
28 // Mark initialized.
29 initialized = true;
30}
31
32} // namespace Kernel
diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h
new file mode 100644
index 000000000..2fb887129
--- /dev/null
+++ b/src/core/hle/kernel/k_event.h
@@ -0,0 +1,57 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/object.h"
8
9namespace Kernel {
10
11class KernelCore;
12class KReadableEvent;
13class KWritableEvent;
14
15class KEvent final : public Object {
16public:
17 explicit KEvent(KernelCore& kernel, std::string&& name);
18 ~KEvent() override;
19
20 static std::shared_ptr<KEvent> Create(KernelCore& kernel, std::string&& name);
21
22 void Initialize();
23
24 void Finalize() override {}
25
26 std::string GetTypeName() const override {
27 return "KEvent";
28 }
29
30 static constexpr HandleType HANDLE_TYPE = HandleType::Event;
31 HandleType GetHandleType() const override {
32 return HANDLE_TYPE;
33 }
34
35 std::shared_ptr<KReadableEvent>& GetReadableEvent() {
36 return readable_event;
37 }
38
39 std::shared_ptr<KWritableEvent>& GetWritableEvent() {
40 return writable_event;
41 }
42
43 const std::shared_ptr<KReadableEvent>& GetReadableEvent() const {
44 return readable_event;
45 }
46
47 const std::shared_ptr<KWritableEvent>& GetWritableEvent() const {
48 return writable_event;
49 }
50
51private:
52 std::shared_ptr<KReadableEvent> readable_event;
53 std::shared_ptr<KWritableEvent> writable_event;
54 bool initialized{};
55};
56
57} // namespace Kernel
diff --git a/src/core/hle/kernel/k_priority_queue.h b/src/core/hle/kernel/k_priority_queue.h
index 13d628b85..4aa669d95 100644
--- a/src/core/hle/kernel/k_priority_queue.h
+++ b/src/core/hle/kernel/k_priority_queue.h
@@ -24,11 +24,11 @@ template <typename T>
24concept KPriorityQueueAffinityMask = !std::is_reference_v<T> && requires(T & t) { 24concept KPriorityQueueAffinityMask = !std::is_reference_v<T> && requires(T & t) {
25 { t.GetAffinityMask() } 25 { t.GetAffinityMask() }
26 ->Common::ConvertibleTo<u64>; 26 ->Common::ConvertibleTo<u64>;
27 {t.SetAffinityMask(std::declval<u64>())}; 27 {t.SetAffinityMask(0)};
28 28
29 { t.GetAffinity(std::declval<int32_t>()) } 29 { t.GetAffinity(0) }
30 ->std::same_as<bool>; 30 ->std::same_as<bool>;
31 {t.SetAffinity(std::declval<int32_t>(), std::declval<bool>())}; 31 {t.SetAffinity(0, false)};
32 {t.SetAll()}; 32 {t.SetAll()};
33}; 33};
34 34
@@ -42,11 +42,11 @@ concept KPriorityQueueMember = !std::is_reference_v<T> && requires(T & t) {
42 ->std::same_as<T*>; 42 ->std::same_as<T*>;
43 { (typename T::QueueEntry()).GetPrev() } 43 { (typename T::QueueEntry()).GetPrev() }
44 ->std::same_as<T*>; 44 ->std::same_as<T*>;
45 { t.GetPriorityQueueEntry(std::declval<s32>()) } 45 { t.GetPriorityQueueEntry(0) }
46 ->std::same_as<typename T::QueueEntry&>; 46 ->std::same_as<typename T::QueueEntry&>;
47 47
48 {t.GetAffinityMask()}; 48 {t.GetAffinityMask()};
49 { typename std::remove_cvref<decltype(t.GetAffinityMask())>::type() } 49 { std::remove_cvref_t<decltype(t.GetAffinityMask())>() }
50 ->KPriorityQueueAffinityMask; 50 ->KPriorityQueueAffinityMask;
51 51
52 { t.GetActiveCore() } 52 { t.GetActiveCore() }
@@ -55,17 +55,17 @@ concept KPriorityQueueMember = !std::is_reference_v<T> && requires(T & t) {
55 ->Common::ConvertibleTo<s32>; 55 ->Common::ConvertibleTo<s32>;
56}; 56};
57 57
58template <typename Member, size_t _NumCores, int LowestPriority, int HighestPriority> 58template <typename Member, size_t NumCores_, int LowestPriority, int HighestPriority>
59requires KPriorityQueueMember<Member> class KPriorityQueue { 59requires KPriorityQueueMember<Member> class KPriorityQueue {
60public: 60public:
61 using AffinityMaskType = typename std::remove_cv_t< 61 using AffinityMaskType = std::remove_cv_t<
62 typename std::remove_reference<decltype(std::declval<Member>().GetAffinityMask())>::type>; 62 std::remove_reference_t<decltype(std::declval<Member>().GetAffinityMask())>>;
63 63
64 static_assert(LowestPriority >= 0); 64 static_assert(LowestPriority >= 0);
65 static_assert(HighestPriority >= 0); 65 static_assert(HighestPriority >= 0);
66 static_assert(LowestPriority >= HighestPriority); 66 static_assert(LowestPriority >= HighestPriority);
67 static constexpr size_t NumPriority = LowestPriority - HighestPriority + 1; 67 static constexpr size_t NumPriority = LowestPriority - HighestPriority + 1;
68 static constexpr size_t NumCores = _NumCores; 68 static constexpr size_t NumCores = NumCores_;
69 69
70 static constexpr bool IsValidCore(s32 core) { 70 static constexpr bool IsValidCore(s32 core) {
71 return 0 <= core && core < static_cast<s32>(NumCores); 71 return 0 <= core && core < static_cast<s32>(NumCores);
diff --git a/src/core/hle/kernel/k_readable_event.cpp b/src/core/hle/kernel/k_readable_event.cpp
new file mode 100644
index 000000000..d8a42dbaf
--- /dev/null
+++ b/src/core/hle/kernel/k_readable_event.cpp
@@ -0,0 +1,57 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include "common/assert.h"
7#include "common/common_funcs.h"
8#include "common/logging/log.h"
9#include "core/hle/kernel/errors.h"
10#include "core/hle/kernel/k_readable_event.h"
11#include "core/hle/kernel/k_scheduler.h"
12#include "core/hle/kernel/k_thread.h"
13#include "core/hle/kernel/kernel.h"
14#include "core/hle/kernel/object.h"
15#include "core/hle/kernel/svc_results.h"
16
17namespace Kernel {
18
19KReadableEvent::KReadableEvent(KernelCore& kernel, std::string&& name)
20 : KSynchronizationObject{kernel, std::move(name)} {}
21KReadableEvent::~KReadableEvent() = default;
22
23bool KReadableEvent::IsSignaled() const {
24 ASSERT(kernel.GlobalSchedulerContext().IsLocked());
25
26 return is_signaled;
27}
28
29ResultCode KReadableEvent::Signal() {
30 KScopedSchedulerLock lk{kernel};
31
32 if (!is_signaled) {
33 is_signaled = true;
34 NotifyAvailable();
35 }
36
37 return RESULT_SUCCESS;
38}
39
40ResultCode KReadableEvent::Clear() {
41 Reset();
42
43 return RESULT_SUCCESS;
44}
45
46ResultCode KReadableEvent::Reset() {
47 KScopedSchedulerLock lk{kernel};
48
49 if (!is_signaled) {
50 return Svc::ResultInvalidState;
51 }
52
53 is_signaled = false;
54 return RESULT_SUCCESS;
55}
56
57} // namespace Kernel
diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h
new file mode 100644
index 000000000..e6f0fd900
--- /dev/null
+++ b/src/core/hle/kernel/k_readable_event.h
@@ -0,0 +1,51 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/k_synchronization_object.h"
8#include "core/hle/kernel/object.h"
9#include "core/hle/result.h"
10
11namespace Kernel {
12
13class KernelCore;
14class KEvent;
15
16class KReadableEvent final : public KSynchronizationObject {
17public:
18 explicit KReadableEvent(KernelCore& kernel, std::string&& name);
19 ~KReadableEvent() override;
20
21 std::string GetTypeName() const override {
22 return "KReadableEvent";
23 }
24
25 static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
26 HandleType GetHandleType() const override {
27 return HANDLE_TYPE;
28 }
29
30 KEvent* GetParent() const {
31 return parent;
32 }
33
34 void Initialize(KEvent* parent_) {
35 is_signaled = false;
36 parent = parent_;
37 }
38
39 bool IsSignaled() const override;
40 void Finalize() override {}
41
42 ResultCode Signal();
43 ResultCode Clear();
44 ResultCode Reset();
45
46private:
47 bool is_signaled{};
48 KEvent* parent{};
49};
50
51} // namespace Kernel
diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp
index a3b34f82f..140cc46a7 100644
--- a/src/core/hle/kernel/k_synchronization_object.cpp
+++ b/src/core/hle/kernel/k_synchronization_object.cpp
@@ -132,6 +132,9 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,
132 132
133KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : Object{kernel} {} 133KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : Object{kernel} {}
134 134
135KSynchronizationObject::KSynchronizationObject(KernelCore& kernel, std::string&& name)
136 : Object{kernel, std::move(name)} {}
137
135KSynchronizationObject::~KSynchronizationObject() = default; 138KSynchronizationObject::~KSynchronizationObject() = default;
136 139
137void KSynchronizationObject::NotifyAvailable(ResultCode result) { 140void KSynchronizationObject::NotifyAvailable(ResultCode result) {
diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h
index f65c71c28..5803718fd 100644
--- a/src/core/hle/kernel/k_synchronization_object.h
+++ b/src/core/hle/kernel/k_synchronization_object.h
@@ -33,6 +33,7 @@ public:
33 33
34protected: 34protected:
35 explicit KSynchronizationObject(KernelCore& kernel); 35 explicit KSynchronizationObject(KernelCore& kernel);
36 explicit KSynchronizationObject(KernelCore& kernel, std::string&& name);
36 virtual ~KSynchronizationObject(); 37 virtual ~KSynchronizationObject();
37 38
38 void NotifyAvailable(ResultCode result); 39 void NotifyAvailable(ResultCode result);
diff --git a/src/core/hle/kernel/k_writable_event.cpp b/src/core/hle/kernel/k_writable_event.cpp
new file mode 100644
index 000000000..25c52edb2
--- /dev/null
+++ b/src/core/hle/kernel/k_writable_event.cpp
@@ -0,0 +1,27 @@
1// Copyright 2021 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/k_event.h"
6#include "core/hle/kernel/k_readable_event.h"
7#include "core/hle/kernel/k_writable_event.h"
8
9namespace Kernel {
10
11KWritableEvent::KWritableEvent(KernelCore& kernel, std::string&& name)
12 : Object{kernel, std::move(name)} {}
13KWritableEvent::~KWritableEvent() = default;
14
15void KWritableEvent::Initialize(KEvent* parent_) {
16 parent = parent_;
17}
18
19ResultCode KWritableEvent::Signal() {
20 return parent->GetReadableEvent()->Signal();
21}
22
23ResultCode KWritableEvent::Clear() {
24 return parent->GetReadableEvent()->Clear();
25}
26
27} // namespace Kernel
diff --git a/src/core/hle/kernel/k_writable_event.h b/src/core/hle/kernel/k_writable_event.h
new file mode 100644
index 000000000..518f5448d
--- /dev/null
+++ b/src/core/hle/kernel/k_writable_event.h
@@ -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#pragma once
6
7#include "core/hle/kernel/object.h"
8#include "core/hle/result.h"
9
10namespace Kernel {
11
12class KernelCore;
13class KEvent;
14
15class KWritableEvent final : public Object {
16public:
17 explicit KWritableEvent(KernelCore& kernel, std::string&& name);
18 ~KWritableEvent() override;
19
20 std::string GetTypeName() const override {
21 return "KWritableEvent";
22 }
23
24 static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent;
25 HandleType GetHandleType() const override {
26 return HANDLE_TYPE;
27 }
28
29 void Initialize(KEvent* parent_);
30
31 void Finalize() override {}
32
33 ResultCode Signal();
34 ResultCode Clear();
35
36 KEvent* GetParent() const {
37 return parent;
38 }
39
40private:
41 KEvent* parent{};
42};
43
44} // namespace Kernel
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp
index 2c571792b..d7f40c403 100644
--- a/src/core/hle/kernel/object.cpp
+++ b/src/core/hle/kernel/object.cpp
@@ -8,7 +8,10 @@
8 8
9namespace Kernel { 9namespace Kernel {
10 10
11Object::Object(KernelCore& kernel) : kernel{kernel}, object_id{kernel.CreateNewObjectID()} {} 11Object::Object(KernelCore& kernel_)
12 : kernel{kernel_}, object_id{kernel_.CreateNewObjectID()}, name{"[UNKNOWN KERNEL OBJECT]"} {}
13Object::Object(KernelCore& kernel_, std::string&& name_)
14 : kernel{kernel_}, object_id{kernel_.CreateNewObjectID()}, name{std::move(name_)} {}
12Object::~Object() = default; 15Object::~Object() = default;
13 16
14bool Object::IsWaitable() const { 17bool Object::IsWaitable() const {
@@ -21,6 +24,7 @@ bool Object::IsWaitable() const {
21 return true; 24 return true;
22 25
23 case HandleType::Unknown: 26 case HandleType::Unknown:
27 case HandleType::Event:
24 case HandleType::WritableEvent: 28 case HandleType::WritableEvent:
25 case HandleType::SharedMemory: 29 case HandleType::SharedMemory:
26 case HandleType::TransferMemory: 30 case HandleType::TransferMemory:
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index be7fcb5fb..501e58b33 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -18,6 +18,7 @@ using Handle = u32;
18 18
19enum class HandleType : u32 { 19enum class HandleType : u32 {
20 Unknown, 20 Unknown,
21 Event,
21 WritableEvent, 22 WritableEvent,
22 ReadableEvent, 23 ReadableEvent,
23 SharedMemory, 24 SharedMemory,
@@ -34,7 +35,8 @@ enum class HandleType : u32 {
34 35
35class Object : NonCopyable, public std::enable_shared_from_this<Object> { 36class Object : NonCopyable, public std::enable_shared_from_this<Object> {
36public: 37public:
37 explicit Object(KernelCore& kernel); 38 explicit Object(KernelCore& kernel_);
39 explicit Object(KernelCore& kernel_, std::string&& name_);
38 virtual ~Object(); 40 virtual ~Object();
39 41
40 /// Returns a unique identifier for the object. For debugging purposes only. 42 /// Returns a unique identifier for the object. For debugging purposes only.
@@ -46,7 +48,7 @@ public:
46 return "[BAD KERNEL OBJECT TYPE]"; 48 return "[BAD KERNEL OBJECT TYPE]";
47 } 49 }
48 virtual std::string GetName() const { 50 virtual std::string GetName() const {
49 return "[UNKNOWN KERNEL OBJECT]"; 51 return name;
50 } 52 }
51 virtual HandleType GetHandleType() const = 0; 53 virtual HandleType GetHandleType() const = 0;
52 54
@@ -69,6 +71,7 @@ protected:
69 71
70private: 72private:
71 std::atomic<u32> object_id{0}; 73 std::atomic<u32> object_id{0};
74 std::string name;
72}; 75};
73 76
74template <typename T> 77template <typename T>
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index afdb27c54..2286b292d 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -23,6 +23,7 @@
23#include "core/hle/kernel/memory/page_table.h" 23#include "core/hle/kernel/memory/page_table.h"
24#include "core/hle/kernel/memory/slab_heap.h" 24#include "core/hle/kernel/memory/slab_heap.h"
25#include "core/hle/kernel/process.h" 25#include "core/hle/kernel/process.h"
26#include "core/hle/kernel/svc_results.h"
26#include "core/hle/lock.h" 27#include "core/hle/lock.h"
27#include "core/memory.h" 28#include "core/memory.h"
28#include "core/settings.h" 29#include "core/settings.h"
@@ -241,18 +242,16 @@ void Process::UnregisterThread(const KThread* thread) {
241 thread_list.remove(thread); 242 thread_list.remove(thread);
242} 243}
243 244
244ResultCode Process::ClearSignalState() { 245ResultCode Process::Reset() {
245 KScopedSchedulerLock lock(system.Kernel()); 246 // Lock the process and the scheduler.
246 if (status == ProcessStatus::Exited) { 247 KScopedLightLock lk(state_lock);
247 LOG_ERROR(Kernel, "called on a terminated process instance."); 248 KScopedSchedulerLock sl{kernel};
248 return ERR_INVALID_STATE;
249 }
250 249
251 if (!is_signaled) { 250 // Validate that we're in a state that we can reset.
252 LOG_ERROR(Kernel, "called on a process instance that isn't signaled."); 251 R_UNLESS(status != ProcessStatus::Exited, Svc::ResultInvalidState);
253 return ERR_INVALID_STATE; 252 R_UNLESS(is_signaled, Svc::ResultInvalidState);
254 }
255 253
254 // Clear signaled.
256 is_signaled = false; 255 is_signaled = false;
257 return RESULT_SUCCESS; 256 return RESULT_SUCCESS;
258} 257}
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index c8af76ce8..320b0f347 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -312,7 +312,7 @@ public:
312 /// @pre The process must be in a signaled state. If this is called on a 312 /// @pre The process must be in a signaled state. If this is called on a
313 /// process instance that is not signaled, ERR_INVALID_STATE will be 313 /// process instance that is not signaled, ERR_INVALID_STATE will be
314 /// returned. 314 /// returned.
315 ResultCode ClearSignalState(); 315 ResultCode Reset();
316 316
317 /** 317 /**
318 * Loads process-specifics configuration info with metadata provided 318 * Loads process-specifics configuration info with metadata provided
diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp
deleted file mode 100644
index 596d01479..000000000
--- a/src/core/hle/kernel/readable_event.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include "common/assert.h"
7#include "common/logging/log.h"
8#include "core/hle/kernel/errors.h"
9#include "core/hle/kernel/k_scheduler.h"
10#include "core/hle/kernel/k_thread.h"
11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/object.h"
13#include "core/hle/kernel/readable_event.h"
14
15namespace Kernel {
16
17ReadableEvent::ReadableEvent(KernelCore& kernel) : KSynchronizationObject{kernel} {}
18ReadableEvent::~ReadableEvent() = default;
19
20void ReadableEvent::Signal() {
21 if (is_signaled) {
22 return;
23 }
24
25 is_signaled = true;
26 NotifyAvailable();
27}
28
29bool ReadableEvent::IsSignaled() const {
30 ASSERT(kernel.GlobalSchedulerContext().IsLocked());
31
32 return is_signaled;
33}
34
35void ReadableEvent::Clear() {
36 is_signaled = false;
37}
38
39ResultCode ReadableEvent::Reset() {
40 KScopedSchedulerLock lock(kernel);
41 if (!is_signaled) {
42 LOG_TRACE(Kernel, "Handle is not signaled! object_id={}, object_type={}, object_name={}",
43 GetObjectId(), GetTypeName(), GetName());
44 return ERR_INVALID_STATE;
45 }
46
47 Clear();
48
49 return RESULT_SUCCESS;
50}
51
52} // namespace Kernel
diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h
deleted file mode 100644
index 2195710c2..000000000
--- a/src/core/hle/kernel/readable_event.h
+++ /dev/null
@@ -1,59 +0,0 @@
1// Copyright 2014 Citra 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/kernel/k_synchronization_object.h"
8#include "core/hle/kernel/object.h"
9
10union ResultCode;
11
12namespace Kernel {
13
14class KernelCore;
15class WritableEvent;
16
17class ReadableEvent final : public KSynchronizationObject {
18 friend class WritableEvent;
19
20public:
21 ~ReadableEvent() override;
22
23 std::string GetTypeName() const override {
24 return "ReadableEvent";
25 }
26 std::string GetName() const override {
27 return name;
28 }
29
30 static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
31 HandleType GetHandleType() const override {
32 return HANDLE_TYPE;
33 }
34
35 /// Unconditionally clears the readable event's state.
36 void Clear();
37
38 /// Clears the readable event's state if and only if it
39 /// has already been signaled.
40 ///
41 /// @pre The event must be in a signaled state. If this event
42 /// is in an unsignaled state and this function is called,
43 /// then ERR_INVALID_STATE will be returned.
44 ResultCode Reset();
45
46 void Signal();
47
48 bool IsSignaled() const override;
49
50 void Finalize() override {}
51
52private:
53 explicit ReadableEvent(KernelCore& kernel);
54
55 bool is_signaled{};
56 std::string name; ///< Name of event (optional)
57};
58
59} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 74eb90100..26650a513 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -14,6 +14,7 @@
14#include "common/fiber.h" 14#include "common/fiber.h"
15#include "common/logging/log.h" 15#include "common/logging/log.h"
16#include "common/microprofile.h" 16#include "common/microprofile.h"
17#include "common/scope_exit.h"
17#include "common/string_util.h" 18#include "common/string_util.h"
18#include "core/arm/exclusive_monitor.h" 19#include "core/arm/exclusive_monitor.h"
19#include "core/core.h" 20#include "core/core.h"
@@ -26,18 +27,20 @@
26#include "core/hle/kernel/handle_table.h" 27#include "core/hle/kernel/handle_table.h"
27#include "core/hle/kernel/k_address_arbiter.h" 28#include "core/hle/kernel/k_address_arbiter.h"
28#include "core/hle/kernel/k_condition_variable.h" 29#include "core/hle/kernel/k_condition_variable.h"
30#include "core/hle/kernel/k_event.h"
31#include "core/hle/kernel/k_readable_event.h"
29#include "core/hle/kernel/k_resource_limit.h" 32#include "core/hle/kernel/k_resource_limit.h"
30#include "core/hle/kernel/k_scheduler.h" 33#include "core/hle/kernel/k_scheduler.h"
31#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" 34#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
32#include "core/hle/kernel/k_synchronization_object.h" 35#include "core/hle/kernel/k_synchronization_object.h"
33#include "core/hle/kernel/k_thread.h" 36#include "core/hle/kernel/k_thread.h"
37#include "core/hle/kernel/k_writable_event.h"
34#include "core/hle/kernel/kernel.h" 38#include "core/hle/kernel/kernel.h"
35#include "core/hle/kernel/memory/memory_block.h" 39#include "core/hle/kernel/memory/memory_block.h"
36#include "core/hle/kernel/memory/memory_layout.h" 40#include "core/hle/kernel/memory/memory_layout.h"
37#include "core/hle/kernel/memory/page_table.h" 41#include "core/hle/kernel/memory/page_table.h"
38#include "core/hle/kernel/physical_core.h" 42#include "core/hle/kernel/physical_core.h"
39#include "core/hle/kernel/process.h" 43#include "core/hle/kernel/process.h"
40#include "core/hle/kernel/readable_event.h"
41#include "core/hle/kernel/shared_memory.h" 44#include "core/hle/kernel/shared_memory.h"
42#include "core/hle/kernel/svc.h" 45#include "core/hle/kernel/svc.h"
43#include "core/hle/kernel/svc_results.h" 46#include "core/hle/kernel/svc_results.h"
@@ -45,7 +48,6 @@
45#include "core/hle/kernel/svc_wrap.h" 48#include "core/hle/kernel/svc_wrap.h"
46#include "core/hle/kernel/time_manager.h" 49#include "core/hle/kernel/time_manager.h"
47#include "core/hle/kernel/transfer_memory.h" 50#include "core/hle/kernel/transfer_memory.h"
48#include "core/hle/kernel/writable_event.h"
49#include "core/hle/lock.h" 51#include "core/hle/lock.h"
50#include "core/hle/result.h" 52#include "core/hle/result.h"
51#include "core/hle/service/service.h" 53#include "core/hle/service/service.h"
@@ -366,7 +368,10 @@ static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle t
366 // Get the thread from its handle. 368 // Get the thread from its handle.
367 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 369 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
368 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 370 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
369 R_UNLESS(thread, Svc::ResultInvalidHandle); 371 if (!thread) {
372 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
373 return ResultInvalidHandle;
374 }
370 375
371 // Get the thread's id. 376 // Get the thread's id.
372 *out_thread_id = thread->GetThreadID(); 377 *out_thread_id = thread->GetThreadID();
@@ -476,7 +481,10 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand
476 // Get the thread from its handle. 481 // Get the thread from its handle.
477 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 482 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
478 std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 483 std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
479 R_UNLESS(thread, Svc::ResultInvalidHandle); 484 if (!thread) {
485 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
486 return ResultInvalidHandle;
487 }
480 488
481 // Cancel the thread's wait. 489 // Cancel the thread's wait.
482 thread->WaitCancel(); 490 thread->WaitCancel();
@@ -494,8 +502,15 @@ static ResultCode ArbitrateLock(Core::System& system, Handle thread_handle, VAdd
494 thread_handle, address, tag); 502 thread_handle, address, tag);
495 503
496 // Validate the input address. 504 // Validate the input address.
497 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); 505 if (Memory::IsKernelAddress(address)) {
498 R_UNLESS(Common::IsAligned(address, sizeof(u32)), Svc::ResultInvalidAddress); 506 LOG_ERROR(Kernel_SVC, "Attempting to arbitrate a lock on a kernel address (address={:08X})",
507 address);
508 return ResultInvalidCurrentMemory;
509 }
510 if (!Common::IsAligned(address, sizeof(u32))) {
511 LOG_ERROR(Kernel_SVC, "Input address must be 4 byte aligned (address: {:08X})", address);
512 return ResultInvalidAddress;
513 }
499 514
500 return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag); 515 return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag);
501} 516}
@@ -510,8 +525,16 @@ static ResultCode ArbitrateUnlock(Core::System& system, VAddr address) {
510 LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address); 525 LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address);
511 526
512 // Validate the input address. 527 // Validate the input address.
513 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); 528 if (Memory::IsKernelAddress(address)) {
514 R_UNLESS(Common::IsAligned(address, sizeof(u32)), Svc::ResultInvalidAddress); 529 LOG_ERROR(Kernel_SVC,
530 "Attempting to arbitrate an unlock on a kernel address (address={:08X})",
531 address);
532 return ResultInvalidCurrentMemory;
533 }
534 if (!Common::IsAligned(address, sizeof(u32))) {
535 LOG_ERROR(Kernel_SVC, "Input address must be 4 byte aligned (address: {:08X})", address);
536 return ResultInvalidAddress;
537 }
515 538
516 return system.Kernel().CurrentProcess()->SignalToAddress(address); 539 return system.Kernel().CurrentProcess()->SignalToAddress(address);
517} 540}
@@ -1023,37 +1046,47 @@ static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size
1023 return UnmapPhysicalMemory(system, addr, size); 1046 return UnmapPhysicalMemory(system, addr, size);
1024} 1047}
1025 1048
1026constexpr bool IsValidThreadActivity(Svc::ThreadActivity thread_activity) {
1027 switch (thread_activity) {
1028 case Svc::ThreadActivity::Runnable:
1029 case Svc::ThreadActivity::Paused:
1030 return true;
1031 default:
1032 return false;
1033 }
1034}
1035
1036/// Sets the thread activity 1049/// Sets the thread activity
1037static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle, 1050static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle,
1038 Svc::ThreadActivity thread_activity) { 1051 ThreadActivity thread_activity) {
1039 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle, 1052 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle,
1040 thread_activity); 1053 thread_activity);
1041 1054
1042 // Validate the activity. 1055 // Validate the activity.
1043 R_UNLESS(IsValidThreadActivity(thread_activity), Svc::ResultInvalidEnumValue); 1056 constexpr auto IsValidThreadActivity = [](ThreadActivity activity) {
1057 return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused;
1058 };
1059 if (!IsValidThreadActivity(thread_activity)) {
1060 LOG_ERROR(Kernel_SVC, "Invalid thread activity value provided (activity={})",
1061 thread_activity);
1062 return ResultInvalidEnumValue;
1063 }
1044 1064
1045 // Get the thread from its handle. 1065 // Get the thread from its handle.
1046 auto& kernel = system.Kernel(); 1066 auto& kernel = system.Kernel();
1047 const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); 1067 const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
1048 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 1068 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1049 R_UNLESS(thread, Svc::ResultInvalidHandle); 1069 if (!thread) {
1070 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
1071 return ResultInvalidHandle;
1072 }
1050 1073
1051 // Check that the activity is being set on a non-current thread for the current process. 1074 // Check that the activity is being set on a non-current thread for the current process.
1052 R_UNLESS(thread->GetOwnerProcess() == kernel.CurrentProcess(), Svc::ResultInvalidHandle); 1075 if (thread->GetOwnerProcess() != kernel.CurrentProcess()) {
1053 R_UNLESS(thread.get() != GetCurrentThreadPointer(kernel), Svc::ResultBusy); 1076 LOG_ERROR(Kernel_SVC, "Invalid owning process for the created thread.");
1077 return ResultInvalidHandle;
1078 }
1079 if (thread.get() == GetCurrentThreadPointer(kernel)) {
1080 LOG_ERROR(Kernel_SVC, "Thread is busy");
1081 return ResultBusy;
1082 }
1054 1083
1055 // Set the activity. 1084 // Set the activity.
1056 R_TRY(thread->SetActivity(thread_activity)); 1085 const auto set_result = thread->SetActivity(thread_activity);
1086 if (set_result.IsError()) {
1087 LOG_ERROR(Kernel_SVC, "Failed to set thread activity.");
1088 return set_result;
1089 }
1057 1090
1058 return RESULT_SUCCESS; 1091 return RESULT_SUCCESS;
1059} 1092}
@@ -1072,16 +1105,29 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand
1072 const auto* current_process = system.Kernel().CurrentProcess(); 1105 const auto* current_process = system.Kernel().CurrentProcess();
1073 const std::shared_ptr<KThread> thread = 1106 const std::shared_ptr<KThread> thread =
1074 current_process->GetHandleTable().Get<KThread>(thread_handle); 1107 current_process->GetHandleTable().Get<KThread>(thread_handle);
1075 R_UNLESS(thread, Svc::ResultInvalidHandle); 1108 if (!thread) {
1109 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={})", thread_handle);
1110 return ResultInvalidHandle;
1111 }
1076 1112
1077 // Require the handle be to a non-current thread in the current process. 1113 // Require the handle be to a non-current thread in the current process.
1078 R_UNLESS(thread->GetOwnerProcess() == current_process, Svc::ResultInvalidHandle); 1114 if (thread->GetOwnerProcess() != current_process) {
1079 R_UNLESS(thread.get() != system.Kernel().CurrentScheduler()->GetCurrentThread(), 1115 LOG_ERROR(Kernel_SVC, "Thread owning process is not the current process.");
1080 Svc::ResultBusy); 1116 return ResultInvalidHandle;
1117 }
1118 if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) {
1119 LOG_ERROR(Kernel_SVC, "Current thread is busy.");
1120 return ResultBusy;
1121 }
1081 1122
1082 // Get the thread context. 1123 // Get the thread context.
1083 std::vector<u8> context; 1124 std::vector<u8> context;
1084 R_TRY(thread->GetThreadContext3(context)); 1125 const auto context_result = thread->GetThreadContext3(context);
1126 if (context_result.IsError()) {
1127 LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve thread context (result: {})",
1128 context_result.raw);
1129 return context_result;
1130 }
1085 1131
1086 // Copy the thread context to user space. 1132 // Copy the thread context to user space.
1087 system.Memory().WriteBlock(out_context, context.data(), context.size()); 1133 system.Memory().WriteBlock(out_context, context.data(), context.size());
@@ -1100,7 +1146,10 @@ static ResultCode GetThreadPriority(Core::System& system, u32* out_priority, Han
1100 // Get the thread from its handle. 1146 // Get the thread from its handle.
1101 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1147 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1102 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); 1148 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
1103 R_UNLESS(thread, Svc::ResultInvalidHandle); 1149 if (!thread) {
1150 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", handle);
1151 return ResultInvalidHandle;
1152 }
1104 1153
1105 // Get the thread's priority. 1154 // Get the thread's priority.
1106 *out_priority = thread->GetPriority(); 1155 *out_priority = thread->GetPriority();
@@ -1116,13 +1165,18 @@ static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 pri
1116 LOG_TRACE(Kernel_SVC, "called"); 1165 LOG_TRACE(Kernel_SVC, "called");
1117 1166
1118 // Validate the priority. 1167 // Validate the priority.
1119 R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority, 1168 if (HighestThreadPriority > priority || priority > LowestThreadPriority) {
1120 Svc::ResultInvalidPriority); 1169 LOG_ERROR(Kernel_SVC, "Invalid thread priority specified (priority={})", priority);
1170 return ResultInvalidPriority;
1171 }
1121 1172
1122 // Get the thread from its handle. 1173 // Get the thread from its handle.
1123 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1174 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1124 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); 1175 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
1125 R_UNLESS(thread, Svc::ResultInvalidHandle); 1176 if (!thread) {
1177 LOG_ERROR(Kernel_SVC, "Invalid handle provided (handle={:08X})", handle);
1178 return ResultInvalidHandle;
1179 }
1126 1180
1127 // Set the thread priority. 1181 // Set the thread priority.
1128 thread->SetBasePriority(priority); 1182 thread->SetBasePriority(priority);
@@ -1438,17 +1492,28 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
1438 // Adjust core id, if it's the default magic. 1492 // Adjust core id, if it's the default magic.
1439 auto& kernel = system.Kernel(); 1493 auto& kernel = system.Kernel();
1440 auto& process = *kernel.CurrentProcess(); 1494 auto& process = *kernel.CurrentProcess();
1441 if (core_id == Svc::IdealCoreUseProcessValue) { 1495 if (core_id == IdealCoreUseProcessValue) {
1442 core_id = process.GetIdealCoreId(); 1496 core_id = process.GetIdealCoreId();
1443 } 1497 }
1444 1498
1445 // Validate arguments. 1499 // Validate arguments.
1446 R_UNLESS(IsValidCoreId(core_id), Svc::ResultInvalidCoreId); 1500 if (!IsValidCoreId(core_id)) {
1447 R_UNLESS(((1ULL << core_id) & process.GetCoreMask()) != 0, Svc::ResultInvalidCoreId); 1501 LOG_ERROR(Kernel_SVC, "Invalid Core ID specified (id={})", core_id);
1502 return ResultInvalidCoreId;
1503 }
1504 if (((1ULL << core_id) & process.GetCoreMask()) == 0) {
1505 LOG_ERROR(Kernel_SVC, "Core ID doesn't fall within allowable cores (id={})", core_id);
1506 return ResultInvalidCoreId;
1507 }
1448 1508
1449 R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority, 1509 if (HighestThreadPriority > priority || priority > LowestThreadPriority) {
1450 Svc::ResultInvalidPriority); 1510 LOG_ERROR(Kernel_SVC, "Invalid priority specified (priority={})", priority);
1451 R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority); 1511 return ResultInvalidPriority;
1512 }
1513 if (!process.CheckThreadPriority(priority)) {
1514 LOG_ERROR(Kernel_SVC, "Invalid allowable thread priority (priority={})", priority);
1515 return ResultInvalidPriority;
1516 }
1452 1517
1453 ASSERT(process.GetResourceLimit()->Reserve( 1518 ASSERT(process.GetResourceLimit()->Reserve(
1454 LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000)); 1519 LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000));
@@ -1487,10 +1552,19 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) {
1487 // Get the thread from its handle. 1552 // Get the thread from its handle.
1488 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1553 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1489 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 1554 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1490 R_UNLESS(thread, Svc::ResultInvalidHandle); 1555 if (!thread) {
1556 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
1557 return ResultInvalidHandle;
1558 }
1491 1559
1492 // Try to start the thread. 1560 // Try to start the thread.
1493 R_TRY(thread->Run()); 1561 const auto run_result = thread->Run();
1562 if (run_result.IsError()) {
1563 LOG_ERROR(Kernel_SVC,
1564 "Unable to successfuly start thread (thread handle={:08X}, result={})",
1565 thread_handle, run_result.raw);
1566 return run_result;
1567 }
1494 1568
1495 return RESULT_SUCCESS; 1569 return RESULT_SUCCESS;
1496} 1570}
@@ -1551,8 +1625,14 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr address,
1551 cv_key, tag, timeout_ns); 1625 cv_key, tag, timeout_ns);
1552 1626
1553 // Validate input. 1627 // Validate input.
1554 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); 1628 if (Memory::IsKernelAddress(address)) {
1555 R_UNLESS(Common::IsAligned(address, sizeof(int32_t)), Svc::ResultInvalidAddress); 1629 LOG_ERROR(Kernel_SVC, "Attempted to wait on kernel address (address={:08X})", address);
1630 return ResultInvalidCurrentMemory;
1631 }
1632 if (!Common::IsAligned(address, sizeof(s32))) {
1633 LOG_ERROR(Kernel_SVC, "Address must be 4 byte aligned (address={:08X})", address);
1634 return ResultInvalidAddress;
1635 }
1556 1636
1557 // Convert timeout from nanoseconds to ticks. 1637 // Convert timeout from nanoseconds to ticks.
1558 s64 timeout{}; 1638 s64 timeout{};
@@ -1627,9 +1707,18 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, Svc::Arbit
1627 address, arb_type, value, timeout_ns); 1707 address, arb_type, value, timeout_ns);
1628 1708
1629 // Validate input. 1709 // Validate input.
1630 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); 1710 if (Memory::IsKernelAddress(address)) {
1631 R_UNLESS(Common::IsAligned(address, sizeof(int32_t)), Svc::ResultInvalidAddress); 1711 LOG_ERROR(Kernel_SVC, "Attempting to wait on kernel address (address={:08X})", address);
1632 R_UNLESS(IsValidArbitrationType(arb_type), Svc::ResultInvalidEnumValue); 1712 return ResultInvalidCurrentMemory;
1713 }
1714 if (!Common::IsAligned(address, sizeof(s32))) {
1715 LOG_ERROR(Kernel_SVC, "Wait address must be 4 byte aligned (address={:08X})", address);
1716 return ResultInvalidAddress;
1717 }
1718 if (!IsValidArbitrationType(arb_type)) {
1719 LOG_ERROR(Kernel_SVC, "Invalid arbitration type specified (type={})", arb_type);
1720 return ResultInvalidEnumValue;
1721 }
1633 1722
1634 // Convert timeout from nanoseconds to ticks. 1723 // Convert timeout from nanoseconds to ticks.
1635 s64 timeout{}; 1724 s64 timeout{};
@@ -1663,9 +1752,18 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, Svc::Sign
1663 address, signal_type, value, count); 1752 address, signal_type, value, count);
1664 1753
1665 // Validate input. 1754 // Validate input.
1666 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); 1755 if (Memory::IsKernelAddress(address)) {
1667 R_UNLESS(Common::IsAligned(address, sizeof(s32)), Svc::ResultInvalidAddress); 1756 LOG_ERROR(Kernel_SVC, "Attempting to signal to a kernel address (address={:08X})", address);
1668 R_UNLESS(IsValidSignalType(signal_type), Svc::ResultInvalidEnumValue); 1757 return ResultInvalidCurrentMemory;
1758 }
1759 if (!Common::IsAligned(address, sizeof(s32))) {
1760 LOG_ERROR(Kernel_SVC, "Signaled address must be 4 byte aligned (address={:08X})", address);
1761 return ResultInvalidAddress;
1762 }
1763 if (!IsValidSignalType(signal_type)) {
1764 LOG_ERROR(Kernel_SVC, "Invalid signal type specified (type={})", signal_type);
1765 return ResultInvalidEnumValue;
1766 }
1669 1767
1670 return system.Kernel().CurrentProcess()->SignalAddressArbiter(address, signal_type, value, 1768 return system.Kernel().CurrentProcess()->SignalAddressArbiter(address, signal_type, value,
1671 count); 1769 count);
@@ -1725,20 +1823,28 @@ static ResultCode CloseHandle32(Core::System& system, Handle handle) {
1725static ResultCode ResetSignal(Core::System& system, Handle handle) { 1823static ResultCode ResetSignal(Core::System& system, Handle handle) {
1726 LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle); 1824 LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
1727 1825
1826 // Get the current handle table.
1728 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1827 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1729 1828
1730 auto event = handle_table.Get<ReadableEvent>(handle); 1829 // Try to reset as readable event.
1731 if (event) { 1830 {
1732 return event->Reset(); 1831 auto readable_event = handle_table.Get<KReadableEvent>(handle);
1832 if (readable_event) {
1833 return readable_event->Reset();
1834 }
1733 } 1835 }
1734 1836
1735 auto process = handle_table.Get<Process>(handle); 1837 // Try to reset as process.
1736 if (process) { 1838 {
1737 return process->ClearSignalState(); 1839 auto process = handle_table.Get<Process>(handle);
1840 if (process) {
1841 return process->Reset();
1842 }
1738 } 1843 }
1739 1844
1740 LOG_ERROR(Kernel_SVC, "Invalid handle (0x{:08X})", handle); 1845 LOG_ERROR(Kernel_SVC, "invalid handle (0x{:08X})", handle);
1741 return ERR_INVALID_HANDLE; 1846
1847 return Svc::ResultInvalidHandle;
1742} 1848}
1743 1849
1744static ResultCode ResetSignal32(Core::System& system, Handle handle) { 1850static ResultCode ResetSignal32(Core::System& system, Handle handle) {
@@ -1805,10 +1911,17 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle,
1805 // Get the thread from its handle. 1911 // Get the thread from its handle.
1806 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1912 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1807 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 1913 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1808 R_UNLESS(thread, Svc::ResultInvalidHandle); 1914 if (!thread) {
1915 LOG_ERROR(Kernel_SVC, "Invalid thread handle specified (handle={:08X})", thread_handle);
1916 return ResultInvalidHandle;
1917 }
1809 1918
1810 // Get the core mask. 1919 // Get the core mask.
1811 R_TRY(thread->GetCoreMask(out_core_id, out_affinity_mask)); 1920 const auto result = thread->GetCoreMask(out_core_id, out_affinity_mask);
1921 if (result.IsError()) {
1922 LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve core mask (result={})", result.raw);
1923 return result;
1924 }
1812 1925
1813 return RESULT_SUCCESS; 1926 return RESULT_SUCCESS;
1814} 1927}
@@ -1836,26 +1949,46 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle,
1836 } else { 1949 } else {
1837 // Validate the affinity mask. 1950 // Validate the affinity mask.
1838 const u64 process_core_mask = current_process.GetCoreMask(); 1951 const u64 process_core_mask = current_process.GetCoreMask();
1839 R_UNLESS((affinity_mask | process_core_mask) == process_core_mask, 1952 if ((affinity_mask | process_core_mask) != process_core_mask) {
1840 Svc::ResultInvalidCoreId); 1953 LOG_ERROR(Kernel_SVC,
1841 R_UNLESS(affinity_mask != 0, Svc::ResultInvalidCombination); 1954 "Affinity mask does match the process core mask (affinity mask={:016X}, core "
1955 "mask={:016X})",
1956 affinity_mask, process_core_mask);
1957 return ResultInvalidCoreId;
1958 }
1959 if (affinity_mask == 0) {
1960 LOG_ERROR(Kernel_SVC, "Affinity mask is zero.");
1961 return ResultInvalidCombination;
1962 }
1842 1963
1843 // Validate the core id. 1964 // Validate the core id.
1844 if (IsValidCoreId(core_id)) { 1965 if (IsValidCoreId(core_id)) {
1845 R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, Svc::ResultInvalidCombination); 1966 if (((1ULL << core_id) & affinity_mask) == 0) {
1967 LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id);
1968 return ResultInvalidCombination;
1969 }
1846 } else { 1970 } else {
1847 R_UNLESS(core_id == Svc::IdealCoreNoUpdate || core_id == Svc::IdealCoreDontCare, 1971 if (core_id != IdealCoreNoUpdate && core_id != IdealCoreDontCare) {
1848 Svc::ResultInvalidCoreId); 1972 LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id);
1973 return ResultInvalidCoreId;
1974 }
1849 } 1975 }
1850 } 1976 }
1851 1977
1852 // Get the thread from its handle. 1978 // Get the thread from its handle.
1853 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1979 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1854 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 1980 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1855 R_UNLESS(thread, Svc::ResultInvalidHandle); 1981 if (!thread) {
1982 LOG_ERROR(Kernel_SVC, "Invalid thread handle (handle={:08X})", thread_handle);
1983 return ResultInvalidHandle;
1984 }
1856 1985
1857 // Set the core mask. 1986 // Set the core mask.
1858 R_TRY(thread->SetCoreMask(core_id, affinity_mask)); 1987 const auto set_result = thread->SetCoreMask(core_id, affinity_mask);
1988 if (set_result.IsError()) {
1989 LOG_ERROR(Kernel_SVC, "Unable to successfully set core mask (result={})", set_result.raw);
1990 return set_result;
1991 }
1859 1992
1860 return RESULT_SUCCESS; 1993 return RESULT_SUCCESS;
1861} 1994}
@@ -1866,80 +1999,98 @@ static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle
1866 return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask); 1999 return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask);
1867} 2000}
1868 2001
1869static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) { 2002static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
1870 LOG_DEBUG(Kernel_SVC, "called"); 2003 LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
1871
1872 auto& kernel = system.Kernel();
1873 const auto [readable_event, writable_event] =
1874 WritableEvent::CreateEventPair(kernel, "CreateEvent");
1875 2004
1876 HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); 2005 // Get the current handle table.
1877 2006 const HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1878 const auto write_create_result = handle_table.Create(writable_event);
1879 if (write_create_result.Failed()) {
1880 return write_create_result.Code();
1881 }
1882 *write_handle = *write_create_result;
1883 2007
1884 const auto read_create_result = handle_table.Create(readable_event); 2008 // Get the writable event.
1885 if (read_create_result.Failed()) { 2009 auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
1886 handle_table.Close(*write_create_result); 2010 if (!writable_event) {
1887 return read_create_result.Code(); 2011 LOG_ERROR(Kernel_SVC, "Invalid event handle provided (handle={:08X})", event_handle);
2012 return ResultInvalidHandle;
1888 } 2013 }
1889 *read_handle = *read_create_result;
1890 2014
1891 LOG_DEBUG(Kernel_SVC, 2015 return writable_event->Signal();
1892 "successful. Writable event handle=0x{:08X}, Readable event handle=0x{:08X}",
1893 *write_create_result, *read_create_result);
1894 return RESULT_SUCCESS;
1895} 2016}
1896 2017
1897static ResultCode CreateEvent32(Core::System& system, Handle* write_handle, Handle* read_handle) { 2018static ResultCode SignalEvent32(Core::System& system, Handle event_handle) {
1898 return CreateEvent(system, write_handle, read_handle); 2019 return SignalEvent(system, event_handle);
1899} 2020}
1900 2021
1901static ResultCode ClearEvent(Core::System& system, Handle handle) { 2022static ResultCode ClearEvent(Core::System& system, Handle event_handle) {
1902 LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle); 2023 LOG_TRACE(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
1903 2024
2025 // Get the current handle table.
1904 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 2026 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1905 2027
1906 auto writable_event = handle_table.Get<WritableEvent>(handle); 2028 // Try to clear the writable event.
1907 if (writable_event) { 2029 {
1908 writable_event->Clear(); 2030 auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
1909 return RESULT_SUCCESS; 2031 if (writable_event) {
2032 return writable_event->Clear();
2033 }
1910 } 2034 }
1911 2035
1912 auto readable_event = handle_table.Get<ReadableEvent>(handle); 2036 // Try to clear the readable event.
1913 if (readable_event) { 2037 {
1914 readable_event->Clear(); 2038 auto readable_event = handle_table.Get<KReadableEvent>(event_handle);
1915 return RESULT_SUCCESS; 2039 if (readable_event) {
2040 return readable_event->Clear();
2041 }
1916 } 2042 }
1917 2043
1918 LOG_ERROR(Kernel_SVC, "Event handle does not exist, handle=0x{:08X}", handle); 2044 LOG_ERROR(Kernel_SVC, "Event handle does not exist, event_handle=0x{:08X}", event_handle);
1919 return ERR_INVALID_HANDLE; 2045
2046 return Svc::ResultInvalidHandle;
1920} 2047}
1921 2048
1922static ResultCode ClearEvent32(Core::System& system, Handle handle) { 2049static ResultCode ClearEvent32(Core::System& system, Handle event_handle) {
1923 return ClearEvent(system, handle); 2050 return ClearEvent(system, event_handle);
1924} 2051}
1925 2052
1926static ResultCode SignalEvent(Core::System& system, Handle handle) { 2053static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
1927 LOG_DEBUG(Kernel_SVC, "called. Handle=0x{:08X}", handle); 2054 LOG_DEBUG(Kernel_SVC, "called");
2055
2056 // Get the kernel reference and handle table.
2057 auto& kernel = system.Kernel();
2058 HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
2059
2060 // Create a new event.
2061 const auto event = KEvent::Create(kernel, "CreateEvent");
2062 if (!event) {
2063 LOG_ERROR(Kernel_SVC, "Unable to create new events. Event creation limit reached.");
2064 return ResultOutOfResource;
2065 }
1928 2066
1929 HandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 2067 // Initialize the event.
1930 auto writable_event = handle_table.Get<WritableEvent>(handle); 2068 event->Initialize();
1931 2069
1932 if (!writable_event) { 2070 // Add the writable event to the handle table.
1933 LOG_ERROR(Kernel_SVC, "Non-existent writable event handle used (0x{:08X})", handle); 2071 const auto write_create_result = handle_table.Create(event->GetWritableEvent());
1934 return ERR_INVALID_HANDLE; 2072 if (write_create_result.Failed()) {
2073 return write_create_result.Code();
2074 }
2075 *out_write = *write_create_result;
2076
2077 // Add the writable event to the handle table.
2078 auto handle_guard = SCOPE_GUARD({ handle_table.Close(*write_create_result); });
2079
2080 // Add the readable event to the handle table.
2081 const auto read_create_result = handle_table.Create(event->GetReadableEvent());
2082 if (read_create_result.Failed()) {
2083 return read_create_result.Code();
1935 } 2084 }
2085 *out_read = *read_create_result;
1936 2086
1937 writable_event->Signal(); 2087 // We succeeded.
2088 handle_guard.Cancel();
1938 return RESULT_SUCCESS; 2089 return RESULT_SUCCESS;
1939} 2090}
1940 2091
1941static ResultCode SignalEvent32(Core::System& system, Handle handle) { 2092static ResultCode CreateEvent32(Core::System& system, Handle* out_write, Handle* out_read) {
1942 return SignalEvent(system, handle); 2093 return CreateEvent(system, out_write, out_read);
1943} 2094}
1944 2095
1945static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) { 2096static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) {
diff --git a/src/core/hle/kernel/svc_results.h b/src/core/hle/kernel/svc_results.h
index 7b897fbce..204cd989d 100644
--- a/src/core/hle/kernel/svc_results.h
+++ b/src/core/hle/kernel/svc_results.h
@@ -11,6 +11,7 @@ namespace Kernel::Svc {
11constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57}; 11constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57};
12constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59}; 12constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59};
13constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102}; 13constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102};
14constexpr ResultCode ResultOutOfResource{ErrorModule::Kernel, 103};
14constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106}; 15constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106};
15constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112}; 16constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112};
16constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113}; 17constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113};
diff --git a/src/core/hle/kernel/writable_event.cpp b/src/core/hle/kernel/writable_event.cpp
deleted file mode 100644
index 142212ee4..000000000
--- a/src/core/hle/kernel/writable_event.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include "common/assert.h"
7#include "core/hle/kernel/k_thread.h"
8#include "core/hle/kernel/kernel.h"
9#include "core/hle/kernel/object.h"
10#include "core/hle/kernel/readable_event.h"
11#include "core/hle/kernel/writable_event.h"
12
13namespace Kernel {
14
15WritableEvent::WritableEvent(KernelCore& kernel) : Object{kernel} {}
16WritableEvent::~WritableEvent() = default;
17
18EventPair WritableEvent::CreateEventPair(KernelCore& kernel, std::string name) {
19 std::shared_ptr<WritableEvent> writable_event(new WritableEvent(kernel));
20 std::shared_ptr<ReadableEvent> readable_event(new ReadableEvent(kernel));
21
22 writable_event->name = name + ":Writable";
23 writable_event->readable = readable_event;
24 readable_event->name = name + ":Readable";
25
26 return {std::move(readable_event), std::move(writable_event)};
27}
28
29std::shared_ptr<ReadableEvent> WritableEvent::GetReadableEvent() const {
30 return readable;
31}
32
33void WritableEvent::Signal() {
34 readable->Signal();
35}
36
37void WritableEvent::Clear() {
38 readable->Clear();
39}
40
41} // namespace Kernel
diff --git a/src/core/hle/kernel/writable_event.h b/src/core/hle/kernel/writable_event.h
deleted file mode 100644
index 467eb2c21..000000000
--- a/src/core/hle/kernel/writable_event.h
+++ /dev/null
@@ -1,60 +0,0 @@
1// Copyright 2014 Citra 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 <memory>
8
9#include "core/hle/kernel/object.h"
10
11namespace Kernel {
12
13class KernelCore;
14class ReadableEvent;
15class WritableEvent;
16
17struct EventPair {
18 std::shared_ptr<ReadableEvent> readable;
19 std::shared_ptr<WritableEvent> writable;
20};
21
22class WritableEvent final : public Object {
23public:
24 ~WritableEvent() override;
25
26 /**
27 * Creates an event
28 * @param kernel The kernel instance to create this event under.
29 * @param name Optional name of event
30 */
31 static EventPair CreateEventPair(KernelCore& kernel, std::string name = "Unknown");
32
33 std::string GetTypeName() const override {
34 return "WritableEvent";
35 }
36 std::string GetName() const override {
37 return name;
38 }
39
40 static constexpr HandleType HANDLE_TYPE = HandleType::WritableEvent;
41 HandleType GetHandleType() const override {
42 return HANDLE_TYPE;
43 }
44
45 std::shared_ptr<ReadableEvent> GetReadableEvent() const;
46
47 void Signal();
48 void Clear();
49
50 void Finalize() override {}
51
52private:
53 explicit WritableEvent(KernelCore& kernel);
54
55 std::shared_ptr<ReadableEvent> readable;
56
57 std::string name; ///< Name of event (optional)
58};
59
60} // namespace Kernel
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index d42236a3a..bb77c2569 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -13,11 +13,12 @@
13#include "core/file_sys/registered_cache.h" 13#include "core/file_sys/registered_cache.h"
14#include "core/file_sys/savedata_factory.h" 14#include "core/file_sys/savedata_factory.h"
15#include "core/hle/ipc_helpers.h" 15#include "core/hle/ipc_helpers.h"
16#include "core/hle/kernel/k_event.h"
17#include "core/hle/kernel/k_readable_event.h"
18#include "core/hle/kernel/k_writable_event.h"
16#include "core/hle/kernel/kernel.h" 19#include "core/hle/kernel/kernel.h"
17#include "core/hle/kernel/process.h" 20#include "core/hle/kernel/process.h"
18#include "core/hle/kernel/readable_event.h"
19#include "core/hle/kernel/transfer_memory.h" 21#include "core/hle/kernel/transfer_memory.h"
20#include "core/hle/kernel/writable_event.h"
21#include "core/hle/service/acc/profile_manager.h" 22#include "core/hle/service/acc/profile_manager.h"
22#include "core/hle/service/am/am.h" 23#include "core/hle/service/am/am.h"
23#include "core/hle/service/am/applet_ae.h" 24#include "core/hle/service/am/applet_ae.h"
@@ -303,17 +304,18 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
303 RegisterHandlers(functions); 304 RegisterHandlers(functions);
304 305
305 auto& kernel = system.Kernel(); 306 auto& kernel = system.Kernel();
306 launchable_event = 307 launchable_event = Kernel::KEvent::Create(kernel, "ISelfController:LaunchableEvent");
307 Kernel::WritableEvent::CreateEventPair(kernel, "ISelfController:LaunchableEvent"); 308 launchable_event->Initialize();
308 309
309 // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is 310 // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is
310 // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple 311 // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple
311 // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not 312 // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not
312 // suspended if the event has previously been created by a call to 313 // suspended if the event has previously been created by a call to
313 // GetAccumulatedSuspendedTickChangedEvent. 314 // GetAccumulatedSuspendedTickChangedEvent.
314 accumulated_suspended_tick_changed_event = Kernel::WritableEvent::CreateEventPair( 315 accumulated_suspended_tick_changed_event =
315 kernel, "ISelfController:AccumulatedSuspendedTickChangedEvent"); 316 Kernel::KEvent::Create(kernel, "ISelfController:AccumulatedSuspendedTickChangedEvent");
316 accumulated_suspended_tick_changed_event.writable->Signal(); 317 accumulated_suspended_tick_changed_event->Initialize();
318 accumulated_suspended_tick_changed_event->GetWritableEvent()->Signal();
317} 319}
318 320
319ISelfController::~ISelfController() = default; 321ISelfController::~ISelfController() = default;
@@ -372,11 +374,11 @@ void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) {
372void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { 374void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
373 LOG_WARNING(Service_AM, "(STUBBED) called"); 375 LOG_WARNING(Service_AM, "(STUBBED) called");
374 376
375 launchable_event.writable->Signal(); 377 launchable_event->GetWritableEvent()->Signal();
376 378
377 IPC::ResponseBuilder rb{ctx, 2, 1}; 379 IPC::ResponseBuilder rb{ctx, 2, 1};
378 rb.Push(RESULT_SUCCESS); 380 rb.Push(RESULT_SUCCESS);
379 rb.PushCopyObjects(launchable_event.readable); 381 rb.PushCopyObjects(launchable_event->GetReadableEvent());
380} 382}
381 383
382void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { 384void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
@@ -555,41 +557,42 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequest
555 557
556 IPC::ResponseBuilder rb{ctx, 2, 1}; 558 IPC::ResponseBuilder rb{ctx, 2, 1};
557 rb.Push(RESULT_SUCCESS); 559 rb.Push(RESULT_SUCCESS);
558 rb.PushCopyObjects(accumulated_suspended_tick_changed_event.readable); 560 rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent());
559} 561}
560 562
561AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) { 563AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) {
562 on_new_message = 564 on_new_message = Kernel::KEvent::Create(kernel, "AMMessageQueue:OnMessageReceived");
563 Kernel::WritableEvent::CreateEventPair(kernel, "AMMessageQueue:OnMessageReceived"); 565 on_new_message->Initialize();
564 on_operation_mode_changed = 566 on_operation_mode_changed =
565 Kernel::WritableEvent::CreateEventPair(kernel, "AMMessageQueue:OperationModeChanged"); 567 Kernel::KEvent::Create(kernel, "AMMessageQueue:OperationModeChanged");
568 on_operation_mode_changed->Initialize();
566} 569}
567 570
568AppletMessageQueue::~AppletMessageQueue() = default; 571AppletMessageQueue::~AppletMessageQueue() = default;
569 572
570const std::shared_ptr<Kernel::ReadableEvent>& AppletMessageQueue::GetMessageReceiveEvent() const { 573const std::shared_ptr<Kernel::KReadableEvent>& AppletMessageQueue::GetMessageReceiveEvent() const {
571 return on_new_message.readable; 574 return on_new_message->GetReadableEvent();
572} 575}
573 576
574const std::shared_ptr<Kernel::ReadableEvent>& AppletMessageQueue::GetOperationModeChangedEvent() 577const std::shared_ptr<Kernel::KReadableEvent>& AppletMessageQueue::GetOperationModeChangedEvent()
575 const { 578 const {
576 return on_operation_mode_changed.readable; 579 return on_operation_mode_changed->GetReadableEvent();
577} 580}
578 581
579void AppletMessageQueue::PushMessage(AppletMessage msg) { 582void AppletMessageQueue::PushMessage(AppletMessage msg) {
580 messages.push(msg); 583 messages.push(msg);
581 on_new_message.writable->Signal(); 584 on_new_message->GetWritableEvent()->Signal();
582} 585}
583 586
584AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { 587AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
585 if (messages.empty()) { 588 if (messages.empty()) {
586 on_new_message.writable->Clear(); 589 on_new_message->GetWritableEvent()->Clear();
587 return AppletMessage::NoMessage; 590 return AppletMessage::NoMessage;
588 } 591 }
589 auto msg = messages.front(); 592 auto msg = messages.front();
590 messages.pop(); 593 messages.pop();
591 if (messages.empty()) { 594 if (messages.empty()) {
592 on_new_message.writable->Clear(); 595 on_new_message->GetWritableEvent()->Clear();
593 } 596 }
594 return msg; 597 return msg;
595} 598}
@@ -601,7 +604,7 @@ std::size_t AppletMessageQueue::GetMessageCount() const {
601void AppletMessageQueue::OperationModeChanged() { 604void AppletMessageQueue::OperationModeChanged() {
602 PushMessage(AppletMessage::OperationModeChanged); 605 PushMessage(AppletMessage::OperationModeChanged);
603 PushMessage(AppletMessage::PerformanceModeChanged); 606 PushMessage(AppletMessage::PerformanceModeChanged);
604 on_operation_mode_changed.writable->Signal(); 607 on_operation_mode_changed->GetWritableEvent()->Signal();
605} 608}
606 609
607void AppletMessageQueue::RequestExit() { 610void AppletMessageQueue::RequestExit() {
@@ -1216,7 +1219,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
1216 {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"}, 1219 {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
1217 {150, nullptr, "GetNotificationStorageChannelEvent"}, 1220 {150, nullptr, "GetNotificationStorageChannelEvent"},
1218 {151, nullptr, "TryPopFromNotificationStorageChannel"}, 1221 {151, nullptr, "TryPopFromNotificationStorageChannel"},
1219 {160, nullptr, "GetHealthWarningDisappearedSystemEvent"}, 1222 {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
1220 {170, nullptr, "SetHdcpAuthenticationActivated"}, 1223 {170, nullptr, "SetHdcpAuthenticationActivated"},
1221 {180, nullptr, "GetLaunchRequiredVersion"}, 1224 {180, nullptr, "GetLaunchRequiredVersion"},
1222 {181, nullptr, "UpgradeLaunchRequiredVersion"}, 1225 {181, nullptr, "UpgradeLaunchRequiredVersion"},
@@ -1229,11 +1232,15 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
1229 RegisterHandlers(functions); 1232 RegisterHandlers(functions);
1230 1233
1231 auto& kernel = system.Kernel(); 1234 auto& kernel = system.Kernel();
1232 gpu_error_detected_event = Kernel::WritableEvent::CreateEventPair( 1235 gpu_error_detected_event =
1233 kernel, "IApplicationFunctions:GpuErrorDetectedSystemEvent"); 1236 Kernel::KEvent::Create(kernel, "IApplicationFunctions:GpuErrorDetectedSystemEvent");
1234 1237 gpu_error_detected_event->Initialize();
1235 friend_invitation_storage_channel_event = Kernel::WritableEvent::CreateEventPair( 1238 friend_invitation_storage_channel_event =
1236 kernel, "IApplicationFunctions:FriendInvitationStorageChannelEvent"); 1239 Kernel::KEvent::Create(kernel, "IApplicationFunctions:FriendInvitationStorageChannelEvent");
1240 friend_invitation_storage_channel_event->Initialize();
1241 health_warning_disappeared_system_event =
1242 Kernel::KEvent::Create(kernel, "IApplicationFunctions:HealthWarningDisappearedSystemEvent");
1243 health_warning_disappeared_system_event->Initialize();
1237} 1244}
1238 1245
1239IApplicationFunctions::~IApplicationFunctions() = default; 1246IApplicationFunctions::~IApplicationFunctions() = default;
@@ -1630,7 +1637,7 @@ void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(Kernel::HLERequestCon
1630 1637
1631 IPC::ResponseBuilder rb{ctx, 2, 1}; 1638 IPC::ResponseBuilder rb{ctx, 2, 1};
1632 rb.Push(RESULT_SUCCESS); 1639 rb.Push(RESULT_SUCCESS);
1633 rb.PushCopyObjects(gpu_error_detected_event.readable); 1640 rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent());
1634} 1641}
1635 1642
1636void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx) { 1643void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx) {
@@ -1638,7 +1645,7 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERe
1638 1645
1639 IPC::ResponseBuilder rb{ctx, 2, 1}; 1646 IPC::ResponseBuilder rb{ctx, 2, 1};
1640 rb.Push(RESULT_SUCCESS); 1647 rb.Push(RESULT_SUCCESS);
1641 rb.PushCopyObjects(friend_invitation_storage_channel_event.readable); 1648 rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent());
1642} 1649}
1643 1650
1644void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel( 1651void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
@@ -1649,6 +1656,14 @@ void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
1649 rb.Push(ERR_NO_DATA_IN_CHANNEL); 1656 rb.Push(ERR_NO_DATA_IN_CHANNEL);
1650} 1657}
1651 1658
1659void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx) {
1660 LOG_DEBUG(Service_AM, "called");
1661
1662 IPC::ResponseBuilder rb{ctx, 2, 1};
1663 rb.Push(RESULT_SUCCESS);
1664 rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent());
1665}
1666
1652void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, 1667void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
1653 Core::System& system) { 1668 Core::System& system) {
1654 auto message_queue = std::make_shared<AppletMessageQueue>(system.Kernel()); 1669 auto message_queue = std::make_shared<AppletMessageQueue>(system.Kernel());
@@ -1682,8 +1697,9 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
1682 1697
1683 RegisterHandlers(functions); 1698 RegisterHandlers(functions);
1684 1699
1685 pop_from_general_channel_event = Kernel::WritableEvent::CreateEventPair( 1700 pop_from_general_channel_event =
1686 system.Kernel(), "IHomeMenuFunctions:PopFromGeneralChannelEvent"); 1701 Kernel::KEvent::Create(system.Kernel(), "IHomeMenuFunctions:PopFromGeneralChannelEvent");
1702 pop_from_general_channel_event->Initialize();
1687} 1703}
1688 1704
1689IHomeMenuFunctions::~IHomeMenuFunctions() = default; 1705IHomeMenuFunctions::~IHomeMenuFunctions() = default;
@@ -1700,7 +1716,7 @@ void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(Kernel::HLERequestContext
1700 1716
1701 IPC::ResponseBuilder rb{ctx, 2, 1}; 1717 IPC::ResponseBuilder rb{ctx, 2, 1};
1702 rb.Push(RESULT_SUCCESS); 1718 rb.Push(RESULT_SUCCESS);
1703 rb.PushCopyObjects(pop_from_general_channel_event.readable); 1719 rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent());
1704} 1720}
1705 1721
1706IGlobalStateController::IGlobalStateController(Core::System& system_) 1722IGlobalStateController::IGlobalStateController(Core::System& system_)
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index f5db41ac8..6911f0d6e 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -7,11 +7,12 @@
7#include <chrono> 7#include <chrono>
8#include <memory> 8#include <memory>
9#include <queue> 9#include <queue>
10#include "core/hle/kernel/writable_event.h" 10
11#include "core/hle/service/service.h" 11#include "core/hle/service/service.h"
12 12
13namespace Kernel { 13namespace Kernel {
14class KernelCore; 14class KernelCore;
15class KEvent;
15class TransferMemory; 16class TransferMemory;
16} // namespace Kernel 17} // namespace Kernel
17 18
@@ -55,8 +56,8 @@ public:
55 explicit AppletMessageQueue(Kernel::KernelCore& kernel); 56 explicit AppletMessageQueue(Kernel::KernelCore& kernel);
56 ~AppletMessageQueue(); 57 ~AppletMessageQueue();
57 58
58 const std::shared_ptr<Kernel::ReadableEvent>& GetMessageReceiveEvent() const; 59 const std::shared_ptr<Kernel::KReadableEvent>& GetMessageReceiveEvent() const;
59 const std::shared_ptr<Kernel::ReadableEvent>& GetOperationModeChangedEvent() const; 60 const std::shared_ptr<Kernel::KReadableEvent>& GetOperationModeChangedEvent() const;
60 void PushMessage(AppletMessage msg); 61 void PushMessage(AppletMessage msg);
61 AppletMessage PopMessage(); 62 AppletMessage PopMessage();
62 std::size_t GetMessageCount() const; 63 std::size_t GetMessageCount() const;
@@ -65,8 +66,8 @@ public:
65 66
66private: 67private:
67 std::queue<AppletMessage> messages; 68 std::queue<AppletMessage> messages;
68 Kernel::EventPair on_new_message; 69 std::shared_ptr<Kernel::KEvent> on_new_message;
69 Kernel::EventPair on_operation_mode_changed; 70 std::shared_ptr<Kernel::KEvent> on_operation_mode_changed;
70}; 71};
71 72
72class IWindowController final : public ServiceFramework<IWindowController> { 73class IWindowController final : public ServiceFramework<IWindowController> {
@@ -153,8 +154,8 @@ private:
153 }; 154 };
154 155
155 NVFlinger::NVFlinger& nvflinger; 156 NVFlinger::NVFlinger& nvflinger;
156 Kernel::EventPair launchable_event; 157 std::shared_ptr<Kernel::KEvent> launchable_event;
157 Kernel::EventPair accumulated_suspended_tick_changed_event; 158 std::shared_ptr<Kernel::KEvent> accumulated_suspended_tick_changed_event;
158 159
159 u32 idle_time_detection_extension = 0; 160 u32 idle_time_detection_extension = 0;
160 u64 num_fatal_sections_entered = 0; 161 u64 num_fatal_sections_entered = 0;
@@ -290,12 +291,14 @@ private:
290 void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx); 291 void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx);
291 void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx); 292 void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx);
292 void TryPopFromFriendInvitationStorageChannel(Kernel::HLERequestContext& ctx); 293 void TryPopFromFriendInvitationStorageChannel(Kernel::HLERequestContext& ctx);
294 void GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx);
293 295
294 bool launch_popped_application_specific = false; 296 bool launch_popped_application_specific = false;
295 bool launch_popped_account_preselect = false; 297 bool launch_popped_account_preselect = false;
296 s32 previous_program_index{-1}; 298 s32 previous_program_index{-1};
297 Kernel::EventPair gpu_error_detected_event; 299 std::shared_ptr<Kernel::KEvent> gpu_error_detected_event;
298 Kernel::EventPair friend_invitation_storage_channel_event; 300 std::shared_ptr<Kernel::KEvent> friend_invitation_storage_channel_event;
301 std::shared_ptr<Kernel::KEvent> health_warning_disappeared_system_event;
299}; 302};
300 303
301class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { 304class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
@@ -307,7 +310,7 @@ private:
307 void RequestToGetForeground(Kernel::HLERequestContext& ctx); 310 void RequestToGetForeground(Kernel::HLERequestContext& ctx);
308 void GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx); 311 void GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx);
309 312
310 Kernel::EventPair pop_from_general_channel_event; 313 std::shared_ptr<Kernel::KEvent> pop_from_general_channel_event;
311}; 314};
312 315
313class IGlobalStateController final : public ServiceFramework<IGlobalStateController> { 316class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 08676c3fc..e2f3b7563 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring> 5#include <cstring>
6
6#include "common/assert.h" 7#include "common/assert.h"
7#include "core/core.h" 8#include "core/core.h"
8#include "core/frontend/applets/controller.h" 9#include "core/frontend/applets/controller.h"
@@ -11,9 +12,10 @@
11#include "core/frontend/applets/profile_select.h" 12#include "core/frontend/applets/profile_select.h"
12#include "core/frontend/applets/software_keyboard.h" 13#include "core/frontend/applets/software_keyboard.h"
13#include "core/frontend/applets/web_browser.h" 14#include "core/frontend/applets/web_browser.h"
14#include "core/hle/kernel/readable_event.h" 15#include "core/hle/kernel/k_event.h"
16#include "core/hle/kernel/k_readable_event.h"
17#include "core/hle/kernel/k_writable_event.h"
15#include "core/hle/kernel/server_session.h" 18#include "core/hle/kernel/server_session.h"
16#include "core/hle/kernel/writable_event.h"
17#include "core/hle/service/am/am.h" 19#include "core/hle/service/am/am.h"
18#include "core/hle/service/am/applets/applets.h" 20#include "core/hle/service/am/applets/applets.h"
19#include "core/hle/service/am/applets/controller.h" 21#include "core/hle/service/am/applets/controller.h"
@@ -27,11 +29,13 @@ namespace Service::AM::Applets {
27 29
28AppletDataBroker::AppletDataBroker(Kernel::KernelCore& kernel) { 30AppletDataBroker::AppletDataBroker(Kernel::KernelCore& kernel) {
29 state_changed_event = 31 state_changed_event =
30 Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:StateChangedEvent"); 32 Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:StateChangedEvent");
31 pop_out_data_event = 33 state_changed_event->Initialize();
32 Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:PopDataOutEvent"); 34 pop_out_data_event = Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:PopDataOutEvent");
33 pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair( 35 pop_out_data_event->Initialize();
34 kernel, "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); 36 pop_interactive_out_data_event =
37 Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
38 pop_interactive_out_data_event->Initialize();
35} 39}
36 40
37AppletDataBroker::~AppletDataBroker() = default; 41AppletDataBroker::~AppletDataBroker() = default;
@@ -58,7 +62,7 @@ std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() {
58 62
59 auto out = std::move(out_channel.front()); 63 auto out = std::move(out_channel.front());
60 out_channel.pop_front(); 64 out_channel.pop_front();
61 pop_out_data_event.writable->Clear(); 65 pop_out_data_event->GetWritableEvent()->Clear();
62 return out; 66 return out;
63} 67}
64 68
@@ -77,7 +81,7 @@ std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() {
77 81
78 auto out = std::move(out_interactive_channel.front()); 82 auto out = std::move(out_interactive_channel.front());
79 out_interactive_channel.pop_front(); 83 out_interactive_channel.pop_front();
80 pop_interactive_out_data_event.writable->Clear(); 84 pop_interactive_out_data_event->GetWritableEvent()->Clear();
81 return out; 85 return out;
82} 86}
83 87
@@ -96,7 +100,7 @@ void AppletDataBroker::PushNormalDataFromGame(std::shared_ptr<IStorage>&& storag
96 100
97void AppletDataBroker::PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage) { 101void AppletDataBroker::PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage) {
98 out_channel.emplace_back(std::move(storage)); 102 out_channel.emplace_back(std::move(storage));
99 pop_out_data_event.writable->Signal(); 103 pop_out_data_event->GetWritableEvent()->Signal();
100} 104}
101 105
102void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage) { 106void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage) {
@@ -105,23 +109,23 @@ void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& s
105 109
106void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage) { 110void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage) {
107 out_interactive_channel.emplace_back(std::move(storage)); 111 out_interactive_channel.emplace_back(std::move(storage));
108 pop_interactive_out_data_event.writable->Signal(); 112 pop_interactive_out_data_event->GetWritableEvent()->Signal();
109} 113}
110 114
111void AppletDataBroker::SignalStateChanged() const { 115void AppletDataBroker::SignalStateChanged() const {
112 state_changed_event.writable->Signal(); 116 state_changed_event->GetWritableEvent()->Signal();
113} 117}
114 118
115std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetNormalDataEvent() const { 119std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetNormalDataEvent() const {
116 return pop_out_data_event.readable; 120 return pop_out_data_event->GetReadableEvent();
117} 121}
118 122
119std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetInteractiveDataEvent() const { 123std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetInteractiveDataEvent() const {
120 return pop_interactive_out_data_event.readable; 124 return pop_interactive_out_data_event->GetReadableEvent();
121} 125}
122 126
123std::shared_ptr<Kernel::ReadableEvent> AppletDataBroker::GetStateChangedEvent() const { 127std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetStateChangedEvent() const {
124 return state_changed_event.readable; 128 return state_changed_event->GetReadableEvent();
125} 129}
126 130
127Applet::Applet(Kernel::KernelCore& kernel_) : broker{kernel_} {} 131Applet::Applet(Kernel::KernelCore& kernel_) : broker{kernel_} {}
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index 4fd792c05..b9a006317 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -6,9 +6,9 @@
6 6
7#include <memory> 7#include <memory>
8#include <queue> 8#include <queue>
9
9#include "common/swap.h" 10#include "common/swap.h"
10#include "core/hle/kernel/object.h" 11#include "core/hle/kernel/object.h"
11#include "core/hle/kernel/writable_event.h"
12 12
13union ResultCode; 13union ResultCode;
14 14
@@ -29,7 +29,9 @@ class WebBrowserApplet;
29 29
30namespace Kernel { 30namespace Kernel {
31class KernelCore; 31class KernelCore;
32} 32class KEvent;
33class KReadableEvent;
34} // namespace Kernel
33 35
34namespace Service::AM { 36namespace Service::AM {
35 37
@@ -87,9 +89,9 @@ public:
87 89
88 void SignalStateChanged() const; 90 void SignalStateChanged() const;
89 91
90 std::shared_ptr<Kernel::ReadableEvent> GetNormalDataEvent() const; 92 std::shared_ptr<Kernel::KReadableEvent> GetNormalDataEvent() const;
91 std::shared_ptr<Kernel::ReadableEvent> GetInteractiveDataEvent() const; 93 std::shared_ptr<Kernel::KReadableEvent> GetInteractiveDataEvent() const;
92 std::shared_ptr<Kernel::ReadableEvent> GetStateChangedEvent() const; 94 std::shared_ptr<Kernel::KReadableEvent> GetStateChangedEvent() const;
93 95
94private: 96private:
95 // Queues are named from applet's perspective 97 // Queues are named from applet's perspective
@@ -106,13 +108,13 @@ private:
106 // PopInteractiveDataToGame and PushInteractiveDataFromApplet 108 // PopInteractiveDataToGame and PushInteractiveDataFromApplet
107 std::deque<std::shared_ptr<IStorage>> out_interactive_channel; 109 std::deque<std::shared_ptr<IStorage>> out_interactive_channel;
108 110
109 Kernel::EventPair state_changed_event; 111 std::shared_ptr<Kernel::KEvent> state_changed_event;
110 112
111 // Signaled on PushNormalDataFromApplet 113 // Signaled on PushNormalDataFromApplet
112 Kernel::EventPair pop_out_data_event; 114 std::shared_ptr<Kernel::KEvent> pop_out_data_event;
113 115
114 // Signaled on PushInteractiveDataFromApplet 116 // Signaled on PushInteractiveDataFromApplet
115 Kernel::EventPair pop_interactive_out_data_event; 117 std::shared_ptr<Kernel::KEvent> pop_interactive_out_data_event;
116}; 118};
117 119
118class Applet { 120class Applet {
diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp
index 7edfca64e..d7d3ee99a 100644
--- a/src/core/hle/service/am/applets/controller.cpp
+++ b/src/core/hle/service/am/applets/controller.cpp
@@ -37,7 +37,7 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
37 .border_colors = std::move(identification_colors), 37 .border_colors = std::move(identification_colors),
38 .enable_explain_text = enable_text, 38 .enable_explain_text = enable_text,
39 .explain_text = std::move(text), 39 .explain_text = std::move(text),
40 .allow_pro_controller = npad_style_set.pro_controller == 1, 40 .allow_pro_controller = npad_style_set.fullkey == 1,
41 .allow_handheld = npad_style_set.handheld == 1, 41 .allow_handheld = npad_style_set.handheld == 1,
42 .allow_dual_joycons = npad_style_set.joycon_dual == 1, 42 .allow_dual_joycons = npad_style_set.joycon_dual == 1,
43 .allow_left_joycon = npad_style_set.joycon_left == 1, 43 .allow_left_joycon = npad_style_set.joycon_left == 1,
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 23e28565b..8d657c0bf 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -5,6 +5,7 @@
5#include <algorithm> 5#include <algorithm>
6#include <numeric> 6#include <numeric>
7#include <vector> 7#include <vector>
8
8#include "common/logging/log.h" 9#include "common/logging/log.h"
9#include "core/core.h" 10#include "core/core.h"
10#include "core/file_sys/common_funcs.h" 11#include "core/file_sys/common_funcs.h"
@@ -14,10 +15,10 @@
14#include "core/file_sys/patch_manager.h" 15#include "core/file_sys/patch_manager.h"
15#include "core/file_sys/registered_cache.h" 16#include "core/file_sys/registered_cache.h"
16#include "core/hle/ipc_helpers.h" 17#include "core/hle/ipc_helpers.h"
18#include "core/hle/kernel/k_event.h"
19#include "core/hle/kernel/k_readable_event.h"
17#include "core/hle/kernel/kernel.h" 20#include "core/hle/kernel/kernel.h"
18#include "core/hle/kernel/process.h" 21#include "core/hle/kernel/process.h"
19#include "core/hle/kernel/readable_event.h"
20#include "core/hle/kernel/writable_event.h"
21#include "core/hle/service/aoc/aoc_u.h" 22#include "core/hle/service/aoc/aoc_u.h"
22#include "core/loader/loader.h" 23#include "core/loader/loader.h"
23#include "core/settings.h" 24#include "core/settings.h"
@@ -62,8 +63,9 @@ public:
62 63
63 RegisterHandlers(functions); 64 RegisterHandlers(functions);
64 65
65 purchased_event = Kernel::WritableEvent::CreateEventPair( 66 purchased_event =
66 system.Kernel(), "IPurchaseEventManager:PurchasedEvent"); 67 Kernel::KEvent::Create(system.Kernel(), "IPurchaseEventManager:PurchasedEvent");
68 purchased_event->Initialize();
67 } 69 }
68 70
69private: 71private:
@@ -96,10 +98,10 @@ private:
96 98
97 IPC::ResponseBuilder rb{ctx, 2, 1}; 99 IPC::ResponseBuilder rb{ctx, 2, 1};
98 rb.Push(RESULT_SUCCESS); 100 rb.Push(RESULT_SUCCESS);
99 rb.PushCopyObjects(purchased_event.readable); 101 rb.PushCopyObjects(purchased_event->GetReadableEvent());
100 } 102 }
101 103
102 Kernel::EventPair purchased_event; 104 std::shared_ptr<Kernel::KEvent> purchased_event;
103}; 105};
104 106
105AOC_U::AOC_U(Core::System& system_) 107AOC_U::AOC_U(Core::System& system_)
@@ -124,8 +126,8 @@ AOC_U::AOC_U(Core::System& system_)
124 RegisterHandlers(functions); 126 RegisterHandlers(functions);
125 127
126 auto& kernel = system.Kernel(); 128 auto& kernel = system.Kernel();
127 aoc_change_event = 129 aoc_change_event = Kernel::KEvent::Create(kernel, "GetAddOnContentListChanged:Event");
128 Kernel::WritableEvent::CreateEventPair(kernel, "GetAddOnContentListChanged:Event"); 130 aoc_change_event->Initialize();
129} 131}
130 132
131AOC_U::~AOC_U() = default; 133AOC_U::~AOC_U() = default;
@@ -252,7 +254,7 @@ void AOC_U::GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx) {
252 254
253 IPC::ResponseBuilder rb{ctx, 2, 1}; 255 IPC::ResponseBuilder rb{ctx, 2, 1};
254 rb.Push(RESULT_SUCCESS); 256 rb.Push(RESULT_SUCCESS);
255 rb.PushCopyObjects(aoc_change_event.readable); 257 rb.PushCopyObjects(aoc_change_event->GetReadableEvent());
256} 258}
257 259
258void AOC_U::CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx) { 260void AOC_U::CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h
index 26ee51be0..1aa23529e 100644
--- a/src/core/hle/service/aoc/aoc_u.h
+++ b/src/core/hle/service/aoc/aoc_u.h
@@ -11,7 +11,7 @@ class System;
11} 11}
12 12
13namespace Kernel { 13namespace Kernel {
14class WritableEvent; 14class KEvent;
15} 15}
16 16
17namespace Service::AOC { 17namespace Service::AOC {
@@ -31,7 +31,7 @@ private:
31 void CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ctx); 31 void CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ctx);
32 32
33 std::vector<u64> add_on_content; 33 std::vector<u64> add_on_content;
34 Kernel::EventPair aoc_change_event; 34 std::shared_ptr<Kernel::KEvent> aoc_change_event;
35}; 35};
36 36
37/// Registers all AOC services with the specified service manager. 37/// Registers all AOC services with the specified service manager.
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 273a46265..5ed9cb20e 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -14,9 +14,10 @@
14#include "core/core.h" 14#include "core/core.h"
15#include "core/hle/ipc_helpers.h" 15#include "core/hle/ipc_helpers.h"
16#include "core/hle/kernel/hle_ipc.h" 16#include "core/hle/kernel/hle_ipc.h"
17#include "core/hle/kernel/k_event.h"
18#include "core/hle/kernel/k_readable_event.h"
19#include "core/hle/kernel/k_writable_event.h"
17#include "core/hle/kernel/kernel.h" 20#include "core/hle/kernel/kernel.h"
18#include "core/hle/kernel/readable_event.h"
19#include "core/hle/kernel/writable_event.h"
20#include "core/hle/service/audio/audout_u.h" 21#include "core/hle/service/audio/audout_u.h"
21#include "core/hle/service/audio/errors.h" 22#include "core/hle/service/audio/errors.h"
22#include "core/memory.h" 23#include "core/memory.h"
@@ -66,13 +67,13 @@ public:
66 RegisterHandlers(functions); 67 RegisterHandlers(functions);
67 68
68 // This is the event handle used to check if the audio buffer was released 69 // This is the event handle used to check if the audio buffer was released
69 buffer_event = 70 buffer_event = Kernel::KEvent::Create(system.Kernel(), "IAudioOutBufferReleased");
70 Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioOutBufferReleased"); 71 buffer_event->Initialize();
71 72
72 stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate, 73 stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate,
73 audio_params.channel_count, std::move(unique_name), [this] { 74 audio_params.channel_count, std::move(unique_name), [this] {
74 const auto guard = LockService(); 75 const auto guard = LockService();
75 buffer_event.writable->Signal(); 76 buffer_event->GetWritableEvent()->Signal();
76 }); 77 });
77 } 78 }
78 79
@@ -125,7 +126,7 @@ private:
125 126
126 IPC::ResponseBuilder rb{ctx, 2, 1}; 127 IPC::ResponseBuilder rb{ctx, 2, 1};
127 rb.Push(RESULT_SUCCESS); 128 rb.Push(RESULT_SUCCESS);
128 rb.PushCopyObjects(buffer_event.readable); 129 rb.PushCopyObjects(buffer_event->GetReadableEvent());
129 } 130 }
130 131
131 void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) { 132 void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
@@ -219,7 +220,7 @@ private:
219 [[maybe_unused]] AudoutParams audio_params{}; 220 [[maybe_unused]] AudoutParams audio_params{};
220 221
221 /// This is the event handle used to check if the audio buffer was released 222 /// This is the event handle used to check if the audio buffer was released
222 Kernel::EventPair buffer_event; 223 std::shared_ptr<Kernel::KEvent> buffer_event;
223 Core::Memory::Memory& main_memory; 224 Core::Memory::Memory& main_memory;
224}; 225};
225 226
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index c5c22d053..b2b2ffc5a 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -16,9 +16,10 @@
16#include "core/core.h" 16#include "core/core.h"
17#include "core/hle/ipc_helpers.h" 17#include "core/hle/ipc_helpers.h"
18#include "core/hle/kernel/hle_ipc.h" 18#include "core/hle/kernel/hle_ipc.h"
19#include "core/hle/kernel/k_event.h"
20#include "core/hle/kernel/k_readable_event.h"
21#include "core/hle/kernel/k_writable_event.h"
19#include "core/hle/kernel/kernel.h" 22#include "core/hle/kernel/kernel.h"
20#include "core/hle/kernel/readable_event.h"
21#include "core/hle/kernel/writable_event.h"
22#include "core/hle/service/audio/audren_u.h" 23#include "core/hle/service/audio/audren_u.h"
23#include "core/hle/service/audio/errors.h" 24#include "core/hle/service/audio/errors.h"
24 25
@@ -47,13 +48,13 @@ public:
47 // clang-format on 48 // clang-format on
48 RegisterHandlers(functions); 49 RegisterHandlers(functions);
49 50
50 system_event = 51 system_event = Kernel::KEvent::Create(system.Kernel(), "IAudioRenderer:SystemEvent");
51 Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioRenderer:SystemEvent"); 52 system_event->Initialize();
52 renderer = std::make_unique<AudioCore::AudioRenderer>( 53 renderer = std::make_unique<AudioCore::AudioRenderer>(
53 system.CoreTiming(), system.Memory(), audren_params, 54 system.CoreTiming(), system.Memory(), audren_params,
54 [this]() { 55 [this]() {
55 const auto guard = LockService(); 56 const auto guard = LockService();
56 system_event.writable->Signal(); 57 system_event->GetWritableEvent()->Signal();
57 }, 58 },
58 instance_number); 59 instance_number);
59 } 60 }
@@ -126,7 +127,7 @@ private:
126 127
127 IPC::ResponseBuilder rb{ctx, 2, 1}; 128 IPC::ResponseBuilder rb{ctx, 2, 1};
128 rb.Push(RESULT_SUCCESS); 129 rb.Push(RESULT_SUCCESS);
129 rb.PushCopyObjects(system_event.readable); 130 rb.PushCopyObjects(system_event->GetReadableEvent());
130 } 131 }
131 132
132 void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) { 133 void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) {
@@ -160,7 +161,7 @@ private:
160 rb.Push(ERR_NOT_SUPPORTED); 161 rb.Push(ERR_NOT_SUPPORTED);
161 } 162 }
162 163
163 Kernel::EventPair system_event; 164 std::shared_ptr<Kernel::KEvent> system_event;
164 std::unique_ptr<AudioCore::AudioRenderer> renderer; 165 std::unique_ptr<AudioCore::AudioRenderer> renderer;
165 u32 rendering_time_limit_percent = 100; 166 u32 rendering_time_limit_percent = 100;
166}; 167};
@@ -187,17 +188,19 @@ public:
187 RegisterHandlers(functions); 188 RegisterHandlers(functions);
188 189
189 auto& kernel = system.Kernel(); 190 auto& kernel = system.Kernel();
190 buffer_event = 191 buffer_event = Kernel::KEvent::Create(kernel, "IAudioOutBufferReleasedEvent");
191 Kernel::WritableEvent::CreateEventPair(kernel, "IAudioOutBufferReleasedEvent"); 192 buffer_event->Initialize();
192 193
193 // Should be similar to audio_output_device_switch_event 194 // Should be similar to audio_output_device_switch_event
194 audio_input_device_switch_event = Kernel::WritableEvent::CreateEventPair( 195 audio_input_device_switch_event =
195 kernel, "IAudioDevice:AudioInputDeviceSwitchedEvent"); 196 Kernel::KEvent::Create(kernel, "IAudioDevice:AudioInputDeviceSwitchedEvent");
197 audio_input_device_switch_event->Initialize();
196 198
197 // Should only be signalled when an audio output device has been changed, example: speaker 199 // Should only be signalled when an audio output device has been changed, example: speaker
198 // to headset 200 // to headset
199 audio_output_device_switch_event = Kernel::WritableEvent::CreateEventPair( 201 audio_output_device_switch_event =
200 kernel, "IAudioDevice:AudioOutputDeviceSwitchedEvent"); 202 Kernel::KEvent::Create(kernel, "IAudioDevice:AudioOutputDeviceSwitchedEvent");
203 audio_output_device_switch_event->Initialize();
201 } 204 }
202 205
203private: 206private:
@@ -286,11 +289,11 @@ private:
286 void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) { 289 void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) {
287 LOG_WARNING(Service_Audio, "(STUBBED) called"); 290 LOG_WARNING(Service_Audio, "(STUBBED) called");
288 291
289 buffer_event.writable->Signal(); 292 buffer_event->GetWritableEvent()->Signal();
290 293
291 IPC::ResponseBuilder rb{ctx, 2, 1}; 294 IPC::ResponseBuilder rb{ctx, 2, 1};
292 rb.Push(RESULT_SUCCESS); 295 rb.Push(RESULT_SUCCESS);
293 rb.PushCopyObjects(buffer_event.readable); 296 rb.PushCopyObjects(buffer_event->GetReadableEvent());
294 } 297 }
295 298
296 void GetActiveChannelCount(Kernel::HLERequestContext& ctx) { 299 void GetActiveChannelCount(Kernel::HLERequestContext& ctx) {
@@ -307,7 +310,7 @@ private:
307 310
308 IPC::ResponseBuilder rb{ctx, 2, 1}; 311 IPC::ResponseBuilder rb{ctx, 2, 1};
309 rb.Push(RESULT_SUCCESS); 312 rb.Push(RESULT_SUCCESS);
310 rb.PushCopyObjects(audio_input_device_switch_event.readable); 313 rb.PushCopyObjects(audio_input_device_switch_event->GetReadableEvent());
311 } 314 }
312 315
313 void QueryAudioDeviceOutputEvent(Kernel::HLERequestContext& ctx) { 316 void QueryAudioDeviceOutputEvent(Kernel::HLERequestContext& ctx) {
@@ -315,13 +318,13 @@ private:
315 318
316 IPC::ResponseBuilder rb{ctx, 2, 1}; 319 IPC::ResponseBuilder rb{ctx, 2, 1};
317 rb.Push(RESULT_SUCCESS); 320 rb.Push(RESULT_SUCCESS);
318 rb.PushCopyObjects(audio_output_device_switch_event.readable); 321 rb.PushCopyObjects(audio_output_device_switch_event->GetReadableEvent());
319 } 322 }
320 323
321 u32_le revision = 0; 324 u32_le revision = 0;
322 Kernel::EventPair buffer_event; 325 std::shared_ptr<Kernel::KEvent> buffer_event;
323 Kernel::EventPair audio_input_device_switch_event; 326 std::shared_ptr<Kernel::KEvent> audio_input_device_switch_event;
324 Kernel::EventPair audio_output_device_switch_event; 327 std::shared_ptr<Kernel::KEvent> audio_output_device_switch_event;
325 328
326}; // namespace Audio 329}; // namespace Audio
327 330
diff --git a/src/core/hle/service/bcat/backend/backend.cpp b/src/core/hle/service/bcat/backend/backend.cpp
index 174388445..92d25dbe4 100644
--- a/src/core/hle/service/bcat/backend/backend.cpp
+++ b/src/core/hle/service/bcat/backend/backend.cpp
@@ -5,6 +5,9 @@
5#include "common/hex_util.h" 5#include "common/hex_util.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/hle/kernel/k_event.h"
9#include "core/hle/kernel/k_readable_event.h"
10#include "core/hle/kernel/k_writable_event.h"
8#include "core/hle/lock.h" 11#include "core/hle/lock.h"
9#include "core/hle/service/bcat/backend/backend.h" 12#include "core/hle/service/bcat/backend/backend.h"
10 13
@@ -12,12 +15,13 @@ namespace Service::BCAT {
12 15
13ProgressServiceBackend::ProgressServiceBackend(Kernel::KernelCore& kernel, 16ProgressServiceBackend::ProgressServiceBackend(Kernel::KernelCore& kernel,
14 std::string_view event_name) { 17 std::string_view event_name) {
15 event = Kernel::WritableEvent::CreateEventPair( 18 event = Kernel::KEvent::Create(kernel,
16 kernel, std::string("ProgressServiceBackend:UpdateEvent:").append(event_name)); 19 "ProgressServiceBackend:UpdateEvent:" + std::string(event_name));
20 event->Initialize();
17} 21}
18 22
19std::shared_ptr<Kernel::ReadableEvent> ProgressServiceBackend::GetEvent() const { 23std::shared_ptr<Kernel::KReadableEvent> ProgressServiceBackend::GetEvent() const {
20 return event.readable; 24 return event->GetReadableEvent();
21} 25}
22 26
23DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() { 27DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() {
@@ -85,9 +89,9 @@ void ProgressServiceBackend::FinishDownload(ResultCode result) {
85void ProgressServiceBackend::SignalUpdate() const { 89void ProgressServiceBackend::SignalUpdate() const {
86 if (need_hle_lock) { 90 if (need_hle_lock) {
87 std::lock_guard lock(HLE::g_hle_lock); 91 std::lock_guard lock(HLE::g_hle_lock);
88 event.writable->Signal(); 92 event->GetWritableEvent()->Signal();
89 } else { 93 } else {
90 event.writable->Signal(); 94 event->GetWritableEvent()->Signal();
91 } 95 }
92} 96}
93 97
diff --git a/src/core/hle/service/bcat/backend/backend.h b/src/core/hle/service/bcat/backend/backend.h
index 48bbbe66f..db585b069 100644
--- a/src/core/hle/service/bcat/backend/backend.h
+++ b/src/core/hle/service/bcat/backend/backend.h
@@ -11,8 +11,6 @@
11 11
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "core/file_sys/vfs_types.h" 13#include "core/file_sys/vfs_types.h"
14#include "core/hle/kernel/readable_event.h"
15#include "core/hle/kernel/writable_event.h"
16#include "core/hle/result.h" 14#include "core/hle/result.h"
17 15
18namespace Core { 16namespace Core {
@@ -21,7 +19,9 @@ class System;
21 19
22namespace Kernel { 20namespace Kernel {
23class KernelCore; 21class KernelCore;
24} 22class KEvent;
23class KReadableEvent;
24} // namespace Kernel
25 25
26namespace Service::BCAT { 26namespace Service::BCAT {
27 27
@@ -98,13 +98,13 @@ public:
98private: 98private:
99 explicit ProgressServiceBackend(Kernel::KernelCore& kernel, std::string_view event_name); 99 explicit ProgressServiceBackend(Kernel::KernelCore& kernel, std::string_view event_name);
100 100
101 std::shared_ptr<Kernel::ReadableEvent> GetEvent() const; 101 std::shared_ptr<Kernel::KReadableEvent> GetEvent() const;
102 DeliveryCacheProgressImpl& GetImpl(); 102 DeliveryCacheProgressImpl& GetImpl();
103 103
104 void SignalUpdate() const; 104 void SignalUpdate() const;
105 105
106 DeliveryCacheProgressImpl impl{}; 106 DeliveryCacheProgressImpl impl{};
107 Kernel::EventPair event; 107 std::shared_ptr<Kernel::KEvent> event;
108 bool need_hle_lock = false; 108 bool need_hle_lock = false;
109}; 109};
110 110
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp
index b8696a395..503109fdd 100644
--- a/src/core/hle/service/bcat/module.cpp
+++ b/src/core/hle/service/bcat/module.cpp
@@ -11,9 +11,9 @@
11#include "core/core.h" 11#include "core/core.h"
12#include "core/file_sys/vfs.h" 12#include "core/file_sys/vfs.h"
13#include "core/hle/ipc_helpers.h" 13#include "core/hle/ipc_helpers.h"
14#include "core/hle/kernel/k_readable_event.h"
15#include "core/hle/kernel/k_writable_event.h"
14#include "core/hle/kernel/process.h" 16#include "core/hle/kernel/process.h"
15#include "core/hle/kernel/readable_event.h"
16#include "core/hle/kernel/writable_event.h"
17#include "core/hle/service/bcat/backend/backend.h" 17#include "core/hle/service/bcat/backend/backend.h"
18#include "core/hle/service/bcat/bcat.h" 18#include "core/hle/service/bcat/bcat.h"
19#include "core/hle/service/bcat/module.h" 19#include "core/hle/service/bcat/module.h"
@@ -89,7 +89,7 @@ struct DeliveryCacheDirectoryEntry {
89class IDeliveryCacheProgressService final : public ServiceFramework<IDeliveryCacheProgressService> { 89class IDeliveryCacheProgressService final : public ServiceFramework<IDeliveryCacheProgressService> {
90public: 90public:
91 explicit IDeliveryCacheProgressService(Core::System& system_, 91 explicit IDeliveryCacheProgressService(Core::System& system_,
92 std::shared_ptr<Kernel::ReadableEvent> event_, 92 std::shared_ptr<Kernel::KReadableEvent> event_,
93 const DeliveryCacheProgressImpl& impl_) 93 const DeliveryCacheProgressImpl& impl_)
94 : ServiceFramework{system_, "IDeliveryCacheProgressService"}, event{std::move(event_)}, 94 : ServiceFramework{system_, "IDeliveryCacheProgressService"}, event{std::move(event_)},
95 impl{impl_} { 95 impl{impl_} {
@@ -121,7 +121,7 @@ private:
121 rb.Push(RESULT_SUCCESS); 121 rb.Push(RESULT_SUCCESS);
122 } 122 }
123 123
124 std::shared_ptr<Kernel::ReadableEvent> event; 124 std::shared_ptr<Kernel::KReadableEvent> event;
125 const DeliveryCacheProgressImpl& impl; 125 const DeliveryCacheProgressImpl& impl;
126}; 126};
127 127
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp
index 2de86f1f1..17a2ac899 100644
--- a/src/core/hle/service/btdrv/btdrv.cpp
+++ b/src/core/hle/service/btdrv/btdrv.cpp
@@ -6,9 +6,9 @@
6#include "core/core.h" 6#include "core/core.h"
7#include "core/hle/ipc_helpers.h" 7#include "core/hle/ipc_helpers.h"
8#include "core/hle/kernel/hle_ipc.h" 8#include "core/hle/kernel/hle_ipc.h"
9#include "core/hle/kernel/k_event.h"
10#include "core/hle/kernel/k_readable_event.h"
9#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
10#include "core/hle/kernel/readable_event.h"
11#include "core/hle/kernel/writable_event.h"
12#include "core/hle/service/btdrv/btdrv.h" 12#include "core/hle/service/btdrv/btdrv.h"
13#include "core/hle/service/service.h" 13#include "core/hle/service/service.h"
14#include "core/hle/service/sm/sm.h" 14#include "core/hle/service/sm/sm.h"
@@ -35,7 +35,8 @@ public:
35 RegisterHandlers(functions); 35 RegisterHandlers(functions);
36 36
37 auto& kernel = system.Kernel(); 37 auto& kernel = system.Kernel();
38 register_event = Kernel::WritableEvent::CreateEventPair(kernel, "BT:RegisterEvent"); 38 register_event = Kernel::KEvent::Create(kernel, "BT:RegisterEvent");
39 register_event->Initialize();
39 } 40 }
40 41
41private: 42private:
@@ -44,10 +45,10 @@ private:
44 45
45 IPC::ResponseBuilder rb{ctx, 2, 1}; 46 IPC::ResponseBuilder rb{ctx, 2, 1};
46 rb.Push(RESULT_SUCCESS); 47 rb.Push(RESULT_SUCCESS);
47 rb.PushCopyObjects(register_event.readable); 48 rb.PushCopyObjects(register_event->GetReadableEvent());
48 } 49 }
49 50
50 Kernel::EventPair register_event; 51 std::shared_ptr<Kernel::KEvent> register_event;
51}; 52};
52 53
53class BtDrv final : public ServiceFramework<BtDrv> { 54class BtDrv final : public ServiceFramework<BtDrv> {
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp
index 38b55300e..9cf2ee92a 100644
--- a/src/core/hle/service/btm/btm.cpp
+++ b/src/core/hle/service/btm/btm.cpp
@@ -8,9 +8,9 @@
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
10#include "core/hle/kernel/hle_ipc.h" 10#include "core/hle/kernel/hle_ipc.h"
11#include "core/hle/kernel/k_event.h"
12#include "core/hle/kernel/k_readable_event.h"
11#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/readable_event.h"
13#include "core/hle/kernel/writable_event.h"
14#include "core/hle/service/btm/btm.h" 14#include "core/hle/service/btm/btm.h"
15#include "core/hle/service/service.h" 15#include "core/hle/service/service.h"
16 16
@@ -58,12 +58,14 @@ public:
58 RegisterHandlers(functions); 58 RegisterHandlers(functions);
59 59
60 auto& kernel = system.Kernel(); 60 auto& kernel = system.Kernel();
61 scan_event = Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ScanEvent"); 61 scan_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ScanEvent");
62 connection_event = 62 scan_event->Initialize();
63 Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ConnectionEvent"); 63 connection_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ConnectionEvent");
64 service_discovery = 64 connection_event->Initialize();
65 Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:Discovery"); 65 service_discovery = Kernel::KEvent::Create(kernel, "IBtmUserCore:Discovery");
66 config_event = Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ConfigEvent"); 66 service_discovery->Initialize();
67 config_event = Kernel::KEvent::Create(kernel, "IBtmUserCore:ConfigEvent");
68 config_event->Initialize();
67 } 69 }
68 70
69private: 71private:
@@ -72,7 +74,7 @@ private:
72 74
73 IPC::ResponseBuilder rb{ctx, 2, 1}; 75 IPC::ResponseBuilder rb{ctx, 2, 1};
74 rb.Push(RESULT_SUCCESS); 76 rb.Push(RESULT_SUCCESS);
75 rb.PushCopyObjects(scan_event.readable); 77 rb.PushCopyObjects(scan_event->GetReadableEvent());
76 } 78 }
77 79
78 void AcquireBleConnectionEvent(Kernel::HLERequestContext& ctx) { 80 void AcquireBleConnectionEvent(Kernel::HLERequestContext& ctx) {
@@ -80,7 +82,7 @@ private:
80 82
81 IPC::ResponseBuilder rb{ctx, 2, 1}; 83 IPC::ResponseBuilder rb{ctx, 2, 1};
82 rb.Push(RESULT_SUCCESS); 84 rb.Push(RESULT_SUCCESS);
83 rb.PushCopyObjects(connection_event.readable); 85 rb.PushCopyObjects(connection_event->GetReadableEvent());
84 } 86 }
85 87
86 void AcquireBleServiceDiscoveryEvent(Kernel::HLERequestContext& ctx) { 88 void AcquireBleServiceDiscoveryEvent(Kernel::HLERequestContext& ctx) {
@@ -88,7 +90,7 @@ private:
88 90
89 IPC::ResponseBuilder rb{ctx, 2, 1}; 91 IPC::ResponseBuilder rb{ctx, 2, 1};
90 rb.Push(RESULT_SUCCESS); 92 rb.Push(RESULT_SUCCESS);
91 rb.PushCopyObjects(service_discovery.readable); 93 rb.PushCopyObjects(service_discovery->GetReadableEvent());
92 } 94 }
93 95
94 void AcquireBleMtuConfigEvent(Kernel::HLERequestContext& ctx) { 96 void AcquireBleMtuConfigEvent(Kernel::HLERequestContext& ctx) {
@@ -96,13 +98,13 @@ private:
96 98
97 IPC::ResponseBuilder rb{ctx, 2, 1}; 99 IPC::ResponseBuilder rb{ctx, 2, 1};
98 rb.Push(RESULT_SUCCESS); 100 rb.Push(RESULT_SUCCESS);
99 rb.PushCopyObjects(config_event.readable); 101 rb.PushCopyObjects(config_event->GetReadableEvent());
100 } 102 }
101 103
102 Kernel::EventPair scan_event; 104 std::shared_ptr<Kernel::KEvent> scan_event;
103 Kernel::EventPair connection_event; 105 std::shared_ptr<Kernel::KEvent> connection_event;
104 Kernel::EventPair service_discovery; 106 std::shared_ptr<Kernel::KEvent> service_discovery;
105 Kernel::EventPair config_event; 107 std::shared_ptr<Kernel::KEvent> config_event;
106}; 108};
107 109
108class BTM_USR final : public ServiceFramework<BTM_USR> { 110class BTM_USR final : public ServiceFramework<BTM_USR> {
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index c5b053c31..72a877d68 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -7,8 +7,9 @@
7#include "common/uuid.h" 7#include "common/uuid.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
10#include "core/hle/kernel/readable_event.h" 10#include "core/hle/kernel/k_event.h"
11#include "core/hle/kernel/writable_event.h" 11#include "core/hle/kernel/k_readable_event.h"
12#include "core/hle/kernel/k_writable_event.h"
12#include "core/hle/service/friend/errors.h" 13#include "core/hle/service/friend/errors.h"
13#include "core/hle/service/friend/friend.h" 14#include "core/hle/service/friend/friend.h"
14#include "core/hle/service/friend/interface.h" 15#include "core/hle/service/friend/interface.h"
@@ -183,8 +184,9 @@ public:
183 184
184 RegisterHandlers(functions); 185 RegisterHandlers(functions);
185 186
186 notification_event = Kernel::WritableEvent::CreateEventPair( 187 notification_event =
187 system.Kernel(), "INotificationService:NotifyEvent"); 188 Kernel::KEvent::Create(system.Kernel(), "INotificationService:NotifyEvent");
189 notification_event->Initialize();
188 } 190 }
189 191
190private: 192private:
@@ -193,7 +195,7 @@ private:
193 195
194 IPC::ResponseBuilder rb{ctx, 2, 1}; 196 IPC::ResponseBuilder rb{ctx, 2, 1};
195 rb.Push(RESULT_SUCCESS); 197 rb.Push(RESULT_SUCCESS);
196 rb.PushCopyObjects(notification_event.readable); 198 rb.PushCopyObjects(notification_event->GetReadableEvent());
197 } 199 }
198 200
199 void Clear(Kernel::HLERequestContext& ctx) { 201 void Clear(Kernel::HLERequestContext& ctx) {
@@ -258,7 +260,7 @@ private:
258 }; 260 };
259 261
260 Common::UUID uuid{Common::INVALID_UUID}; 262 Common::UUID uuid{Common::INVALID_UUID};
261 Kernel::EventPair notification_event; 263 std::shared_ptr<Kernel::KEvent> notification_event;
262 std::queue<SizedNotificationInfo> notifications; 264 std::queue<SizedNotificationInfo> notifications;
263 States states{}; 265 States states{};
264}; 266};
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index 59b694cd4..c4a59147d 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -39,16 +39,25 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
39 cur_entry.sampling_number2 = cur_entry.sampling_number; 39 cur_entry.sampling_number2 = cur_entry.sampling_number;
40 40
41 cur_entry.key.fill(0); 41 cur_entry.key.fill(0);
42 cur_entry.modifier = 0;
43 if (Settings::values.keyboard_enabled) { 42 if (Settings::values.keyboard_enabled) {
44 for (std::size_t i = 0; i < keyboard_keys.size(); ++i) { 43 for (std::size_t i = 0; i < keyboard_keys.size(); ++i) {
45 auto& entry = cur_entry.key[i / KEYS_PER_BYTE]; 44 auto& entry = cur_entry.key[i / KEYS_PER_BYTE];
46 entry = static_cast<u8>(entry | (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE))); 45 entry = static_cast<u8>(entry | (keyboard_keys[i]->GetStatus() << (i % KEYS_PER_BYTE)));
47 } 46 }
48 47
49 for (std::size_t i = 0; i < keyboard_mods.size(); ++i) { 48 using namespace Settings::NativeKeyboard;
50 cur_entry.modifier |= (keyboard_mods[i]->GetStatus() << i); 49
51 } 50 // TODO: Assign the correct key to all modifiers
51 cur_entry.modifier.control.Assign(keyboard_mods[LeftControl]->GetStatus());
52 cur_entry.modifier.shift.Assign(keyboard_mods[LeftShift]->GetStatus());
53 cur_entry.modifier.left_alt.Assign(keyboard_mods[LeftAlt]->GetStatus());
54 cur_entry.modifier.right_alt.Assign(keyboard_mods[RightAlt]->GetStatus());
55 cur_entry.modifier.gui.Assign(0);
56 cur_entry.modifier.caps_lock.Assign(keyboard_mods[CapsLock]->GetStatus());
57 cur_entry.modifier.scroll_lock.Assign(keyboard_mods[ScrollLock]->GetStatus());
58 cur_entry.modifier.num_lock.Assign(keyboard_mods[NumLock]->GetStatus());
59 cur_entry.modifier.katakana.Assign(0);
60 cur_entry.modifier.hiragana.Assign(0);
52 } 61 }
53 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); 62 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
54} 63}
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index f3eef5936..b5b281752 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include "common/bit_field.h"
8#include "common/common_funcs.h" 9#include "common/common_funcs.h"
9#include "common/common_types.h" 10#include "common/common_types.h"
10#include "common/swap.h" 11#include "common/swap.h"
@@ -31,12 +32,28 @@ public:
31 void OnLoadInputDevices() override; 32 void OnLoadInputDevices() override;
32 33
33private: 34private:
35 struct Modifiers {
36 union {
37 u32_le raw{};
38 BitField<0, 1, u32> control;
39 BitField<1, 1, u32> shift;
40 BitField<2, 1, u32> left_alt;
41 BitField<3, 1, u32> right_alt;
42 BitField<4, 1, u32> gui;
43 BitField<8, 1, u32> caps_lock;
44 BitField<9, 1, u32> scroll_lock;
45 BitField<10, 1, u32> num_lock;
46 BitField<11, 1, u32> katakana;
47 BitField<12, 1, u32> hiragana;
48 };
49 };
50 static_assert(sizeof(Modifiers) == 0x4, "Modifiers is an invalid size");
51
34 struct KeyboardState { 52 struct KeyboardState {
35 s64_le sampling_number; 53 s64_le sampling_number;
36 s64_le sampling_number2; 54 s64_le sampling_number2;
37 55
38 s32_le modifier; 56 Modifiers modifier;
39 s32_le attribute;
40 std::array<u8, 32> key; 57 std::array<u8, 32> key;
41 }; 58 };
42 static_assert(sizeof(KeyboardState) == 0x38, "KeyboardState is an invalid size"); 59 static_assert(sizeof(KeyboardState) == 0x38, "KeyboardState is an invalid size");
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index ac40989c5..2e7457604 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -36,6 +36,7 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
36 cur_entry.sampling_number = last_entry.sampling_number + 1; 36 cur_entry.sampling_number = last_entry.sampling_number + 1;
37 cur_entry.sampling_number2 = cur_entry.sampling_number; 37 cur_entry.sampling_number2 = cur_entry.sampling_number;
38 38
39 cur_entry.attribute.raw = 0;
39 if (Settings::values.mouse_enabled) { 40 if (Settings::values.mouse_enabled) {
40 const auto [px, py, sx, sy] = mouse_device->GetStatus(); 41 const auto [px, py, sx, sy] = mouse_device->GetStatus();
41 const auto x = static_cast<s32>(px * Layout::ScreenUndocked::Width); 42 const auto x = static_cast<s32>(px * Layout::ScreenUndocked::Width);
@@ -46,10 +47,14 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
46 cur_entry.delta_y = y - last_entry.y; 47 cur_entry.delta_y = y - last_entry.y;
47 cur_entry.mouse_wheel_x = sx; 48 cur_entry.mouse_wheel_x = sx;
48 cur_entry.mouse_wheel_y = sy; 49 cur_entry.mouse_wheel_y = sy;
50 cur_entry.attribute.is_connected.Assign(1);
49 51
50 for (std::size_t i = 0; i < mouse_button_devices.size(); ++i) { 52 using namespace Settings::NativeMouseButton;
51 cur_entry.button |= (mouse_button_devices[i]->GetStatus() << i); 53 cur_entry.button.left.Assign(mouse_button_devices[Left]->GetStatus());
52 } 54 cur_entry.button.right.Assign(mouse_button_devices[Right]->GetStatus());
55 cur_entry.button.middle.Assign(mouse_button_devices[Middle]->GetStatus());
56 cur_entry.button.forward.Assign(mouse_button_devices[Forward]->GetStatus());
57 cur_entry.button.back.Assign(mouse_button_devices[Back]->GetStatus());
53 } 58 }
54 59
55 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); 60 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 357ab7107..3b432a36e 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include "common/bit_field.h"
8#include "common/common_types.h" 9#include "common/common_types.h"
9#include "common/swap.h" 10#include "common/swap.h"
10#include "core/frontend/input.h" 11#include "core/frontend/input.h"
@@ -30,6 +31,27 @@ public:
30 void OnLoadInputDevices() override; 31 void OnLoadInputDevices() override;
31 32
32private: 33private:
34 struct Buttons {
35 union {
36 u32_le raw{};
37 BitField<0, 1, u32> left;
38 BitField<1, 1, u32> right;
39 BitField<2, 1, u32> middle;
40 BitField<3, 1, u32> forward;
41 BitField<4, 1, u32> back;
42 };
43 };
44 static_assert(sizeof(Buttons) == 0x4, "Buttons is an invalid size");
45
46 struct Attributes {
47 union {
48 u32_le raw{};
49 BitField<0, 1, u32> transferable;
50 BitField<1, 1, u32> is_connected;
51 };
52 };
53 static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size");
54
33 struct MouseState { 55 struct MouseState {
34 s64_le sampling_number; 56 s64_le sampling_number;
35 s64_le sampling_number2; 57 s64_le sampling_number2;
@@ -39,8 +61,8 @@ private:
39 s32_le delta_y; 61 s32_le delta_y;
40 s32_le mouse_wheel_x; 62 s32_le mouse_wheel_x;
41 s32_le mouse_wheel_y; 63 s32_le mouse_wheel_y;
42 s32_le button; 64 Buttons button;
43 s32_le attribute; 65 Attributes attribute;
44 }; 66 };
45 static_assert(sizeof(MouseState) == 0x30, "MouseState is an invalid size"); 67 static_assert(sizeof(MouseState) == 0x30, "MouseState is an invalid size");
46 68
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 0c227b135..dbf198345 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -12,9 +12,10 @@
12#include "core/core.h" 12#include "core/core.h"
13#include "core/core_timing.h" 13#include "core/core_timing.h"
14#include "core/frontend/input.h" 14#include "core/frontend/input.h"
15#include "core/hle/kernel/k_event.h"
16#include "core/hle/kernel/k_readable_event.h"
17#include "core/hle/kernel/k_writable_event.h"
15#include "core/hle/kernel/kernel.h" 18#include "core/hle/kernel/kernel.h"
16#include "core/hle/kernel/readable_event.h"
17#include "core/hle/kernel/writable_event.h"
18#include "core/hle/service/hid/controllers/npad.h" 19#include "core/hle/service/hid/controllers/npad.h"
19#include "core/settings.h" 20#include "core/settings.h"
20 21
@@ -153,79 +154,86 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
153 const auto controller_type = connected_controllers[controller_idx].type; 154 const auto controller_type = connected_controllers[controller_idx].type;
154 auto& controller = shared_memory_entries[controller_idx]; 155 auto& controller = shared_memory_entries[controller_idx];
155 if (controller_type == NPadControllerType::None) { 156 if (controller_type == NPadControllerType::None) {
156 styleset_changed_events[controller_idx].writable->Signal(); 157 styleset_changed_events[controller_idx]->GetWritableEvent()->Signal();
157 return; 158 return;
158 } 159 }
159 controller.joy_styles.raw = 0; // Zero out 160 controller.style_set.raw = 0; // Zero out
160 controller.device_type.raw = 0; 161 controller.device_type.raw = 0;
161 controller.properties.raw = 0; 162 controller.system_properties.raw = 0;
162 switch (controller_type) { 163 switch (controller_type) {
163 case NPadControllerType::None: 164 case NPadControllerType::None:
164 UNREACHABLE(); 165 UNREACHABLE();
165 break; 166 break;
166 case NPadControllerType::ProController: 167 case NPadControllerType::ProController:
167 controller.joy_styles.pro_controller.Assign(1); 168 controller.style_set.fullkey.Assign(1);
168 controller.device_type.pro_controller.Assign(1); 169 controller.device_type.fullkey.Assign(1);
169 controller.properties.is_vertical.Assign(1); 170 controller.system_properties.is_vertical.Assign(1);
170 controller.properties.use_plus.Assign(1); 171 controller.system_properties.use_plus.Assign(1);
171 controller.properties.use_minus.Assign(1); 172 controller.system_properties.use_minus.Assign(1);
172 controller.pad_assignment = NpadAssignments::Single; 173 controller.assignment_mode = NpadAssignments::Single;
174 controller.footer_type = AppletFooterUiType::SwitchProController;
173 break; 175 break;
174 case NPadControllerType::Handheld: 176 case NPadControllerType::Handheld:
175 controller.joy_styles.handheld.Assign(1); 177 controller.style_set.handheld.Assign(1);
176 controller.device_type.handheld.Assign(1); 178 controller.device_type.handheld_left.Assign(1);
177 controller.properties.is_vertical.Assign(1); 179 controller.device_type.handheld_right.Assign(1);
178 controller.properties.use_plus.Assign(1); 180 controller.system_properties.is_vertical.Assign(1);
179 controller.properties.use_minus.Assign(1); 181 controller.system_properties.use_plus.Assign(1);
180 controller.pad_assignment = NpadAssignments::Dual; 182 controller.system_properties.use_minus.Assign(1);
183 controller.assignment_mode = NpadAssignments::Dual;
184 controller.footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
181 break; 185 break;
182 case NPadControllerType::JoyDual: 186 case NPadControllerType::JoyDual:
183 controller.joy_styles.joycon_dual.Assign(1); 187 controller.style_set.joycon_dual.Assign(1);
184 controller.device_type.joycon_left.Assign(1); 188 controller.device_type.joycon_left.Assign(1);
185 controller.device_type.joycon_right.Assign(1); 189 controller.device_type.joycon_right.Assign(1);
186 controller.properties.is_vertical.Assign(1); 190 controller.system_properties.is_vertical.Assign(1);
187 controller.properties.use_plus.Assign(1); 191 controller.system_properties.use_plus.Assign(1);
188 controller.properties.use_minus.Assign(1); 192 controller.system_properties.use_minus.Assign(1);
189 controller.pad_assignment = NpadAssignments::Dual; 193 controller.assignment_mode = NpadAssignments::Dual;
194 controller.footer_type = AppletFooterUiType::JoyDual;
190 break; 195 break;
191 case NPadControllerType::JoyLeft: 196 case NPadControllerType::JoyLeft:
192 controller.joy_styles.joycon_left.Assign(1); 197 controller.style_set.joycon_left.Assign(1);
193 controller.device_type.joycon_left.Assign(1); 198 controller.device_type.joycon_left.Assign(1);
194 controller.properties.is_horizontal.Assign(1); 199 controller.system_properties.is_horizontal.Assign(1);
195 controller.properties.use_minus.Assign(1); 200 controller.system_properties.use_minus.Assign(1);
196 controller.pad_assignment = NpadAssignments::Single; 201 controller.assignment_mode = NpadAssignments::Single;
202 controller.footer_type = AppletFooterUiType::JoyLeftHorizontal;
197 break; 203 break;
198 case NPadControllerType::JoyRight: 204 case NPadControllerType::JoyRight:
199 controller.joy_styles.joycon_right.Assign(1); 205 controller.style_set.joycon_right.Assign(1);
200 controller.device_type.joycon_right.Assign(1); 206 controller.device_type.joycon_right.Assign(1);
201 controller.properties.is_horizontal.Assign(1); 207 controller.system_properties.is_horizontal.Assign(1);
202 controller.properties.use_plus.Assign(1); 208 controller.system_properties.use_plus.Assign(1);
203 controller.pad_assignment = NpadAssignments::Single; 209 controller.assignment_mode = NpadAssignments::Single;
210 controller.footer_type = AppletFooterUiType::JoyRightHorizontal;
204 break; 211 break;
205 case NPadControllerType::Pokeball: 212 case NPadControllerType::Pokeball:
206 controller.joy_styles.pokeball.Assign(1); 213 controller.style_set.palma.Assign(1);
207 controller.device_type.pokeball.Assign(1); 214 controller.device_type.palma.Assign(1);
208 controller.pad_assignment = NpadAssignments::Single; 215 controller.assignment_mode = NpadAssignments::Single;
209 break; 216 break;
210 } 217 }
211 218
212 controller.single_color_error = ColorReadError::ReadOk; 219 controller.fullkey_color.attribute = ColorAttributes::Ok;
213 controller.single_color.body_color = 0; 220 controller.fullkey_color.fullkey.body = 0;
214 controller.single_color.button_color = 0; 221 controller.fullkey_color.fullkey.button = 0;
215 222
216 controller.dual_color_error = ColorReadError::ReadOk; 223 controller.joycon_color.attribute = ColorAttributes::Ok;
217 controller.left_color.body_color = 224 controller.joycon_color.left.body =
218 Settings::values.players.GetValue()[controller_idx].body_color_left; 225 Settings::values.players.GetValue()[controller_idx].body_color_left;
219 controller.left_color.button_color = 226 controller.joycon_color.left.button =
220 Settings::values.players.GetValue()[controller_idx].button_color_left; 227 Settings::values.players.GetValue()[controller_idx].button_color_left;
221 controller.right_color.body_color = 228 controller.joycon_color.right.body =
222 Settings::values.players.GetValue()[controller_idx].body_color_right; 229 Settings::values.players.GetValue()[controller_idx].body_color_right;
223 controller.right_color.button_color = 230 controller.joycon_color.right.button =
224 Settings::values.players.GetValue()[controller_idx].button_color_right; 231 Settings::values.players.GetValue()[controller_idx].button_color_right;
225 232
226 controller.battery_level[0] = BATTERY_FULL; 233 // TODO: Investigate when we should report all batery types
227 controller.battery_level[1] = BATTERY_FULL; 234 controller.battery_level_dual = BATTERY_FULL;
228 controller.battery_level[2] = BATTERY_FULL; 235 controller.battery_level_left = BATTERY_FULL;
236 controller.battery_level_right = BATTERY_FULL;
229 237
230 SignalStyleSetChangedEvent(IndexToNPad(controller_idx)); 238 SignalStyleSetChangedEvent(IndexToNPad(controller_idx));
231} 239}
@@ -233,8 +241,9 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
233void Controller_NPad::OnInit() { 241void Controller_NPad::OnInit() {
234 auto& kernel = system.Kernel(); 242 auto& kernel = system.Kernel();
235 for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) { 243 for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) {
236 styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair( 244 styleset_changed_events[i] =
237 kernel, fmt::format("npad:NpadStyleSetChanged_{}", i)); 245 Kernel::KEvent::Create(kernel, fmt::format("npad:NpadStyleSetChanged_{}", i));
246 styleset_changed_events[i]->Initialize();
238 } 247 }
239 248
240 if (!IsControllerActivated()) { 249 if (!IsControllerActivated()) {
@@ -249,8 +258,8 @@ void Controller_NPad::OnInit() {
249 style.joycon_left.Assign(1); 258 style.joycon_left.Assign(1);
250 style.joycon_right.Assign(1); 259 style.joycon_right.Assign(1);
251 style.joycon_dual.Assign(1); 260 style.joycon_dual.Assign(1);
252 style.pro_controller.Assign(1); 261 style.fullkey.Assign(1);
253 style.pokeball.Assign(1); 262 style.palma.Assign(1);
254 } 263 }
255 264
256 std::transform(Settings::values.players.GetValue().begin(), 265 std::transform(Settings::values.players.GetValue().begin(),
@@ -404,13 +413,10 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
404 } 413 }
405 for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) { 414 for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) {
406 auto& npad = shared_memory_entries[i]; 415 auto& npad = shared_memory_entries[i];
407 const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, 416 const std::array<NPadGeneric*, 7> controller_npads{
408 &npad.handheld_states, 417 &npad.fullkey_states, &npad.handheld_states, &npad.joy_dual_states,
409 &npad.dual_states, 418 &npad.joy_left_states, &npad.joy_right_states, &npad.palma_states,
410 &npad.left_joy_states, 419 &npad.system_ext_states};
411 &npad.right_joy_states,
412 &npad.pokeball_states,
413 &npad.libnx};
414 420
415 for (auto* main_controller : controller_npads) { 421 for (auto* main_controller : controller_npads) {
416 main_controller->common.entry_count = 16; 422 main_controller->common.entry_count = 16;
@@ -440,19 +446,19 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
440 auto& pad_state = npad_pad_states[npad_index]; 446 auto& pad_state = npad_pad_states[npad_index];
441 447
442 auto& main_controller = 448 auto& main_controller =
443 npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index]; 449 npad.fullkey_states.npad[npad.fullkey_states.common.last_entry_index];
444 auto& handheld_entry = 450 auto& handheld_entry =
445 npad.handheld_states.npad[npad.handheld_states.common.last_entry_index]; 451 npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
446 auto& dual_entry = npad.dual_states.npad[npad.dual_states.common.last_entry_index]; 452 auto& dual_entry = npad.joy_dual_states.npad[npad.joy_dual_states.common.last_entry_index];
447 auto& left_entry = npad.left_joy_states.npad[npad.left_joy_states.common.last_entry_index]; 453 auto& left_entry = npad.joy_left_states.npad[npad.joy_left_states.common.last_entry_index];
448 auto& right_entry = 454 auto& right_entry =
449 npad.right_joy_states.npad[npad.right_joy_states.common.last_entry_index]; 455 npad.joy_right_states.npad[npad.joy_right_states.common.last_entry_index];
450 auto& pokeball_entry = 456 auto& pokeball_entry = npad.palma_states.npad[npad.palma_states.common.last_entry_index];
451 npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index]; 457 auto& libnx_entry =
452 auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index]; 458 npad.system_ext_states.npad[npad.system_ext_states.common.last_entry_index];
453 459
454 libnx_entry.connection_status.raw = 0; 460 libnx_entry.connection_status.raw = 0;
455 libnx_entry.connection_status.IsConnected.Assign(1); 461 libnx_entry.connection_status.is_connected.Assign(1);
456 462
457 switch (controller_type) { 463 switch (controller_type) {
458 case NPadControllerType::None: 464 case NPadControllerType::None:
@@ -460,67 +466,67 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
460 break; 466 break;
461 case NPadControllerType::ProController: 467 case NPadControllerType::ProController:
462 main_controller.connection_status.raw = 0; 468 main_controller.connection_status.raw = 0;
463 main_controller.connection_status.IsConnected.Assign(1); 469 main_controller.connection_status.is_connected.Assign(1);
464 main_controller.connection_status.IsWired.Assign(1); 470 main_controller.connection_status.is_wired.Assign(1);
465 main_controller.pad.pad_states.raw = pad_state.pad_states.raw; 471 main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
466 main_controller.pad.l_stick = pad_state.l_stick; 472 main_controller.pad.l_stick = pad_state.l_stick;
467 main_controller.pad.r_stick = pad_state.r_stick; 473 main_controller.pad.r_stick = pad_state.r_stick;
468 474
469 libnx_entry.connection_status.IsWired.Assign(1); 475 libnx_entry.connection_status.is_wired.Assign(1);
470 break; 476 break;
471 case NPadControllerType::Handheld: 477 case NPadControllerType::Handheld:
472 handheld_entry.connection_status.raw = 0; 478 handheld_entry.connection_status.raw = 0;
473 handheld_entry.connection_status.IsConnected.Assign(1); 479 handheld_entry.connection_status.is_connected.Assign(1);
474 handheld_entry.connection_status.IsWired.Assign(1); 480 handheld_entry.connection_status.is_wired.Assign(1);
475 handheld_entry.connection_status.IsLeftJoyConnected.Assign(1); 481 handheld_entry.connection_status.is_left_connected.Assign(1);
476 handheld_entry.connection_status.IsRightJoyConnected.Assign(1); 482 handheld_entry.connection_status.is_right_connected.Assign(1);
477 handheld_entry.connection_status.IsLeftJoyWired.Assign(1); 483 handheld_entry.connection_status.is_left_wired.Assign(1);
478 handheld_entry.connection_status.IsRightJoyWired.Assign(1); 484 handheld_entry.connection_status.is_right_wired.Assign(1);
479 handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; 485 handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
480 handheld_entry.pad.l_stick = pad_state.l_stick; 486 handheld_entry.pad.l_stick = pad_state.l_stick;
481 handheld_entry.pad.r_stick = pad_state.r_stick; 487 handheld_entry.pad.r_stick = pad_state.r_stick;
482 488
483 libnx_entry.connection_status.IsWired.Assign(1); 489 libnx_entry.connection_status.is_wired.Assign(1);
484 libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); 490 libnx_entry.connection_status.is_left_connected.Assign(1);
485 libnx_entry.connection_status.IsRightJoyConnected.Assign(1); 491 libnx_entry.connection_status.is_right_connected.Assign(1);
486 libnx_entry.connection_status.IsLeftJoyWired.Assign(1); 492 libnx_entry.connection_status.is_left_wired.Assign(1);
487 libnx_entry.connection_status.IsRightJoyWired.Assign(1); 493 libnx_entry.connection_status.is_right_wired.Assign(1);
488 break; 494 break;
489 case NPadControllerType::JoyDual: 495 case NPadControllerType::JoyDual:
490 dual_entry.connection_status.raw = 0; 496 dual_entry.connection_status.raw = 0;
491 dual_entry.connection_status.IsConnected.Assign(1); 497 dual_entry.connection_status.is_connected.Assign(1);
492 dual_entry.connection_status.IsLeftJoyConnected.Assign(1); 498 dual_entry.connection_status.is_left_connected.Assign(1);
493 dual_entry.connection_status.IsRightJoyConnected.Assign(1); 499 dual_entry.connection_status.is_right_connected.Assign(1);
494 dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; 500 dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
495 dual_entry.pad.l_stick = pad_state.l_stick; 501 dual_entry.pad.l_stick = pad_state.l_stick;
496 dual_entry.pad.r_stick = pad_state.r_stick; 502 dual_entry.pad.r_stick = pad_state.r_stick;
497 503
498 libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); 504 libnx_entry.connection_status.is_left_connected.Assign(1);
499 libnx_entry.connection_status.IsRightJoyConnected.Assign(1); 505 libnx_entry.connection_status.is_right_connected.Assign(1);
500 break; 506 break;
501 case NPadControllerType::JoyLeft: 507 case NPadControllerType::JoyLeft:
502 left_entry.connection_status.raw = 0; 508 left_entry.connection_status.raw = 0;
503 left_entry.connection_status.IsConnected.Assign(1); 509 left_entry.connection_status.is_connected.Assign(1);
504 left_entry.connection_status.IsLeftJoyConnected.Assign(1); 510 left_entry.connection_status.is_left_connected.Assign(1);
505 left_entry.pad.pad_states.raw = pad_state.pad_states.raw; 511 left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
506 left_entry.pad.l_stick = pad_state.l_stick; 512 left_entry.pad.l_stick = pad_state.l_stick;
507 left_entry.pad.r_stick = pad_state.r_stick; 513 left_entry.pad.r_stick = pad_state.r_stick;
508 514
509 libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); 515 libnx_entry.connection_status.is_left_connected.Assign(1);
510 break; 516 break;
511 case NPadControllerType::JoyRight: 517 case NPadControllerType::JoyRight:
512 right_entry.connection_status.raw = 0; 518 right_entry.connection_status.raw = 0;
513 right_entry.connection_status.IsConnected.Assign(1); 519 right_entry.connection_status.is_connected.Assign(1);
514 right_entry.connection_status.IsRightJoyConnected.Assign(1); 520 right_entry.connection_status.is_right_connected.Assign(1);
515 right_entry.pad.pad_states.raw = pad_state.pad_states.raw; 521 right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
516 right_entry.pad.l_stick = pad_state.l_stick; 522 right_entry.pad.l_stick = pad_state.l_stick;
517 right_entry.pad.r_stick = pad_state.r_stick; 523 right_entry.pad.r_stick = pad_state.r_stick;
518 524
519 libnx_entry.connection_status.IsRightJoyConnected.Assign(1); 525 libnx_entry.connection_status.is_right_connected.Assign(1);
520 break; 526 break;
521 case NPadControllerType::Pokeball: 527 case NPadControllerType::Pokeball:
522 pokeball_entry.connection_status.raw = 0; 528 pokeball_entry.connection_status.raw = 0;
523 pokeball_entry.connection_status.IsConnected.Assign(1); 529 pokeball_entry.connection_status.is_connected.Assign(1);
524 pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; 530 pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
525 pokeball_entry.pad.l_stick = pad_state.l_stick; 531 pokeball_entry.pad.l_stick = pad_state.l_stick;
526 pokeball_entry.pad.r_stick = pad_state.r_stick; 532 pokeball_entry.pad.r_stick = pad_state.r_stick;
@@ -554,7 +560,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
554 } 560 }
555 561
556 const std::array<SixAxisGeneric*, 6> controller_sixaxes{ 562 const std::array<SixAxisGeneric*, 6> controller_sixaxes{
557 &npad.sixaxis_full, &npad.sixaxis_handheld, &npad.sixaxis_dual_left, 563 &npad.sixaxis_fullkey, &npad.sixaxis_handheld, &npad.sixaxis_dual_left,
558 &npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right, 564 &npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right,
559 }; 565 };
560 566
@@ -592,7 +598,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
592 } 598 }
593 599
594 auto& full_sixaxis_entry = 600 auto& full_sixaxis_entry =
595 npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index]; 601 npad.sixaxis_fullkey.sixaxis[npad.sixaxis_fullkey.common.last_entry_index];
596 auto& handheld_sixaxis_entry = 602 auto& handheld_sixaxis_entry =
597 npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index]; 603 npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index];
598 auto& dual_left_sixaxis_entry = 604 auto& dual_left_sixaxis_entry =
@@ -609,7 +615,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
609 UNREACHABLE(); 615 UNREACHABLE();
610 break; 616 break;
611 case NPadControllerType::ProController: 617 case NPadControllerType::ProController:
618 full_sixaxis_entry.attribute.raw = 0;
612 if (sixaxis_sensors_enabled && motions[i][0]) { 619 if (sixaxis_sensors_enabled && motions[i][0]) {
620 full_sixaxis_entry.attribute.is_connected.Assign(1);
613 full_sixaxis_entry.accel = motion_devices[0].accel; 621 full_sixaxis_entry.accel = motion_devices[0].accel;
614 full_sixaxis_entry.gyro = motion_devices[0].gyro; 622 full_sixaxis_entry.gyro = motion_devices[0].gyro;
615 full_sixaxis_entry.rotation = motion_devices[0].rotation; 623 full_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -617,7 +625,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
617 } 625 }
618 break; 626 break;
619 case NPadControllerType::Handheld: 627 case NPadControllerType::Handheld:
628 handheld_sixaxis_entry.attribute.raw = 0;
620 if (sixaxis_sensors_enabled && motions[i][0]) { 629 if (sixaxis_sensors_enabled && motions[i][0]) {
630 handheld_sixaxis_entry.attribute.is_connected.Assign(1);
621 handheld_sixaxis_entry.accel = motion_devices[0].accel; 631 handheld_sixaxis_entry.accel = motion_devices[0].accel;
622 handheld_sixaxis_entry.gyro = motion_devices[0].gyro; 632 handheld_sixaxis_entry.gyro = motion_devices[0].gyro;
623 handheld_sixaxis_entry.rotation = motion_devices[0].rotation; 633 handheld_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -625,8 +635,11 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
625 } 635 }
626 break; 636 break;
627 case NPadControllerType::JoyDual: 637 case NPadControllerType::JoyDual:
638 dual_left_sixaxis_entry.attribute.raw = 0;
639 dual_right_sixaxis_entry.attribute.raw = 0;
628 if (sixaxis_sensors_enabled && motions[i][0]) { 640 if (sixaxis_sensors_enabled && motions[i][0]) {
629 // Set motion for the left joycon 641 // Set motion for the left joycon
642 dual_left_sixaxis_entry.attribute.is_connected.Assign(1);
630 dual_left_sixaxis_entry.accel = motion_devices[0].accel; 643 dual_left_sixaxis_entry.accel = motion_devices[0].accel;
631 dual_left_sixaxis_entry.gyro = motion_devices[0].gyro; 644 dual_left_sixaxis_entry.gyro = motion_devices[0].gyro;
632 dual_left_sixaxis_entry.rotation = motion_devices[0].rotation; 645 dual_left_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -634,6 +647,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
634 } 647 }
635 if (sixaxis_sensors_enabled && motions[i][1]) { 648 if (sixaxis_sensors_enabled && motions[i][1]) {
636 // Set motion for the right joycon 649 // Set motion for the right joycon
650 dual_right_sixaxis_entry.attribute.is_connected.Assign(1);
637 dual_right_sixaxis_entry.accel = motion_devices[1].accel; 651 dual_right_sixaxis_entry.accel = motion_devices[1].accel;
638 dual_right_sixaxis_entry.gyro = motion_devices[1].gyro; 652 dual_right_sixaxis_entry.gyro = motion_devices[1].gyro;
639 dual_right_sixaxis_entry.rotation = motion_devices[1].rotation; 653 dual_right_sixaxis_entry.rotation = motion_devices[1].rotation;
@@ -641,7 +655,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
641 } 655 }
642 break; 656 break;
643 case NPadControllerType::JoyLeft: 657 case NPadControllerType::JoyLeft:
658 left_sixaxis_entry.attribute.raw = 0;
644 if (sixaxis_sensors_enabled && motions[i][0]) { 659 if (sixaxis_sensors_enabled && motions[i][0]) {
660 left_sixaxis_entry.attribute.is_connected.Assign(1);
645 left_sixaxis_entry.accel = motion_devices[0].accel; 661 left_sixaxis_entry.accel = motion_devices[0].accel;
646 left_sixaxis_entry.gyro = motion_devices[0].gyro; 662 left_sixaxis_entry.gyro = motion_devices[0].gyro;
647 left_sixaxis_entry.rotation = motion_devices[0].rotation; 663 left_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -649,7 +665,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
649 } 665 }
650 break; 666 break;
651 case NPadControllerType::JoyRight: 667 case NPadControllerType::JoyRight:
668 right_sixaxis_entry.attribute.raw = 0;
652 if (sixaxis_sensors_enabled && motions[i][1]) { 669 if (sixaxis_sensors_enabled && motions[i][1]) {
670 right_sixaxis_entry.attribute.is_connected.Assign(1);
653 right_sixaxis_entry.accel = motion_devices[1].accel; 671 right_sixaxis_entry.accel = motion_devices[1].accel;
654 right_sixaxis_entry.gyro = motion_devices[1].gyro; 672 right_sixaxis_entry.gyro = motion_devices[1].gyro;
655 right_sixaxis_entry.rotation = motion_devices[1].rotation; 673 right_sixaxis_entry.rotation = motion_devices[1].rotation;
@@ -715,8 +733,8 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode
715void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) { 733void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) {
716 const std::size_t npad_index = NPadIdToIndex(npad_id); 734 const std::size_t npad_index = NPadIdToIndex(npad_id);
717 ASSERT(npad_index < shared_memory_entries.size()); 735 ASSERT(npad_index < shared_memory_entries.size());
718 if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) { 736 if (shared_memory_entries[npad_index].assignment_mode != assignment_mode) {
719 shared_memory_entries[npad_index].pad_assignment = assignment_mode; 737 shared_memory_entries[npad_index].assignment_mode = assignment_mode;
720 } 738 }
721} 739}
722 740
@@ -872,13 +890,14 @@ bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_dev
872 return vibration_devices_mounted[npad_index][device_index]; 890 return vibration_devices_mounted[npad_index][device_index];
873} 891}
874 892
875std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { 893std::shared_ptr<Kernel::KReadableEvent> Controller_NPad::GetStyleSetChangedEvent(
894 u32 npad_id) const {
876 const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; 895 const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)];
877 return styleset_event.readable; 896 return styleset_event->GetReadableEvent();
878} 897}
879 898
880void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const { 899void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const {
881 styleset_changed_events[NPadIdToIndex(npad_id)].writable->Signal(); 900 styleset_changed_events[NPadIdToIndex(npad_id)]->GetWritableEvent()->Signal();
882} 901}
883 902
884void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { 903void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) {
@@ -923,9 +942,17 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
923 connected_controllers[npad_index].is_connected = false; 942 connected_controllers[npad_index].is_connected = false;
924 943
925 auto& controller = shared_memory_entries[npad_index]; 944 auto& controller = shared_memory_entries[npad_index];
926 controller.joy_styles.raw = 0; // Zero out 945 controller.style_set.raw = 0; // Zero out
927 controller.device_type.raw = 0; 946 controller.device_type.raw = 0;
928 controller.properties.raw = 0; 947 controller.system_properties.raw = 0;
948 controller.button_properties.raw = 0;
949 controller.battery_level_dual = 0;
950 controller.battery_level_left = 0;
951 controller.battery_level_right = 0;
952 controller.fullkey_color = {};
953 controller.joycon_color = {};
954 controller.assignment_mode = NpadAssignments::Dual;
955 controller.footer_type = AppletFooterUiType::None;
929 956
930 SignalStyleSetChangedEvent(IndexToNPad(npad_index)); 957 SignalStyleSetChangedEvent(IndexToNPad(npad_index));
931} 958}
@@ -1101,7 +1128,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
1101 [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) { 1128 [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
1102 switch (controller) { 1129 switch (controller) {
1103 case NPadControllerType::ProController: 1130 case NPadControllerType::ProController:
1104 return style.pro_controller; 1131 return style.fullkey;
1105 case NPadControllerType::JoyDual: 1132 case NPadControllerType::JoyDual:
1106 return style.joycon_dual; 1133 return style.joycon_dual;
1107 case NPadControllerType::JoyLeft: 1134 case NPadControllerType::JoyLeft:
@@ -1109,7 +1136,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
1109 case NPadControllerType::JoyRight: 1136 case NPadControllerType::JoyRight:
1110 return style.joycon_right; 1137 return style.joycon_right;
1111 case NPadControllerType::Pokeball: 1138 case NPadControllerType::Pokeball:
1112 return style.pokeball; 1139 return style.palma;
1113 default: 1140 default:
1114 return false; 1141 return false;
1115 } 1142 }
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 2e13922b9..48bab988c 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -10,10 +10,14 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "core/frontend/input.h" 11#include "core/frontend/input.h"
12#include "core/hle/kernel/object.h" 12#include "core/hle/kernel/object.h"
13#include "core/hle/kernel/writable_event.h"
14#include "core/hle/service/hid/controllers/controller_base.h" 13#include "core/hle/service/hid/controllers/controller_base.h"
15#include "core/settings.h" 14#include "core/settings.h"
16 15
16namespace Kernel {
17class KEvent;
18class KReadableEvent;
19} // namespace Kernel
20
17namespace Service::HID { 21namespace Service::HID {
18 22
19constexpr u32 NPAD_HANDHELD = 32; 23constexpr u32 NPAD_HANDHELD = 32;
@@ -90,10 +94,10 @@ public:
90 }; 94 };
91 95
92 enum class NpadCommunicationMode : u64 { 96 enum class NpadCommunicationMode : u64 {
93 Unknown0 = 0, 97 Mode_5ms = 0,
94 Unknown1 = 1, 98 Mode_10ms = 1,
95 Unknown2 = 2, 99 Mode_15ms = 2,
96 Unknown3 = 3, 100 Default = 3,
97 }; 101 };
98 102
99 struct DeviceHandle { 103 struct DeviceHandle {
@@ -108,13 +112,18 @@ public:
108 union { 112 union {
109 u32_le raw{}; 113 u32_le raw{};
110 114
111 BitField<0, 1, u32> pro_controller; 115 BitField<0, 1, u32> fullkey;
112 BitField<1, 1, u32> handheld; 116 BitField<1, 1, u32> handheld;
113 BitField<2, 1, u32> joycon_dual; 117 BitField<2, 1, u32> joycon_dual;
114 BitField<3, 1, u32> joycon_left; 118 BitField<3, 1, u32> joycon_left;
115 BitField<4, 1, u32> joycon_right; 119 BitField<4, 1, u32> joycon_right;
116 120 BitField<5, 1, u32> gamecube;
117 BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible 121 BitField<6, 1, u32> palma;
122 BitField<7, 1, u32> lark;
123 BitField<8, 1, u32> handheld_lark;
124 BitField<9, 1, u32> lucia;
125 BitField<29, 1, u32> system_ext;
126 BitField<30, 1, u32> system;
118 }; 127 };
119 }; 128 };
120 static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); 129 static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
@@ -187,7 +196,7 @@ public:
187 196
188 bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const; 197 bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const;
189 198
190 std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; 199 std::shared_ptr<Kernel::KReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const;
191 void SignalStyleSetChangedEvent(u32 npad_id) const; 200 void SignalStyleSetChangedEvent(u32 npad_id) const;
192 201
193 // Adds a new controller at an index. 202 // Adds a new controller at an index.
@@ -238,12 +247,32 @@ private:
238 }; 247 };
239 static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); 248 static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
240 249
250 enum class ColorAttributes : u32_le {
251 Ok = 0,
252 ReadError = 1,
253 NoController = 2,
254 };
255 static_assert(sizeof(ColorAttributes) == 4, "ColorAttributes is an invalid size");
256
241 struct ControllerColor { 257 struct ControllerColor {
242 u32_le body_color; 258 u32_le body;
243 u32_le button_color; 259 u32_le button;
244 }; 260 };
245 static_assert(sizeof(ControllerColor) == 8, "ControllerColor is an invalid size"); 261 static_assert(sizeof(ControllerColor) == 8, "ControllerColor is an invalid size");
246 262
263 struct FullKeyColor {
264 ColorAttributes attribute;
265 ControllerColor fullkey;
266 };
267 static_assert(sizeof(FullKeyColor) == 0xC, "FullKeyColor is an invalid size");
268
269 struct JoyconColor {
270 ColorAttributes attribute;
271 ControllerColor left;
272 ControllerColor right;
273 };
274 static_assert(sizeof(JoyconColor) == 0x14, "JoyconColor is an invalid size");
275
247 struct ControllerPadState { 276 struct ControllerPadState {
248 union { 277 union {
249 u64_le raw{}; 278 u64_le raw{};
@@ -285,6 +314,9 @@ private:
285 314
286 BitField<26, 1, u64> right_sl; 315 BitField<26, 1, u64> right_sl;
287 BitField<27, 1, u64> right_sr; 316 BitField<27, 1, u64> right_sr;
317
318 BitField<28, 1, u64> palma;
319 BitField<30, 1, u64> handheld_left_b;
288 }; 320 };
289 }; 321 };
290 static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size"); 322 static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size");
@@ -298,12 +330,12 @@ private:
298 struct ConnectionState { 330 struct ConnectionState {
299 union { 331 union {
300 u32_le raw{}; 332 u32_le raw{};
301 BitField<0, 1, u32> IsConnected; 333 BitField<0, 1, u32> is_connected;
302 BitField<1, 1, u32> IsWired; 334 BitField<1, 1, u32> is_wired;
303 BitField<2, 1, u32> IsLeftJoyConnected; 335 BitField<2, 1, u32> is_left_connected;
304 BitField<3, 1, u32> IsLeftJoyWired; 336 BitField<3, 1, u32> is_left_wired;
305 BitField<4, 1, u32> IsRightJoyConnected; 337 BitField<4, 1, u32> is_right_connected;
306 BitField<5, 1, u32> IsRightJoyWired; 338 BitField<5, 1, u32> is_right_wired;
307 }; 339 };
308 }; 340 };
309 static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size"); 341 static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size");
@@ -329,6 +361,15 @@ private:
329 }; 361 };
330 static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size"); 362 static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size");
331 363
364 struct SixAxisAttributes {
365 union {
366 u32_le raw{};
367 BitField<0, 1, u32> is_connected;
368 BitField<1, 1, u32> is_interpolated;
369 };
370 };
371 static_assert(sizeof(SixAxisAttributes) == 4, "SixAxisAttributes is an invalid size");
372
332 struct SixAxisStates { 373 struct SixAxisStates {
333 s64_le timestamp{}; 374 s64_le timestamp{};
334 INSERT_PADDING_WORDS(2); 375 INSERT_PADDING_WORDS(2);
@@ -337,7 +378,8 @@ private:
337 Common::Vec3f gyro{}; 378 Common::Vec3f gyro{};
338 Common::Vec3f rotation{}; 379 Common::Vec3f rotation{};
339 std::array<Common::Vec3f, 3> orientation{}; 380 std::array<Common::Vec3f, 3> orientation{};
340 s64_le always_one{1}; 381 SixAxisAttributes attribute;
382 INSERT_PADDING_BYTES(4); // Reserved
341 }; 383 };
342 static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size"); 384 static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size");
343 385
@@ -347,32 +389,54 @@ private:
347 }; 389 };
348 static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size"); 390 static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size");
349 391
350 enum class ColorReadError : u32_le { 392 struct NPadSystemProperties {
351 ReadOk = 0,
352 ColorDoesntExist = 1,
353 NoController = 2,
354 };
355
356 struct NPadProperties {
357 union { 393 union {
358 s64_le raw{}; 394 s64_le raw{};
395 BitField<0, 1, s64> is_charging_joy_dual;
396 BitField<1, 1, s64> is_charging_joy_left;
397 BitField<2, 1, s64> is_charging_joy_right;
398 BitField<3, 1, s64> is_powered_joy_dual;
399 BitField<4, 1, s64> is_powered_joy_left;
400 BitField<5, 1, s64> is_powered_joy_right;
401 BitField<9, 1, s64> is_system_unsupported_button;
402 BitField<10, 1, s64> is_system_ext_unsupported_button;
359 BitField<11, 1, s64> is_vertical; 403 BitField<11, 1, s64> is_vertical;
360 BitField<12, 1, s64> is_horizontal; 404 BitField<12, 1, s64> is_horizontal;
361 BitField<13, 1, s64> use_plus; 405 BitField<13, 1, s64> use_plus;
362 BitField<14, 1, s64> use_minus; 406 BitField<14, 1, s64> use_minus;
407 BitField<15, 1, s64> use_directional_buttons;
408 };
409 };
410 static_assert(sizeof(NPadSystemProperties) == 0x8, "NPadSystemProperties is an invalid size");
411
412 struct NPadButtonProperties {
413 union {
414 s32_le raw{};
415 BitField<0, 1, s32> is_home_button_protection_enabled;
363 }; 416 };
364 }; 417 };
418 static_assert(sizeof(NPadButtonProperties) == 0x4, "NPadButtonProperties is an invalid size");
365 419
366 struct NPadDevice { 420 struct NPadDevice {
367 union { 421 union {
368 u32_le raw{}; 422 u32_le raw{};
369 BitField<0, 1, s32> pro_controller; 423 BitField<0, 1, s32> fullkey;
370 BitField<1, 1, s32> handheld; 424 BitField<1, 1, s32> debug_pad;
371 BitField<2, 1, s32> handheld_left; 425 BitField<2, 1, s32> handheld_left;
372 BitField<3, 1, s32> handheld_right; 426 BitField<3, 1, s32> handheld_right;
373 BitField<4, 1, s32> joycon_left; 427 BitField<4, 1, s32> joycon_left;
374 BitField<5, 1, s32> joycon_right; 428 BitField<5, 1, s32> joycon_right;
375 BitField<6, 1, s32> pokeball; 429 BitField<6, 1, s32> palma;
430 BitField<7, 1, s32> lark_hvc_left;
431 BitField<8, 1, s32> lark_hvc_right;
432 BitField<9, 1, s32> lark_nes_left;
433 BitField<10, 1, s32> lark_nes_right;
434 BitField<11, 1, s32> handheld_lark_hvc_left;
435 BitField<12, 1, s32> handheld_lark_hvc_right;
436 BitField<13, 1, s32> handheld_lark_nes_left;
437 BitField<14, 1, s32> handheld_lark_nes_right;
438 BitField<15, 1, s32> lucia;
439 BitField<31, 1, s32> system;
376 }; 440 };
377 }; 441 };
378 442
@@ -383,37 +447,69 @@ private:
383 std::array<Common::Vec3f, 3> orientation; 447 std::array<Common::Vec3f, 3> orientation;
384 }; 448 };
385 449
386 struct NPadEntry { 450 struct NfcXcdHandle {
387 NpadStyleSet joy_styles; 451 INSERT_PADDING_BYTES(0x60);
388 NpadAssignments pad_assignment; 452 };
389 453
390 ColorReadError single_color_error; 454 struct AppletFooterUiAttributes {
391 ControllerColor single_color; 455 INSERT_PADDING_BYTES(0x4);
456 };
392 457
393 ColorReadError dual_color_error; 458 enum class AppletFooterUiType : u8 {
394 ControllerColor left_color; 459 None = 0,
395 ControllerColor right_color; 460 HandheldNone = 1,
461 HandheldJoyConLeftOnly = 1,
462 HandheldJoyConRightOnly = 3,
463 HandheldJoyConLeftJoyConRight = 4,
464 JoyDual = 5,
465 JoyDualLeftOnly = 6,
466 JoyDualRightOnly = 7,
467 JoyLeftHorizontal = 8,
468 JoyLeftVertical = 9,
469 JoyRightHorizontal = 10,
470 JoyRightVertical = 11,
471 SwitchProController = 12,
472 CompatibleProController = 13,
473 CompatibleJoyCon = 14,
474 LarkHvc1 = 15,
475 LarkHvc2 = 16,
476 LarkNesLeft = 17,
477 LarkNesRight = 18,
478 Lucia = 19,
479 Verification = 20,
480 };
481
482 struct NPadEntry {
483 NpadStyleSet style_set;
484 NpadAssignments assignment_mode;
485 FullKeyColor fullkey_color;
486 JoyconColor joycon_color;
396 487
397 NPadGeneric main_controller_states; 488 NPadGeneric fullkey_states;
398 NPadGeneric handheld_states; 489 NPadGeneric handheld_states;
399 NPadGeneric dual_states; 490 NPadGeneric joy_dual_states;
400 NPadGeneric left_joy_states; 491 NPadGeneric joy_left_states;
401 NPadGeneric right_joy_states; 492 NPadGeneric joy_right_states;
402 NPadGeneric pokeball_states; 493 NPadGeneric palma_states;
403 NPadGeneric libnx; // TODO(ogniK): Find out what this actually is, libnx seems to only be 494 NPadGeneric system_ext_states;
404 // relying on this for the time being 495 SixAxisGeneric sixaxis_fullkey;
405 SixAxisGeneric sixaxis_full;
406 SixAxisGeneric sixaxis_handheld; 496 SixAxisGeneric sixaxis_handheld;
407 SixAxisGeneric sixaxis_dual_left; 497 SixAxisGeneric sixaxis_dual_left;
408 SixAxisGeneric sixaxis_dual_right; 498 SixAxisGeneric sixaxis_dual_right;
409 SixAxisGeneric sixaxis_left; 499 SixAxisGeneric sixaxis_left;
410 SixAxisGeneric sixaxis_right; 500 SixAxisGeneric sixaxis_right;
411 NPadDevice device_type; 501 NPadDevice device_type;
412 NPadProperties properties; 502 INSERT_PADDING_BYTES(0x4); // reserved
413 INSERT_PADDING_WORDS(1); 503 NPadSystemProperties system_properties;
414 std::array<u32, 3> battery_level; 504 NPadButtonProperties button_properties;
415 INSERT_PADDING_BYTES(0x5c); 505 u32 battery_level_dual;
416 INSERT_PADDING_BYTES(0xdf8); 506 u32 battery_level_left;
507 u32 battery_level_right;
508 AppletFooterUiAttributes footer_attributes;
509 AppletFooterUiType footer_type;
510 // nfc_states needs to be checked switchbrew does not match with HW
511 NfcXcdHandle nfc_states;
512 INSERT_PADDING_BYTES(0xdef);
417 }; 513 };
418 static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size"); 514 static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size");
419 515
@@ -449,10 +545,9 @@ private:
449 std::vector<u32> supported_npad_id_types{}; 545 std::vector<u32> supported_npad_id_types{};
450 NpadHoldType hold_type{NpadHoldType::Vertical}; 546 NpadHoldType hold_type{NpadHoldType::Vertical};
451 NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; 547 NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
452 // NpadCommunicationMode is unknown, default value is 1 548 NpadCommunicationMode communication_mode{NpadCommunicationMode::Default};
453 NpadCommunicationMode communication_mode{NpadCommunicationMode::Unknown1};
454 // Each controller should have their own styleset changed event 549 // Each controller should have their own styleset changed event
455 std::array<Kernel::EventPair, 10> styleset_changed_events; 550 std::array<std::shared_ptr<Kernel::KEvent>, 10> styleset_changed_events;
456 std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints; 551 std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints;
457 std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{}; 552 std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{};
458 bool permit_vibration_session_enabled{false}; 553 bool permit_vibration_session_enabled{false};
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
index ad229787c..5b59961bd 100644
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ b/src/core/hle/service/hid/controllers/xpad.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/bit_field.h"
7#include "common/common_funcs.h" 8#include "common/common_funcs.h"
8#include "common/common_types.h" 9#include "common/common_types.h"
9#include "common/swap.h" 10#include "common/swap.h"
@@ -28,6 +29,67 @@ public:
28 void OnLoadInputDevices() override; 29 void OnLoadInputDevices() override;
29 30
30private: 31private:
32 struct Attributes {
33 union {
34 u32_le raw{};
35 BitField<0, 1, u32> is_connected;
36 BitField<1, 1, u32> is_wired;
37 BitField<2, 1, u32> is_left_connected;
38 BitField<3, 1, u32> is_left_wired;
39 BitField<4, 1, u32> is_right_connected;
40 BitField<5, 1, u32> is_right_wired;
41 };
42 };
43 static_assert(sizeof(Attributes) == 4, "Attributes is an invalid size");
44
45 struct Buttons {
46 union {
47 u32_le raw{};
48 // Button states
49 BitField<0, 1, u32> a;
50 BitField<1, 1, u32> b;
51 BitField<2, 1, u32> x;
52 BitField<3, 1, u32> y;
53 BitField<4, 1, u32> l_stick;
54 BitField<5, 1, u32> r_stick;
55 BitField<6, 1, u32> l;
56 BitField<7, 1, u32> r;
57 BitField<8, 1, u32> zl;
58 BitField<9, 1, u32> zr;
59 BitField<10, 1, u32> plus;
60 BitField<11, 1, u32> minus;
61
62 // D-Pad
63 BitField<12, 1, u32> d_left;
64 BitField<13, 1, u32> d_up;
65 BitField<14, 1, u32> d_right;
66 BitField<15, 1, u32> d_down;
67
68 // Left JoyStick
69 BitField<16, 1, u32> l_stick_left;
70 BitField<17, 1, u32> l_stick_up;
71 BitField<18, 1, u32> l_stick_right;
72 BitField<19, 1, u32> l_stick_down;
73
74 // Right JoyStick
75 BitField<20, 1, u32> r_stick_left;
76 BitField<21, 1, u32> r_stick_up;
77 BitField<22, 1, u32> r_stick_right;
78 BitField<23, 1, u32> r_stick_down;
79
80 // Not always active?
81 BitField<24, 1, u32> left_sl;
82 BitField<25, 1, u32> left_sr;
83
84 BitField<26, 1, u32> right_sl;
85 BitField<27, 1, u32> right_sr;
86
87 BitField<28, 1, u32> palma;
88 BitField<30, 1, u32> handheld_left_b;
89 };
90 };
91 static_assert(sizeof(Buttons) == 4, "Buttons is an invalid size");
92
31 struct AnalogStick { 93 struct AnalogStick {
32 s32_le x; 94 s32_le x;
33 s32_le y; 95 s32_le y;
@@ -37,10 +99,10 @@ private:
37 struct XPadState { 99 struct XPadState {
38 s64_le sampling_number; 100 s64_le sampling_number;
39 s64_le sampling_number2; 101 s64_le sampling_number2;
40 s32_le attributes; 102 Attributes attributes;
41 u32_le pad_states; 103 Buttons pad_states;
42 AnalogStick x_stick; 104 AnalogStick l_stick;
43 AnalogStick y_stick; 105 AnalogStick r_stick;
44 }; 106 };
45 static_assert(sizeof(XPadState) == 0x28, "XPadState is an invalid size"); 107 static_assert(sizeof(XPadState) == 0x28, "XPadState is an invalid size");
46 108
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 4cee4838c..1e2677320 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -14,10 +14,10 @@
14#include "core/hle/ipc_helpers.h" 14#include "core/hle/ipc_helpers.h"
15#include "core/hle/kernel/client_port.h" 15#include "core/hle/kernel/client_port.h"
16#include "core/hle/kernel/client_session.h" 16#include "core/hle/kernel/client_session.h"
17#include "core/hle/kernel/k_readable_event.h"
18#include "core/hle/kernel/k_writable_event.h"
17#include "core/hle/kernel/kernel.h" 19#include "core/hle/kernel/kernel.h"
18#include "core/hle/kernel/readable_event.h"
19#include "core/hle/kernel/shared_memory.h" 20#include "core/hle/kernel/shared_memory.h"
20#include "core/hle/kernel/writable_event.h"
21#include "core/hle/service/hid/errors.h" 21#include "core/hle/service/hid/errors.h"
22#include "core/hle/service/hid/hid.h" 22#include "core/hle/service/hid/hid.h"
23#include "core/hle/service/hid/irs.h" 23#include "core/hle/service/hid/irs.h"
@@ -59,20 +59,26 @@ IAppletResource::IAppletResource(Core::System& system_)
59 MakeController<Controller_Mouse>(HidController::Mouse); 59 MakeController<Controller_Mouse>(HidController::Mouse);
60 MakeController<Controller_Keyboard>(HidController::Keyboard); 60 MakeController<Controller_Keyboard>(HidController::Keyboard);
61 MakeController<Controller_XPad>(HidController::XPad); 61 MakeController<Controller_XPad>(HidController::XPad);
62 MakeController<Controller_Stubbed>(HidController::Unknown1); 62 MakeController<Controller_Stubbed>(HidController::HomeButton);
63 MakeController<Controller_Stubbed>(HidController::Unknown2); 63 MakeController<Controller_Stubbed>(HidController::SleepButton);
64 MakeController<Controller_Stubbed>(HidController::Unknown3); 64 MakeController<Controller_Stubbed>(HidController::CaptureButton);
65 MakeController<Controller_Stubbed>(HidController::SixAxisSensor); 65 MakeController<Controller_Stubbed>(HidController::InputDetector);
66 MakeController<Controller_Stubbed>(HidController::UniquePad);
66 MakeController<Controller_NPad>(HidController::NPad); 67 MakeController<Controller_NPad>(HidController::NPad);
67 MakeController<Controller_Gesture>(HidController::Gesture); 68 MakeController<Controller_Gesture>(HidController::Gesture);
69 MakeController<Controller_Stubbed>(HidController::ConsoleSixAxisSensor);
68 70
69 // Homebrew doesn't try to activate some controllers, so we activate them by default 71 // Homebrew doesn't try to activate some controllers, so we activate them by default
70 GetController<Controller_NPad>(HidController::NPad).ActivateController(); 72 GetController<Controller_NPad>(HidController::NPad).ActivateController();
71 GetController<Controller_Touchscreen>(HidController::Touchscreen).ActivateController(); 73 GetController<Controller_Touchscreen>(HidController::Touchscreen).ActivateController();
72 74
73 GetController<Controller_Stubbed>(HidController::Unknown1).SetCommonHeaderOffset(0x4c00); 75 GetController<Controller_Stubbed>(HidController::HomeButton).SetCommonHeaderOffset(0x4C00);
74 GetController<Controller_Stubbed>(HidController::Unknown2).SetCommonHeaderOffset(0x4e00); 76 GetController<Controller_Stubbed>(HidController::SleepButton).SetCommonHeaderOffset(0x4E00);
75 GetController<Controller_Stubbed>(HidController::Unknown3).SetCommonHeaderOffset(0x5000); 77 GetController<Controller_Stubbed>(HidController::CaptureButton).SetCommonHeaderOffset(0x5000);
78 GetController<Controller_Stubbed>(HidController::InputDetector).SetCommonHeaderOffset(0x5200);
79 GetController<Controller_Stubbed>(HidController::UniquePad).SetCommonHeaderOffset(0x5A00);
80 GetController<Controller_Stubbed>(HidController::ConsoleSixAxisSensor)
81 .SetCommonHeaderOffset(0x3C200);
76 82
77 // Register update callbacks 83 // Register update callbacks
78 pad_update_event = Core::Timing::CreateEvent( 84 pad_update_event = Core::Timing::CreateEvent(
@@ -104,6 +110,7 @@ void IAppletResource::DeactivateController(HidController controller) {
104 110
105IAppletResource ::~IAppletResource() { 111IAppletResource ::~IAppletResource() {
106 system.CoreTiming().UnscheduleEvent(pad_update_event, 0); 112 system.CoreTiming().UnscheduleEvent(pad_update_event, 0);
113 system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
107} 114}
108 115
109void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) { 116void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index d991bd721..7cc0433e2 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -29,12 +29,14 @@ enum class HidController : std::size_t {
29 Mouse, 29 Mouse,
30 Keyboard, 30 Keyboard,
31 XPad, 31 XPad,
32 Unknown1, 32 HomeButton,
33 Unknown2, 33 SleepButton,
34 Unknown3, 34 CaptureButton,
35 SixAxisSensor, 35 InputDetector,
36 UniquePad,
36 NPad, 37 NPad,
37 Gesture, 38 Gesture,
39 ConsoleSixAxisSensor,
38 40
39 MaxControllers, 41 MaxControllers,
40}; 42};
diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp
index 2a6d43d2a..7d7542fc2 100644
--- a/src/core/hle/service/lm/lm.cpp
+++ b/src/core/hle/service/lm/lm.cpp
@@ -143,17 +143,19 @@ private:
143 rb.Push(RESULT_SUCCESS); 143 rb.Push(RESULT_SUCCESS);
144 } 144 }
145 145
146 u32 ReadLeb128(const std::vector<u8>& data, std::size_t& offset) { 146 u64 ReadLeb128(const std::vector<u8>& data, std::size_t& offset) {
147 u32 result{}; 147 u64 result{};
148 u32 shift{}; 148 u32 shift{};
149 do { 149
150 result |= (data[offset] & 0x7f) << shift; 150 for (std::size_t i = 0; i < sizeof(u64); i++) {
151 const auto v = data[offset];
152 result |= (static_cast<u64>(v & 0x7f) << shift);
151 shift += 7; 153 shift += 7;
152 offset++; 154 offset++;
153 if (offset >= data.size()) { 155 if (offset >= data.size() || ((v & 0x80) == 0)) {
154 break; 156 break;
155 } 157 }
156 } while ((data[offset] & 0x80) != 0); 158 }
157 return result; 159 return result;
158 } 160 }
159 161
@@ -262,7 +264,7 @@ private:
262 264
263 switch (entry.severity) { 265 switch (entry.severity) {
264 case LogSeverity::Trace: 266 case LogSeverity::Trace:
265 LOG_DEBUG(Service_LM, "LogManager DEBUG ({}):\n{}", DestinationToString(destination), 267 LOG_DEBUG(Service_LM, "LogManager TRACE ({}):\n{}", DestinationToString(destination),
266 output_log); 268 output_log);
267 break; 269 break;
268 case LogSeverity::Info: 270 case LogSeverity::Info:
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index a515fdc60..5d6d25696 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -8,10 +8,11 @@
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/ipc_helpers.h" 10#include "core/hle/ipc_helpers.h"
11#include "core/hle/kernel/k_event.h"
12#include "core/hle/kernel/k_readable_event.h"
11#include "core/hle/kernel/k_thread.h" 13#include "core/hle/kernel/k_thread.h"
14#include "core/hle/kernel/k_writable_event.h"
12#include "core/hle/kernel/kernel.h" 15#include "core/hle/kernel/kernel.h"
13#include "core/hle/kernel/readable_event.h"
14#include "core/hle/kernel/writable_event.h"
15#include "core/hle/lock.h" 16#include "core/hle/lock.h"
16#include "core/hle/service/nfp/nfp.h" 17#include "core/hle/service/nfp/nfp.h"
17#include "core/hle/service/nfp/nfp_user.h" 18#include "core/hle/service/nfp/nfp_user.h"
@@ -25,7 +26,8 @@ Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& syst
25 const char* name) 26 const char* name)
26 : ServiceFramework{system_, name}, module{std::move(module_)} { 27 : ServiceFramework{system_, name}, module{std::move(module_)} {
27 auto& kernel = system.Kernel(); 28 auto& kernel = system.Kernel();
28 nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:NFCTagDetected"); 29 nfc_tag_load = Kernel::KEvent::Create(kernel, "IUser:NFCTagDetected");
30 nfc_tag_load->Initialize();
29} 31}
30 32
31Module::Interface::~Interface() = default; 33Module::Interface::~Interface() = default;
@@ -64,9 +66,10 @@ public:
64 RegisterHandlers(functions); 66 RegisterHandlers(functions);
65 67
66 auto& kernel = system.Kernel(); 68 auto& kernel = system.Kernel();
67 deactivate_event = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:DeactivateEvent"); 69 deactivate_event = Kernel::KEvent::Create(kernel, "IUser:DeactivateEvent");
68 availability_change_event = 70 deactivate_event->Initialize();
69 Kernel::WritableEvent::CreateEventPair(kernel, "IUser:AvailabilityChangeEvent"); 71 availability_change_event = Kernel::KEvent::Create(kernel, "IUser:AvailabilityChangeEvent");
72 availability_change_event->Initialize();
70 } 73 }
71 74
72private: 75private:
@@ -164,7 +167,7 @@ private:
164 167
165 IPC::ResponseBuilder rb{ctx, 2, 1}; 168 IPC::ResponseBuilder rb{ctx, 2, 1};
166 rb.Push(RESULT_SUCCESS); 169 rb.Push(RESULT_SUCCESS);
167 rb.PushCopyObjects(deactivate_event.readable); 170 rb.PushCopyObjects(deactivate_event->GetReadableEvent());
168 } 171 }
169 172
170 void StopDetection(Kernel::HLERequestContext& ctx) { 173 void StopDetection(Kernel::HLERequestContext& ctx) {
@@ -173,7 +176,7 @@ private:
173 switch (device_state) { 176 switch (device_state) {
174 case DeviceState::TagFound: 177 case DeviceState::TagFound:
175 case DeviceState::TagNearby: 178 case DeviceState::TagNearby:
176 deactivate_event.writable->Signal(); 179 deactivate_event->GetWritableEvent()->Signal();
177 device_state = DeviceState::Initialized; 180 device_state = DeviceState::Initialized;
178 break; 181 break;
179 case DeviceState::SearchingForTag: 182 case DeviceState::SearchingForTag:
@@ -262,7 +265,7 @@ private:
262 265
263 IPC::ResponseBuilder rb{ctx, 2, 1}; 266 IPC::ResponseBuilder rb{ctx, 2, 1};
264 rb.Push(RESULT_SUCCESS); 267 rb.Push(RESULT_SUCCESS);
265 rb.PushCopyObjects(availability_change_event.readable); 268 rb.PushCopyObjects(availability_change_event->GetReadableEvent());
266 } 269 }
267 270
268 void GetRegisterInfo(Kernel::HLERequestContext& ctx) { 271 void GetRegisterInfo(Kernel::HLERequestContext& ctx) {
@@ -316,8 +319,8 @@ private:
316 const u32 npad_id{0}; // Player 1 controller 319 const u32 npad_id{0}; // Player 1 controller
317 State state{State::NonInitialized}; 320 State state{State::NonInitialized};
318 DeviceState device_state{DeviceState::Initialized}; 321 DeviceState device_state{DeviceState::Initialized};
319 Kernel::EventPair deactivate_event; 322 std::shared_ptr<Kernel::KEvent> deactivate_event;
320 Kernel::EventPair availability_change_event; 323 std::shared_ptr<Kernel::KEvent> availability_change_event;
321 const Module::Interface& nfp_interface; 324 const Module::Interface& nfp_interface;
322}; 325};
323 326
@@ -336,12 +339,12 @@ bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
336 } 339 }
337 340
338 std::memcpy(&amiibo, buffer.data(), sizeof(amiibo)); 341 std::memcpy(&amiibo, buffer.data(), sizeof(amiibo));
339 nfc_tag_load.writable->Signal(); 342 nfc_tag_load->GetWritableEvent()->Signal();
340 return true; 343 return true;
341} 344}
342 345
343const std::shared_ptr<Kernel::ReadableEvent>& Module::Interface::GetNFCEvent() const { 346const std::shared_ptr<Kernel::KReadableEvent>& Module::Interface::GetNFCEvent() const {
344 return nfc_tag_load.readable; 347 return nfc_tag_load->GetReadableEvent();
345} 348}
346 349
347const Module::Interface::AmiiboFile& Module::Interface::GetAmiiboBuffer() const { 350const Module::Interface::AmiiboFile& Module::Interface::GetAmiiboBuffer() const {
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h
index 295de535b..c46551760 100644
--- a/src/core/hle/service/nfp/nfp.h
+++ b/src/core/hle/service/nfp/nfp.h
@@ -6,10 +6,13 @@
6 6
7#include <array> 7#include <array>
8#include <vector> 8#include <vector>
9#include "core/hle/kernel/readable_event.h" 9
10#include "core/hle/kernel/writable_event.h"
11#include "core/hle/service/service.h" 10#include "core/hle/service/service.h"
12 11
12namespace Kernel {
13class KEvent;
14}
15
13namespace Service::NFP { 16namespace Service::NFP {
14 17
15class Module final { 18class Module final {
@@ -35,11 +38,11 @@ public:
35 38
36 void CreateUserInterface(Kernel::HLERequestContext& ctx); 39 void CreateUserInterface(Kernel::HLERequestContext& ctx);
37 bool LoadAmiibo(const std::vector<u8>& buffer); 40 bool LoadAmiibo(const std::vector<u8>& buffer);
38 const std::shared_ptr<Kernel::ReadableEvent>& GetNFCEvent() const; 41 const std::shared_ptr<Kernel::KReadableEvent>& GetNFCEvent() const;
39 const AmiiboFile& GetAmiiboBuffer() const; 42 const AmiiboFile& GetAmiiboBuffer() const;
40 43
41 private: 44 private:
42 Kernel::EventPair nfc_tag_load{}; 45 std::shared_ptr<Kernel::KEvent> nfc_tag_load;
43 AmiiboFile amiibo{}; 46 AmiiboFile amiibo{};
44 47
45 protected: 48 protected:
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index 8372e170c..afb3342d6 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -4,9 +4,9 @@
4 4
5#include "core/core.h" 5#include "core/core.h"
6#include "core/hle/ipc_helpers.h" 6#include "core/hle/ipc_helpers.h"
7#include "core/hle/kernel/k_event.h"
8#include "core/hle/kernel/k_readable_event.h"
7#include "core/hle/kernel/kernel.h" 9#include "core/hle/kernel/kernel.h"
8#include "core/hle/kernel/readable_event.h"
9#include "core/hle/kernel/writable_event.h"
10#include "core/hle/service/nifm/nifm.h" 10#include "core/hle/service/nifm/nifm.h"
11#include "core/hle/service/service.h" 11#include "core/hle/service/service.h"
12#include "core/network/network.h" 12#include "core/network/network.h"
@@ -158,8 +158,11 @@ public:
158 RegisterHandlers(functions); 158 RegisterHandlers(functions);
159 159
160 auto& kernel = system.Kernel(); 160 auto& kernel = system.Kernel();
161 event1 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event1"); 161
162 event2 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event2"); 162 event1 = Kernel::KEvent::Create(kernel, "IRequest:Event1");
163 event1->Initialize();
164 event2 = Kernel::KEvent::Create(kernel, "IRequest:Event2");
165 event2->Initialize();
163 } 166 }
164 167
165private: 168private:
@@ -195,7 +198,7 @@ private:
195 198
196 IPC::ResponseBuilder rb{ctx, 2, 2}; 199 IPC::ResponseBuilder rb{ctx, 2, 2};
197 rb.Push(RESULT_SUCCESS); 200 rb.Push(RESULT_SUCCESS);
198 rb.PushCopyObjects(event1.readable, event2.readable); 201 rb.PushCopyObjects(event1->GetReadableEvent(), event2->GetReadableEvent());
199 } 202 }
200 203
201 void Cancel(Kernel::HLERequestContext& ctx) { 204 void Cancel(Kernel::HLERequestContext& ctx) {
@@ -226,7 +229,7 @@ private:
226 rb.Push<u32>(0); 229 rb.Push<u32>(0);
227 } 230 }
228 231
229 Kernel::EventPair event1, event2; 232 std::shared_ptr<Kernel::KEvent> event1, event2;
230}; 233};
231 234
232class INetworkProfile final : public ServiceFramework<INetworkProfile> { 235class INetworkProfile final : public ServiceFramework<INetworkProfile> {
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
index d16223064..f3be0b878 100644
--- a/src/core/hle/service/nim/nim.cpp
+++ b/src/core/hle/service/nim/nim.cpp
@@ -6,9 +6,10 @@
6#include <ctime> 6#include <ctime>
7#include "core/core.h" 7#include "core/core.h"
8#include "core/hle/ipc_helpers.h" 8#include "core/hle/ipc_helpers.h"
9#include "core/hle/kernel/k_event.h"
10#include "core/hle/kernel/k_readable_event.h"
11#include "core/hle/kernel/k_writable_event.h"
9#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
10#include "core/hle/kernel/readable_event.h"
11#include "core/hle/kernel/writable_event.h"
12#include "core/hle/service/nim/nim.h" 13#include "core/hle/service/nim/nim.h"
13#include "core/hle/service/service.h" 14#include "core/hle/service/service.h"
14#include "core/hle/service/sm/sm.h" 15#include "core/hle/service/sm/sm.h"
@@ -301,17 +302,18 @@ public:
301 RegisterHandlers(functions); 302 RegisterHandlers(functions);
302 303
303 auto& kernel = system.Kernel(); 304 auto& kernel = system.Kernel();
304 finished_event = Kernel::WritableEvent::CreateEventPair( 305 finished_event =
305 kernel, "IEnsureNetworkClockAvailabilityService:FinishEvent"); 306 Kernel::KEvent::Create(kernel, "IEnsureNetworkClockAvailabilityService:FinishEvent");
307 finished_event->Initialize();
306 } 308 }
307 309
308private: 310private:
309 Kernel::EventPair finished_event; 311 std::shared_ptr<Kernel::KEvent> finished_event;
310 312
311 void StartTask(Kernel::HLERequestContext& ctx) { 313 void StartTask(Kernel::HLERequestContext& ctx) {
312 // No need to connect to the internet, just finish the task straight away. 314 // No need to connect to the internet, just finish the task straight away.
313 LOG_DEBUG(Service_NIM, "called"); 315 LOG_DEBUG(Service_NIM, "called");
314 finished_event.writable->Signal(); 316 finished_event->GetWritableEvent()->Signal();
315 IPC::ResponseBuilder rb{ctx, 2}; 317 IPC::ResponseBuilder rb{ctx, 2};
316 rb.Push(RESULT_SUCCESS); 318 rb.Push(RESULT_SUCCESS);
317 } 319 }
@@ -321,7 +323,7 @@ private:
321 323
322 IPC::ResponseBuilder rb{ctx, 2, 1}; 324 IPC::ResponseBuilder rb{ctx, 2, 1};
323 rb.Push(RESULT_SUCCESS); 325 rb.Push(RESULT_SUCCESS);
324 rb.PushCopyObjects(finished_event.readable); 326 rb.PushCopyObjects(finished_event->GetReadableEvent());
325 } 327 }
326 328
327 void GetResult(Kernel::HLERequestContext& ctx) { 329 void GetResult(Kernel::HLERequestContext& ctx) {
@@ -333,7 +335,7 @@ private:
333 335
334 void Cancel(Kernel::HLERequestContext& ctx) { 336 void Cancel(Kernel::HLERequestContext& ctx) {
335 LOG_DEBUG(Service_NIM, "called"); 337 LOG_DEBUG(Service_NIM, "called");
336 finished_event.writable->Clear(); 338 finished_event->GetWritableEvent()->Clear();
337 IPC::ResponseBuilder rb{ctx, 2}; 339 IPC::ResponseBuilder rb{ctx, 2};
338 rb.Push(RESULT_SUCCESS); 340 rb.Push(RESULT_SUCCESS);
339 } 341 }
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp
index 71c7587db..b6ac0a81a 100644
--- a/src/core/hle/service/ns/pl_u.cpp
+++ b/src/core/hle/service/ns/pl_u.cpp
@@ -65,13 +65,18 @@ static void DecryptSharedFont(const std::vector<u32>& input, Kernel::PhysicalMem
65void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output) { 65void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output) {
66 ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number"); 66 ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number");
67 67
68 if (input.size() < 2) {
69 LOG_ERROR(Service_NS, "Input font is empty");
70 return;
71 }
72
68 const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor 73 const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor
69 std::vector<u32> transformed_font(input.size()); 74 std::vector<u32> transformed_font(input.size());
70 // TODO(ogniK): Figure out a better way to do this 75 // TODO(ogniK): Figure out a better way to do this
71 std::transform(input.begin(), input.end(), transformed_font.begin(), 76 std::transform(input.begin(), input.end(), transformed_font.begin(),
72 [&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); }); 77 [&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); });
73 transformed_font[1] = Common::swap32(transformed_font[1]) ^ KEY; // "re-encrypt" the size 78 std::memcpy(output.data(), transformed_font.data() + 2,
74 std::memcpy(output.data(), transformed_font.data() + 2, transformed_font.size() * sizeof(u32)); 79 (transformed_font.size() - 2) * sizeof(u32));
75} 80}
76 81
77void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, 82void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output,
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index 060599bab..f6129ef10 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -8,8 +8,8 @@
8#include "common/assert.h" 8#include "common/assert.h"
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "core/core.h" 10#include "core/core.h"
11#include "core/hle/kernel/readable_event.h" 11#include "core/hle/kernel/k_event.h"
12#include "core/hle/kernel/writable_event.h" 12#include "core/hle/kernel/k_writable_event.h"
13#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" 13#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"
14#include "video_core/gpu.h" 14#include "video_core/gpu.h"
15 15
@@ -103,14 +103,14 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
103 // This is mostly to take into account unimplemented features. As synced 103 // This is mostly to take into account unimplemented features. As synced
104 // gpu is always synced. 104 // gpu is always synced.
105 if (!gpu.IsAsync()) { 105 if (!gpu.IsAsync()) {
106 event.event.writable->Signal(); 106 event.event->GetWritableEvent()->Signal();
107 return NvResult::Success; 107 return NvResult::Success;
108 } 108 }
109 auto lock = gpu.LockSync(); 109 auto lock = gpu.LockSync();
110 const u32 current_syncpoint_value = event.fence.value; 110 const u32 current_syncpoint_value = event.fence.value;
111 const s32 diff = current_syncpoint_value - params.threshold; 111 const s32 diff = current_syncpoint_value - params.threshold;
112 if (diff >= 0) { 112 if (diff >= 0) {
113 event.event.writable->Signal(); 113 event.event->GetWritableEvent()->Signal();
114 params.value = current_syncpoint_value; 114 params.value = current_syncpoint_value;
115 std::memcpy(output.data(), &params, sizeof(params)); 115 std::memcpy(output.data(), &params, sizeof(params));
116 return NvResult::Success; 116 return NvResult::Success;
@@ -137,7 +137,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
137 params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000; 137 params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000;
138 } 138 }
139 params.value |= event_id; 139 params.value |= event_id;
140 event.event.writable->Clear(); 140 event.event->GetWritableEvent()->Clear();
141 gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); 141 gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value);
142 std::memcpy(output.data(), &params, sizeof(params)); 142 std::memcpy(output.data(), &params, sizeof(params));
143 return NvResult::Timeout; 143 return NvResult::Timeout;
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp
index 1328b64d0..2e1150867 100644
--- a/src/core/hle/service/nvdrv/interface.cpp
+++ b/src/core/hle/service/nvdrv/interface.cpp
@@ -6,10 +6,10 @@
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/hle/ipc_helpers.h" 8#include "core/hle/ipc_helpers.h"
9#include "core/hle/kernel/k_readable_event.h"
9#include "core/hle/kernel/k_thread.h" 10#include "core/hle/kernel/k_thread.h"
11#include "core/hle/kernel/k_writable_event.h"
10#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/readable_event.h"
12#include "core/hle/kernel/writable_event.h"
13#include "core/hle/service/nvdrv/interface.h" 13#include "core/hle/service/nvdrv/interface.h"
14#include "core/hle/service/nvdrv/nvdata.h" 14#include "core/hle/service/nvdrv/nvdata.h"
15#include "core/hle/service/nvdrv/nvdrv.h" 15#include "core/hle/service/nvdrv/nvdrv.h"
diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h
index 5c777c59b..0e764c53f 100644
--- a/src/core/hle/service/nvdrv/interface.h
+++ b/src/core/hle/service/nvdrv/interface.h
@@ -9,7 +9,7 @@
9#include "core/hle/service/service.h" 9#include "core/hle/service/service.h"
10 10
11namespace Kernel { 11namespace Kernel {
12class WritableEvent; 12class KWritableEvent;
13} 13}
14 14
15namespace Service::Nvidia { 15namespace Service::Nvidia {
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 620c18728..abba80112 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -7,8 +7,9 @@
7#include <fmt/format.h> 7#include <fmt/format.h>
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
10#include "core/hle/kernel/readable_event.h" 10#include "core/hle/kernel/k_event.h"
11#include "core/hle/kernel/writable_event.h" 11#include "core/hle/kernel/k_readable_event.h"
12#include "core/hle/kernel/k_writable_event.h"
12#include "core/hle/service/nvdrv/devices/nvdevice.h" 13#include "core/hle/service/nvdrv/devices/nvdevice.h"
13#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" 14#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
14#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" 15#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
@@ -42,7 +43,8 @@ Module::Module(Core::System& system) : syncpoint_manager{system.GPU()} {
42 auto& kernel = system.Kernel(); 43 auto& kernel = system.Kernel();
43 for (u32 i = 0; i < MaxNvEvents; i++) { 44 for (u32 i = 0; i < MaxNvEvents; i++) {
44 std::string event_label = fmt::format("NVDRV::NvEvent_{}", i); 45 std::string event_label = fmt::format("NVDRV::NvEvent_{}", i);
45 events_interface.events[i] = {Kernel::WritableEvent::CreateEventPair(kernel, event_label)}; 46 events_interface.events[i] = {Kernel::KEvent::Create(kernel, std::move(event_label))};
47 events_interface.events[i].event->Initialize();
46 events_interface.status[i] = EventState::Free; 48 events_interface.status[i] = EventState::Free;
47 events_interface.registered[i] = false; 49 events_interface.registered[i] = false;
48 } 50 }
@@ -166,17 +168,17 @@ void Module::SignalSyncpt(const u32 syncpoint_id, const u32 value) {
166 if (events_interface.assigned_syncpt[i] == syncpoint_id && 168 if (events_interface.assigned_syncpt[i] == syncpoint_id &&
167 events_interface.assigned_value[i] == value) { 169 events_interface.assigned_value[i] == value) {
168 events_interface.LiberateEvent(i); 170 events_interface.LiberateEvent(i);
169 events_interface.events[i].event.writable->Signal(); 171 events_interface.events[i].event->GetWritableEvent()->Signal();
170 } 172 }
171 } 173 }
172} 174}
173 175
174std::shared_ptr<Kernel::ReadableEvent> Module::GetEvent(const u32 event_id) const { 176std::shared_ptr<Kernel::KReadableEvent> Module::GetEvent(const u32 event_id) const {
175 return events_interface.events[event_id].event.readable; 177 return events_interface.events[event_id].event->GetReadableEvent();
176} 178}
177 179
178std::shared_ptr<Kernel::WritableEvent> Module::GetEventWriteable(const u32 event_id) const { 180std::shared_ptr<Kernel::KWritableEvent> Module::GetEventWriteable(const u32 event_id) const {
179 return events_interface.events[event_id].event.writable; 181 return events_interface.events[event_id].event->GetWritableEvent();
180} 182}
181 183
182} // namespace Service::Nvidia 184} // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index 144e657e5..53719aadd 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -7,8 +7,8 @@
7#include <memory> 7#include <memory>
8#include <unordered_map> 8#include <unordered_map>
9#include <vector> 9#include <vector>
10
10#include "common/common_types.h" 11#include "common/common_types.h"
11#include "core/hle/kernel/writable_event.h"
12#include "core/hle/service/nvdrv/nvdata.h" 12#include "core/hle/service/nvdrv/nvdata.h"
13#include "core/hle/service/nvdrv/syncpoint_manager.h" 13#include "core/hle/service/nvdrv/syncpoint_manager.h"
14#include "core/hle/service/service.h" 14#include "core/hle/service/service.h"
@@ -17,6 +17,10 @@ namespace Core {
17class System; 17class System;
18} 18}
19 19
20namespace Kernel {
21class KEvent;
22}
23
20namespace Service::NVFlinger { 24namespace Service::NVFlinger {
21class NVFlinger; 25class NVFlinger;
22} 26}
@@ -31,7 +35,7 @@ class nvdevice;
31 35
32/// Represents an Nvidia event 36/// Represents an Nvidia event
33struct NvEvent { 37struct NvEvent {
34 Kernel::EventPair event; 38 std::shared_ptr<Kernel::KEvent> event;
35 Fence fence{}; 39 Fence fence{};
36}; 40};
37 41
@@ -132,9 +136,9 @@ public:
132 136
133 void SignalSyncpt(const u32 syncpoint_id, const u32 value); 137 void SignalSyncpt(const u32 syncpoint_id, const u32 value);
134 138
135 std::shared_ptr<Kernel::ReadableEvent> GetEvent(u32 event_id) const; 139 std::shared_ptr<Kernel::KReadableEvent> GetEvent(u32 event_id) const;
136 140
137 std::shared_ptr<Kernel::WritableEvent> GetEventWriteable(u32 event_id) const; 141 std::shared_ptr<Kernel::KWritableEvent> GetEventWriteable(u32 event_id) const;
138 142
139private: 143private:
140 /// Manages syncpoints on the host 144 /// Manages syncpoints on the host
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 5578181a4..7842a82ed 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -7,16 +7,17 @@
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/kernel/k_event.h"
11#include "core/hle/kernel/k_writable_event.h"
10#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/readable_event.h"
12#include "core/hle/kernel/writable_event.h"
13#include "core/hle/service/nvflinger/buffer_queue.h" 13#include "core/hle/service/nvflinger/buffer_queue.h"
14 14
15namespace Service::NVFlinger { 15namespace Service::NVFlinger {
16 16
17BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id) 17BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id)
18 : id(id), layer_id(layer_id) { 18 : id(id), layer_id(layer_id) {
19 buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, "BufferQueue NativeHandle"); 19 buffer_wait_event = Kernel::KEvent::Create(kernel, "BufferQueue:WaitEvent");
20 buffer_wait_event->Initialize();
20} 21}
21 22
22BufferQueue::~BufferQueue() = default; 23BufferQueue::~BufferQueue() = default;
@@ -41,7 +42,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
41 .multi_fence = {}, 42 .multi_fence = {},
42 }; 43 };
43 44
44 buffer_wait_event.writable->Signal(); 45 buffer_wait_event->GetWritableEvent()->Signal();
45} 46}
46 47
47std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width, 48std::optional<std::pair<u32, Service::Nvidia::MultiFence*>> BufferQueue::DequeueBuffer(u32 width,
@@ -119,7 +120,7 @@ void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& mult
119 } 120 }
120 free_buffers_condition.notify_one(); 121 free_buffers_condition.notify_one();
121 122
122 buffer_wait_event.writable->Signal(); 123 buffer_wait_event->GetWritableEvent()->Signal();
123} 124}
124 125
125std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { 126std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
@@ -154,7 +155,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
154 } 155 }
155 free_buffers_condition.notify_one(); 156 free_buffers_condition.notify_one();
156 157
157 buffer_wait_event.writable->Signal(); 158 buffer_wait_event->GetWritableEvent()->Signal();
158} 159}
159 160
160void BufferQueue::Connect() { 161void BufferQueue::Connect() {
@@ -169,7 +170,7 @@ void BufferQueue::Disconnect() {
169 std::unique_lock lock{queue_sequence_mutex}; 170 std::unique_lock lock{queue_sequence_mutex};
170 queue_sequence.clear(); 171 queue_sequence.clear();
171 } 172 }
172 buffer_wait_event.writable->Signal(); 173 buffer_wait_event->GetWritableEvent()->Signal();
173 is_connect = false; 174 is_connect = false;
174 free_buffers_condition.notify_one(); 175 free_buffers_condition.notify_one();
175} 176}
@@ -188,12 +189,12 @@ u32 BufferQueue::Query(QueryType type) {
188 return 0; 189 return 0;
189} 190}
190 191
191std::shared_ptr<Kernel::WritableEvent> BufferQueue::GetWritableBufferWaitEvent() const { 192std::shared_ptr<Kernel::KWritableEvent> BufferQueue::GetWritableBufferWaitEvent() const {
192 return buffer_wait_event.writable; 193 return buffer_wait_event->GetWritableEvent();
193} 194}
194 195
195std::shared_ptr<Kernel::ReadableEvent> BufferQueue::GetBufferWaitEvent() const { 196std::shared_ptr<Kernel::KReadableEvent> BufferQueue::GetBufferWaitEvent() const {
196 return buffer_wait_event.readable; 197 return buffer_wait_event->GetReadableEvent();
197} 198}
198 199
199} // namespace Service::NVFlinger 200} // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
index ad7469277..163fa4c54 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ b/src/core/hle/service/nvflinger/buffer_queue.h
@@ -14,12 +14,14 @@
14#include "common/math_util.h" 14#include "common/math_util.h"
15#include "common/swap.h" 15#include "common/swap.h"
16#include "core/hle/kernel/object.h" 16#include "core/hle/kernel/object.h"
17#include "core/hle/kernel/writable_event.h"
18#include "core/hle/service/nvdrv/nvdata.h" 17#include "core/hle/service/nvdrv/nvdata.h"
19 18
20namespace Kernel { 19namespace Kernel {
21class KernelCore; 20class KernelCore;
22} 21class KEvent;
22class KReadableEvent;
23class KWritableEvent;
24} // namespace Kernel
23 25
24namespace Service::NVFlinger { 26namespace Service::NVFlinger {
25 27
@@ -113,9 +115,9 @@ public:
113 return is_connect; 115 return is_connect;
114 } 116 }
115 117
116 std::shared_ptr<Kernel::WritableEvent> GetWritableBufferWaitEvent() const; 118 std::shared_ptr<Kernel::KWritableEvent> GetWritableBufferWaitEvent() const;
117 119
118 std::shared_ptr<Kernel::ReadableEvent> GetBufferWaitEvent() const; 120 std::shared_ptr<Kernel::KReadableEvent> GetBufferWaitEvent() const;
119 121
120private: 122private:
121 BufferQueue(const BufferQueue&) = delete; 123 BufferQueue(const BufferQueue&) = delete;
@@ -127,7 +129,7 @@ private:
127 std::list<u32> free_buffers; 129 std::list<u32> free_buffers;
128 std::array<Buffer, buffer_slots> buffers; 130 std::array<Buffer, buffer_slots> buffers;
129 std::list<u32> queue_sequence; 131 std::list<u32> queue_sequence;
130 Kernel::EventPair buffer_wait_event; 132 std::shared_ptr<Kernel::KEvent> buffer_wait_event;
131 133
132 std::mutex free_buffers_mutex; 134 std::mutex free_buffers_mutex;
133 std::condition_variable free_buffers_condition; 135 std::condition_variable free_buffers_condition;
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index ceaa93d28..ac2906e5b 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -14,8 +14,8 @@
14#include "core/core_timing.h" 14#include "core/core_timing.h"
15#include "core/core_timing_util.h" 15#include "core/core_timing_util.h"
16#include "core/hardware_properties.h" 16#include "core/hardware_properties.h"
17#include "core/hle/kernel/k_readable_event.h"
17#include "core/hle/kernel/kernel.h" 18#include "core/hle/kernel/kernel.h"
18#include "core/hle/kernel/readable_event.h"
19#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" 19#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
20#include "core/hle/service/nvdrv/nvdrv.h" 20#include "core/hle/service/nvdrv/nvdrv.h"
21#include "core/hle/service/nvflinger/buffer_queue.h" 21#include "core/hle/service/nvflinger/buffer_queue.h"
@@ -165,7 +165,7 @@ std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) co
165 return layer->GetBufferQueue().GetId(); 165 return layer->GetBufferQueue().GetId();
166} 166}
167 167
168std::shared_ptr<Kernel::ReadableEvent> NVFlinger::FindVsyncEvent(u64 display_id) const { 168std::shared_ptr<Kernel::KReadableEvent> NVFlinger::FindVsyncEvent(u64 display_id) const {
169 const auto guard = Lock(); 169 const auto guard = Lock();
170 auto* const display = FindDisplay(display_id); 170 auto* const display = FindDisplay(display_id);
171 171
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index c6765259f..6fe2c7f2a 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -26,8 +26,8 @@ struct EventType;
26} // namespace Core::Timing 26} // namespace Core::Timing
27 27
28namespace Kernel { 28namespace Kernel {
29class ReadableEvent; 29class KReadableEvent;
30class WritableEvent; 30class KWritableEvent;
31} // namespace Kernel 31} // namespace Kernel
32 32
33namespace Service::Nvidia { 33namespace Service::Nvidia {
@@ -72,7 +72,7 @@ public:
72 /// Gets the vsync event for the specified display. 72 /// Gets the vsync event for the specified display.
73 /// 73 ///
74 /// If an invalid display ID is provided, then nullptr is returned. 74 /// If an invalid display ID is provided, then nullptr is returned.
75 [[nodiscard]] std::shared_ptr<Kernel::ReadableEvent> FindVsyncEvent(u64 display_id) const; 75 [[nodiscard]] std::shared_ptr<Kernel::KReadableEvent> FindVsyncEvent(u64 display_id) const;
76 76
77 /// Obtains a buffer queue identified by the ID. 77 /// Obtains a buffer queue identified by the ID.
78 [[nodiscard]] BufferQueue* FindBufferQueue(u32 id); 78 [[nodiscard]] BufferQueue* FindBufferQueue(u32 id);
diff --git a/src/core/hle/service/olsc/olsc.cpp b/src/core/hle/service/olsc/olsc.cpp
index 4440135ed..e2ac71fa1 100644
--- a/src/core/hle/service/olsc/olsc.cpp
+++ b/src/core/hle/service/olsc/olsc.cpp
@@ -17,7 +17,7 @@ public:
17 static const FunctionInfo functions[] = { 17 static const FunctionInfo functions[] = {
18 {0, &OLSC::Initialize, "Initialize"}, 18 {0, &OLSC::Initialize, "Initialize"},
19 {10, nullptr, "VerifySaveDataBackupLicenseAsync"}, 19 {10, nullptr, "VerifySaveDataBackupLicenseAsync"},
20 {13, nullptr, "GetSaveDataBackupSetting"}, 20 {13, &OLSC::GetSaveDataBackupSetting, "GetSaveDataBackupSetting"},
21 {14, &OLSC::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"}, 21 {14, &OLSC::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"},
22 {15, nullptr, "SetCustomData"}, 22 {15, nullptr, "SetCustomData"},
23 {16, nullptr, "DeleteSaveDataBackupSetting"}, 23 {16, nullptr, "DeleteSaveDataBackupSetting"},
@@ -52,6 +52,17 @@ private:
52 rb.Push(RESULT_SUCCESS); 52 rb.Push(RESULT_SUCCESS);
53 } 53 }
54 54
55 void GetSaveDataBackupSetting(Kernel::HLERequestContext& ctx) {
56 LOG_WARNING(Service_OLSC, "(STUBBED) called");
57
58 // backup_setting is set to 0 since real value is unknown
59 constexpr u64 backup_setting = 0;
60
61 IPC::ResponseBuilder rb{ctx, 4};
62 rb.Push(RESULT_SUCCESS);
63 rb.Push(backup_setting);
64 }
65
55 void SetSaveDataBackupSettingEnabled(Kernel::HLERequestContext& ctx) { 66 void SetSaveDataBackupSettingEnabled(Kernel::HLERequestContext& ctx) {
56 LOG_WARNING(Service_OLSC, "(STUBBED) called"); 67 LOG_WARNING(Service_OLSC, "(STUBBED) called");
57 68
diff --git a/src/core/hle/service/ptm/psm.cpp b/src/core/hle/service/ptm/psm.cpp
index a7cfccda3..26ed52273 100644
--- a/src/core/hle/service/ptm/psm.cpp
+++ b/src/core/hle/service/ptm/psm.cpp
@@ -7,9 +7,10 @@
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
10#include "core/hle/kernel/k_event.h"
11#include "core/hle/kernel/k_readable_event.h"
12#include "core/hle/kernel/k_writable_event.h"
10#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/readable_event.h"
12#include "core/hle/kernel/writable_event.h"
13#include "core/hle/service/ptm/psm.h" 14#include "core/hle/service/ptm/psm.h"
14#include "core/hle/service/service.h" 15#include "core/hle/service/service.h"
15#include "core/hle/service/sm/sm.h" 16#include "core/hle/service/sm/sm.h"
@@ -31,27 +32,28 @@ public:
31 32
32 RegisterHandlers(functions); 33 RegisterHandlers(functions);
33 34
34 state_change_event = Kernel::WritableEvent::CreateEventPair( 35 state_change_event =
35 system_.Kernel(), "IPsmSession::state_change_event"); 36 Kernel::KEvent::Create(system_.Kernel(), "IPsmSession::state_change_event");
37 state_change_event->Initialize();
36 } 38 }
37 39
38 ~IPsmSession() override = default; 40 ~IPsmSession() override = default;
39 41
40 void SignalChargerTypeChanged() { 42 void SignalChargerTypeChanged() {
41 if (should_signal && should_signal_charger_type) { 43 if (should_signal && should_signal_charger_type) {
42 state_change_event.writable->Signal(); 44 state_change_event->GetWritableEvent()->Signal();
43 } 45 }
44 } 46 }
45 47
46 void SignalPowerSupplyChanged() { 48 void SignalPowerSupplyChanged() {
47 if (should_signal && should_signal_power_supply) { 49 if (should_signal && should_signal_power_supply) {
48 state_change_event.writable->Signal(); 50 state_change_event->GetWritableEvent()->Signal();
49 } 51 }
50 } 52 }
51 53
52 void SignalBatteryVoltageStateChanged() { 54 void SignalBatteryVoltageStateChanged() {
53 if (should_signal && should_signal_battery_voltage) { 55 if (should_signal && should_signal_battery_voltage) {
54 state_change_event.writable->Signal(); 56 state_change_event->GetWritableEvent()->Signal();
55 } 57 }
56 } 58 }
57 59
@@ -63,7 +65,7 @@ private:
63 65
64 IPC::ResponseBuilder rb{ctx, 2, 1}; 66 IPC::ResponseBuilder rb{ctx, 2, 1};
65 rb.Push(RESULT_SUCCESS); 67 rb.Push(RESULT_SUCCESS);
66 rb.PushCopyObjects(state_change_event.readable); 68 rb.PushCopyObjects(state_change_event->GetReadableEvent());
67 } 69 }
68 70
69 void UnbindStateChangeEvent(Kernel::HLERequestContext& ctx) { 71 void UnbindStateChangeEvent(Kernel::HLERequestContext& ctx) {
@@ -112,7 +114,7 @@ private:
112 bool should_signal_power_supply{}; 114 bool should_signal_power_supply{};
113 bool should_signal_battery_voltage{}; 115 bool should_signal_battery_voltage{};
114 bool should_signal{}; 116 bool should_signal{};
115 Kernel::EventPair state_change_event; 117 std::shared_ptr<Kernel::KEvent> state_change_event;
116}; 118};
117 119
118class PSM final : public ServiceFramework<PSM> { 120class PSM final : public ServiceFramework<PSM> {
diff --git a/src/core/hle/service/time/standard_user_system_clock_core.cpp b/src/core/hle/service/time/standard_user_system_clock_core.cpp
index 8af17091c..b9faa474e 100644
--- a/src/core/hle/service/time/standard_user_system_clock_core.cpp
+++ b/src/core/hle/service/time/standard_user_system_clock_core.cpp
@@ -4,7 +4,7 @@
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6#include "core/core.h" 6#include "core/core.h"
7#include "core/hle/kernel/writable_event.h" 7#include "core/hle/kernel/k_event.h"
8#include "core/hle/service/time/standard_local_system_clock_core.h" 8#include "core/hle/service/time/standard_local_system_clock_core.h"
9#include "core/hle/service/time/standard_network_system_clock_core.h" 9#include "core/hle/service/time/standard_network_system_clock_core.h"
10#include "core/hle/service/time/standard_user_system_clock_core.h" 10#include "core/hle/service/time/standard_user_system_clock_core.h"
@@ -18,8 +18,10 @@ StandardUserSystemClockCore::StandardUserSystemClockCore(
18 local_system_clock_core{local_system_clock_core}, 18 local_system_clock_core{local_system_clock_core},
19 network_system_clock_core{network_system_clock_core}, auto_correction_enabled{}, 19 network_system_clock_core{network_system_clock_core}, auto_correction_enabled{},
20 auto_correction_time{SteadyClockTimePoint::GetRandom()}, 20 auto_correction_time{SteadyClockTimePoint::GetRandom()},
21 auto_correction_event{Kernel::WritableEvent::CreateEventPair( 21 auto_correction_event{Kernel::KEvent::Create(
22 system.Kernel(), "StandardUserSystemClockCore:AutoCorrectionEvent")} {} 22 system.Kernel(), "StandardUserSystemClockCore:AutoCorrectionEvent")} {
23 auto_correction_event->Initialize();
24}
23 25
24ResultCode StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::System& system, 26ResultCode StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::System& system,
25 bool value) { 27 bool value) {
diff --git a/src/core/hle/service/time/standard_user_system_clock_core.h b/src/core/hle/service/time/standard_user_system_clock_core.h
index ef3d468b7..aac44d72f 100644
--- a/src/core/hle/service/time/standard_user_system_clock_core.h
+++ b/src/core/hle/service/time/standard_user_system_clock_core.h
@@ -4,7 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "core/hle/kernel/writable_event.h"
8#include "core/hle/service/time/clock_types.h" 7#include "core/hle/service/time/clock_types.h"
9#include "core/hle/service/time/system_clock_core.h" 8#include "core/hle/service/time/system_clock_core.h"
10 9
@@ -12,6 +11,10 @@ namespace Core {
12class System; 11class System;
13} 12}
14 13
14namespace Kernel {
15class KEvent;
16}
17
15namespace Service::Time::Clock { 18namespace Service::Time::Clock {
16 19
17class StandardLocalSystemClockCore; 20class StandardLocalSystemClockCore;
@@ -51,7 +54,7 @@ private:
51 StandardNetworkSystemClockCore& network_system_clock_core; 54 StandardNetworkSystemClockCore& network_system_clock_core;
52 bool auto_correction_enabled{}; 55 bool auto_correction_enabled{};
53 SteadyClockTimePoint auto_correction_time; 56 SteadyClockTimePoint auto_correction_time;
54 Kernel::EventPair auto_correction_event; 57 std::shared_ptr<Kernel::KEvent> auto_correction_event;
55}; 58};
56 59
57} // namespace Service::Time::Clock 60} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/time/system_clock_context_update_callback.cpp b/src/core/hle/service/time/system_clock_context_update_callback.cpp
index 5cdb80703..bca7d869e 100644
--- a/src/core/hle/service/time/system_clock_context_update_callback.cpp
+++ b/src/core/hle/service/time/system_clock_context_update_callback.cpp
@@ -2,7 +2,7 @@
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 "core/hle/kernel/writable_event.h" 5#include "core/hle/kernel/k_writable_event.h"
6#include "core/hle/service/time/errors.h" 6#include "core/hle/service/time/errors.h"
7#include "core/hle/service/time/system_clock_context_update_callback.h" 7#include "core/hle/service/time/system_clock_context_update_callback.h"
8 8
@@ -21,7 +21,7 @@ bool SystemClockContextUpdateCallback::NeedUpdate(const SystemClockContext& valu
21} 21}
22 22
23void SystemClockContextUpdateCallback::RegisterOperationEvent( 23void SystemClockContextUpdateCallback::RegisterOperationEvent(
24 std::shared_ptr<Kernel::WritableEvent>&& writable_event) { 24 std::shared_ptr<Kernel::KWritableEvent>&& writable_event) {
25 operation_event_list.emplace_back(std::move(writable_event)); 25 operation_event_list.emplace_back(std::move(writable_event));
26} 26}
27 27
diff --git a/src/core/hle/service/time/system_clock_context_update_callback.h b/src/core/hle/service/time/system_clock_context_update_callback.h
index 2b0fa7e75..797954958 100644
--- a/src/core/hle/service/time/system_clock_context_update_callback.h
+++ b/src/core/hle/service/time/system_clock_context_update_callback.h
@@ -9,7 +9,7 @@
9#include "core/hle/service/time/clock_types.h" 9#include "core/hle/service/time/clock_types.h"
10 10
11namespace Kernel { 11namespace Kernel {
12class WritableEvent; 12class KWritableEvent;
13} 13}
14 14
15namespace Service::Time::Clock { 15namespace Service::Time::Clock {
@@ -24,7 +24,7 @@ public:
24 24
25 bool NeedUpdate(const SystemClockContext& value) const; 25 bool NeedUpdate(const SystemClockContext& value) const;
26 26
27 void RegisterOperationEvent(std::shared_ptr<Kernel::WritableEvent>&& writable_event); 27 void RegisterOperationEvent(std::shared_ptr<Kernel::KWritableEvent>&& writable_event);
28 28
29 void BroadcastOperationEvent(); 29 void BroadcastOperationEvent();
30 30
@@ -37,7 +37,7 @@ protected:
37 37
38private: 38private:
39 bool has_context{}; 39 bool has_context{};
40 std::vector<std::shared_ptr<Kernel::WritableEvent>> operation_event_list; 40 std::vector<std::shared_ptr<Kernel::KWritableEvent>> operation_event_list;
41}; 41};
42 42
43} // namespace Service::Time::Clock 43} // namespace Service::Time::Clock
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
index 5a202ac81..7f42aa4a0 100644
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ b/src/core/hle/service/vi/display/vi_display.cpp
@@ -9,7 +9,9 @@
9 9
10#include "common/assert.h" 10#include "common/assert.h"
11#include "core/core.h" 11#include "core/core.h"
12#include "core/hle/kernel/readable_event.h" 12#include "core/hle/kernel/k_event.h"
13#include "core/hle/kernel/k_readable_event.h"
14#include "core/hle/kernel/k_writable_event.h"
13#include "core/hle/service/vi/display/vi_display.h" 15#include "core/hle/service/vi/display/vi_display.h"
14#include "core/hle/service/vi/layer/vi_layer.h" 16#include "core/hle/service/vi/layer/vi_layer.h"
15 17
@@ -17,8 +19,8 @@ namespace Service::VI {
17 19
18Display::Display(u64 id, std::string name, Core::System& system) : id{id}, name{std::move(name)} { 20Display::Display(u64 id, std::string name, Core::System& system) : id{id}, name{std::move(name)} {
19 auto& kernel = system.Kernel(); 21 auto& kernel = system.Kernel();
20 vsync_event = 22 vsync_event = Kernel::KEvent::Create(kernel, fmt::format("Display VSync Event {}", id));
21 Kernel::WritableEvent::CreateEventPair(kernel, fmt::format("Display VSync Event {}", id)); 23 vsync_event->Initialize();
22} 24}
23 25
24Display::~Display() = default; 26Display::~Display() = default;
@@ -31,12 +33,12 @@ const Layer& Display::GetLayer(std::size_t index) const {
31 return *layers.at(index); 33 return *layers.at(index);
32} 34}
33 35
34std::shared_ptr<Kernel::ReadableEvent> Display::GetVSyncEvent() const { 36std::shared_ptr<Kernel::KReadableEvent> Display::GetVSyncEvent() const {
35 return vsync_event.readable; 37 return vsync_event->GetReadableEvent();
36} 38}
37 39
38void Display::SignalVSyncEvent() { 40void Display::SignalVSyncEvent() {
39 vsync_event.writable->Signal(); 41 vsync_event->GetWritableEvent()->Signal();
40} 42}
41 43
42void Display::CreateLayer(u64 id, NVFlinger::BufferQueue& buffer_queue) { 44void Display::CreateLayer(u64 id, NVFlinger::BufferQueue& buffer_queue) {
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h
index a3855d8cd..931c898f6 100644
--- a/src/core/hle/service/vi/display/vi_display.h
+++ b/src/core/hle/service/vi/display/vi_display.h
@@ -9,7 +9,10 @@
9#include <vector> 9#include <vector>
10 10
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "core/hle/kernel/writable_event.h" 12
13namespace Kernel {
14class KEvent;
15}
13 16
14namespace Service::NVFlinger { 17namespace Service::NVFlinger {
15class BufferQueue; 18class BufferQueue;
@@ -58,7 +61,7 @@ public:
58 const Layer& GetLayer(std::size_t index) const; 61 const Layer& GetLayer(std::size_t index) const;
59 62
60 /// Gets the readable vsync event. 63 /// Gets the readable vsync event.
61 std::shared_ptr<Kernel::ReadableEvent> GetVSyncEvent() const; 64 std::shared_ptr<Kernel::KReadableEvent> GetVSyncEvent() const;
62 65
63 /// Signals the internal vsync event. 66 /// Signals the internal vsync event.
64 void SignalVSyncEvent(); 67 void SignalVSyncEvent();
@@ -99,7 +102,7 @@ private:
99 std::string name; 102 std::string name;
100 103
101 std::vector<std::shared_ptr<Layer>> layers; 104 std::vector<std::shared_ptr<Layer>> layers;
102 Kernel::EventPair vsync_event; 105 std::shared_ptr<Kernel::KEvent> vsync_event;
103}; 106};
104 107
105} // namespace Service::VI 108} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index f3de2c428..8661895ae 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -18,9 +18,9 @@
18#include "common/swap.h" 18#include "common/swap.h"
19#include "core/core_timing.h" 19#include "core/core_timing.h"
20#include "core/hle/ipc_helpers.h" 20#include "core/hle/ipc_helpers.h"
21#include "core/hle/kernel/k_readable_event.h"
21#include "core/hle/kernel/k_thread.h" 22#include "core/hle/kernel/k_thread.h"
22#include "core/hle/kernel/readable_event.h" 23#include "core/hle/kernel/k_writable_event.h"
23#include "core/hle/kernel/writable_event.h"
24#include "core/hle/service/nvdrv/nvdata.h" 24#include "core/hle/service/nvdrv/nvdata.h"
25#include "core/hle/service/nvdrv/nvdrv.h" 25#include "core/hle/service/nvdrv/nvdrv.h"
26#include "core/hle/service/nvflinger/buffer_queue.h" 26#include "core/hle/service/nvflinger/buffer_queue.h"
diff --git a/src/input_common/analog_from_button.cpp b/src/input_common/analog_from_button.cpp
index 07a0fa4a1..770893687 100755
--- a/src/input_common/analog_from_button.cpp
+++ b/src/input_common/analog_from_button.cpp
@@ -139,6 +139,10 @@ public:
139 static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF)); 139 static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF));
140 } 140 }
141 141
142 Input::AnalogProperties GetAnalogProperties() const override {
143 return {modifier_scale, 1.0f, 0.5f};
144 }
145
142 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { 146 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
143 switch (direction) { 147 switch (direction) {
144 case Input::AnalogDirection::RIGHT: 148 case Input::AnalogDirection::RIGHT:
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp
index 9670bdeb2..1b6ded8d6 100644
--- a/src/input_common/gcadapter/gc_poller.cpp
+++ b/src/input_common/gcadapter/gc_poller.cpp
@@ -185,6 +185,16 @@ public:
185 return {0.0f, 0.0f}; 185 return {0.0f, 0.0f};
186 } 186 }
187 187
188 std::tuple<float, float> GetRawStatus() const override {
189 const float x = GetAxis(axis_x);
190 const float y = GetAxis(axis_y);
191 return {x, y};
192 }
193
194 Input::AnalogProperties GetAnalogProperties() const override {
195 return {deadzone, range, 0.5f};
196 }
197
188 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { 198 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
189 const auto [x, y] = GetStatus(); 199 const auto [x, y] = GetStatus();
190 const float directional_deadzone = 0.5f; 200 const float directional_deadzone = 0.5f;
diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp
index 508eb0c7d..3d799b293 100644
--- a/src/input_common/mouse/mouse_poller.cpp
+++ b/src/input_common/mouse/mouse_poller.cpp
@@ -106,6 +106,16 @@ public:
106 return {0.0f, 0.0f}; 106 return {0.0f, 0.0f};
107 } 107 }
108 108
109 std::tuple<float, float> GetRawStatus() const override {
110 const float x = GetAxis(axis_x);
111 const float y = GetAxis(axis_y);
112 return {x, y};
113 }
114
115 Input::AnalogProperties GetAnalogProperties() const override {
116 return {deadzone, range, 0.5f};
117 }
118
109private: 119private:
110 const u32 button; 120 const u32 button;
111 const u32 axis_x; 121 const u32 axis_x;
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index 1b5750937..f67de37e3 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -377,6 +377,16 @@ public:
377 return {}; 377 return {};
378 } 378 }
379 379
380 std::tuple<float, float> GetRawStatus() const override {
381 const float x = joystick->GetAxis(axis_x, range);
382 const float y = joystick->GetAxis(axis_y, range);
383 return {x, -y};
384 }
385
386 Input::AnalogProperties GetAnalogProperties() const override {
387 return {deadzone, range, 0.5f};
388 }
389
380 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { 390 bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
381 const auto [x, y] = GetStatus(); 391 const auto [x, y] = GetStatus();
382 const float directional_deadzone = 0.5f; 392 const float directional_deadzone = 0.5f;
diff --git a/src/tests/common/ring_buffer.cpp b/src/tests/common/ring_buffer.cpp
index 54def22da..903626e4b 100644
--- a/src/tests/common/ring_buffer.cpp
+++ b/src/tests/common/ring_buffer.cpp
@@ -14,7 +14,7 @@
14namespace Common { 14namespace Common {
15 15
16TEST_CASE("RingBuffer: Basic Tests", "[common]") { 16TEST_CASE("RingBuffer: Basic Tests", "[common]") {
17 RingBuffer<char, 4, 1> buf; 17 RingBuffer<char, 4> buf;
18 18
19 // Pushing values into a ring buffer with space should succeed. 19 // Pushing values into a ring buffer with space should succeed.
20 for (std::size_t i = 0; i < 4; i++) { 20 for (std::size_t i = 0; i < 4; i++) {
@@ -77,7 +77,7 @@ TEST_CASE("RingBuffer: Basic Tests", "[common]") {
77} 77}
78 78
79TEST_CASE("RingBuffer: Threaded Test", "[common]") { 79TEST_CASE("RingBuffer: Threaded Test", "[common]") {
80 RingBuffer<char, 4, 2> buf; 80 RingBuffer<char, 8> buf;
81 const char seed = 42; 81 const char seed = 42;
82 const std::size_t count = 1000000; 82 const std::size_t count = 1000000;
83 std::size_t full = 0; 83 std::size_t full = 0;
@@ -92,8 +92,8 @@ TEST_CASE("RingBuffer: Threaded Test", "[common]") {
92 std::array<char, 2> value = {seed, seed}; 92 std::array<char, 2> value = {seed, seed};
93 std::size_t i = 0; 93 std::size_t i = 0;
94 while (i < count) { 94 while (i < count) {
95 if (const std::size_t c = buf.Push(&value[0], 1); c > 0) { 95 if (const std::size_t c = buf.Push(&value[0], 2); c > 0) {
96 REQUIRE(c == 1U); 96 REQUIRE(c == 2U);
97 i++; 97 i++;
98 next_value(value); 98 next_value(value);
99 } else { 99 } else {
@@ -107,7 +107,7 @@ TEST_CASE("RingBuffer: Threaded Test", "[common]") {
107 std::array<char, 2> value = {seed, seed}; 107 std::array<char, 2> value = {seed, seed};
108 std::size_t i = 0; 108 std::size_t i = 0;
109 while (i < count) { 109 while (i < count) {
110 if (const std::vector<char> v = buf.Pop(1); v.size() > 0) { 110 if (const std::vector<char> v = buf.Pop(2); v.size() > 0) {
111 REQUIRE(v.size() == 2U); 111 REQUIRE(v.size() == 2U);
112 REQUIRE(v[0] == value[0]); 112 REQUIRE(v[0] == value[0]);
113 REQUIRE(v[1] == value[1]); 113 REQUIRE(v[1] == value[1]);
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 1434d0260..dd4c29ed3 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -67,8 +67,6 @@ add_library(video_core STATIC
67 guest_driver.h 67 guest_driver.h
68 memory_manager.cpp 68 memory_manager.cpp
69 memory_manager.h 69 memory_manager.h
70 morton.cpp
71 morton.h
72 query_cache.h 70 query_cache.h
73 rasterizer_accelerated.cpp 71 rasterizer_accelerated.cpp
74 rasterizer_accelerated.h 72 rasterizer_accelerated.h
diff --git a/src/video_core/morton.cpp b/src/video_core/morton.cpp
deleted file mode 100644
index e69de29bb..000000000
--- a/src/video_core/morton.cpp
+++ /dev/null
diff --git a/src/video_core/morton.h b/src/video_core/morton.h
deleted file mode 100644
index e69de29bb..000000000
--- a/src/video_core/morton.h
+++ /dev/null
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index dd77a543c..21159e498 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -506,7 +506,7 @@ bool RendererOpenGL::Init() {
506 506
507 AddTelemetryFields(); 507 AddTelemetryFields();
508 508
509 if (!GLAD_GL_VERSION_4_3) { 509 if (!GLAD_GL_VERSION_4_6) {
510 return false; 510 return false;
511 } 511 }
512 512
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index e1bab2112..fb9967c8f 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -71,6 +71,8 @@ add_executable(yuzu
71 configuration/configure_input_player.cpp 71 configuration/configure_input_player.cpp
72 configuration/configure_input_player.h 72 configuration/configure_input_player.h
73 configuration/configure_input_player.ui 73 configuration/configure_input_player.ui
74 configuration/configure_input_player_widget.cpp
75 configuration/configure_input_player_widget.h
74 configuration/configure_input_profile_dialog.cpp 76 configuration/configure_input_profile_dialog.cpp
75 configuration/configure_input_profile_dialog.h 77 configuration/configure_input_profile_dialog.h
76 configuration/configure_input_profile_dialog.ui 78 configuration/configure_input_profile_dialog.ui
@@ -115,6 +117,8 @@ add_executable(yuzu
115 configuration/input_profiles.h 117 configuration/input_profiles.h
116 debugger/console.cpp 118 debugger/console.cpp
117 debugger/console.h 119 debugger/console.h
120 debugger/controller.cpp
121 debugger/controller.h
118 debugger/profiler.cpp 122 debugger/profiler.cpp
119 debugger/profiler.h 123 debugger/profiler.h
120 debugger/wait_tree.cpp 124 debugger/wait_tree.cpp
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 4528eb196..ffdf34a4a 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -126,7 +126,7 @@ public:
126 /// Create the original context that should be shared from 126 /// Create the original context that should be shared from
127 explicit OpenGLSharedContext(QSurface* surface) : surface(surface) { 127 explicit OpenGLSharedContext(QSurface* surface) : surface(surface) {
128 QSurfaceFormat format; 128 QSurfaceFormat format;
129 format.setVersion(4, 3); 129 format.setVersion(4, 6);
130 format.setProfile(QSurfaceFormat::CompatibilityProfile); 130 format.setProfile(QSurfaceFormat::CompatibilityProfile);
131 format.setOption(QSurfaceFormat::FormatOption::DeprecatedFunctions); 131 format.setOption(QSurfaceFormat::FormatOption::DeprecatedFunctions);
132 if (Settings::values.renderer_debug) { 132 if (Settings::values.renderer_debug) {
@@ -651,10 +651,10 @@ bool GRenderWindow::LoadOpenGL() {
651 const QString renderer = 651 const QString renderer =
652 QString::fromUtf8(reinterpret_cast<const char*>(glGetString(GL_RENDERER))); 652 QString::fromUtf8(reinterpret_cast<const char*>(glGetString(GL_RENDERER)));
653 653
654 if (!GLAD_GL_VERSION_4_3) { 654 if (!GLAD_GL_VERSION_4_6) {
655 LOG_ERROR(Frontend, "GPU does not support OpenGL 4.3: {}", renderer.toStdString()); 655 LOG_ERROR(Frontend, "GPU does not support OpenGL 4.6: {}", renderer.toStdString());
656 QMessageBox::warning(this, tr("Error while initializing OpenGL 4.3!"), 656 QMessageBox::warning(this, tr("Error while initializing OpenGL 4.6!"),
657 tr("Your GPU may not support OpenGL 4.3, or you do not have the " 657 tr("Your GPU may not support OpenGL 4.6, or you do not have the "
658 "latest graphics driver.<br><br>GL Renderer:<br>%1") 658 "latest graphics driver.<br><br>GL Renderer:<br>%1")
659 .arg(renderer)); 659 .arg(renderer));
660 return false; 660 return false;
@@ -677,26 +677,13 @@ bool GRenderWindow::LoadOpenGL() {
677QStringList GRenderWindow::GetUnsupportedGLExtensions() const { 677QStringList GRenderWindow::GetUnsupportedGLExtensions() const {
678 QStringList unsupported_ext; 678 QStringList unsupported_ext;
679 679
680 if (!GLAD_GL_ARB_buffer_storage)
681 unsupported_ext.append(QStringLiteral("ARB_buffer_storage"));
682 if (!GLAD_GL_ARB_direct_state_access)
683 unsupported_ext.append(QStringLiteral("ARB_direct_state_access"));
684 if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev)
685 unsupported_ext.append(QStringLiteral("ARB_vertex_type_10f_11f_11f_rev"));
686 if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge)
687 unsupported_ext.append(QStringLiteral("ARB_texture_mirror_clamp_to_edge"));
688 if (!GLAD_GL_ARB_multi_bind)
689 unsupported_ext.append(QStringLiteral("ARB_multi_bind"));
690 if (!GLAD_GL_ARB_clip_control)
691 unsupported_ext.append(QStringLiteral("ARB_clip_control"));
692
693 // Extensions required to support some texture formats. 680 // Extensions required to support some texture formats.
694 if (!GLAD_GL_EXT_texture_compression_s3tc) 681 if (!GLAD_GL_EXT_texture_compression_s3tc) {
695 unsupported_ext.append(QStringLiteral("EXT_texture_compression_s3tc")); 682 unsupported_ext.append(QStringLiteral("EXT_texture_compression_s3tc"));
696 if (!GLAD_GL_ARB_texture_compression_rgtc) 683 }
684 if (!GLAD_GL_ARB_texture_compression_rgtc) {
697 unsupported_ext.append(QStringLiteral("ARB_texture_compression_rgtc")); 685 unsupported_ext.append(QStringLiteral("ARB_texture_compression_rgtc"));
698 if (!GLAD_GL_ARB_depth_buffer_float) 686 }
699 unsupported_ext.append(QStringLiteral("ARB_depth_buffer_float"));
700 687
701 if (!unsupported_ext.empty()) { 688 if (!unsupported_ext.empty()) {
702 LOG_ERROR(Frontend, "GPU does not support all required extensions: {}", 689 LOG_ERROR(Frontend, "GPU does not support all required extensions: {}",
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 1ab5bcbb9..c9d19c948 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -23,6 +23,7 @@
23#include "ui_configure_input_player.h" 23#include "ui_configure_input_player.h"
24#include "yuzu/configuration/config.h" 24#include "yuzu/configuration/config.h"
25#include "yuzu/configuration/configure_input_player.h" 25#include "yuzu/configuration/configure_input_player.h"
26#include "yuzu/configuration/configure_input_player_widget.h"
26#include "yuzu/configuration/configure_vibration.h" 27#include "yuzu/configuration/configure_vibration.h"
27#include "yuzu/configuration/input_profiles.h" 28#include "yuzu/configuration/input_profiles.h"
28#include "yuzu/util/limitable_input_dialog.h" 29#include "yuzu/util/limitable_input_dialog.h"
@@ -254,11 +255,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
254 analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup}; 255 analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup};
255 analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange}; 256 analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange};
256 257
257 const auto ConfigureButtonClick = [&](QPushButton* button, Common::ParamPackage* param, 258 const auto ConfigureButtonClick = [&](QPushButton* button, std::size_t button_id,
258 int default_val, InputCommon::Polling::DeviceType type) { 259 Common::ParamPackage* param, int default_val,
260 InputCommon::Polling::DeviceType type) {
259 connect(button, &QPushButton::clicked, [=, this] { 261 connect(button, &QPushButton::clicked, [=, this] {
260 HandleClick( 262 HandleClick(
261 button, 263 button, button_id,
262 [=, this](Common::ParamPackage params) { 264 [=, this](Common::ParamPackage params) {
263 // Workaround for ZL & ZR for analog triggers like on XBOX 265 // Workaround for ZL & ZR for analog triggers like on XBOX
264 // controllers. Analog triggers (from controllers like the XBOX 266 // controllers. Analog triggers (from controllers like the XBOX
@@ -286,12 +288,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
286 continue; 288 continue;
287 } 289 }
288 290
289 ConfigureButtonClick(button_map[button_id], &buttons_param[button_id], 291 ConfigureButtonClick(button_map[button_id], button_id, &buttons_param[button_id],
290 Config::default_buttons[button_id], 292 Config::default_buttons[button_id],
291 InputCommon::Polling::DeviceType::Button); 293 InputCommon::Polling::DeviceType::Button);
292 294
293 button->setContextMenuPolicy(Qt::CustomContextMenu); 295 button->setContextMenuPolicy(Qt::CustomContextMenu);
294
295 connect(button, &QPushButton::customContextMenuRequested, 296 connect(button, &QPushButton::customContextMenuRequested,
296 [=, this](const QPoint& menu_location) { 297 [=, this](const QPoint& menu_location) {
297 QMenu context_menu; 298 QMenu context_menu;
@@ -300,6 +301,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
300 button_map[button_id]->setText(tr("[not set]")); 301 button_map[button_id]->setText(tr("[not set]"));
301 }); 302 });
302 context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); 303 context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
304 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
303 }); 305 });
304 } 306 }
305 307
@@ -309,7 +311,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
309 continue; 311 continue;
310 } 312 }
311 313
312 ConfigureButtonClick(motion_map[motion_id], &motions_param[motion_id], 314 ConfigureButtonClick(motion_map[motion_id], motion_id, &motions_param[motion_id],
313 Config::default_motions[motion_id], 315 Config::default_motions[motion_id],
314 InputCommon::Polling::DeviceType::Motion); 316 InputCommon::Polling::DeviceType::Motion);
315 317
@@ -348,7 +350,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
348 } 350 }
349 } 351 }
350 HandleClick( 352 HandleClick(
351 analog_map_buttons[analog_id][sub_button_id], 353 analog_map_buttons[analog_id][sub_button_id], analog_id,
352 [=, this](const Common::ParamPackage& params) { 354 [=, this](const Common::ParamPackage& params) {
353 SetAnalogParam(params, analogs_param[analog_id], 355 SetAnalogParam(params, analogs_param[analog_id],
354 analog_sub_buttons[sub_button_id]); 356 analog_sub_buttons[sub_button_id]);
@@ -358,41 +360,43 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
358 360
359 analog_button->setContextMenuPolicy(Qt::CustomContextMenu); 361 analog_button->setContextMenuPolicy(Qt::CustomContextMenu);
360 362
361 connect(analog_button, &QPushButton::customContextMenuRequested, 363 connect(
362 [=, this](const QPoint& menu_location) { 364 analog_button, &QPushButton::customContextMenuRequested,
363 QMenu context_menu; 365 [=, this](const QPoint& menu_location) {
364 context_menu.addAction(tr("Clear"), [&] { 366 QMenu context_menu;
365 analogs_param[analog_id].Clear(); 367 context_menu.addAction(tr("Clear"), [&] {
366 analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]")); 368 analogs_param[analog_id].Clear();
367 }); 369 analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]"));
368 context_menu.addAction(tr("Invert axis"), [&] { 370 });
369 if (sub_button_id == 2 || sub_button_id == 3) { 371 context_menu.addAction(tr("Invert axis"), [&] {
370 const bool invert_value = 372 if (sub_button_id == 2 || sub_button_id == 3) {
371 analogs_param[analog_id].Get("invert_x", "+") == "-"; 373 const bool invert_value =
372 const std::string invert_str = invert_value ? "+" : "-"; 374 analogs_param[analog_id].Get("invert_x", "+") == "-";
373 analogs_param[analog_id].Set("invert_x", invert_str); 375 const std::string invert_str = invert_value ? "+" : "-";
374 } 376 analogs_param[analog_id].Set("invert_x", invert_str);
375 if (sub_button_id == 0 || sub_button_id == 1) { 377 }
376 const bool invert_value = 378 if (sub_button_id == 0 || sub_button_id == 1) {
377 analogs_param[analog_id].Get("invert_y", "+") == "-"; 379 const bool invert_value =
378 const std::string invert_str = invert_value ? "+" : "-"; 380 analogs_param[analog_id].Get("invert_y", "+") == "-";
379 analogs_param[analog_id].Set("invert_y", invert_str); 381 const std::string invert_str = invert_value ? "+" : "-";
380 } 382 analogs_param[analog_id].Set("invert_y", invert_str);
381 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; 383 }
382 ++sub_button_id) { 384 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM;
383 analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText( 385 ++sub_button_id) {
384 analogs_param[analog_id], analog_sub_buttons[sub_button_id])); 386 analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText(
385 } 387 analogs_param[analog_id], analog_sub_buttons[sub_button_id]));
386 }); 388 }
387 context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal(
388 menu_location));
389 }); 389 });
390 context_menu.exec(
391 analog_map_buttons[analog_id][sub_button_id]->mapToGlobal(menu_location));
392 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
393 });
390 } 394 }
391 395
392 // Handle clicks for the modifier buttons as well. 396 // Handle clicks for the modifier buttons as well.
393 connect(analog_map_modifier_button[analog_id], &QPushButton::clicked, [=, this] { 397 connect(analog_map_modifier_button[analog_id], &QPushButton::clicked, [=, this] {
394 HandleClick( 398 HandleClick(
395 analog_map_modifier_button[analog_id], 399 analog_map_modifier_button[analog_id], analog_id,
396 [=, this](const Common::ParamPackage& params) { 400 [=, this](const Common::ParamPackage& params) {
397 analogs_param[analog_id].Set("modifier", params.Serialize()); 401 analogs_param[analog_id].Set("modifier", params.Serialize());
398 }, 402 },
@@ -416,12 +420,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
416 [=, this] { 420 [=, this] {
417 const auto spinbox_value = analog_map_range_spinbox[analog_id]->value(); 421 const auto spinbox_value = analog_map_range_spinbox[analog_id]->value();
418 analogs_param[analog_id].Set("range", spinbox_value / 100.0f); 422 analogs_param[analog_id].Set("range", spinbox_value / 100.0f);
423 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
419 }); 424 });
420 425
421 connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] { 426 connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] {
422 const auto slider_value = analog_map_deadzone_slider[analog_id]->value(); 427 const auto slider_value = analog_map_deadzone_slider[analog_id]->value();
423 analog_map_deadzone_label[analog_id]->setText(tr("Deadzone: %1%").arg(slider_value)); 428 analog_map_deadzone_label[analog_id]->setText(tr("Deadzone: %1%").arg(slider_value));
424 analogs_param[analog_id].Set("deadzone", slider_value / 100.0f); 429 analogs_param[analog_id].Set("deadzone", slider_value / 100.0f);
430 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
425 }); 431 });
426 432
427 connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] { 433 connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] {
@@ -433,8 +439,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
433 } 439 }
434 440
435 // Player Connected checkbox 441 // Player Connected checkbox
436 connect(ui->groupConnectedController, &QGroupBox::toggled, 442 connect(ui->groupConnectedController, &QGroupBox::toggled, [this](bool checked) {
437 [this](bool checked) { emit Connected(checked); }); 443 emit Connected(checked);
444 ui->controllerFrame->SetConnectedStatus(checked);
445 });
438 446
439 if (player_index == 0) { 447 if (player_index == 0) {
440 connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), 448 connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged),
@@ -553,6 +561,8 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
553 561
554 // TODO(wwylele): enable this when we actually emulate it 562 // TODO(wwylele): enable this when we actually emulate it
555 ui->buttonHome->setEnabled(false); 563 ui->buttonHome->setEnabled(false);
564 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
565 ui->controllerFrame->SetConnectedStatus(ui->groupConnectedController->isChecked());
556} 566}
557 567
558ConfigureInputPlayer::~ConfigureInputPlayer() = default; 568ConfigureInputPlayer::~ConfigureInputPlayer() = default;
@@ -875,6 +885,7 @@ void ConfigureInputPlayer::UpdateUI() {
875 modifier_label->setVisible(!is_controller); 885 modifier_label->setVisible(!is_controller);
876 modifier_slider->setVisible(!is_controller); 886 modifier_slider->setVisible(!is_controller);
877 range_groupbox->setVisible(is_controller); 887 range_groupbox->setVisible(is_controller);
888 ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
878 } 889 }
879} 890}
880 891
@@ -884,7 +895,7 @@ void ConfigureInputPlayer::SetConnectableControllers() {
884 index_controller_type_pairs.clear(); 895 index_controller_type_pairs.clear();
885 ui->comboControllerType->clear(); 896 ui->comboControllerType->clear();
886 897
887 if (enable_all || npad_style_set.pro_controller == 1) { 898 if (enable_all || npad_style_set.fullkey == 1) {
888 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 899 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
889 Settings::ControllerType::ProController); 900 Settings::ControllerType::ProController);
890 ui->comboControllerType->addItem(tr("Pro Controller")); 901 ui->comboControllerType->addItem(tr("Pro Controller"));
@@ -991,8 +1002,8 @@ void ConfigureInputPlayer::UpdateControllerIcon() {
991 return QString{}; 1002 return QString{};
992 } 1003 }
993 }(); 1004 }();
994 1005 ui->controllerFrame->SetControllerType(
995 ui->controllerFrame->setStyleSheet(stylesheet.arg(theme)); 1006 GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()));
996} 1007}
997 1008
998void ConfigureInputPlayer::UpdateControllerAvailableButtons() { 1009void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
@@ -1129,7 +1140,8 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
1129} 1140}
1130 1141
1131void ConfigureInputPlayer::HandleClick( 1142void ConfigureInputPlayer::HandleClick(
1132 QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, 1143 QPushButton* button, std::size_t button_id,
1144 std::function<void(const Common::ParamPackage&)> new_input_setter,
1133 InputCommon::Polling::DeviceType type) { 1145 InputCommon::Polling::DeviceType type) {
1134 if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) { 1146 if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) {
1135 button->setText(tr("Shake!")); 1147 button->setText(tr("Shake!"));
@@ -1173,6 +1185,12 @@ void ConfigureInputPlayer::HandleClick(
1173 input_subsystem->GetMouseTouch()->BeginConfiguration(); 1185 input_subsystem->GetMouseTouch()->BeginConfiguration();
1174 } 1186 }
1175 1187
1188 if (type == InputCommon::Polling::DeviceType::Button) {
1189 ui->controllerFrame->BeginMappingButton(button_id);
1190 } else if (type == InputCommon::Polling::DeviceType::AnalogPreferred) {
1191 ui->controllerFrame->BeginMappingAnalog(button_id);
1192 }
1193
1176 timeout_timer->start(2500); // Cancel after 2.5 seconds 1194 timeout_timer->start(2500); // Cancel after 2.5 seconds
1177 poll_timer->start(50); // Check for new inputs every 50ms 1195 poll_timer->start(50); // Check for new inputs every 50ms
1178} 1196}
@@ -1203,6 +1221,7 @@ void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params,
1203 1221
1204 UpdateUI(); 1222 UpdateUI();
1205 UpdateInputDeviceCombobox(); 1223 UpdateInputDeviceCombobox();
1224 ui->controllerFrame->EndMapping();
1206 1225
1207 input_setter = std::nullopt; 1226 input_setter = std::nullopt;
1208} 1227}
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index c4ae50de7..da2b89136 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -106,7 +106,7 @@ private:
106 void LoadConfiguration(); 106 void LoadConfiguration();
107 107
108 /// Called when the button was pressed. 108 /// Called when the button was pressed.
109 void HandleClick(QPushButton* button, 109 void HandleClick(QPushButton* button, std::size_t button_id,
110 std::function<void(const Common::ParamPackage&)> new_input_setter, 110 std::function<void(const Common::ParamPackage&)> new_input_setter,
111 InputCommon::Polling::DeviceType type); 111 InputCommon::Polling::DeviceType type);
112 112
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui
index 1e78b4c10..e76aa484f 100644
--- a/src/yuzu/configuration/configure_input_player.ui
+++ b/src/yuzu/configuration/configure_input_player.ui
@@ -1964,39 +1964,39 @@
1964 </item> 1964 </item>
1965 </layout> 1965 </layout>
1966 </item> 1966 </item>
1967 <item> 1967 <item>
1968 <widget class="QFrame" name="controllerFrame"> 1968 <widget class="PlayerControlPreview" name="controllerFrame">
1969 <property name="sizePolicy"> 1969 <property name="sizePolicy">
1970 <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> 1970 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
1971 <horstretch>0</horstretch> 1971 <horstretch>0</horstretch>
1972 <verstretch>0</verstretch> 1972 <verstretch>0</verstretch>
1973 </sizepolicy> 1973 </sizepolicy>
1974 </property> 1974 </property>
1975 <property name="font"> 1975 <property name="font">
1976 <font> 1976 <font>
1977 <weight>75</weight> 1977 <weight>75</weight>
1978 <bold>true</bold> 1978 <bold>true</bold>
1979 </font> 1979 </font>
1980 </property> 1980 </property>
1981 <property name="styleSheet"> 1981 <property name="styleSheet">
1982 <string notr="true">image: url(:/controller/pro);</string> 1982 <string notr="true">image: url(:/controller/pro);</string>
1983 </property> 1983 </property>
1984 <layout class="QVBoxLayout" name="verticalLayout_4"> 1984 <layout class="QVBoxLayout" name="verticalLayout_4">
1985 <property name="leftMargin"> 1985 <property name="leftMargin">
1986 <number>0</number> 1986 <number>0</number>
1987 </property> 1987 </property>
1988 <property name="topMargin"> 1988 <property name="topMargin">
1989 <number>0</number> 1989 <number>0</number>
1990 </property> 1990 </property>
1991 <property name="rightMargin"> 1991 <property name="rightMargin">
1992 <number>0</number> 1992 <number>0</number>
1993 </property> 1993 </property>
1994 <property name="bottomMargin"> 1994 <property name="bottomMargin">
1995 <number>0</number> 1995 <number>0</number>
1996 </property> 1996 </property>
1997 </layout> 1997 </layout>
1998 </widget> 1998 </widget>
1999 </item> 1999 </item>
2000 <item> 2000 <item>
2001 <layout class="QHBoxLayout" name="miscButtons"> 2001 <layout class="QHBoxLayout" name="miscButtons">
2002 <property name="spacing"> 2002 <property name="spacing">
@@ -3087,6 +3087,14 @@
3087 </item> 3087 </item>
3088 </layout> 3088 </layout>
3089 </widget> 3089 </widget>
3090 <customwidgets>
3091 <customwidget>
3092 <class>PlayerControlPreview</class>
3093 <extends>QFrame</extends>
3094 <header>yuzu/configuration/configure_input_player_widget.h</header>
3095 <container>1</container>
3096 </customwidget>
3097 </customwidgets>
3090 <resources> 3098 <resources>
3091 <include location="../../../dist/icons/controller/controller.qrc"/> 3099 <include location="../../../dist/icons/controller/controller.qrc"/>
3092 </resources> 3100 </resources>
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
new file mode 100644
index 000000000..e3e8bde48
--- /dev/null
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -0,0 +1,2694 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <QMenu>
7#include <QPainter>
8#include <QTimer>
9#include "yuzu/configuration/configure_input_player_widget.h"
10
11PlayerControlPreview::PlayerControlPreview(QWidget* parent) : QFrame(parent) {
12 UpdateColors();
13 QTimer* timer = new QTimer(this);
14 connect(timer, &QTimer::timeout, this, QOverload<>::of(&PlayerControlPreview::UpdateInput));
15
16 // refresh at 60hz
17 timer->start(16);
18}
19
20PlayerControlPreview::~PlayerControlPreview() = default;
21
22void PlayerControlPreview::SetPlayerInput(std::size_t index, const ButtonParam& buttons_param,
23 const AnalogParam& analogs_param) {
24 player_index = index;
25 Settings::ButtonsRaw buttonss;
26 Settings::AnalogsRaw analogs;
27 std::transform(buttons_param.begin(), buttons_param.end(), buttonss.begin(),
28 [](const Common::ParamPackage& param) { return param.Serialize(); });
29 std::transform(analogs_param.begin(), analogs_param.end(), analogs.begin(),
30 [](const Common::ParamPackage& param) { return param.Serialize(); });
31
32 std::transform(buttonss.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
33 buttonss.begin() + Settings::NativeButton::BUTTON_NS_END, buttons.begin(),
34 Input::CreateDevice<Input::ButtonDevice>);
35 std::transform(analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
36 analogs.begin() + Settings::NativeAnalog::STICK_HID_END, sticks.begin(),
37 Input::CreateDevice<Input::AnalogDevice>);
38 UpdateColors();
39}
40void PlayerControlPreview::SetPlayerInputRaw(std::size_t index, const Settings::ButtonsRaw buttons_,
41 Settings::AnalogsRaw analogs_) {
42 player_index = index;
43 std::transform(buttons_.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
44 buttons_.begin() + Settings::NativeButton::BUTTON_NS_END, buttons.begin(),
45 Input::CreateDevice<Input::ButtonDevice>);
46 std::transform(analogs_.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
47 analogs_.begin() + Settings::NativeAnalog::STICK_HID_END, sticks.begin(),
48 Input::CreateDevice<Input::AnalogDevice>);
49 UpdateColors();
50}
51
52PlayerControlPreview::LedPattern PlayerControlPreview::GetColorPattern(std::size_t index,
53 bool player_on) {
54 if (!player_on) {
55 return {0, 0, 0, 0};
56 }
57
58 switch (index) {
59 case 0:
60 return {1, 0, 0, 0};
61 case 1:
62 return {1, 1, 0, 0};
63 case 2:
64 return {1, 1, 1, 0};
65 case 3:
66 return {1, 1, 1, 1};
67 case 4:
68 return {1, 0, 0, 1};
69 case 5:
70 return {1, 0, 1, 0};
71 case 6:
72 return {1, 0, 1, 1};
73 case 7:
74 return {0, 1, 1, 0};
75 default:
76 return {0, 0, 0, 0};
77 }
78}
79
80void PlayerControlPreview::SetConnectedStatus(bool checked) {
81 LedPattern led_pattern = GetColorPattern(player_index, checked);
82
83 led_color[0] = led_pattern.position1 ? colors.led_on : colors.led_off;
84 led_color[1] = led_pattern.position2 ? colors.led_on : colors.led_off;
85 led_color[2] = led_pattern.position3 ? colors.led_on : colors.led_off;
86 led_color[3] = led_pattern.position4 ? colors.led_on : colors.led_off;
87}
88
89void PlayerControlPreview::SetControllerType(const Settings::ControllerType type) {
90 controller_type = type;
91 UpdateColors();
92}
93
94void PlayerControlPreview::BeginMappingButton(std::size_t index) {
95 button_mapping_index = index;
96 mapping_active = true;
97}
98
99void PlayerControlPreview::BeginMappingAnalog(std::size_t index) {
100 button_mapping_index = Settings::NativeButton::LStick + index;
101 analog_mapping_index = index;
102 mapping_active = true;
103}
104
105void PlayerControlPreview::EndMapping() {
106 button_mapping_index = Settings::NativeButton::BUTTON_NS_END;
107 analog_mapping_index = Settings::NativeAnalog::NumAnalogs;
108 mapping_active = false;
109 blink_counter = 0;
110}
111
112void PlayerControlPreview::UpdateColors() {
113 if (QIcon::themeName().contains(QStringLiteral("dark")) ||
114 QIcon::themeName().contains(QStringLiteral("midnight"))) {
115 colors.primary = QColor(204, 204, 204);
116 colors.button = QColor(35, 38, 41);
117 colors.button2 = QColor(26, 27, 30);
118 colors.slider_arrow = QColor(14, 15, 18);
119 colors.font2 = QColor(255, 255, 255);
120 colors.indicator = QColor(170, 238, 255);
121 colors.deadzone = QColor(204, 136, 136);
122 colors.slider_button = colors.button;
123 }
124
125 if (QIcon::themeName().contains(QStringLiteral("dark"))) {
126 colors.outline = QColor(160, 160, 160);
127 } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
128 colors.outline = QColor(145, 145, 145);
129 } else {
130 colors.outline = QColor(0, 0, 0);
131 colors.primary = QColor(225, 225, 225);
132 colors.button = QColor(109, 111, 114);
133 colors.button2 = QColor(109, 111, 114);
134 colors.button2 = QColor(77, 80, 84);
135 colors.slider_arrow = QColor(65, 68, 73);
136 colors.font2 = QColor(0, 0, 0);
137 colors.indicator = QColor(0, 0, 200);
138 colors.deadzone = QColor(170, 0, 0);
139 colors.slider_button = QColor(153, 149, 149);
140 }
141
142 // Constant colors
143 colors.highlight = QColor(170, 0, 0);
144 colors.highlight2 = QColor(119, 0, 0);
145 colors.slider = QColor(103, 106, 110);
146 colors.transparent = QColor(0, 0, 0, 0);
147 colors.font = QColor(255, 255, 255);
148 colors.led_on = QColor(255, 255, 0);
149 colors.led_off = QColor(170, 238, 255);
150
151 colors.left = colors.primary;
152 colors.right = colors.primary;
153 // Possible alternative to set colors from settings
154 // colors.left = QColor(Settings::values.players.GetValue()[player_index].body_color_left);
155 // colors.right = QColor(Settings::values.players.GetValue()[player_index].body_color_right);
156}
157
158void PlayerControlPreview::UpdateInput() {
159 bool input_changed = false;
160 const auto& button_state = buttons;
161 for (std::size_t index = 0; index < button_values.size(); ++index) {
162 bool value = false;
163 if (index < Settings::NativeButton::BUTTON_NS_END) {
164 value = button_state[index]->GetStatus();
165 }
166 bool blink = mapping_active && index == button_mapping_index;
167 if (analog_mapping_index == Settings::NativeAnalog::NUM_STICKS_HID) {
168 blink &= blink_counter > 25;
169 }
170 if (button_values[index] != value || blink) {
171 input_changed = true;
172 }
173 button_values[index] = value || blink;
174 }
175
176 const auto& analog_state = sticks;
177 for (std::size_t index = 0; index < axis_values.size(); ++index) {
178 const auto [stick_x_f, stick_y_f] = analog_state[index]->GetStatus();
179 const auto [stick_x_rf, stick_y_rf] = analog_state[index]->GetRawStatus();
180
181 if (static_cast<int>(stick_x_rf * 45) !=
182 static_cast<int>(axis_values[index].raw_value.x() * 45) ||
183 static_cast<int>(-stick_y_rf * 45) !=
184 static_cast<int>(axis_values[index].raw_value.y() * 45)) {
185 input_changed = true;
186 }
187
188 axis_values[index].properties = analog_state[index]->GetAnalogProperties();
189 axis_values[index].value = QPointF(stick_x_f, -stick_y_f);
190 axis_values[index].raw_value = QPointF(stick_x_rf, -stick_y_rf);
191
192 const bool blink_analog = mapping_active && index == analog_mapping_index;
193 if (blink_analog) {
194 input_changed = true;
195 axis_values[index].value =
196 QPointF(blink_counter < 25 ? -blink_counter / 25.0f : 0,
197 blink_counter > 25 ? -(blink_counter - 25) / 25.0f : 0);
198 }
199 }
200
201 if (input_changed) {
202 update();
203 }
204
205 if (mapping_active) {
206 blink_counter = (blink_counter + 1) % 50;
207 }
208}
209
210void PlayerControlPreview::paintEvent(QPaintEvent* event) {
211 QFrame::paintEvent(event);
212 QPainter p(this);
213 p.setRenderHint(QPainter::Antialiasing);
214 const QPointF center = rect().center();
215
216 switch (controller_type) {
217 case Settings::ControllerType::Handheld:
218 DrawHandheldController(p, center);
219 break;
220 case Settings::ControllerType::DualJoyconDetached:
221 DrawDualController(p, center);
222 break;
223 case Settings::ControllerType::LeftJoycon:
224 DrawLeftController(p, center);
225 break;
226 case Settings::ControllerType::RightJoycon:
227 DrawRightController(p, center);
228 break;
229 case Settings::ControllerType::ProController:
230 default:
231 DrawProController(p, center);
232 break;
233 }
234}
235
236void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center) {
237 {
238 using namespace Settings::NativeButton;
239
240 // Sideview left joystick
241 DrawJoystickSideview(p, center + QPoint(142, -69),
242 -axis_values[Settings::NativeAnalog::LStick].value.y(), 1.15f,
243 button_values[LStick]);
244
245 // Topview D-pad buttons
246 p.setPen(colors.outline);
247 button_color = colors.button;
248 DrawRoundButton(p, center + QPoint(-163, -21), button_values[DLeft], 11, 5, Direction::Up);
249 DrawRoundButton(p, center + QPoint(-117, -21), button_values[DRight], 11, 5, Direction::Up);
250
251 // Topview left joystick
252 DrawJoystickSideview(p, center + QPointF(-140.5f, -28),
253 -axis_values[Settings::NativeAnalog::LStick].value.x() + 15.0f, 1.15f,
254 button_values[LStick]);
255
256 // Topview minus button
257 p.setPen(colors.outline);
258 button_color = colors.button;
259 DrawRoundButton(p, center + QPoint(-111, -22), button_values[Minus], 8, 4, Direction::Up,
260 1);
261
262 // Left trigger
263 DrawLeftTriggers(p, center, button_values[L]);
264 DrawRoundButton(p, center + QPoint(151, -146), button_values[L], 8, 4, Direction::Down);
265 DrawLeftZTriggers(p, center, button_values[ZL]);
266
267 // Sideview D-pad buttons
268 DrawRoundButton(p, center + QPoint(135, 14), button_values[DLeft], 5, 11, Direction::Right);
269 DrawRoundButton(p, center + QPoint(135, 36), button_values[DDown], 5, 11, Direction::Right);
270 DrawRoundButton(p, center + QPoint(135, -10), button_values[DUp], 5, 11, Direction::Right);
271 DrawRoundButton(p, center + QPoint(135, 14), button_values[DRight], 5, 11,
272 Direction::Right);
273 DrawRoundButton(p, center + QPoint(135, 71), button_values[Screenshot], 3, 8,
274 Direction::Right, 1);
275
276 // Sideview minus button
277 DrawRoundButton(p, center + QPoint(135, -118), button_values[Minus], 4, 2.66f,
278 Direction::Right, 1);
279
280 // Sideview SL and SR buttons
281 button_color = colors.slider_button;
282 DrawRoundButton(p, center + QPoint(59, 52), button_values[SR], 5, 12, Direction::Left);
283 DrawRoundButton(p, center + QPoint(59, -69), button_values[SL], 5, 12, Direction::Left);
284
285 DrawLeftBody(p, center);
286
287 // Left trigger top view
288 DrawLeftTriggersTopView(p, center, button_values[L]);
289 DrawLeftZTriggersTopView(p, center, button_values[ZL]);
290 }
291
292 {
293 // Draw joysticks
294 using namespace Settings::NativeAnalog;
295 DrawJoystick(p, center + QPointF(9, -69) + (axis_values[LStick].value * 8), 1.8f,
296 button_values[Settings::NativeButton::LStick]);
297 DrawRawJoystick(p, center + QPointF(-140, 90), axis_values[LStick].raw_value,
298 axis_values[LStick].properties);
299 }
300
301 using namespace Settings::NativeButton;
302
303 // D-pad constants
304 const QPointF dpad_center = center + QPoint(9, 14);
305 constexpr int dpad_distance = 23;
306 constexpr int dpad_radius = 11;
307 constexpr float dpad_arrow_size = 1.2f;
308
309 // D-pad buttons
310 p.setPen(colors.outline);
311 button_color = colors.button;
312 DrawCircleButton(p, dpad_center + QPoint(dpad_distance, 0), button_values[DRight], dpad_radius);
313 DrawCircleButton(p, dpad_center + QPoint(0, dpad_distance), button_values[DDown], dpad_radius);
314 DrawCircleButton(p, dpad_center + QPoint(0, -dpad_distance), button_values[DUp], dpad_radius);
315 DrawCircleButton(p, dpad_center + QPoint(-dpad_distance, 0), button_values[DLeft], dpad_radius);
316
317 // D-pad arrows
318 p.setPen(colors.font2);
319 p.setBrush(colors.font2);
320 DrawArrow(p, dpad_center + QPoint(dpad_distance, 0), Direction::Right, dpad_arrow_size);
321 DrawArrow(p, dpad_center + QPoint(0, dpad_distance), Direction::Down, dpad_arrow_size);
322 DrawArrow(p, dpad_center + QPoint(0, -dpad_distance), Direction::Up, dpad_arrow_size);
323 DrawArrow(p, dpad_center + QPoint(-dpad_distance, 0), Direction::Left, dpad_arrow_size);
324
325 // SR and SL buttons
326 p.setPen(colors.outline);
327 button_color = colors.slider_button;
328 DrawRoundButton(p, center + QPoint(155, 52), button_values[SR], 5.2f, 12, Direction::None, 4);
329 DrawRoundButton(p, center + QPoint(155, -69), button_values[SL], 5.2f, 12, Direction::None, 4);
330
331 // SR and SL text
332 p.setPen(colors.transparent);
333 p.setBrush(colors.font2);
334 DrawSymbol(p, center + QPointF(155, 52), Symbol::SR, 1.0f);
335 DrawSymbol(p, center + QPointF(155, -69), Symbol::SL, 1.0f);
336
337 // Minus button
338 button_color = colors.button;
339 DrawMinusButton(p, center + QPoint(39, -118), button_values[Minus], 16);
340
341 // Screenshot button
342 DrawRoundButton(p, center + QPoint(26, 71), button_values[Screenshot], 8, 8);
343 p.setPen(colors.font2);
344 p.setBrush(colors.font2);
345 DrawCircle(p, center + QPoint(26, 71), 5);
346}
347
348void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center) {
349 {
350 using namespace Settings::NativeButton;
351
352 // Sideview right joystick
353 DrawJoystickSideview(p, center + QPoint(173 - 315, 11),
354 axis_values[Settings::NativeAnalog::RStick].value.y() + 10.0f, 1.15f,
355 button_values[Settings::NativeButton::RStick]);
356
357 // Topview face buttons
358 p.setPen(colors.outline);
359 button_color = colors.button;
360 DrawRoundButton(p, center + QPoint(163, -21), button_values[A], 11, 5, Direction::Up);
361 DrawRoundButton(p, center + QPoint(117, -21), button_values[Y], 11, 5, Direction::Up);
362
363 // Topview right joystick
364 DrawJoystickSideview(p, center + QPointF(140, -28),
365 -axis_values[Settings::NativeAnalog::RStick].value.x() + 15.0f, 1.15f,
366 button_values[RStick]);
367
368 // Topview plus button
369 p.setPen(colors.outline);
370 button_color = colors.button;
371 DrawRoundButton(p, center + QPoint(111, -22), button_values[Plus], 8, 4, Direction::Up, 1);
372 DrawRoundButton(p, center + QPoint(111, -22), button_values[Plus], 2.66f, 4, Direction::Up,
373 1);
374
375 // Right trigger
376 p.setPen(colors.outline);
377 button_color = colors.button;
378 DrawRightTriggers(p, center, button_values[R]);
379 DrawRoundButton(p, center + QPoint(-151, -146), button_values[R], 8, 4, Direction::Down);
380 DrawRightZTriggers(p, center, button_values[ZR]);
381
382 // Sideview face buttons
383 DrawRoundButton(p, center + QPoint(-135, -73), button_values[A], 5, 11, Direction::Left);
384 DrawRoundButton(p, center + QPoint(-135, -50), button_values[B], 5, 11, Direction::Left);
385 DrawRoundButton(p, center + QPoint(-135, -95), button_values[X], 5, 11, Direction::Left);
386 DrawRoundButton(p, center + QPoint(-135, -73), button_values[Y], 5, 11, Direction::Left);
387
388 // Sideview home and plus button
389 DrawRoundButton(p, center + QPoint(-135, 66), button_values[Home], 3, 12, Direction::Left);
390 DrawRoundButton(p, center + QPoint(-135, -118), button_values[Plus], 4, 8, Direction::Left,
391 1);
392 DrawRoundButton(p, center + QPoint(-135, -118), button_values[Plus], 4, 2.66f,
393 Direction::Left, 1);
394
395 // Sideview SL and SR buttons
396 button_color = colors.slider_button;
397 DrawRoundButton(p, center + QPoint(-59, 52), button_values[SL], 5, 11, Direction::Right);
398 DrawRoundButton(p, center + QPoint(-59, -69), button_values[SR], 5, 11, Direction::Right);
399
400 DrawRightBody(p, center);
401
402 // Right trigger top view
403 DrawRightTriggersTopView(p, center, button_values[R]);
404 DrawRightZTriggersTopView(p, center, button_values[ZR]);
405 }
406
407 {
408 // Draw joysticks
409 using namespace Settings::NativeAnalog;
410 DrawJoystick(p, center + QPointF(-9, 11) + (axis_values[RStick].value * 8), 1.8f,
411 button_values[Settings::NativeButton::RStick]);
412 DrawRawJoystick(p, center + QPointF(140, 90), axis_values[RStick].raw_value,
413 axis_values[RStick].properties);
414 }
415
416 using namespace Settings::NativeButton;
417
418 // Face buttons constants
419 const QPointF face_center = center + QPoint(-9, -73);
420 constexpr int face_distance = 23;
421 constexpr int face_radius = 11;
422 constexpr float text_size = 1.1f;
423
424 // Face buttons
425 p.setPen(colors.outline);
426 button_color = colors.button;
427 DrawCircleButton(p, face_center + QPoint(face_distance, 0), button_values[A], face_radius);
428 DrawCircleButton(p, face_center + QPoint(0, face_distance), button_values[B], face_radius);
429 DrawCircleButton(p, face_center + QPoint(0, -face_distance), button_values[X], face_radius);
430 DrawCircleButton(p, face_center + QPoint(-face_distance, 0), button_values[Y], face_radius);
431
432 // Face buttons text
433 p.setPen(colors.transparent);
434 p.setBrush(colors.font);
435 DrawSymbol(p, face_center + QPoint(face_distance, 0), Symbol::A, text_size);
436 DrawSymbol(p, face_center + QPoint(0, face_distance), Symbol::B, text_size);
437 DrawSymbol(p, face_center + QPoint(0, -face_distance), Symbol::X, text_size);
438 DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size);
439
440 // SR and SL buttons
441 p.setPen(colors.outline);
442 button_color = colors.slider_button;
443 DrawRoundButton(p, center + QPoint(-155, 52), button_values[SL], 5, 12, Direction::None, 4.0f);
444 DrawRoundButton(p, center + QPoint(-155, -69), button_values[SR], 5, 12, Direction::None, 4.0f);
445
446 // SR and SL text
447 p.setPen(colors.transparent);
448 p.setBrush(colors.font2);
449 p.rotate(-180);
450 DrawSymbol(p, QPointF(-center.x(), -center.y()) + QPointF(155, 69), Symbol::SR, 1.0f);
451 DrawSymbol(p, QPointF(-center.x(), -center.y()) + QPointF(155, -52), Symbol::SL, 1.0f);
452 p.rotate(180);
453
454 // Plus Button
455 DrawPlusButton(p, center + QPoint(-40, -118), button_values[Plus], 16);
456
457 // Home Button
458 p.setPen(colors.outline);
459 button_color = colors.slider_button;
460 DrawCircleButton(p, center + QPoint(-26, 66), button_values[Home], 12);
461 button_color = colors.button;
462 DrawCircleButton(p, center + QPoint(-26, 66), button_values[Home], 9);
463 p.setPen(colors.transparent);
464 p.setBrush(colors.font2);
465 DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5);
466}
467
468void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) {
469 {
470 using namespace Settings::NativeButton;
471
472 // Left/Right trigger
473 DrawDualTriggers(p, center, button_values[L], button_values[R]);
474
475 // Topview face buttons
476 p.setPen(colors.outline);
477 button_color = colors.button;
478 DrawRoundButton(p, center + QPoint(200, -71), button_values[A], 10, 5, Direction::Up);
479 DrawRoundButton(p, center + QPoint(160, -71), button_values[Y], 10, 5, Direction::Up);
480
481 // Topview right joystick
482 DrawJoystickSideview(p, center + QPointF(180, -78),
483 -axis_values[Settings::NativeAnalog::RStick].value.x() + 15.0f, 1,
484 button_values[RStick]);
485
486 // Topview plus button
487 p.setPen(colors.outline);
488 button_color = colors.button;
489 DrawRoundButton(p, center + QPoint(154, -72), button_values[Plus], 7, 4, Direction::Up, 1);
490 DrawRoundButton(p, center + QPoint(154, -72), button_values[Plus], 2.33f, 4, Direction::Up,
491 1);
492
493 // Topview D-pad buttons
494 p.setPen(colors.outline);
495 button_color = colors.button;
496 DrawRoundButton(p, center + QPoint(-200, -71), button_values[DLeft], 10, 5, Direction::Up);
497 DrawRoundButton(p, center + QPoint(-160, -71), button_values[DRight], 10, 5, Direction::Up);
498
499 // Topview left joystick
500 DrawJoystickSideview(p, center + QPointF(-180.5f, -78),
501 -axis_values[Settings::NativeAnalog::LStick].value.x() + 15.0f, 1,
502 button_values[LStick]);
503
504 // Topview minus button
505 p.setPen(colors.outline);
506 button_color = colors.button;
507 DrawRoundButton(p, center + QPoint(-154, -72), button_values[Minus], 7, 4, Direction::Up,
508 1);
509
510 DrawDualBody(p, center);
511
512 // Right trigger top view
513 DrawDualTriggersTopView(p, center, button_values[L], button_values[R]);
514 DrawDualZTriggersTopView(p, center, button_values[ZL], button_values[ZR]);
515 }
516
517 {
518 // Draw joysticks
519 using namespace Settings::NativeAnalog;
520 DrawJoystick(p, center + QPointF(-65, -65) + (axis_values[LStick].value * 7), 1.62f,
521 button_values[Settings::NativeButton::LStick]);
522 DrawJoystick(p, center + QPointF(65, 12) + (axis_values[RStick].value * 7), 1.62f,
523 button_values[Settings::NativeButton::RStick]);
524 DrawRawJoystick(p, center + QPointF(-180, 90), axis_values[LStick].raw_value,
525 axis_values[LStick].properties);
526 DrawRawJoystick(p, center + QPointF(180, 90), axis_values[RStick].raw_value,
527 axis_values[RStick].properties);
528 }
529
530 using namespace Settings::NativeButton;
531
532 // Face buttons constants
533 const QPointF face_center = center + QPoint(65, -65);
534 constexpr int face_distance = 20;
535 constexpr int face_radius = 10;
536 constexpr float text_size = 1.0f;
537
538 // Face buttons
539 p.setPen(colors.outline);
540 button_color = colors.button;
541 DrawCircleButton(p, face_center + QPoint(face_distance, 0), button_values[A], face_radius);
542 DrawCircleButton(p, face_center + QPoint(0, face_distance), button_values[B], face_radius);
543 DrawCircleButton(p, face_center + QPoint(0, -face_distance), button_values[X], face_radius);
544 DrawCircleButton(p, face_center + QPoint(-face_distance, 0), button_values[Y], face_radius);
545
546 // Face buttons text
547 p.setPen(colors.transparent);
548 p.setBrush(colors.font);
549 DrawSymbol(p, face_center + QPoint(face_distance, 0), Symbol::A, text_size);
550 DrawSymbol(p, face_center + QPoint(0, face_distance), Symbol::B, text_size);
551 DrawSymbol(p, face_center + QPoint(0, -face_distance), Symbol::X, text_size);
552 DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size);
553
554 // D-pad constants
555 const QPointF dpad_center = center + QPoint(-65, 12);
556 constexpr int dpad_distance = 20;
557 constexpr int dpad_radius = 10;
558 constexpr float dpad_arrow_size = 1.1f;
559
560 // D-pad buttons
561 p.setPen(colors.outline);
562 button_color = colors.button;
563 DrawCircleButton(p, dpad_center + QPoint(dpad_distance, 0), button_values[DRight], dpad_radius);
564 DrawCircleButton(p, dpad_center + QPoint(0, dpad_distance), button_values[DDown], dpad_radius);
565 DrawCircleButton(p, dpad_center + QPoint(0, -dpad_distance), button_values[DUp], dpad_radius);
566 DrawCircleButton(p, dpad_center + QPoint(-dpad_distance, 0), button_values[DLeft], dpad_radius);
567
568 // D-pad arrows
569 p.setPen(colors.font2);
570 p.setBrush(colors.font2);
571 DrawArrow(p, dpad_center + QPoint(dpad_distance, 0), Direction::Right, dpad_arrow_size);
572 DrawArrow(p, dpad_center + QPoint(0, dpad_distance), Direction::Down, dpad_arrow_size);
573 DrawArrow(p, dpad_center + QPoint(0, -dpad_distance), Direction::Up, dpad_arrow_size);
574 DrawArrow(p, dpad_center + QPoint(-dpad_distance, 0), Direction::Left, dpad_arrow_size);
575
576 // Minus and Plus button
577 button_color = colors.button;
578 DrawMinusButton(p, center + QPoint(-39, -106), button_values[Minus], 14);
579 DrawPlusButton(p, center + QPoint(39, -106), button_values[Plus], 14);
580
581 // Screenshot button
582 p.setPen(colors.outline);
583 DrawRoundButton(p, center + QPoint(-52, 63), button_values[Screenshot], 8, 8);
584 p.setPen(colors.font2);
585 p.setBrush(colors.font2);
586 DrawCircle(p, center + QPoint(-52, 63), 5);
587
588 // Home Button
589 p.setPen(colors.outline);
590 button_color = colors.slider_button;
591 DrawCircleButton(p, center + QPoint(50, 60), button_values[Home], 11);
592 button_color = colors.button;
593 DrawCircleButton(p, center + QPoint(50, 60), button_values[Home], 8.5f);
594 p.setPen(colors.transparent);
595 p.setBrush(colors.font2);
596 DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f);
597}
598
599void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF center) {
600 DrawHandheldTriggers(p, center, button_values[Settings::NativeButton::L],
601 button_values[Settings::NativeButton::R]);
602 DrawHandheldBody(p, center);
603 {
604 // Draw joysticks
605 using namespace Settings::NativeAnalog;
606 DrawJoystick(p, center + QPointF(-171, -41) + (axis_values[LStick].value * 4), 1.0f,
607 button_values[Settings::NativeButton::LStick]);
608 DrawJoystick(p, center + QPointF(171, 8) + (axis_values[RStick].value * 4), 1.0f,
609 button_values[Settings::NativeButton::RStick]);
610 DrawRawJoystick(p, center + QPointF(-50, 0), axis_values[LStick].raw_value,
611 axis_values[LStick].properties);
612 DrawRawJoystick(p, center + QPointF(50, 0), axis_values[RStick].raw_value,
613 axis_values[RStick].properties);
614 }
615
616 using namespace Settings::NativeButton;
617
618 // Face buttons constants
619 const QPointF face_center = center + QPoint(171, -41);
620 constexpr float face_distance = 12.8f;
621 constexpr float face_radius = 6.4f;
622 constexpr float text_size = 0.6f;
623
624 // Face buttons
625 p.setPen(colors.outline);
626 button_color = colors.button;
627 DrawCircleButton(p, face_center + QPoint(face_distance, 0), button_values[A], face_radius);
628 DrawCircleButton(p, face_center + QPoint(0, face_distance), button_values[B], face_radius);
629 DrawCircleButton(p, face_center + QPoint(0, -face_distance), button_values[X], face_radius);
630 DrawCircleButton(p, face_center + QPoint(-face_distance, 0), button_values[Y], face_radius);
631
632 // Face buttons text
633 p.setPen(colors.transparent);
634 p.setBrush(colors.font);
635 DrawSymbol(p, face_center + QPoint(face_distance, 0), Symbol::A, text_size);
636 DrawSymbol(p, face_center + QPoint(0, face_distance), Symbol::B, text_size);
637 DrawSymbol(p, face_center + QPoint(0, -face_distance), Symbol::X, text_size);
638 DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size);
639
640 // D-pad constants
641 const QPointF dpad_center = center + QPoint(-171, 8);
642 constexpr float dpad_distance = 12.8f;
643 constexpr float dpad_radius = 6.4f;
644 constexpr float dpad_arrow_size = 0.68f;
645
646 // D-pad buttons
647 p.setPen(colors.outline);
648 button_color = colors.button;
649 DrawCircleButton(p, dpad_center + QPoint(dpad_distance, 0), button_values[DRight], dpad_radius);
650 DrawCircleButton(p, dpad_center + QPoint(0, dpad_distance), button_values[DDown], dpad_radius);
651 DrawCircleButton(p, dpad_center + QPoint(0, -dpad_distance), button_values[DUp], dpad_radius);
652 DrawCircleButton(p, dpad_center + QPoint(-dpad_distance, 0), button_values[DLeft], dpad_radius);
653
654 // D-pad arrows
655 p.setPen(colors.font2);
656 p.setBrush(colors.font2);
657 DrawArrow(p, dpad_center + QPoint(dpad_distance, 0), Direction::Right, dpad_arrow_size);
658 DrawArrow(p, dpad_center + QPoint(0, dpad_distance), Direction::Down, dpad_arrow_size);
659 DrawArrow(p, dpad_center + QPoint(0, -dpad_distance), Direction::Up, dpad_arrow_size);
660 DrawArrow(p, dpad_center + QPoint(-dpad_distance, 0), Direction::Left, dpad_arrow_size);
661
662 // ZL and ZR buttons
663 p.setPen(colors.outline);
664 DrawTriggerButton(p, center + QPoint(-210, -130), Direction::Left, button_values[ZL]);
665 DrawTriggerButton(p, center + QPoint(210, -130), Direction::Right, button_values[ZR]);
666 p.setPen(colors.transparent);
667 p.setBrush(colors.font);
668 DrawSymbol(p, center + QPoint(-210, -130), Symbol::ZL, 1.5f);
669 DrawSymbol(p, center + QPoint(210, -130), Symbol::ZR, 1.5f);
670
671 // Minus and Plus button
672 p.setPen(colors.outline);
673 button_color = colors.button;
674 DrawMinusButton(p, center + QPoint(-155, -67), button_values[Minus], 8);
675 DrawPlusButton(p, center + QPoint(155, -67), button_values[Plus], 8);
676
677 // Screenshot button
678 p.setPen(colors.outline);
679 DrawRoundButton(p, center + QPoint(-162, 39), button_values[Screenshot], 5, 5);
680 p.setPen(colors.font2);
681 p.setBrush(colors.font2);
682 DrawCircle(p, center + QPoint(-162, 39), 3);
683
684 // Home Button
685 p.setPen(colors.outline);
686 button_color = colors.slider_button;
687 DrawCircleButton(p, center + QPoint(161, 37), button_values[Home], 7);
688 button_color = colors.button;
689 DrawCircleButton(p, center + QPoint(161, 37), button_values[Home], 5);
690 p.setPen(colors.transparent);
691 p.setBrush(colors.font2);
692 DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f);
693}
694
695void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) {
696 DrawProTriggers(p, center, button_values[Settings::NativeButton::L],
697 button_values[Settings::NativeButton::R]);
698 DrawProBody(p, center);
699 {
700 // Draw joysticks
701 using namespace Settings::NativeAnalog;
702 DrawProJoystick(p, center + QPointF(-111, -55) + (axis_values[LStick].value * 11),
703 button_values[Settings::NativeButton::LStick]);
704 DrawProJoystick(p, center + QPointF(51, 0) + (axis_values[RStick].value * 11),
705 button_values[Settings::NativeButton::RStick]);
706 DrawRawJoystick(p, center + QPointF(-50, 105), axis_values[LStick].raw_value,
707 axis_values[LStick].properties);
708 DrawRawJoystick(p, center + QPointF(50, 105), axis_values[RStick].raw_value,
709 axis_values[RStick].properties);
710 }
711
712 using namespace Settings::NativeButton;
713
714 // Face buttons constants
715 const QPointF face_center = center + QPoint(105, -56);
716 constexpr int face_distance = 31;
717 constexpr int face_radius = 15;
718 constexpr float text_size = 1.5f;
719
720 // Face buttons
721 p.setPen(colors.outline);
722 button_color = colors.button;
723 DrawCircleButton(p, face_center + QPoint(face_distance, 0), button_values[A], face_radius);
724 DrawCircleButton(p, face_center + QPoint(0, face_distance), button_values[B], face_radius);
725 DrawCircleButton(p, face_center + QPoint(0, -face_distance), button_values[X], face_radius);
726 DrawCircleButton(p, face_center + QPoint(-face_distance, 0), button_values[Y], face_radius);
727
728 // Face buttons text
729 p.setPen(colors.transparent);
730 p.setBrush(colors.font);
731 DrawSymbol(p, face_center + QPoint(face_distance, 0), Symbol::A, text_size);
732 DrawSymbol(p, face_center + QPoint(0, face_distance), Symbol::B, text_size);
733 DrawSymbol(p, face_center + QPoint(0, -face_distance), Symbol::X, text_size);
734 DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size);
735
736 // D-pad buttons
737 const QPointF dpad_postion = center + QPoint(-61, 0);
738 DrawArrowButton(p, dpad_postion, Direction::Up, button_values[DUp]);
739 DrawArrowButton(p, dpad_postion, Direction::Left, button_values[DLeft]);
740 DrawArrowButton(p, dpad_postion, Direction::Right, button_values[DRight]);
741 DrawArrowButton(p, dpad_postion, Direction::Down, button_values[DDown]);
742 DrawArrowButtonOutline(p, dpad_postion);
743
744 // ZL and ZR buttons
745 p.setPen(colors.outline);
746 DrawTriggerButton(p, center + QPoint(-210, -130), Direction::Left, button_values[ZL]);
747 DrawTriggerButton(p, center + QPoint(210, -130), Direction::Right, button_values[ZR]);
748 p.setPen(colors.transparent);
749 p.setBrush(colors.font);
750 DrawSymbol(p, center + QPoint(-210, -130), Symbol::ZL, 1.5f);
751 DrawSymbol(p, center + QPoint(210, -130), Symbol::ZR, 1.5f);
752
753 // Minus and Plus buttons
754 p.setPen(colors.outline);
755 DrawCircleButton(p, center + QPoint(-50, -86), button_values[Minus], 9);
756 DrawCircleButton(p, center + QPoint(50, -86), button_values[Plus], 9);
757
758 // Minus and Plus symbols
759 p.setPen(colors.font2);
760 p.setBrush(colors.font2);
761 DrawRectangle(p, center + QPoint(-50, -86), 9, 1.5f);
762 DrawRectangle(p, center + QPoint(50, -86), 9, 1.5f);
763 DrawRectangle(p, center + QPoint(50, -86), 1.5f, 9);
764
765 // Screenshot button
766 p.setPen(colors.outline);
767 DrawRoundButton(p, center + QPoint(-29, -56), button_values[Screenshot], 7, 7);
768 p.setPen(colors.font2);
769 p.setBrush(colors.font2);
770 DrawCircle(p, center + QPoint(-29, -56), 4.5f);
771
772 // Home Button
773 p.setPen(colors.outline);
774 button_color = colors.slider_button;
775 DrawCircleButton(p, center + QPoint(29, -56), button_values[Home], 10.0f);
776 button_color = colors.button;
777 DrawCircleButton(p, center + QPoint(29, -56), button_values[Home], 7.1f);
778 p.setPen(colors.transparent);
779 p.setBrush(colors.font2);
780 DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f);
781}
782
783void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
784 DrawGCTriggers(p, center, button_values[Settings::NativeButton::ZL],
785 button_values[Settings::NativeButton::ZR]);
786 DrawGCButtonZ(p, center, button_values[Settings::NativeButton::R]);
787 DrawGCBody(p, center);
788 {
789 // Draw joysticks
790 using namespace Settings::NativeAnalog;
791 DrawGCJoystick(p, center + QPointF(-111, -44) + (axis_values[LStick].value * 10), false);
792 button_color = colors.button2;
793 DrawCircleButton(p, center + QPointF(61, 37) + (axis_values[RStick].value * 9.5f), false,
794 15);
795 p.setPen(colors.transparent);
796 p.setBrush(colors.font);
797 DrawSymbol(p, center + QPointF(61, 37) + (axis_values[RStick].value * 9.5f), Symbol::C,
798 1.0f);
799 DrawRawJoystick(p, center + QPointF(-198, -125), axis_values[LStick].raw_value,
800 axis_values[LStick].properties);
801 DrawRawJoystick(p, center + QPointF(198, -125), axis_values[RStick].raw_value,
802 axis_values[RStick].properties);
803 }
804
805 using namespace Settings::NativeButton;
806
807 // Face buttons constants
808 constexpr float text_size = 1.1f;
809
810 // Face buttons
811 p.setPen(colors.outline);
812 button_color = colors.button;
813 DrawCircleButton(p, center + QPoint(111, -44), button_values[A], 21);
814 DrawCircleButton(p, center + QPoint(70, -23), button_values[B], 13);
815 DrawGCButtonX(p, center, button_values[Settings::NativeButton::X]);
816 DrawGCButtonY(p, center, button_values[Settings::NativeButton::Y]);
817
818 // Face buttons text
819 p.setPen(colors.transparent);
820 p.setBrush(colors.font);
821 DrawSymbol(p, center + QPoint(111, -44), Symbol::A, 1.5f);
822 DrawSymbol(p, center + QPoint(70, -23), Symbol::B, text_size);
823 DrawSymbol(p, center + QPoint(151, -53), Symbol::X, text_size);
824 DrawSymbol(p, center + QPoint(100, -83), Symbol::Y, text_size);
825
826 // D-pad buttons
827 const QPointF dpad_postion = center + QPoint(-61, 37);
828 const float dpad_size = 0.8f;
829 DrawArrowButton(p, dpad_postion, Direction::Up, button_values[DUp], dpad_size);
830 DrawArrowButton(p, dpad_postion, Direction::Left, button_values[DLeft], dpad_size);
831 DrawArrowButton(p, dpad_postion, Direction::Right, button_values[DRight], dpad_size);
832 DrawArrowButton(p, dpad_postion, Direction::Down, button_values[DDown], dpad_size);
833 DrawArrowButtonOutline(p, dpad_postion, dpad_size);
834
835 // Minus and Plus buttons
836 p.setPen(colors.outline);
837 DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8);
838}
839
840constexpr std::array<float, 13 * 2> symbol_a = {
841 -1.085f, -5.2f, 1.085f, -5.2f, 5.085f, 5.0f, 2.785f, 5.0f, 1.785f,
842 2.65f, -1.785f, 2.65f, -2.785f, 5.0f, -5.085f, 5.0f, -1.4f, 1.0f,
843 0.0f, -2.8f, 1.4f, 1.0f, -1.4f, 1.0f, -5.085f, 5.0f,
844};
845constexpr std::array<float, 134 * 2> symbol_b = {
846 -4.0f, 0.0f, -4.0f, 0.0f, -4.0f, -0.1f, -3.8f, -5.1f, 1.8f, -5.0f, 2.3f, -4.9f, 2.6f,
847 -4.8f, 2.8f, -4.7f, 2.9f, -4.6f, 3.1f, -4.5f, 3.2f, -4.4f, 3.4f, -4.3f, 3.4f, -4.2f,
848 3.5f, -4.1f, 3.7f, -4.0f, 3.7f, -3.9f, 3.8f, -3.8f, 3.8f, -3.7f, 3.9f, -3.6f, 3.9f,
849 -3.5f, 4.0f, -3.4f, 4.0f, -3.3f, 4.1f, -3.1f, 4.1f, -3.0f, 4.0f, -2.0f, 4.0f, -1.9f,
850 3.9f, -1.7f, 3.9f, -1.6f, 3.8f, -1.5f, 3.8f, -1.4f, 3.7f, -1.3f, 3.7f, -1.2f, 3.6f,
851 -1.1f, 3.6f, -1.0f, 3.5f, -0.9f, 3.3f, -0.8f, 3.3f, -0.7f, 3.2f, -0.6f, 3.0f, -0.5f,
852 2.9f, -0.4f, 2.7f, -0.3f, 2.9f, -0.2f, 3.2f, -0.1f, 3.3f, 0.0f, 3.5f, 0.1f, 3.6f,
853 0.2f, 3.8f, 0.3f, 3.9f, 0.4f, 4.0f, 0.6f, 4.1f, 0.7f, 4.3f, 0.8f, 4.3f, 0.9f,
854 4.4f, 1.0f, 4.4f, 1.1f, 4.5f, 1.3f, 4.5f, 1.4f, 4.6f, 1.6f, 4.6f, 1.7f, 4.5f,
855 2.8f, 4.5f, 2.9f, 4.4f, 3.1f, 4.4f, 3.2f, 4.3f, 3.4f, 4.3f, 3.5f, 4.2f, 3.6f,
856 4.2f, 3.7f, 4.1f, 3.8f, 4.1f, 3.9f, 4.0f, 4.0f, 3.9f, 4.2f, 3.8f, 4.3f, 3.6f,
857 4.4f, 3.6f, 4.5f, 3.4f, 4.6f, 3.3f, 4.7f, 3.1f, 4.8f, 2.8f, 4.9f, 2.6f, 5.0f,
858 2.1f, 5.1f, -4.0f, 5.0f, -4.0f, 4.9f,
859
860 -4.0f, 0.0f, 1.1f, 3.4f, 1.1f, 3.4f, 1.5f, 3.3f, 1.8f, 3.2f, 2.0f, 3.1f, 2.1f,
861 3.0f, 2.3f, 2.9f, 2.3f, 2.8f, 2.4f, 2.7f, 2.4f, 2.6f, 2.5f, 2.3f, 2.5f, 2.2f,
862 2.4f, 1.7f, 2.4f, 1.6f, 2.3f, 1.4f, 2.3f, 1.3f, 2.2f, 1.2f, 2.2f, 1.1f, 2.1f,
863 1.0f, 1.9f, 0.9f, 1.6f, 0.8f, 1.4f, 0.7f, -1.9f, 0.6f, -1.9f, 0.7f, -1.8f, 3.4f,
864 1.1f, 3.4f, -4.0f, 0.0f,
865
866 0.3f, -1.1f, 0.3f, -1.1f, 1.3f, -1.2f, 1.5f, -1.3f, 1.8f, -1.4f, 1.8f, -1.5f, 1.9f,
867 -1.6f, 2.0f, -1.8f, 2.0f, -1.9f, 2.1f, -2.0f, 2.1f, -2.1f, 2.0f, -2.7f, 2.0f, -2.8f,
868 1.9f, -2.9f, 1.9f, -3.0f, 1.8f, -3.1f, 1.6f, -3.2f, 1.6f, -3.3f, 1.3f, -3.4f, -1.9f,
869 -3.3f, -1.9f, -3.2f, -1.8f, -1.0f, 0.2f, -1.1f, 0.3f, -1.1f, -4.0f, 0.0f,
870};
871
872constexpr std::array<float, 9 * 2> symbol_y = {
873 -4.79f, -4.9f, -2.44f, -4.9f, 0.0f, -0.9f, 2.44f, -4.9f, 4.79f,
874 -4.9f, 1.05f, 1.0f, 1.05f, 5.31f, -1.05f, 5.31f, -1.05f, 1.0f,
875
876};
877
878constexpr std::array<float, 12 * 2> symbol_x = {
879 -4.4f, -5.0f, -2.0f, -5.0f, 0.0f, -1.7f, 2.0f, -5.0f, 4.4f, -5.0f, 1.2f, 0.0f,
880 4.4f, 5.0f, 2.0f, 5.0f, 0.0f, 1.7f, -2.0f, 5.0f, -4.4f, 5.0f, -1.2f, 0.0f,
881
882};
883
884constexpr std::array<float, 7 * 2> symbol_l = {
885 2.4f, -3.23f, 2.4f, 2.1f, 5.43f, 2.1f, 5.43f, 3.22f, 0.98f, 3.22f, 0.98f, -3.23f, 2.4f, -3.23f,
886};
887
888constexpr std::array<float, 98 * 2> symbol_r = {
889 1.0f, 0.0f, 1.0f, -0.1f, 1.1f, -3.3f, 4.3f, -3.2f, 5.1f, -3.1f, 5.4f, -3.0f, 5.6f, -2.9f,
890 5.7f, -2.8f, 5.9f, -2.7f, 5.9f, -2.6f, 6.0f, -2.5f, 6.1f, -2.3f, 6.2f, -2.2f, 6.2f, -2.1f,
891 6.3f, -2.0f, 6.3f, -1.9f, 6.2f, -0.8f, 6.2f, -0.7f, 6.1f, -0.6f, 6.1f, -0.5f, 6.0f, -0.4f,
892 6.0f, -0.3f, 5.9f, -0.2f, 5.7f, -0.1f, 5.7f, 0.0f, 5.6f, 0.1f, 5.4f, 0.2f, 5.1f, 0.3f,
893 4.7f, 0.4f, 4.7f, 0.5f, 4.9f, 0.6f, 5.0f, 0.7f, 5.2f, 0.8f, 5.2f, 0.9f, 5.3f, 1.0f,
894 5.5f, 1.1f, 5.5f, 1.2f, 5.6f, 1.3f, 5.7f, 1.5f, 5.8f, 1.6f, 5.9f, 1.8f, 6.0f, 1.9f,
895 6.1f, 2.1f, 6.2f, 2.2f, 6.2f, 2.3f, 6.3f, 2.4f, 6.4f, 2.6f, 6.5f, 2.7f, 6.6f, 2.9f,
896 6.7f, 3.0f, 6.7f, 3.1f, 6.8f, 3.2f, 6.8f, 3.3f, 5.3f, 3.2f, 5.2f, 3.1f, 5.2f, 3.0f,
897 5.1f, 2.9f, 5.0f, 2.7f, 4.9f, 2.6f, 4.8f, 2.4f, 4.7f, 2.3f, 4.6f, 2.1f, 4.5f, 2.0f,
898 4.4f, 1.8f, 4.3f, 1.7f, 4.1f, 1.4f, 4.0f, 1.3f, 3.9f, 1.1f, 3.8f, 1.0f, 3.6f, 0.9f,
899 3.6f, 0.8f, 3.5f, 0.7f, 3.3f, 0.6f, 2.9f, 0.5f, 2.3f, 0.6f, 2.3f, 0.7f, 2.2f, 3.3f,
900 1.0f, 3.2f, 1.0f, 3.1f, 1.0f, 0.0f,
901
902 4.2f, -0.5f, 4.4f, -0.6f, 4.7f, -0.7f, 4.8f, -0.8f, 4.9f, -1.0f, 5.0f, -1.1f, 5.0f, -1.2f,
903 4.9f, -1.7f, 4.9f, -1.8f, 4.8f, -1.9f, 4.8f, -2.0f, 4.6f, -2.1f, 4.3f, -2.2f, 2.3f, -2.1f,
904 2.3f, -2.0f, 2.4f, -0.5f, 4.2f, -0.5f, 1.0f, 0.0f,
905};
906
907constexpr std::array<float, 18 * 2> symbol_zl = {
908 -2.6f, -2.13f, -5.6f, -2.13f, -5.6f, -3.23f, -0.8f, -3.23f, -0.8f, -2.13f, -4.4f, 2.12f,
909 -0.7f, 2.12f, -0.7f, 3.22f, -6.0f, 3.22f, -6.0f, 2.12f, 2.4f, -3.23f, 2.4f, 2.1f,
910 5.43f, 2.1f, 5.43f, 3.22f, 0.98f, 3.22f, 0.98f, -3.23f, 2.4f, -3.23f, -6.0f, 2.12f,
911};
912
913constexpr std::array<float, 57 * 2> symbol_sl = {
914 -3.0f, -3.65f, -2.76f, -4.26f, -2.33f, -4.76f, -1.76f, -5.09f, -1.13f, -5.26f, -0.94f,
915 -4.77f, -0.87f, -4.11f, -1.46f, -3.88f, -1.91f, -3.41f, -2.05f, -2.78f, -1.98f, -2.13f,
916 -1.59f, -1.61f, -0.96f, -1.53f, -0.56f, -2.04f, -0.38f, -2.67f, -0.22f, -3.31f, 0.0f,
917 -3.93f, 0.34f, -4.49f, 0.86f, -4.89f, 1.49f, -5.05f, 2.14f, -4.95f, 2.69f, -4.6f,
918 3.07f, -4.07f, 3.25f, -3.44f, 3.31f, -2.78f, 3.25f, -2.12f, 3.07f, -1.49f, 2.7f,
919 -0.95f, 2.16f, -0.58f, 1.52f, -0.43f, 1.41f, -0.99f, 1.38f, -1.65f, 1.97f, -1.91f,
920 2.25f, -2.49f, 2.25f, -3.15f, 1.99f, -3.74f, 1.38f, -3.78f, 1.06f, -3.22f, 0.88f,
921 -2.58f, 0.71f, -1.94f, 0.49f, -1.32f, 0.13f, -0.77f, -0.4f, -0.4f, -1.04f, -0.25f,
922 -1.69f, -0.32f, -2.28f, -0.61f, -2.73f, -1.09f, -2.98f, -1.69f, -3.09f, -2.34f,
923
924 3.23f, 2.4f, -2.1f, 2.4f, -2.1f, 5.43f, -3.22f, 5.43f, -3.22f, 0.98f, 3.23f,
925 0.98f, 3.23f, 2.4f, -3.09f, -2.34f,
926};
927constexpr std::array<float, 109 * 2> symbol_zr = {
928 -2.6f, -2.13f, -5.6f, -2.13f, -5.6f, -3.23f, -0.8f, -3.23f, -0.8f, -2.13f, -4.4f, 2.12f, -0.7f,
929 2.12f, -0.7f, 3.22f, -6.0f, 3.22f, -6.0f, 2.12f,
930
931 1.0f, 0.0f, 1.0f, -0.1f, 1.1f, -3.3f, 4.3f, -3.2f, 5.1f, -3.1f, 5.4f, -3.0f, 5.6f,
932 -2.9f, 5.7f, -2.8f, 5.9f, -2.7f, 5.9f, -2.6f, 6.0f, -2.5f, 6.1f, -2.3f, 6.2f, -2.2f,
933 6.2f, -2.1f, 6.3f, -2.0f, 6.3f, -1.9f, 6.2f, -0.8f, 6.2f, -0.7f, 6.1f, -0.6f, 6.1f,
934 -0.5f, 6.0f, -0.4f, 6.0f, -0.3f, 5.9f, -0.2f, 5.7f, -0.1f, 5.7f, 0.0f, 5.6f, 0.1f,
935 5.4f, 0.2f, 5.1f, 0.3f, 4.7f, 0.4f, 4.7f, 0.5f, 4.9f, 0.6f, 5.0f, 0.7f, 5.2f,
936 0.8f, 5.2f, 0.9f, 5.3f, 1.0f, 5.5f, 1.1f, 5.5f, 1.2f, 5.6f, 1.3f, 5.7f, 1.5f,
937 5.8f, 1.6f, 5.9f, 1.8f, 6.0f, 1.9f, 6.1f, 2.1f, 6.2f, 2.2f, 6.2f, 2.3f, 6.3f,
938 2.4f, 6.4f, 2.6f, 6.5f, 2.7f, 6.6f, 2.9f, 6.7f, 3.0f, 6.7f, 3.1f, 6.8f, 3.2f,
939 6.8f, 3.3f, 5.3f, 3.2f, 5.2f, 3.1f, 5.2f, 3.0f, 5.1f, 2.9f, 5.0f, 2.7f, 4.9f,
940 2.6f, 4.8f, 2.4f, 4.7f, 2.3f, 4.6f, 2.1f, 4.5f, 2.0f, 4.4f, 1.8f, 4.3f, 1.7f,
941 4.1f, 1.4f, 4.0f, 1.3f, 3.9f, 1.1f, 3.8f, 1.0f, 3.6f, 0.9f, 3.6f, 0.8f, 3.5f,
942 0.7f, 3.3f, 0.6f, 2.9f, 0.5f, 2.3f, 0.6f, 2.3f, 0.7f, 2.2f, 3.3f, 1.0f, 3.2f,
943 1.0f, 3.1f, 1.0f, 0.0f,
944
945 4.2f, -0.5f, 4.4f, -0.6f, 4.7f, -0.7f, 4.8f, -0.8f, 4.9f, -1.0f, 5.0f, -1.1f, 5.0f,
946 -1.2f, 4.9f, -1.7f, 4.9f, -1.8f, 4.8f, -1.9f, 4.8f, -2.0f, 4.6f, -2.1f, 4.3f, -2.2f,
947 2.3f, -2.1f, 2.3f, -2.0f, 2.4f, -0.5f, 4.2f, -0.5f, 1.0f, 0.0f, -6.0f, 2.12f,
948};
949
950constexpr std::array<float, 148 * 2> symbol_sr = {
951 -3.0f, -3.65f, -2.76f, -4.26f, -2.33f, -4.76f, -1.76f, -5.09f, -1.13f, -5.26f, -0.94f, -4.77f,
952 -0.87f, -4.11f, -1.46f, -3.88f, -1.91f, -3.41f, -2.05f, -2.78f, -1.98f, -2.13f, -1.59f, -1.61f,
953 -0.96f, -1.53f, -0.56f, -2.04f, -0.38f, -2.67f, -0.22f, -3.31f, 0.0f, -3.93f, 0.34f, -4.49f,
954 0.86f, -4.89f, 1.49f, -5.05f, 2.14f, -4.95f, 2.69f, -4.6f, 3.07f, -4.07f, 3.25f, -3.44f,
955 3.31f, -2.78f, 3.25f, -2.12f, 3.07f, -1.49f, 2.7f, -0.95f, 2.16f, -0.58f, 1.52f, -0.43f,
956 1.41f, -0.99f, 1.38f, -1.65f, 1.97f, -1.91f, 2.25f, -2.49f, 2.25f, -3.15f, 1.99f, -3.74f,
957 1.38f, -3.78f, 1.06f, -3.22f, 0.88f, -2.58f, 0.71f, -1.94f, 0.49f, -1.32f, 0.13f, -0.77f,
958 -0.4f, -0.4f, -1.04f, -0.25f, -1.69f, -0.32f, -2.28f, -0.61f, -2.73f, -1.09f, -2.98f, -1.69f,
959 -3.09f, -2.34f,
960
961 -1.0f, 0.0f, 0.1f, 1.0f, 3.3f, 1.1f, 3.2f, 4.3f, 3.1f, 5.1f, 3.0f, 5.4f,
962 2.9f, 5.6f, 2.8f, 5.7f, 2.7f, 5.9f, 2.6f, 5.9f, 2.5f, 6.0f, 2.3f, 6.1f,
963 2.2f, 6.2f, 2.1f, 6.2f, 2.0f, 6.3f, 1.9f, 6.3f, 0.8f, 6.2f, 0.7f, 6.2f,
964 0.6f, 6.1f, 0.5f, 6.1f, 0.4f, 6.0f, 0.3f, 6.0f, 0.2f, 5.9f, 0.1f, 5.7f,
965 0.0f, 5.7f, -0.1f, 5.6f, -0.2f, 5.4f, -0.3f, 5.1f, -0.4f, 4.7f, -0.5f, 4.7f,
966 -0.6f, 4.9f, -0.7f, 5.0f, -0.8f, 5.2f, -0.9f, 5.2f, -1.0f, 5.3f, -1.1f, 5.5f,
967 -1.2f, 5.5f, -1.3f, 5.6f, -1.5f, 5.7f, -1.6f, 5.8f, -1.8f, 5.9f, -1.9f, 6.0f,
968 -2.1f, 6.1f, -2.2f, 6.2f, -2.3f, 6.2f, -2.4f, 6.3f, -2.6f, 6.4f, -2.7f, 6.5f,
969 -2.9f, 6.6f, -3.0f, 6.7f, -3.1f, 6.7f, -3.2f, 6.8f, -3.3f, 6.8f, -3.2f, 5.3f,
970 -3.1f, 5.2f, -3.0f, 5.2f, -2.9f, 5.1f, -2.7f, 5.0f, -2.6f, 4.9f, -2.4f, 4.8f,
971 -2.3f, 4.7f, -2.1f, 4.6f, -2.0f, 4.5f, -1.8f, 4.4f, -1.7f, 4.3f, -1.4f, 4.1f,
972 -1.3f, 4.0f, -1.1f, 3.9f, -1.0f, 3.8f, -0.9f, 3.6f, -0.8f, 3.6f, -0.7f, 3.5f,
973 -0.6f, 3.3f, -0.5f, 2.9f, -0.6f, 2.3f, -0.7f, 2.3f, -3.3f, 2.2f, -3.2f, 1.0f,
974 -3.1f, 1.0f, 0.0f, 1.0f,
975
976 0.5f, 4.2f, 0.6f, 4.4f, 0.7f, 4.7f, 0.8f, 4.8f, 1.0f, 4.9f, 1.1f, 5.0f,
977 1.2f, 5.0f, 1.7f, 4.9f, 1.8f, 4.9f, 1.9f, 4.8f, 2.0f, 4.8f, 2.1f, 4.6f,
978 2.2f, 4.3f, 2.1f, 2.3f, 2.0f, 2.3f, 0.5f, 2.4f, 0.5f, 4.2f, -0.0f, 1.0f,
979 -3.09f, -2.34f,
980
981};
982
983constexpr std::array<float, 30 * 2> symbol_c = {
984 2.86f, 7.57f, 0.99f, 7.94f, -0.91f, 7.87f, -2.73f, 7.31f, -4.23f, 6.14f, -5.2f, 4.51f,
985 -5.65f, 2.66f, -5.68f, 0.75f, -5.31f, -1.12f, -4.43f, -2.81f, -3.01f, -4.08f, -1.24f, -4.78f,
986 0.66f, -4.94f, 2.54f, -4.67f, 4.33f, -4.0f, 4.63f, -2.27f, 3.37f, -2.7f, 1.6f, -3.4f,
987 -0.3f, -3.5f, -2.09f, -2.87f, -3.34f, -1.45f, -3.91f, 0.37f, -3.95f, 2.27f, -3.49f, 4.12f,
988 -2.37f, 5.64f, -0.65f, 6.44f, 1.25f, 6.47f, 3.06f, 5.89f, 4.63f, 4.92f, 4.63f, 6.83f,
989};
990
991constexpr std::array<float, 12 * 2> house = {
992 -1.3f, 0.0f, -0.93f, 0.0f, -0.93f, 1.15f, 0.93f, 1.15f, 0.93f, 0.0f, 1.3f, 0.0f,
993 0.0f, -1.2f, -1.3f, 0.0f, -0.43f, 0.0f, -0.43f, .73f, 0.43f, .73f, 0.43f, 0.0f,
994};
995
996constexpr std::array<float, 11 * 2> up_arrow_button = {
997 9.1f, -9.1f, 9.1f, -30.0f, 8.1f, -30.1f, 7.7f, -30.1f, -8.6f, -30.0f, -9.0f,
998 -29.8f, -9.3f, -29.5f, -9.5f, -29.1f, -9.1f, -28.7f, -9.1f, -9.1f, 0.0f, 0.6f,
999};
1000
1001constexpr std::array<float, 3 * 2> up_arrow_symbol = {
1002 0.0f, -3.0f, -3.0f, 2.0f, 3.0f, 2.0f,
1003};
1004
1005constexpr std::array<float, 13 * 2> up_arrow = {
1006 9.4f, -9.8f, 9.4f, -10.2f, 8.9f, -29.8f, 8.5f, -30.0f, 8.1f,
1007 -30.1f, 7.7f, -30.1f, -8.6f, -30.0f, -9.0f, -29.8f, -9.3f, -29.5f,
1008 -9.5f, -29.1f, -9.5f, -28.7f, -9.1f, -9.1f, -8.8f, -8.8f,
1009};
1010
1011constexpr std::array<float, 64 * 2> trigger_button = {
1012 5.5f, -12.6f, 5.8f, -12.6f, 6.7f, -12.5f, 8.1f, -12.3f, 8.6f, -12.2f, 9.2f, -12.0f,
1013 9.5f, -11.9f, 9.9f, -11.8f, 10.6f, -11.5f, 11.0f, -11.3f, 11.2f, -11.2f, 11.4f, -11.1f,
1014 11.8f, -10.9f, 12.0f, -10.8f, 12.2f, -10.7f, 12.4f, -10.5f, 12.6f, -10.4f, 12.8f, -10.3f,
1015 13.6f, -9.7f, 13.8f, -9.6f, 13.9f, -9.4f, 14.1f, -9.3f, 14.8f, -8.6f, 15.0f, -8.5f,
1016 15.1f, -8.3f, 15.6f, -7.8f, 15.7f, -7.6f, 16.1f, -7.0f, 16.3f, -6.8f, 16.4f, -6.6f,
1017 16.5f, -6.4f, 16.8f, -6.0f, 16.9f, -5.8f, 17.0f, -5.6f, 17.1f, -5.4f, 17.2f, -5.2f,
1018 17.3f, -5.0f, 17.4f, -4.8f, 17.5f, -4.6f, 17.6f, -4.4f, 17.7f, -4.1f, 17.8f, -3.9f,
1019 17.9f, -3.5f, 18.0f, -3.3f, 18.1f, -3.0f, 18.2f, -2.6f, 18.2f, -2.3f, 18.3f, -2.1f,
1020 18.3f, -1.9f, 18.4f, -1.4f, 18.5f, -1.2f, 18.6f, -0.3f, 18.6f, 0.0f, 18.3f, 13.9f,
1021 -17.0f, 13.8f, -17.0f, 13.6f, -16.4f, -11.4f, -16.3f, -11.6f, -16.1f, -11.8f, -15.7f, -12.0f,
1022 -15.5f, -12.1f, -15.1f, -12.3f, -14.6f, -12.4f, -13.4f, -12.5f,
1023};
1024
1025constexpr std::array<float, 36 * 2> pro_left_trigger = {
1026 -65.2f, -132.6f, -68.2f, -134.1f, -71.3f, -135.5f, -74.4f, -136.7f, -77.6f,
1027 -137.6f, -80.9f, -138.1f, -84.3f, -138.3f, -87.6f, -138.3f, -91.0f, -138.1f,
1028 -94.3f, -137.8f, -97.6f, -137.3f, -100.9f, -136.7f, -107.5f, -135.3f, -110.7f,
1029 -134.5f, -120.4f, -131.8f, -123.6f, -130.8f, -126.8f, -129.7f, -129.9f, -128.5f,
1030 -132.9f, -127.1f, -135.9f, -125.6f, -138.8f, -123.9f, -141.6f, -122.0f, -144.1f,
1031 -119.8f, -146.3f, -117.3f, -148.4f, -114.7f, -150.4f, -112.0f, -152.3f, -109.2f,
1032 -155.3f, -104.0f, -152.0f, -104.3f, -148.7f, -104.5f, -145.3f, -104.8f, -35.5f,
1033 -117.2f, -38.5f, -118.7f, -41.4f, -120.3f, -44.4f, -121.8f, -50.4f, -124.9f,
1034};
1035
1036constexpr std::array<float, 14 * 2> pro_body_top = {
1037 0.0f, -115.4f, -4.4f, -116.1f, -69.7f, -131.3f, -66.4f, -131.9f, -63.1f, -132.3f,
1038 -56.4f, -133.0f, -53.1f, -133.3f, -49.8f, -133.5f, -43.1f, -133.8f, -39.8f, -134.0f,
1039 -36.5f, -134.1f, -16.4f, -134.4f, -13.1f, -134.4f, 0.0f, -134.1f,
1040};
1041
1042constexpr std::array<float, 145 * 2> pro_left_handle = {
1043 -178.7f, -47.5f, -179.0f, -46.1f, -179.3f, -44.6f, -182.0f, -29.8f, -182.3f, -28.4f,
1044 -182.6f, -26.9f, -182.8f, -25.4f, -183.1f, -23.9f, -183.3f, -22.4f, -183.6f, -21.0f,
1045 -183.8f, -19.5f, -184.1f, -18.0f, -184.3f, -16.5f, -184.6f, -15.1f, -184.8f, -13.6f,
1046 -185.1f, -12.1f, -185.3f, -10.6f, -185.6f, -9.1f, -185.8f, -7.7f, -186.1f, -6.2f,
1047 -186.3f, -4.7f, -186.6f, -3.2f, -186.8f, -1.7f, -187.1f, -0.3f, -187.3f, 1.2f,
1048 -187.6f, 2.7f, -187.8f, 4.2f, -188.3f, 7.1f, -188.5f, 8.6f, -188.8f, 10.1f,
1049 -189.0f, 11.6f, -189.3f, 13.1f, -189.5f, 14.5f, -190.0f, 17.5f, -190.2f, 19.0f,
1050 -190.5f, 20.5f, -190.7f, 21.9f, -191.2f, 24.9f, -191.4f, 26.4f, -191.7f, 27.9f,
1051 -191.9f, 29.3f, -192.4f, 32.3f, -192.6f, 33.8f, -193.1f, 36.8f, -193.3f, 38.2f,
1052 -193.8f, 41.2f, -194.0f, 42.7f, -194.7f, 47.1f, -194.9f, 48.6f, -199.0f, 82.9f,
1053 -199.1f, 84.4f, -199.1f, 85.9f, -199.2f, 87.4f, -199.2f, 88.9f, -199.1f, 94.9f,
1054 -198.9f, 96.4f, -198.8f, 97.8f, -198.5f, 99.3f, -198.3f, 100.8f, -198.0f, 102.3f,
1055 -197.7f, 103.7f, -197.4f, 105.2f, -197.0f, 106.7f, -196.6f, 108.1f, -195.7f, 111.0f,
1056 -195.2f, 112.4f, -194.1f, 115.2f, -193.5f, 116.5f, -192.8f, 117.9f, -192.1f, 119.2f,
1057 -190.6f, 121.8f, -189.8f, 123.1f, -188.9f, 124.3f, -187.0f, 126.6f, -186.0f, 127.7f,
1058 -183.9f, 129.8f, -182.7f, 130.8f, -180.3f, 132.6f, -179.1f, 133.4f, -177.8f, 134.1f,
1059 -176.4f, 134.8f, -175.1f, 135.5f, -173.7f, 136.0f, -169.4f, 137.3f, -167.9f, 137.7f,
1060 -166.5f, 138.0f, -165.0f, 138.3f, -163.5f, 138.4f, -162.0f, 138.4f, -160.5f, 138.3f,
1061 -159.0f, 138.0f, -157.6f, 137.7f, -156.1f, 137.3f, -154.7f, 136.9f, -153.2f, 136.5f,
1062 -151.8f, 136.0f, -150.4f, 135.4f, -149.1f, 134.8f, -147.7f, 134.1f, -146.5f, 133.3f,
1063 -145.2f, 132.5f, -144.0f, 131.6f, -142.8f, 130.6f, -141.7f, 129.6f, -139.6f, 127.5f,
1064 -138.6f, 126.4f, -137.7f, 125.2f, -135.1f, 121.5f, -134.3f, 120.3f, -133.5f, 119.0f,
1065 -131.9f, 116.5f, -131.1f, 115.2f, -128.8f, 111.3f, -128.0f, 110.1f, -127.2f, 108.8f,
1066 -126.5f, 107.5f, -125.7f, 106.2f, -125.0f, 104.9f, -124.2f, 103.6f, -123.5f, 102.3f,
1067 -122.0f, 99.6f, -121.3f, 98.3f, -115.8f, 87.7f, -115.1f, 86.4f, -114.4f, 85.0f,
1068 -113.7f, 83.7f, -112.3f, 81.0f, -111.6f, 79.7f, -110.1f, 77.1f, -109.4f, 75.8f,
1069 -108.0f, 73.1f, -107.2f, 71.8f, -106.4f, 70.6f, -105.7f, 69.3f, -104.8f, 68.0f,
1070 -104.0f, 66.8f, -103.1f, 65.6f, -101.1f, 63.3f, -100.0f, 62.3f, -98.8f, 61.4f,
1071 -97.6f, 60.6f, -97.9f, 59.5f, -98.8f, 58.3f, -101.5f, 54.6f, -102.4f, 53.4f,
1072};
1073
1074constexpr std::array<float, 245 * 2> pro_body = {
1075 -0.7f, -129.1f, -54.3f, -129.1f, -55.0f, -129.1f, -57.8f, -129.0f, -58.5f, -129.0f,
1076 -60.7f, -128.9f, -61.4f, -128.9f, -62.8f, -128.8f, -63.5f, -128.8f, -65.7f, -128.7f,
1077 -66.4f, -128.7f, -67.8f, -128.6f, -68.5f, -128.6f, -69.2f, -128.5f, -70.0f, -128.5f,
1078 -70.7f, -128.4f, -71.4f, -128.4f, -72.1f, -128.3f, -72.8f, -128.3f, -73.5f, -128.2f,
1079 -74.2f, -128.2f, -74.9f, -128.1f, -75.7f, -128.1f, -76.4f, -128.0f, -77.1f, -128.0f,
1080 -77.8f, -127.9f, -78.5f, -127.9f, -79.2f, -127.8f, -80.6f, -127.7f, -81.4f, -127.6f,
1081 -82.1f, -127.5f, -82.8f, -127.5f, -83.5f, -127.4f, -84.9f, -127.3f, -85.6f, -127.2f,
1082 -87.0f, -127.1f, -87.7f, -127.0f, -88.5f, -126.9f, -89.2f, -126.8f, -89.9f, -126.8f,
1083 -90.6f, -126.7f, -94.1f, -126.3f, -94.8f, -126.2f, -113.2f, -123.3f, -113.9f, -123.2f,
1084 -114.6f, -123.0f, -115.3f, -122.9f, -116.7f, -122.6f, -117.4f, -122.5f, -118.1f, -122.3f,
1085 -118.8f, -122.2f, -119.5f, -122.0f, -120.9f, -121.7f, -121.6f, -121.5f, -122.3f, -121.4f,
1086 -122.9f, -121.2f, -123.6f, -121.0f, -126.4f, -120.3f, -127.1f, -120.1f, -127.8f, -119.8f,
1087 -128.4f, -119.6f, -129.1f, -119.4f, -131.2f, -118.7f, -132.5f, -118.3f, -133.2f, -118.0f,
1088 -133.8f, -117.7f, -134.5f, -117.4f, -135.1f, -117.2f, -135.8f, -116.9f, -136.4f, -116.5f,
1089 -137.0f, -116.2f, -137.7f, -115.8f, -138.3f, -115.4f, -138.9f, -115.1f, -139.5f, -114.7f,
1090 -160.0f, -100.5f, -160.5f, -100.0f, -162.5f, -97.9f, -162.9f, -97.4f, -163.4f, -96.8f,
1091 -163.8f, -96.2f, -165.3f, -93.8f, -165.7f, -93.2f, -166.0f, -92.6f, -166.4f, -91.9f,
1092 -166.7f, -91.3f, -167.3f, -90.0f, -167.6f, -89.4f, -167.8f, -88.7f, -168.1f, -88.0f,
1093 -168.4f, -87.4f, -168.6f, -86.7f, -168.9f, -86.0f, -169.1f, -85.4f, -169.3f, -84.7f,
1094 -169.6f, -84.0f, -169.8f, -83.3f, -170.2f, -82.0f, -170.4f, -81.3f, -172.8f, -72.3f,
1095 -173.0f, -71.6f, -173.5f, -69.5f, -173.7f, -68.8f, -173.9f, -68.2f, -174.0f, -67.5f,
1096 -174.2f, -66.8f, -174.5f, -65.4f, -174.7f, -64.7f, -174.8f, -64.0f, -175.0f, -63.3f,
1097 -175.3f, -61.9f, -175.5f, -61.2f, -175.8f, -59.8f, -176.0f, -59.1f, -176.1f, -58.4f,
1098 -176.3f, -57.7f, -176.6f, -56.3f, -176.8f, -55.6f, -176.9f, -54.9f, -177.1f, -54.2f,
1099 -177.3f, -53.6f, -177.4f, -52.9f, -177.6f, -52.2f, -177.9f, -50.8f, -178.1f, -50.1f,
1100 -178.2f, -49.4f, -178.2f, -48.7f, -177.8f, -48.1f, -177.1f, -46.9f, -176.7f, -46.3f,
1101 -176.4f, -45.6f, -176.0f, -45.0f, -175.3f, -43.8f, -174.9f, -43.2f, -174.2f, -42.0f,
1102 -173.4f, -40.7f, -173.1f, -40.1f, -172.7f, -39.5f, -172.0f, -38.3f, -171.6f, -37.7f,
1103 -170.5f, -35.9f, -170.1f, -35.3f, -169.7f, -34.6f, -169.3f, -34.0f, -168.6f, -32.8f,
1104 -168.2f, -32.2f, -166.3f, -29.2f, -165.9f, -28.6f, -163.2f, -24.4f, -162.8f, -23.8f,
1105 -141.8f, 6.8f, -141.4f, 7.4f, -139.4f, 10.3f, -139.0f, 10.9f, -138.5f, 11.5f,
1106 -138.1f, 12.1f, -137.3f, 13.2f, -136.9f, 13.8f, -136.0f, 15.0f, -135.6f, 15.6f,
1107 -135.2f, 16.1f, -134.8f, 16.7f, -133.9f, 17.9f, -133.5f, 18.4f, -133.1f, 19.0f,
1108 -131.8f, 20.7f, -131.4f, 21.3f, -130.1f, 23.0f, -129.7f, 23.6f, -128.4f, 25.3f,
1109 -128.0f, 25.9f, -126.7f, 27.6f, -126.3f, 28.2f, -125.4f, 29.3f, -125.0f, 29.9f,
1110 -124.1f, 31.0f, -123.7f, 31.6f, -122.8f, 32.7f, -122.4f, 33.3f, -121.5f, 34.4f,
1111 -121.1f, 35.0f, -120.6f, 35.6f, -120.2f, 36.1f, -119.7f, 36.7f, -119.3f, 37.2f,
1112 -118.9f, 37.8f, -118.4f, 38.4f, -118.0f, 38.9f, -117.5f, 39.5f, -117.1f, 40.0f,
1113 -116.6f, 40.6f, -116.2f, 41.1f, -115.7f, 41.7f, -115.2f, 42.2f, -114.8f, 42.8f,
1114 -114.3f, 43.3f, -113.9f, 43.9f, -113.4f, 44.4f, -112.4f, 45.5f, -112.0f, 46.0f,
1115 -111.5f, 46.5f, -110.5f, 47.6f, -110.0f, 48.1f, -109.6f, 48.6f, -109.1f, 49.2f,
1116 -108.6f, 49.7f, -107.7f, 50.8f, -107.2f, 51.3f, -105.7f, 52.9f, -105.3f, 53.4f,
1117 -104.8f, 53.9f, -104.3f, 54.5f, -103.8f, 55.0f, -100.7f, 58.0f, -100.2f, 58.4f,
1118 -99.7f, 58.9f, -99.1f, 59.3f, -97.2f, 60.3f, -96.5f, 60.1f, -95.9f, 59.7f,
1119 -95.3f, 59.4f, -94.6f, 59.1f, -93.9f, 58.9f, -92.6f, 58.5f, -91.9f, 58.4f,
1120 -91.2f, 58.2f, -90.5f, 58.1f, -89.7f, 58.0f, -89.0f, 57.9f, -86.2f, 57.6f,
1121 -85.5f, 57.5f, -84.1f, 57.4f, -83.4f, 57.3f, -82.6f, 57.3f, -81.9f, 57.2f,
1122 -81.2f, 57.2f, -80.5f, 57.1f, -79.8f, 57.1f, -78.4f, 57.0f, -77.7f, 57.0f,
1123 -75.5f, 56.9f, -74.8f, 56.9f, -71.9f, 56.8f, -71.2f, 56.8f, 0.0f, 56.8f,
1124};
1125
1126constexpr std::array<float, 199 * 2> gc_body = {
1127 0.0f, -138.03f, -4.91f, -138.01f, -8.02f, -137.94f, -11.14f, -137.82f, -14.25f,
1128 -137.67f, -17.37f, -137.48f, -20.48f, -137.25f, -23.59f, -137.0f, -26.69f, -136.72f,
1129 -29.8f, -136.41f, -32.9f, -136.07f, -35.99f, -135.71f, -39.09f, -135.32f, -42.18f,
1130 -134.91f, -45.27f, -134.48f, -48.35f, -134.03f, -51.43f, -133.55f, -54.51f, -133.05f,
1131 -57.59f, -132.52f, -60.66f, -131.98f, -63.72f, -131.41f, -66.78f, -130.81f, -69.84f,
1132 -130.2f, -72.89f, -129.56f, -75.94f, -128.89f, -78.98f, -128.21f, -82.02f, -127.49f,
1133 -85.05f, -126.75f, -88.07f, -125.99f, -91.09f, -125.19f, -94.1f, -124.37f, -97.1f,
1134 -123.52f, -100.09f, -122.64f, -103.07f, -121.72f, -106.04f, -120.77f, -109.0f, -119.79f,
1135 -111.95f, -118.77f, -114.88f, -117.71f, -117.8f, -116.61f, -120.7f, -115.46f, -123.58f,
1136 -114.27f, -126.44f, -113.03f, -129.27f, -111.73f, -132.08f, -110.38f, -134.86f, -108.96f,
1137 -137.6f, -107.47f, -140.3f, -105.91f, -142.95f, -104.27f, -145.55f, -102.54f, -148.07f,
1138 -100.71f, -150.51f, -98.77f, -152.86f, -96.71f, -155.09f, -94.54f, -157.23f, -92.27f,
1139 -159.26f, -89.9f, -161.2f, -87.46f, -163.04f, -84.94f, -164.78f, -82.35f, -166.42f,
1140 -79.7f, -167.97f, -77.0f, -169.43f, -74.24f, -170.8f, -71.44f, -172.09f, -68.6f,
1141 -173.29f, -65.72f, -174.41f, -62.81f, -175.45f, -59.87f, -176.42f, -56.91f, -177.31f,
1142 -53.92f, -178.14f, -50.91f, -178.9f, -47.89f, -179.6f, -44.85f, -180.24f, -41.8f,
1143 -180.82f, -38.73f, -181.34f, -35.66f, -181.8f, -32.57f, -182.21f, -29.48f, -182.57f,
1144 -26.38f, -182.88f, -23.28f, -183.15f, -20.17f, -183.36f, -17.06f, -183.54f, -13.95f,
1145 -183.71f, -10.84f, -184.0f, -7.73f, -184.23f, -4.62f, -184.44f, -1.51f, -184.62f,
1146 1.6f, -184.79f, 4.72f, -184.95f, 7.83f, -185.11f, 10.95f, -185.25f, 14.06f,
1147 -185.38f, 17.18f, -185.51f, 20.29f, -185.63f, 23.41f, -185.74f, 26.53f, -185.85f,
1148 29.64f, -185.95f, 32.76f, -186.04f, 35.88f, -186.12f, 39.0f, -186.19f, 42.11f,
1149 -186.26f, 45.23f, -186.32f, 48.35f, -186.37f, 51.47f, -186.41f, 54.59f, -186.44f,
1150 57.7f, -186.46f, 60.82f, -186.46f, 63.94f, -186.44f, 70.18f, -186.41f, 73.3f,
1151 -186.36f, 76.42f, -186.3f, 79.53f, -186.22f, 82.65f, -186.12f, 85.77f, -185.99f,
1152 88.88f, -185.84f, 92.0f, -185.66f, 95.11f, -185.44f, 98.22f, -185.17f, 101.33f,
1153 -184.85f, 104.43f, -184.46f, 107.53f, -183.97f, 110.61f, -183.37f, 113.67f, -182.65f,
1154 116.7f, -181.77f, 119.69f, -180.71f, 122.62f, -179.43f, 125.47f, -177.89f, 128.18f,
1155 -176.05f, 130.69f, -173.88f, 132.92f, -171.36f, 134.75f, -168.55f, 136.1f, -165.55f,
1156 136.93f, -162.45f, 137.29f, -156.23f, 137.03f, -153.18f, 136.41f, -150.46f, 134.9f,
1157 -148.14f, 132.83f, -146.14f, 130.43f, -144.39f, 127.85f, -142.83f, 125.16f, -141.41f,
1158 122.38f, -140.11f, 119.54f, -138.9f, 116.67f, -137.77f, 113.76f, -136.7f, 110.84f,
1159 -135.68f, 107.89f, -134.71f, 104.93f, -133.77f, 101.95f, -132.86f, 98.97f, -131.97f,
1160 95.98f, -131.09f, 92.99f, -130.23f, 89.99f, -129.36f, 86.99f, -128.49f, 84.0f,
1161 -127.63f, 81.0f, -126.76f, 78.01f, -125.9f, 75.01f, -124.17f, 69.02f, -123.31f,
1162 66.02f, -121.59f, 60.03f, -120.72f, 57.03f, -119.86f, 54.03f, -118.13f, 48.04f,
1163 -117.27f, 45.04f, -115.55f, 39.05f, -114.68f, 36.05f, -113.82f, 33.05f, -112.96f,
1164 30.06f, -110.4f, 28.29f, -107.81f, 26.55f, -105.23f, 24.8f, -97.48f, 19.55f,
1165 -94.9f, 17.81f, -92.32f, 16.06f, -87.15f, 12.56f, -84.57f, 10.81f, -81.99f,
1166 9.07f, -79.4f, 7.32f, -76.82f, 5.57f, -69.07f, 0.33f, -66.49f, -1.42f,
1167 -58.74f, -6.66f, -56.16f, -8.41f, -48.4f, -13.64f, -45.72f, -15.22f, -42.93f,
1168 -16.62f, -40.07f, -17.86f, -37.15f, -18.96f, -34.19f, -19.94f, -31.19f, -20.79f,
1169 -28.16f, -21.55f, -25.12f, -22.21f, -22.05f, -22.79f, -18.97f, -23.28f, -15.88f,
1170 -23.7f, -12.78f, -24.05f, -9.68f, -24.33f, -6.57f, -24.55f, -3.45f, -24.69f,
1171 0.0f, -24.69f,
1172};
1173
1174constexpr std::array<float, 99 * 2> gc_left_body = {
1175 -74.59f, -97.22f, -70.17f, -94.19f, -65.95f, -90.89f, -62.06f, -87.21f, -58.58f,
1176 -83.14f, -55.58f, -78.7f, -53.08f, -73.97f, -51.05f, -69.01f, -49.46f, -63.89f,
1177 -48.24f, -58.67f, -47.36f, -53.39f, -46.59f, -48.09f, -45.7f, -42.8f, -44.69f,
1178 -37.54f, -43.54f, -32.31f, -42.25f, -27.11f, -40.8f, -21.95f, -39.19f, -16.84f,
1179 -37.38f, -11.8f, -35.34f, -6.84f, -33.04f, -2.0f, -30.39f, 2.65f, -27.26f,
1180 7.0f, -23.84f, 11.11f, -21.19f, 15.76f, -19.18f, 20.73f, -17.73f, 25.88f,
1181 -16.82f, 31.16f, -16.46f, 36.5f, -16.7f, 41.85f, -17.63f, 47.13f, -19.31f,
1182 52.21f, -21.8f, 56.95f, -24.91f, 61.3f, -28.41f, 65.36f, -32.28f, 69.06f,
1183 -36.51f, 72.35f, -41.09f, 75.13f, -45.97f, 77.32f, -51.1f, 78.86f, -56.39f,
1184 79.7f, -61.74f, 79.84f, -67.07f, 79.3f, -72.3f, 78.15f, -77.39f, 76.48f,
1185 -82.29f, 74.31f, -86.76f, 71.37f, -90.7f, 67.75f, -94.16f, 63.66f, -97.27f,
1186 59.3f, -100.21f, 54.81f, -103.09f, 50.3f, -106.03f, 45.82f, -109.11f, 41.44f,
1187 -112.37f, 37.19f, -115.85f, 33.11f, -119.54f, 29.22f, -123.45f, 25.56f, -127.55f,
1188 22.11f, -131.77f, 18.81f, -136.04f, 15.57f, -140.34f, 12.37f, -144.62f, 9.15f,
1189 -148.86f, 5.88f, -153.03f, 2.51f, -157.05f, -1.03f, -160.83f, -4.83f, -164.12f,
1190 -9.05f, -166.71f, -13.73f, -168.91f, -18.62f, -170.77f, -23.64f, -172.3f, -28.78f,
1191 -173.49f, -34.0f, -174.3f, -39.3f, -174.72f, -44.64f, -174.72f, -49.99f, -174.28f,
1192 -55.33f, -173.37f, -60.61f, -172.0f, -65.79f, -170.17f, -70.82f, -167.79f, -75.62f,
1193 -164.84f, -80.09f, -161.43f, -84.22f, -157.67f, -88.03f, -153.63f, -91.55f, -149.37f,
1194 -94.81f, -144.94f, -97.82f, -140.37f, -100.61f, -135.65f, -103.16f, -130.73f, -105.26f,
1195 -125.62f, -106.86f, -120.37f, -107.95f, -115.05f, -108.56f, -109.7f, -108.69f, -104.35f,
1196 -108.36f, -99.05f, -107.6f, -93.82f, -106.41f, -88.72f, -104.79f, -83.78f, -102.7f,
1197};
1198
1199constexpr std::array<float, 47 * 2> left_gc_trigger = {
1200 -99.69f, -125.04f, -101.81f, -126.51f, -104.02f, -127.85f, -106.3f, -129.06f, -108.65f,
1201 -130.12f, -111.08f, -130.99f, -113.58f, -131.62f, -116.14f, -131.97f, -121.26f, -131.55f,
1202 -123.74f, -130.84f, -126.17f, -129.95f, -128.53f, -128.9f, -130.82f, -127.71f, -133.03f,
1203 -126.38f, -135.15f, -124.92f, -137.18f, -123.32f, -139.11f, -121.6f, -140.91f, -119.75f,
1204 -142.55f, -117.77f, -144.0f, -115.63f, -145.18f, -113.34f, -146.17f, -110.95f, -147.05f,
1205 -108.53f, -147.87f, -106.08f, -148.64f, -103.61f, -149.37f, -101.14f, -149.16f, -100.12f,
1206 -147.12f, -101.71f, -144.99f, -103.16f, -142.8f, -104.53f, -140.57f, -105.83f, -138.31f,
1207 -107.08f, -136.02f, -108.27f, -133.71f, -109.42f, -131.38f, -110.53f, -129.04f, -111.61f,
1208 -126.68f, -112.66f, -124.31f, -113.68f, -121.92f, -114.67f, -119.53f, -115.64f, -117.13f,
1209 -116.58f, -114.72f, -117.51f, -112.3f, -118.41f, -109.87f, -119.29f, -107.44f, -120.16f,
1210 -105.0f, -121.0f, -100.11f, -122.65f,
1211};
1212
1213constexpr std::array<float, 50 * 2> gc_button_x = {
1214 142.1f, -50.67f, 142.44f, -48.65f, 142.69f, -46.62f, 142.8f, -44.57f, 143.0f, -42.54f,
1215 143.56f, -40.57f, 144.42f, -38.71f, 145.59f, -37.04f, 147.08f, -35.64f, 148.86f, -34.65f,
1216 150.84f, -34.11f, 152.88f, -34.03f, 154.89f, -34.38f, 156.79f, -35.14f, 158.49f, -36.28f,
1217 159.92f, -37.74f, 161.04f, -39.45f, 161.85f, -41.33f, 162.4f, -43.3f, 162.72f, -45.32f,
1218 162.85f, -47.37f, 162.82f, -49.41f, 162.67f, -51.46f, 162.39f, -53.48f, 162.0f, -55.5f,
1219 161.51f, -57.48f, 160.9f, -59.44f, 160.17f, -61.35f, 159.25f, -63.18f, 158.19f, -64.93f,
1220 157.01f, -66.61f, 155.72f, -68.2f, 154.31f, -69.68f, 152.78f, -71.04f, 151.09f, -72.2f,
1221 149.23f, -73.04f, 147.22f, -73.36f, 145.19f, -73.11f, 143.26f, -72.42f, 141.51f, -71.37f,
1222 140.0f, -69.99f, 138.82f, -68.32f, 138.13f, -66.4f, 138.09f, -64.36f, 138.39f, -62.34f,
1223 139.05f, -60.41f, 139.91f, -58.55f, 140.62f, -56.63f, 141.21f, -54.67f, 141.67f, -52.67f,
1224};
1225
1226constexpr std::array<float, 50 * 2> gc_button_y = {
1227 104.02f, -75.23f, 106.01f, -75.74f, 108.01f, -76.15f, 110.04f, -76.42f, 112.05f, -76.78f,
1228 113.97f, -77.49f, 115.76f, -78.49f, 117.33f, -79.79f, 118.6f, -81.39f, 119.46f, -83.25f,
1229 119.84f, -85.26f, 119.76f, -87.3f, 119.24f, -89.28f, 118.33f, -91.11f, 117.06f, -92.71f,
1230 115.49f, -94.02f, 113.7f, -95.01f, 111.77f, -95.67f, 109.76f, -96.05f, 107.71f, -96.21f,
1231 105.67f, -96.18f, 103.63f, -95.99f, 101.61f, -95.67f, 99.61f, -95.24f, 97.63f, -94.69f,
1232 95.69f, -94.04f, 93.79f, -93.28f, 91.94f, -92.4f, 90.19f, -91.34f, 88.53f, -90.14f,
1233 86.95f, -88.84f, 85.47f, -87.42f, 84.1f, -85.9f, 82.87f, -84.26f, 81.85f, -82.49f,
1234 81.15f, -80.57f, 81.0f, -78.54f, 81.41f, -76.54f, 82.24f, -74.67f, 83.43f, -73.01f,
1235 84.92f, -71.61f, 86.68f, -70.57f, 88.65f, -70.03f, 90.69f, -70.15f, 92.68f, -70.61f,
1236 94.56f, -71.42f, 96.34f, -72.43f, 98.2f, -73.29f, 100.11f, -74.03f, 102.06f, -74.65f,
1237};
1238
1239constexpr std::array<float, 47 * 2> gc_button_z = {
1240 95.74f, -126.41f, 98.34f, -126.38f, 100.94f, -126.24f, 103.53f, -126.01f, 106.11f, -125.7f,
1241 108.69f, -125.32f, 111.25f, -124.87f, 113.8f, -124.34f, 116.33f, -123.73f, 118.84f, -123.05f,
1242 121.33f, -122.3f, 123.79f, -121.47f, 126.23f, -120.56f, 128.64f, -119.58f, 131.02f, -118.51f,
1243 133.35f, -117.37f, 135.65f, -116.14f, 137.9f, -114.84f, 140.1f, -113.46f, 142.25f, -111.99f,
1244 144.35f, -110.45f, 146.38f, -108.82f, 148.35f, -107.13f, 150.25f, -105.35f, 151.89f, -103.38f,
1245 151.43f, -100.86f, 149.15f, -100.15f, 146.73f, -101.06f, 144.36f, -102.12f, 141.98f, -103.18f,
1246 139.6f, -104.23f, 137.22f, -105.29f, 134.85f, -106.35f, 132.47f, -107.41f, 127.72f, -109.53f,
1247 125.34f, -110.58f, 122.96f, -111.64f, 120.59f, -112.7f, 118.21f, -113.76f, 113.46f, -115.88f,
1248 111.08f, -116.93f, 108.7f, -117.99f, 106.33f, -119.05f, 103.95f, -120.11f, 99.2f, -122.23f,
1249 96.82f, -123.29f, 94.44f, -124.34f,
1250};
1251
1252constexpr std::array<float, 84 * 2> left_joycon_body = {
1253 -145.0f, -78.9f, -145.0f, -77.9f, -145.0f, 85.6f, -145.0f, 85.6f, -168.3f, 85.5f,
1254 -169.3f, 85.4f, -171.3f, 85.1f, -172.3f, 84.9f, -173.4f, 84.7f, -174.3f, 84.5f,
1255 -175.3f, 84.2f, -176.3f, 83.8f, -177.3f, 83.5f, -178.2f, 83.1f, -179.2f, 82.7f,
1256 -180.1f, 82.2f, -181.0f, 81.8f, -181.9f, 81.3f, -182.8f, 80.7f, -183.7f, 80.2f,
1257 -184.5f, 79.6f, -186.2f, 78.3f, -186.9f, 77.7f, -187.7f, 77.0f, -189.2f, 75.6f,
1258 -189.9f, 74.8f, -190.6f, 74.1f, -191.3f, 73.3f, -191.9f, 72.5f, -192.5f, 71.6f,
1259 -193.1f, 70.8f, -193.7f, 69.9f, -194.3f, 69.1f, -194.8f, 68.2f, -196.2f, 65.5f,
1260 -196.6f, 64.5f, -197.0f, 63.6f, -197.4f, 62.6f, -198.1f, 60.7f, -198.4f, 59.7f,
1261 -198.6f, 58.7f, -199.2f, 55.6f, -199.3f, 54.6f, -199.5f, 51.5f, -199.5f, 50.5f,
1262 -199.5f, -49.4f, -199.4f, -50.5f, -199.3f, -51.5f, -199.1f, -52.5f, -198.2f, -56.5f,
1263 -197.9f, -57.5f, -197.2f, -59.4f, -196.8f, -60.4f, -196.4f, -61.3f, -195.9f, -62.2f,
1264 -194.3f, -64.9f, -193.7f, -65.7f, -193.1f, -66.6f, -192.5f, -67.4f, -191.8f, -68.2f,
1265 -191.2f, -68.9f, -190.4f, -69.7f, -188.2f, -71.8f, -187.4f, -72.5f, -186.6f, -73.1f,
1266 -185.8f, -73.8f, -185.0f, -74.4f, -184.1f, -74.9f, -183.2f, -75.5f, -182.4f, -76.0f,
1267 -181.5f, -76.5f, -179.6f, -77.5f, -178.7f, -77.9f, -177.8f, -78.4f, -176.8f, -78.8f,
1268 -175.9f, -79.1f, -174.9f, -79.5f, -173.9f, -79.8f, -170.9f, -80.6f, -169.9f, -80.8f,
1269 -167.9f, -81.1f, -166.9f, -81.2f, -165.8f, -81.2f, -145.0f, -80.9f,
1270};
1271
1272constexpr std::array<float, 84 * 2> left_joycon_trigger = {
1273 -166.8f, -83.3f, -167.9f, -83.2f, -168.9f, -83.1f, -170.0f, -83.0f, -171.0f, -82.8f,
1274 -172.1f, -82.6f, -173.1f, -82.4f, -174.2f, -82.1f, -175.2f, -81.9f, -176.2f, -81.5f,
1275 -177.2f, -81.2f, -178.2f, -80.8f, -180.1f, -80.0f, -181.1f, -79.5f, -182.0f, -79.0f,
1276 -183.0f, -78.5f, -183.9f, -78.0f, -184.8f, -77.4f, -185.7f, -76.9f, -186.6f, -76.3f,
1277 -187.4f, -75.6f, -188.3f, -75.0f, -189.1f, -74.3f, -192.2f, -71.5f, -192.9f, -70.7f,
1278 -193.7f, -69.9f, -194.3f, -69.1f, -195.0f, -68.3f, -195.6f, -67.4f, -196.8f, -65.7f,
1279 -197.3f, -64.7f, -197.8f, -63.8f, -198.2f, -62.8f, -198.9f, -60.8f, -198.6f, -59.8f,
1280 -197.6f, -59.7f, -196.6f, -60.0f, -195.6f, -60.5f, -194.7f, -60.9f, -193.7f, -61.4f,
1281 -192.8f, -61.9f, -191.8f, -62.4f, -190.9f, -62.8f, -189.9f, -63.3f, -189.0f, -63.8f,
1282 -187.1f, -64.8f, -186.2f, -65.2f, -185.2f, -65.7f, -184.3f, -66.2f, -183.3f, -66.7f,
1283 -182.4f, -67.1f, -181.4f, -67.6f, -180.5f, -68.1f, -179.5f, -68.6f, -178.6f, -69.0f,
1284 -177.6f, -69.5f, -176.7f, -70.0f, -175.7f, -70.5f, -174.8f, -70.9f, -173.8f, -71.4f,
1285 -172.9f, -71.9f, -171.9f, -72.4f, -171.0f, -72.8f, -170.0f, -73.3f, -169.1f, -73.8f,
1286 -168.1f, -74.3f, -167.2f, -74.7f, -166.2f, -75.2f, -165.3f, -75.7f, -164.3f, -76.2f,
1287 -163.4f, -76.6f, -162.4f, -77.1f, -161.5f, -77.6f, -160.5f, -78.1f, -159.6f, -78.5f,
1288 -158.7f, -79.0f, -157.7f, -79.5f, -156.8f, -80.0f, -155.8f, -80.4f, -154.9f, -80.9f,
1289 -154.2f, -81.6f, -154.3f, -82.6f, -155.2f, -83.3f, -156.2f, -83.3f,
1290};
1291
1292constexpr std::array<float, 70 * 2> handheld_body = {
1293 -137.3f, -81.9f, -137.6f, -81.8f, -137.8f, -81.6f, -138.0f, -81.3f, -138.1f, -81.1f,
1294 -138.1f, -80.8f, -138.2f, -78.7f, -138.2f, -78.4f, -138.3f, -78.1f, -138.7f, -77.3f,
1295 -138.9f, -77.0f, -139.0f, -76.8f, -139.2f, -76.5f, -139.5f, -76.3f, -139.7f, -76.1f,
1296 -139.9f, -76.0f, -140.2f, -75.8f, -140.5f, -75.7f, -140.7f, -75.6f, -141.0f, -75.5f,
1297 -141.9f, -75.3f, -142.2f, -75.3f, -142.5f, -75.2f, -143.0f, -74.9f, -143.2f, -74.7f,
1298 -143.3f, -74.4f, -143.0f, -74.1f, -143.0f, 85.3f, -143.0f, 85.6f, -142.7f, 85.8f,
1299 -142.4f, 85.9f, -142.2f, 85.9f, 143.0f, 85.6f, 143.1f, 85.4f, 143.3f, 85.1f,
1300 143.0f, 84.8f, 143.0f, -74.9f, 142.8f, -75.1f, 142.5f, -75.2f, 141.9f, -75.3f,
1301 141.6f, -75.3f, 141.3f, -75.4f, 141.1f, -75.4f, 140.8f, -75.5f, 140.5f, -75.7f,
1302 140.2f, -75.8f, 140.0f, -76.0f, 139.7f, -76.1f, 139.5f, -76.3f, 139.1f, -76.8f,
1303 138.9f, -77.0f, 138.6f, -77.5f, 138.4f, -77.8f, 138.3f, -78.1f, 138.3f, -78.3f,
1304 138.2f, -78.6f, 138.2f, -78.9f, 138.1f, -79.2f, 138.1f, -79.5f, 138.0f, -81.3f,
1305 137.8f, -81.6f, 137.6f, -81.8f, 137.3f, -81.9f, 137.1f, -81.9f, 120.0f, -70.0f,
1306 -120.0f, -70.0f, -120.0f, 70.0f, 120.0f, 70.0f, 120.0f, -70.0f, 137.1f, -81.9f,
1307};
1308
1309constexpr std::array<float, 40 * 2> handheld_bezel = {
1310 -131.4f, -75.9f, -132.2f, -75.7f, -132.9f, -75.3f, -134.2f, -74.3f, -134.7f, -73.6f,
1311 -135.1f, -72.8f, -135.4f, -72.0f, -135.5f, -71.2f, -135.5f, -70.4f, -135.2f, 76.7f,
1312 -134.8f, 77.5f, -134.3f, 78.1f, -133.7f, 78.8f, -133.1f, 79.2f, -132.3f, 79.6f,
1313 -131.5f, 79.9f, -130.7f, 80.0f, -129.8f, 80.0f, 132.2f, 79.7f, 133.0f, 79.3f,
1314 133.7f, 78.8f, 134.3f, 78.3f, 134.8f, 77.6f, 135.1f, 76.8f, 135.5f, 75.2f,
1315 135.5f, 74.3f, 135.2f, -72.7f, 134.8f, -73.5f, 134.4f, -74.2f, 133.8f, -74.8f,
1316 133.1f, -75.3f, 132.3f, -75.6f, 130.7f, -76.0f, 129.8f, -76.0f, -112.9f, -62.2f,
1317 112.9f, -62.2f, 112.9f, 62.2f, -112.9f, 62.2f, -112.9f, -62.2f, 129.8f, -76.0f,
1318};
1319
1320constexpr std::array<float, 58 * 2> handheld_buttons = {
1321 -82.48f, -82.95f, -82.53f, -82.95f, -106.69f, -82.96f, -106.73f, -82.98f, -106.78f, -83.01f,
1322 -106.81f, -83.05f, -106.83f, -83.1f, -106.83f, -83.15f, -106.82f, -83.93f, -106.81f, -83.99f,
1323 -106.8f, -84.04f, -106.78f, -84.08f, -106.76f, -84.13f, -106.73f, -84.18f, -106.7f, -84.22f,
1324 -106.6f, -84.34f, -106.56f, -84.37f, -106.51f, -84.4f, -106.47f, -84.42f, -106.42f, -84.45f,
1325 -106.37f, -84.47f, -106.32f, -84.48f, -106.17f, -84.5f, -98.9f, -84.48f, -98.86f, -84.45f,
1326 -98.83f, -84.41f, -98.81f, -84.36f, -98.8f, -84.31f, -98.8f, -84.26f, -98.79f, -84.05f,
1327 -90.26f, -84.1f, -90.26f, -84.15f, -90.25f, -84.36f, -90.23f, -84.41f, -90.2f, -84.45f,
1328 -90.16f, -84.48f, -90.11f, -84.5f, -82.79f, -84.49f, -82.74f, -84.48f, -82.69f, -84.46f,
1329 -82.64f, -84.45f, -82.59f, -84.42f, -82.55f, -84.4f, -82.5f, -84.37f, -82.46f, -84.33f,
1330 -82.42f, -84.3f, -82.39f, -84.26f, -82.3f, -84.13f, -82.28f, -84.08f, -82.25f, -83.98f,
1331 -82.24f, -83.93f, -82.23f, -83.83f, -82.23f, -83.78f, -82.24f, -83.1f, -82.26f, -83.05f,
1332 -82.29f, -83.01f, -82.33f, -82.97f, -82.38f, -82.95f,
1333};
1334
1335constexpr std::array<float, 47 * 2> left_joycon_slider = {
1336 -23.7f, -118.2f, -23.7f, -117.3f, -23.7f, 96.6f, -22.8f, 96.6f, -21.5f, 97.2f, -21.5f,
1337 98.1f, -21.2f, 106.7f, -20.8f, 107.5f, -20.1f, 108.2f, -19.2f, 108.2f, -16.4f, 108.1f,
1338 -15.8f, 107.5f, -15.8f, 106.5f, -15.8f, 62.8f, -16.3f, 61.9f, -15.8f, 61.0f, -17.3f,
1339 60.3f, -19.1f, 58.9f, -19.1f, 58.1f, -19.1f, 57.2f, -19.1f, 34.5f, -17.9f, 33.9f,
1340 -17.2f, 33.2f, -16.6f, 32.4f, -16.2f, 31.6f, -15.8f, 30.7f, -15.8f, 29.7f, -15.8f,
1341 28.8f, -15.8f, -46.4f, -16.3f, -47.3f, -15.8f, -48.1f, -17.4f, -48.8f, -19.1f, -49.4f,
1342 -19.1f, -50.1f, -19.1f, -51.0f, -19.1f, -51.9f, -19.1f, -73.7f, -19.1f, -74.5f, -17.5f,
1343 -75.2f, -16.4f, -76.7f, -16.0f, -77.6f, -15.8f, -78.5f, -15.8f, -79.4f, -15.8f, -80.4f,
1344 -15.8f, -118.2f, -15.8f, -118.2f, -18.3f, -118.2f,
1345};
1346
1347constexpr std::array<float, 66 * 2> left_joycon_sideview = {
1348 -158.8f, -133.5f, -159.8f, -133.5f, -173.5f, -133.3f, -174.5f, -133.0f, -175.4f, -132.6f,
1349 -176.2f, -132.1f, -177.0f, -131.5f, -177.7f, -130.9f, -178.3f, -130.1f, -179.4f, -128.5f,
1350 -179.8f, -127.6f, -180.4f, -125.7f, -180.6f, -124.7f, -180.7f, -123.8f, -180.7f, -122.8f,
1351 -180.0f, 128.8f, -179.6f, 129.7f, -179.1f, 130.5f, -177.9f, 132.1f, -177.2f, 132.7f,
1352 -176.4f, 133.3f, -175.6f, 133.8f, -174.7f, 134.3f, -173.8f, 134.6f, -172.8f, 134.8f,
1353 -170.9f, 135.0f, -169.9f, 135.0f, -156.1f, 134.8f, -155.2f, 134.6f, -154.2f, 134.3f,
1354 -153.3f, 134.0f, -152.4f, 133.6f, -151.6f, 133.1f, -150.7f, 132.6f, -149.9f, 132.0f,
1355 -149.2f, 131.4f, -148.5f, 130.7f, -147.1f, 129.2f, -146.5f, 128.5f, -146.0f, 127.7f,
1356 -145.5f, 126.8f, -145.0f, 126.0f, -144.6f, 125.1f, -144.2f, 124.1f, -143.9f, 123.2f,
1357 -143.7f, 122.2f, -143.6f, 121.3f, -143.5f, 120.3f, -143.5f, 119.3f, -144.4f, -123.4f,
1358 -144.8f, -124.3f, -145.3f, -125.1f, -145.8f, -126.0f, -146.3f, -126.8f, -147.0f, -127.5f,
1359 -147.6f, -128.3f, -148.3f, -129.0f, -149.0f, -129.6f, -149.8f, -130.3f, -150.6f, -130.8f,
1360 -151.4f, -131.4f, -152.2f, -131.9f, -153.1f, -132.3f, -155.9f, -133.3f, -156.8f, -133.5f,
1361 -157.8f, -133.5f,
1362};
1363
1364constexpr std::array<float, 40 * 2> left_joycon_body_trigger = {
1365 -146.1f, -124.3f, -146.0f, -122.0f, -145.8f, -119.7f, -145.7f, -117.4f, -145.4f, -112.8f,
1366 -145.3f, -110.5f, -145.0f, -105.9f, -144.9f, -103.6f, -144.6f, -99.1f, -144.5f, -96.8f,
1367 -144.5f, -89.9f, -144.5f, -87.6f, -144.5f, -83.0f, -144.5f, -80.7f, -144.5f, -80.3f,
1368 -142.4f, -82.4f, -141.4f, -84.5f, -140.2f, -86.4f, -138.8f, -88.3f, -137.4f, -90.1f,
1369 -134.5f, -93.6f, -133.0f, -95.3f, -130.0f, -98.8f, -128.5f, -100.6f, -127.1f, -102.4f,
1370 -125.8f, -104.3f, -124.7f, -106.3f, -123.9f, -108.4f, -125.1f, -110.2f, -127.4f, -110.3f,
1371 -129.7f, -110.3f, -134.2f, -110.5f, -136.4f, -111.4f, -138.1f, -112.8f, -139.4f, -114.7f,
1372 -140.5f, -116.8f, -141.4f, -118.9f, -143.3f, -123.1f, -144.6f, -124.9f, -146.2f, -126.0f,
1373};
1374
1375constexpr std::array<float, 49 * 2> left_joycon_topview = {
1376 -184.8f, -20.8f, -185.6f, -21.1f, -186.4f, -21.5f, -187.1f, -22.1f, -187.8f, -22.6f,
1377 -188.4f, -23.2f, -189.6f, -24.5f, -190.2f, -25.2f, -190.7f, -25.9f, -191.1f, -26.7f,
1378 -191.4f, -27.5f, -191.6f, -28.4f, -191.7f, -29.2f, -191.7f, -30.1f, -191.5f, -47.7f,
1379 -191.2f, -48.5f, -191.0f, -49.4f, -190.7f, -50.2f, -190.3f, -51.0f, -190.0f, -51.8f,
1380 -189.6f, -52.6f, -189.1f, -53.4f, -188.6f, -54.1f, -187.5f, -55.4f, -186.9f, -56.1f,
1381 -186.2f, -56.7f, -185.5f, -57.2f, -184.0f, -58.1f, -183.3f, -58.5f, -182.5f, -58.9f,
1382 -181.6f, -59.2f, -180.8f, -59.5f, -179.9f, -59.7f, -179.1f, -59.9f, -178.2f, -60.0f,
1383 -174.7f, -60.1f, -168.5f, -60.2f, -162.4f, -60.3f, -156.2f, -60.4f, -149.2f, -60.5f,
1384 -143.0f, -60.6f, -136.9f, -60.7f, -130.7f, -60.8f, -123.7f, -60.9f, -117.5f, -61.0f,
1385 -110.5f, -61.1f, -94.4f, -60.4f, -94.4f, -59.5f, -94.4f, -20.6f,
1386};
1387
1388constexpr std::array<float, 41 * 2> left_joycon_slider_topview = {
1389 -95.1f, -51.5f, -95.0f, -51.5f, -91.2f, -51.6f, -91.2f, -51.7f, -91.1f, -52.4f, -91.1f, -52.6f,
1390 -91.0f, -54.1f, -86.3f, -54.0f, -86.0f, -53.9f, -85.9f, -53.8f, -85.6f, -53.4f, -85.5f, -53.2f,
1391 -85.5f, -53.1f, -85.4f, -52.9f, -85.4f, -52.8f, -85.3f, -52.4f, -85.3f, -52.3f, -85.4f, -27.2f,
1392 -85.4f, -27.1f, -85.5f, -27.0f, -85.5f, -26.9f, -85.6f, -26.7f, -85.6f, -26.6f, -85.7f, -26.5f,
1393 -85.9f, -26.4f, -86.0f, -26.3f, -86.4f, -26.0f, -86.5f, -25.9f, -86.7f, -25.8f, -87.1f, -25.7f,
1394 -90.4f, -25.8f, -90.7f, -25.9f, -90.8f, -26.0f, -90.9f, -26.3f, -91.0f, -26.4f, -91.0f, -26.5f,
1395 -91.1f, -26.7f, -91.1f, -26.9f, -91.2f, -28.9f, -95.2f, -29.1f, -95.2f, -29.2f,
1396};
1397
1398constexpr std::array<float, 42 * 2> left_joycon_sideview_zl = {
1399 -148.9f, -128.2f, -148.7f, -126.6f, -148.4f, -124.9f, -148.2f, -123.3f, -147.9f, -121.7f,
1400 -147.7f, -120.1f, -147.4f, -118.5f, -147.2f, -116.9f, -146.9f, -115.3f, -146.4f, -112.1f,
1401 -146.1f, -110.5f, -145.9f, -108.9f, -145.6f, -107.3f, -144.2f, -107.3f, -142.6f, -107.5f,
1402 -141.0f, -107.8f, -137.8f, -108.3f, -136.2f, -108.6f, -131.4f, -109.4f, -129.8f, -109.7f,
1403 -125.6f, -111.4f, -124.5f, -112.7f, -123.9f, -114.1f, -123.8f, -115.8f, -123.8f, -117.4f,
1404 -123.9f, -120.6f, -124.5f, -122.1f, -125.8f, -123.1f, -127.4f, -123.4f, -129.0f, -123.6f,
1405 -130.6f, -124.0f, -132.1f, -124.4f, -133.7f, -124.8f, -135.3f, -125.3f, -136.8f, -125.9f,
1406 -138.3f, -126.4f, -139.9f, -126.9f, -141.4f, -127.5f, -142.9f, -128.0f, -144.5f, -128.5f,
1407 -146.0f, -129.0f, -147.6f, -129.4f,
1408};
1409
1410constexpr std::array<float, 72 * 2> left_joystick_sideview = {
1411 -14.7f, -3.8f, -15.2f, -5.6f, -15.2f, -7.6f, -15.5f, -17.6f, -17.4f, -18.3f, -19.4f, -18.2f,
1412 -21.3f, -17.6f, -22.8f, -16.4f, -23.4f, -14.5f, -23.4f, -12.5f, -24.1f, -8.6f, -24.8f, -6.7f,
1413 -25.3f, -4.8f, -25.7f, -2.8f, -25.9f, -0.8f, -26.0f, 1.2f, -26.0f, 3.2f, -25.8f, 5.2f,
1414 -25.5f, 7.2f, -25.0f, 9.2f, -24.4f, 11.1f, -23.7f, 13.0f, -23.4f, 14.9f, -23.4f, 16.9f,
1415 -23.3f, 18.9f, -22.0f, 20.5f, -20.2f, 21.3f, -18.3f, 21.6f, -16.3f, 21.4f, -15.3f, 19.9f,
1416 -15.3f, 17.8f, -15.2f, 7.8f, -13.5f, 6.4f, -12.4f, 7.2f, -11.4f, 8.9f, -10.2f, 10.5f,
1417 -8.7f, 11.8f, -7.1f, 13.0f, -5.3f, 14.0f, -3.5f, 14.7f, -1.5f, 15.0f, 0.5f, 15.0f,
1418 2.5f, 14.7f, 4.4f, 14.2f, 6.3f, 13.4f, 8.0f, 12.4f, 9.6f, 11.1f, 10.9f, 9.6f,
1419 12.0f, 7.9f, 12.7f, 6.0f, 13.2f, 4.1f, 13.3f, 2.1f, 13.2f, 0.1f, 12.9f, -1.9f,
1420 12.2f, -3.8f, 11.3f, -5.6f, 10.2f, -7.2f, 8.8f, -8.6f, 7.1f, -9.8f, 5.4f, -10.8f,
1421 3.5f, -11.5f, 1.5f, -11.9f, -0.5f, -12.0f, -2.5f, -11.8f, -4.4f, -11.3f, -6.2f, -10.4f,
1422 -8.0f, -9.4f, -9.6f, -8.2f, -10.9f, -6.7f, -11.9f, -4.9f, -12.8f, -3.2f, -13.5f, -3.8f,
1423};
1424
1425constexpr std::array<float, 63 * 2> left_joystick_L_topview = {
1426 -186.7f, -43.7f, -186.4f, -43.7f, -110.6f, -43.4f, -110.6f, -43.1f, -110.7f, -34.3f,
1427 -110.7f, -34.0f, -110.8f, -33.7f, -111.1f, -32.9f, -111.2f, -32.6f, -111.4f, -32.3f,
1428 -111.5f, -32.1f, -111.7f, -31.8f, -111.8f, -31.5f, -112.0f, -31.3f, -112.2f, -31.0f,
1429 -112.4f, -30.8f, -112.8f, -30.3f, -113.0f, -30.1f, -114.1f, -29.1f, -114.3f, -28.9f,
1430 -114.6f, -28.7f, -114.8f, -28.6f, -115.1f, -28.4f, -115.3f, -28.3f, -115.6f, -28.1f,
1431 -115.9f, -28.0f, -116.4f, -27.8f, -116.7f, -27.7f, -117.3f, -27.6f, -117.6f, -27.5f,
1432 -182.9f, -27.6f, -183.5f, -27.7f, -183.8f, -27.8f, -184.4f, -27.9f, -184.6f, -28.1f,
1433 -184.9f, -28.2f, -185.4f, -28.5f, -185.7f, -28.7f, -185.9f, -28.8f, -186.2f, -29.0f,
1434 -186.4f, -29.2f, -187.0f, -29.9f, -187.2f, -30.1f, -187.6f, -30.6f, -187.8f, -30.8f,
1435 -187.9f, -31.1f, -188.1f, -31.3f, -188.2f, -31.6f, -188.4f, -31.9f, -188.5f, -32.1f,
1436 -188.6f, -32.4f, -188.8f, -33.3f, -188.9f, -33.6f, -188.9f, -33.9f, -188.8f, -39.9f,
1437 -188.8f, -40.2f, -188.7f, -41.1f, -188.7f, -41.4f, -188.6f, -41.7f, -188.0f, -43.1f,
1438 -187.9f, -43.4f, -187.6f, -43.6f, -187.3f, -43.7f,
1439};
1440
1441constexpr std::array<float, 44 * 2> left_joystick_ZL_topview = {
1442 -179.4f, -53.3f, -177.4f, -53.3f, -111.2f, -53.3f, -111.3f, -53.3f, -111.5f, -58.6f,
1443 -111.8f, -60.5f, -112.2f, -62.4f, -113.1f, -66.1f, -113.8f, -68.0f, -114.5f, -69.8f,
1444 -115.3f, -71.5f, -116.3f, -73.2f, -117.3f, -74.8f, -118.5f, -76.4f, -119.8f, -77.8f,
1445 -121.2f, -79.1f, -122.8f, -80.2f, -124.4f, -81.2f, -126.2f, -82.0f, -128.1f, -82.6f,
1446 -130.0f, -82.9f, -131.9f, -83.0f, -141.5f, -82.9f, -149.3f, -82.8f, -153.1f, -82.6f,
1447 -155.0f, -82.1f, -156.8f, -81.6f, -158.7f, -80.9f, -160.4f, -80.2f, -162.2f, -79.3f,
1448 -163.8f, -78.3f, -165.4f, -77.2f, -166.9f, -76.0f, -168.4f, -74.7f, -169.7f, -73.3f,
1449 -172.1f, -70.3f, -173.2f, -68.7f, -174.2f, -67.1f, -175.2f, -65.4f, -176.1f, -63.7f,
1450 -178.7f, -58.5f, -179.6f, -56.8f, -180.4f, -55.1f, -181.3f, -53.3f,
1451};
1452
1453void PlayerControlPreview::DrawProBody(QPainter& p, const QPointF center) {
1454 std::array<QPointF, pro_left_handle.size() / 2> qleft_handle;
1455 std::array<QPointF, pro_left_handle.size() / 2> qright_handle;
1456 std::array<QPointF, pro_body.size()> qbody;
1457 constexpr int radius1 = 32;
1458
1459 for (std::size_t point = 0; point < pro_left_handle.size() / 2; ++point) {
1460 qleft_handle[point] =
1461 center + QPointF(pro_left_handle[point * 2], pro_left_handle[point * 2 + 1]);
1462 qright_handle[point] =
1463 center + QPointF(-pro_left_handle[point * 2], pro_left_handle[point * 2 + 1]);
1464 }
1465 for (std::size_t point = 0; point < pro_body.size() / 2; ++point) {
1466 qbody[point] = center + QPointF(pro_body[point * 2], pro_body[point * 2 + 1]);
1467 qbody[pro_body.size() - 1 - point] =
1468 center + QPointF(-pro_body[point * 2], pro_body[point * 2 + 1]);
1469 }
1470
1471 // Draw left handle body
1472 p.setPen(colors.outline);
1473 p.setBrush(colors.left);
1474 DrawPolygon(p, qleft_handle);
1475
1476 // Draw right handle body
1477 p.setBrush(colors.right);
1478 DrawPolygon(p, qright_handle);
1479
1480 // Draw body
1481 p.setBrush(colors.primary);
1482 DrawPolygon(p, qbody);
1483
1484 // Draw joycon circles
1485 p.setBrush(colors.transparent);
1486 p.drawEllipse(center + QPoint(-111, -55), radius1, radius1);
1487 p.drawEllipse(center + QPoint(51, 0), radius1, radius1);
1488}
1489
1490void PlayerControlPreview::DrawGCBody(QPainter& p, const QPointF center) {
1491 std::array<QPointF, gc_left_body.size() / 2> qleft_handle;
1492 std::array<QPointF, gc_left_body.size() / 2> qright_handle;
1493 std::array<QPointF, gc_body.size()> qbody;
1494 std::array<QPointF, 8> left_hex;
1495 std::array<QPointF, 8> right_hex;
1496 constexpr float angle = 2 * 3.1415f / 8;
1497
1498 for (std::size_t point = 0; point < gc_left_body.size() / 2; ++point) {
1499 qleft_handle[point] =
1500 center + QPointF(gc_left_body[point * 2], gc_left_body[point * 2 + 1]);
1501 qright_handle[point] =
1502 center + QPointF(-gc_left_body[point * 2], gc_left_body[point * 2 + 1]);
1503 }
1504 for (std::size_t point = 0; point < gc_body.size() / 2; ++point) {
1505 qbody[point] = center + QPointF(gc_body[point * 2], gc_body[point * 2 + 1]);
1506 qbody[gc_body.size() - 1 - point] =
1507 center + QPointF(-gc_body[point * 2], gc_body[point * 2 + 1]);
1508 }
1509 for (std::size_t point = 0; point < 8; ++point) {
1510 left_hex[point] =
1511 center + QPointF(34 * std::cos(point * angle) - 111, 34 * std::sin(point * angle) - 44);
1512 right_hex[point] =
1513 center + QPointF(26 * std::cos(point * angle) + 61, 26 * std::sin(point * angle) + 37);
1514 }
1515
1516 // Draw body
1517 p.setPen(colors.outline);
1518 p.setBrush(colors.primary);
1519 DrawPolygon(p, qbody);
1520
1521 // Draw left handle body
1522 p.setBrush(colors.left);
1523 DrawPolygon(p, qleft_handle);
1524
1525 // Draw right handle body
1526 p.setBrush(colors.right);
1527 DrawPolygon(p, qright_handle);
1528
1529 DrawText(p, center + QPoint(0, -58), 4.7f, tr("START/PAUSE"));
1530
1531 // Draw right joystick body
1532 p.setBrush(colors.button);
1533 DrawCircle(p, center + QPointF(61, 37), 23.5f);
1534
1535 // Draw joystick details
1536 p.setBrush(colors.transparent);
1537 DrawPolygon(p, left_hex);
1538 DrawPolygon(p, right_hex);
1539}
1540
1541void PlayerControlPreview::DrawHandheldBody(QPainter& p, const QPointF center) {
1542 const std::size_t body_outline_end = handheld_body.size() / 2 - 6;
1543 const std::size_t bezel_outline_end = handheld_bezel.size() / 2 - 6;
1544 const std::size_t bezel_inline_size = 4;
1545 const std::size_t bezel_inline_start = 35;
1546 std::array<QPointF, left_joycon_body.size() / 2> left_joycon;
1547 std::array<QPointF, left_joycon_body.size() / 2> right_joycon;
1548 std::array<QPointF, handheld_body.size() / 2> qhandheld_body;
1549 std::array<QPointF, body_outline_end> qhandheld_body_outline;
1550 std::array<QPointF, handheld_bezel.size() / 2> qhandheld_bezel;
1551 std::array<QPointF, bezel_inline_size> qhandheld_bezel_inline;
1552 std::array<QPointF, bezel_outline_end> qhandheld_bezel_outline;
1553 std::array<QPointF, handheld_buttons.size() / 2> qhandheld_buttons;
1554
1555 for (std::size_t point = 0; point < left_joycon_body.size() / 2; ++point) {
1556 left_joycon[point] =
1557 center + QPointF(left_joycon_body[point * 2], left_joycon_body[point * 2 + 1]);
1558 right_joycon[point] =
1559 center + QPointF(-left_joycon_body[point * 2], left_joycon_body[point * 2 + 1]);
1560 }
1561 for (std::size_t point = 0; point < body_outline_end; ++point) {
1562 qhandheld_body_outline[point] =
1563 center + QPointF(handheld_body[point * 2], handheld_body[point * 2 + 1]);
1564 }
1565 for (std::size_t point = 0; point < handheld_body.size() / 2; ++point) {
1566 qhandheld_body[point] =
1567 center + QPointF(handheld_body[point * 2], handheld_body[point * 2 + 1]);
1568 }
1569 for (std::size_t point = 0; point < handheld_bezel.size() / 2; ++point) {
1570 qhandheld_bezel[point] =
1571 center + QPointF(handheld_bezel[point * 2], handheld_bezel[point * 2 + 1]);
1572 }
1573 for (std::size_t point = 0; point < bezel_outline_end; ++point) {
1574 qhandheld_bezel_outline[point] =
1575 center + QPointF(handheld_bezel[point * 2], handheld_bezel[point * 2 + 1]);
1576 }
1577 for (std::size_t point = 0; point < bezel_inline_size; ++point) {
1578 qhandheld_bezel_inline[point] =
1579 center + QPointF(handheld_bezel[(point + bezel_inline_start) * 2],
1580 handheld_bezel[(point + bezel_inline_start) * 2 + 1]);
1581 }
1582 for (std::size_t point = 0; point < handheld_buttons.size() / 2; ++point) {
1583 qhandheld_buttons[point] =
1584 center + QPointF(handheld_buttons[point * 2], handheld_buttons[point * 2 + 1]);
1585 }
1586
1587 // Draw left joycon
1588 p.setPen(colors.outline);
1589 p.setBrush(colors.left);
1590 DrawPolygon(p, left_joycon);
1591
1592 // Draw right joycon
1593 p.setPen(colors.outline);
1594 p.setBrush(colors.right);
1595 DrawPolygon(p, right_joycon);
1596
1597 // Draw Handheld buttons
1598 p.setPen(colors.outline);
1599 p.setBrush(colors.button);
1600 DrawPolygon(p, qhandheld_buttons);
1601
1602 // Draw handheld body
1603 p.setPen(colors.transparent);
1604 p.setBrush(colors.primary);
1605 DrawPolygon(p, qhandheld_body);
1606 p.setPen(colors.outline);
1607 p.setBrush(colors.transparent);
1608 DrawPolygon(p, qhandheld_body_outline);
1609
1610 // Draw Handheld bezel
1611 p.setPen(colors.transparent);
1612 p.setBrush(colors.button);
1613 DrawPolygon(p, qhandheld_bezel);
1614 p.setPen(colors.outline);
1615 p.setBrush(colors.transparent);
1616 DrawPolygon(p, qhandheld_bezel_outline);
1617 DrawPolygon(p, qhandheld_bezel_inline);
1618}
1619
1620void PlayerControlPreview::DrawDualBody(QPainter& p, const QPointF center) {
1621 std::array<QPointF, left_joycon_body.size() / 2> left_joycon;
1622 std::array<QPointF, left_joycon_body.size() / 2> right_joycon;
1623 std::array<QPointF, left_joycon_slider.size() / 2> qleft_joycon_slider;
1624 std::array<QPointF, left_joycon_slider.size() / 2> qright_joycon_slider;
1625 std::array<QPointF, left_joycon_slider_topview.size() / 2> qleft_joycon_slider_topview;
1626 std::array<QPointF, left_joycon_slider_topview.size() / 2> qright_joycon_slider_topview;
1627 std::array<QPointF, left_joycon_topview.size() / 2> qleft_joycon_topview;
1628 std::array<QPointF, left_joycon_topview.size() / 2> qright_joycon_topview;
1629 constexpr float size = 1.61f;
1630 constexpr float size2 = 0.9f;
1631 constexpr float offset = 209.3f;
1632
1633 for (std::size_t point = 0; point < left_joycon_body.size() / 2; ++point) {
1634 left_joycon[point] = center + QPointF(left_joycon_body[point * 2] * size + offset,
1635 left_joycon_body[point * 2 + 1] * size - 1);
1636 right_joycon[point] = center + QPointF(-left_joycon_body[point * 2] * size - offset,
1637 left_joycon_body[point * 2 + 1] * size - 1);
1638 }
1639 for (std::size_t point = 0; point < left_joycon_slider.size() / 2; ++point) {
1640 qleft_joycon_slider[point] =
1641 center + QPointF(left_joycon_slider[point * 2], left_joycon_slider[point * 2 + 1]);
1642 qright_joycon_slider[point] =
1643 center + QPointF(-left_joycon_slider[point * 2], left_joycon_slider[point * 2 + 1]);
1644 }
1645 for (std::size_t point = 0; point < left_joycon_topview.size() / 2; ++point) {
1646 qleft_joycon_topview[point] =
1647 center + QPointF(left_joycon_topview[point * 2] * size2 - 52,
1648 left_joycon_topview[point * 2 + 1] * size2 - 52);
1649 qright_joycon_topview[point] =
1650 center + QPointF(-left_joycon_topview[point * 2] * size2 + 52,
1651 left_joycon_topview[point * 2 + 1] * size2 - 52);
1652 }
1653 for (std::size_t point = 0; point < left_joycon_slider_topview.size() / 2; ++point) {
1654 qleft_joycon_slider_topview[point] =
1655 center + QPointF(left_joycon_slider_topview[point * 2] * size2 - 52,
1656 left_joycon_slider_topview[point * 2 + 1] * size2 - 52);
1657 qright_joycon_slider_topview[point] =
1658 center + QPointF(-left_joycon_slider_topview[point * 2] * size2 + 52,
1659 left_joycon_slider_topview[point * 2 + 1] * size2 - 52);
1660 }
1661
1662 // right joycon body
1663 p.setPen(colors.outline);
1664 p.setBrush(colors.right);
1665 DrawPolygon(p, right_joycon);
1666
1667 // Left joycon body
1668 p.setPen(colors.outline);
1669 p.setBrush(colors.left);
1670 DrawPolygon(p, left_joycon);
1671
1672 // Slider release button top view
1673 p.setBrush(colors.button);
1674 DrawRoundRectangle(p, center + QPoint(-149, -108), 12, 11, 2);
1675 DrawRoundRectangle(p, center + QPoint(149, -108), 12, 11, 2);
1676
1677 // Joycon slider top view
1678 p.setBrush(colors.slider);
1679 DrawPolygon(p, qleft_joycon_slider_topview);
1680 p.drawLine(center + QPointF(-133.8f, -99.0f), center + QPointF(-133.8f, -78.5f));
1681 DrawPolygon(p, qright_joycon_slider_topview);
1682 p.drawLine(center + QPointF(133.8f, -99.0f), center + QPointF(133.8f, -78.5f));
1683
1684 // Joycon body top view
1685 p.setBrush(colors.left);
1686 DrawPolygon(p, qleft_joycon_topview);
1687 p.setBrush(colors.right);
1688 DrawPolygon(p, qright_joycon_topview);
1689
1690 // Right SR and SL sideview buttons
1691 p.setPen(colors.outline);
1692 p.setBrush(colors.slider_button);
1693 DrawRoundRectangle(p, center + QPoint(19, 47), 7, 22, 1);
1694 DrawRoundRectangle(p, center + QPoint(19, -62), 7, 22, 1);
1695
1696 // Left SR and SL sideview buttons
1697 DrawRoundRectangle(p, center + QPoint(-19, 47), 7, 22, 1);
1698 DrawRoundRectangle(p, center + QPoint(-19, -62), 7, 22, 1);
1699
1700 // Right Sideview body
1701 p.setBrush(colors.slider);
1702 DrawPolygon(p, qright_joycon_slider);
1703
1704 // Left Sideview body
1705 p.setBrush(colors.slider);
1706 DrawPolygon(p, qleft_joycon_slider);
1707}
1708
1709void PlayerControlPreview::DrawLeftBody(QPainter& p, const QPointF center) {
1710 std::array<QPointF, left_joycon_body.size() / 2> left_joycon;
1711 std::array<QPointF, left_joycon_sideview.size() / 2> qleft_joycon_sideview;
1712 std::array<QPointF, left_joycon_body_trigger.size() / 2> qleft_joycon_trigger;
1713 std::array<QPointF, left_joycon_slider.size() / 2> qleft_joycon_slider;
1714 std::array<QPointF, left_joycon_slider_topview.size() / 2> qleft_joycon_slider_topview;
1715 std::array<QPointF, left_joycon_topview.size() / 2> qleft_joycon_topview;
1716 constexpr float size = 1.78f;
1717 constexpr float size2 = 1.1115f;
1718 constexpr float offset = 312.39f;
1719 constexpr float offset2 = 335;
1720
1721 for (std::size_t point = 0; point < left_joycon_body.size() / 2; ++point) {
1722 left_joycon[point] = center + QPointF(left_joycon_body[point * 2] * size + offset,
1723 left_joycon_body[point * 2 + 1] * size - 1);
1724 }
1725
1726 for (std::size_t point = 0; point < left_joycon_sideview.size() / 2; ++point) {
1727 qleft_joycon_sideview[point] =
1728 center + QPointF(left_joycon_sideview[point * 2] * size2 + offset2,
1729 left_joycon_sideview[point * 2 + 1] * size2 + 2);
1730 }
1731 for (std::size_t point = 0; point < left_joycon_slider.size() / 2; ++point) {
1732 qleft_joycon_slider[point] = center + QPointF(left_joycon_slider[point * 2] * size2 + 81,
1733 left_joycon_slider[point * 2 + 1] * size2);
1734 }
1735 for (std::size_t point = 0; point < left_joycon_body_trigger.size() / 2; ++point) {
1736 qleft_joycon_trigger[point] =
1737 center + QPointF(left_joycon_body_trigger[point * 2] * size2 + offset2,
1738 left_joycon_body_trigger[point * 2 + 1] * size2 + 2);
1739 }
1740 for (std::size_t point = 0; point < left_joycon_topview.size() / 2; ++point) {
1741 qleft_joycon_topview[point] =
1742 center + QPointF(left_joycon_topview[point * 2], left_joycon_topview[point * 2 + 1]);
1743 }
1744 for (std::size_t point = 0; point < left_joycon_slider_topview.size() / 2; ++point) {
1745 qleft_joycon_slider_topview[point] =
1746 center + QPointF(left_joycon_slider_topview[point * 2],
1747 left_joycon_slider_topview[point * 2 + 1]);
1748 }
1749
1750 // Joycon body
1751 p.setPen(colors.outline);
1752 p.setBrush(colors.left);
1753 DrawPolygon(p, left_joycon);
1754 DrawPolygon(p, qleft_joycon_trigger);
1755
1756 // Slider release button top view
1757 p.setBrush(colors.button);
1758 DrawRoundRectangle(p, center + QPoint(-107, -62), 14, 12, 2);
1759
1760 // Joycon slider top view
1761 p.setBrush(colors.slider);
1762 DrawPolygon(p, qleft_joycon_slider_topview);
1763 p.drawLine(center + QPointF(-91.1f, -51.7f), center + QPointF(-91.1f, -26.5f));
1764
1765 // Joycon body top view
1766 p.setBrush(colors.left);
1767 DrawPolygon(p, qleft_joycon_topview);
1768
1769 // Slider release button
1770 p.setBrush(colors.button);
1771 DrawRoundRectangle(p, center + QPoint(175, -110), 12, 14, 2);
1772
1773 // Sideview body
1774 p.setBrush(colors.left);
1775 DrawPolygon(p, qleft_joycon_sideview);
1776 p.setBrush(colors.slider);
1777 DrawPolygon(p, qleft_joycon_slider);
1778
1779 const QPointF sideview_center = QPointF(155, 0) + center;
1780
1781 // Sideview slider body
1782 p.setBrush(colors.slider);
1783 DrawRoundRectangle(p, sideview_center + QPointF(0, -5), 28, 253, 3);
1784 p.setBrush(colors.button2);
1785 DrawRoundRectangle(p, sideview_center + QPointF(0, 97), 22.44f, 44.66f, 3);
1786
1787 // Slider decorations
1788 p.setPen(colors.outline);
1789 p.setBrush(colors.slider_arrow);
1790 DrawArrow(p, sideview_center + QPoint(0, 83), Direction::Down, 2.2f);
1791 DrawArrow(p, sideview_center + QPoint(0, 96), Direction::Down, 2.2f);
1792 DrawArrow(p, sideview_center + QPoint(0, 109), Direction::Down, 2.2f);
1793 DrawCircle(p, sideview_center + QPointF(0, 19), 4.44f);
1794
1795 // LED indicators
1796 const float led_size = 5.0f;
1797 const QPointF led_position = sideview_center + QPointF(0, -36);
1798 int led_count = 0;
1799 for (const auto color : led_color) {
1800 p.setBrush(color);
1801 DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
1802 }
1803}
1804
1805void PlayerControlPreview::DrawRightBody(QPainter& p, const QPointF center) {
1806 std::array<QPointF, left_joycon_body.size() / 2> right_joycon;
1807 std::array<QPointF, left_joycon_sideview.size() / 2> qright_joycon_sideview;
1808 std::array<QPointF, left_joycon_body_trigger.size() / 2> qright_joycon_trigger;
1809 std::array<QPointF, left_joycon_slider.size() / 2> qright_joycon_slider;
1810 std::array<QPointF, left_joycon_slider_topview.size() / 2> qright_joycon_slider_topview;
1811 std::array<QPointF, left_joycon_topview.size() / 2> qright_joycon_topview;
1812 constexpr float size = 1.78f;
1813 constexpr float size2 = 1.1115f;
1814 constexpr float offset = 312.39f;
1815 constexpr float offset2 = 335;
1816
1817 for (std::size_t point = 0; point < left_joycon_body.size() / 2; ++point) {
1818 right_joycon[point] = center + QPointF(-left_joycon_body[point * 2] * size - offset,
1819 left_joycon_body[point * 2 + 1] * size - 1);
1820 }
1821
1822 for (std::size_t point = 0; point < left_joycon_sideview.size() / 2; ++point) {
1823 qright_joycon_sideview[point] =
1824 center + QPointF(-left_joycon_sideview[point * 2] * size2 - offset2,
1825 left_joycon_sideview[point * 2 + 1] * size2 + 2);
1826 }
1827 for (std::size_t point = 0; point < left_joycon_body_trigger.size() / 2; ++point) {
1828 qright_joycon_trigger[point] =
1829 center + QPointF(-left_joycon_body_trigger[point * 2] * size2 - offset2,
1830 left_joycon_body_trigger[point * 2 + 1] * size2 + 2);
1831 }
1832 for (std::size_t point = 0; point < left_joycon_slider.size() / 2; ++point) {
1833 qright_joycon_slider[point] = center + QPointF(-left_joycon_slider[point * 2] * size2 - 81,
1834 left_joycon_slider[point * 2 + 1] * size2);
1835 }
1836 for (std::size_t point = 0; point < left_joycon_topview.size() / 2; ++point) {
1837 qright_joycon_topview[point] =
1838 center + QPointF(-left_joycon_topview[point * 2], left_joycon_topview[point * 2 + 1]);
1839 }
1840 for (std::size_t point = 0; point < left_joycon_slider_topview.size() / 2; ++point) {
1841 qright_joycon_slider_topview[point] =
1842 center + QPointF(-left_joycon_slider_topview[point * 2],
1843 left_joycon_slider_topview[point * 2 + 1]);
1844 }
1845
1846 // Joycon body
1847 p.setPen(colors.outline);
1848 p.setBrush(colors.left);
1849 DrawPolygon(p, right_joycon);
1850 DrawPolygon(p, qright_joycon_trigger);
1851
1852 // Slider release button top view
1853 p.setBrush(colors.button);
1854 DrawRoundRectangle(p, center + QPoint(107, -62), 14, 12, 2);
1855
1856 // Joycon slider top view
1857 p.setBrush(colors.slider);
1858 DrawPolygon(p, qright_joycon_slider_topview);
1859 p.drawLine(center + QPointF(91.1f, -51.7f), center + QPointF(91.1f, -26.5f));
1860
1861 // Joycon body top view
1862 p.setBrush(colors.left);
1863 DrawPolygon(p, qright_joycon_topview);
1864
1865 // Slider release button
1866 p.setBrush(colors.button);
1867 DrawRoundRectangle(p, center + QPoint(-175, -110), 12, 14, 2);
1868
1869 // Sideview body
1870 p.setBrush(colors.left);
1871 DrawPolygon(p, qright_joycon_sideview);
1872 p.setBrush(colors.slider);
1873 DrawPolygon(p, qright_joycon_slider);
1874
1875 const QPointF sideview_center = QPointF(-155, 0) + center;
1876
1877 // Sideview slider body
1878 p.setBrush(colors.slider);
1879 DrawRoundRectangle(p, sideview_center + QPointF(0, -5), 28, 253, 3);
1880 p.setBrush(colors.button2);
1881 DrawRoundRectangle(p, sideview_center + QPointF(0, 97), 22.44f, 44.66f, 3);
1882
1883 // Slider decorations
1884 p.setPen(colors.outline);
1885 p.setBrush(colors.slider_arrow);
1886 DrawArrow(p, sideview_center + QPoint(0, 83), Direction::Down, 2.2f);
1887 DrawArrow(p, sideview_center + QPoint(0, 96), Direction::Down, 2.2f);
1888 DrawArrow(p, sideview_center + QPoint(0, 109), Direction::Down, 2.2f);
1889 DrawCircle(p, sideview_center + QPointF(0, 19), 4.44f);
1890
1891 // LED indicators
1892 const float led_size = 5.0f;
1893 const QPointF led_position = sideview_center + QPointF(0, -36);
1894 int led_count = 0;
1895 for (const auto color : led_color) {
1896 p.setBrush(color);
1897 DrawRectangle(p, led_position + QPointF(0, 12 * led_count++), led_size, led_size);
1898 }
1899}
1900
1901void PlayerControlPreview::DrawProTriggers(QPainter& p, const QPointF center, bool left_pressed,
1902 bool right_pressed) {
1903 std::array<QPointF, pro_left_trigger.size() / 2> qleft_trigger;
1904 std::array<QPointF, pro_left_trigger.size() / 2> qright_trigger;
1905 std::array<QPointF, pro_body_top.size()> qbody_top;
1906
1907 for (std::size_t point = 0; point < pro_left_trigger.size() / 2; ++point) {
1908 qleft_trigger[point] =
1909 center + QPointF(pro_left_trigger[point * 2],
1910 pro_left_trigger[point * 2 + 1] + (left_pressed ? 2 : 0));
1911 qright_trigger[point] =
1912 center + QPointF(-pro_left_trigger[point * 2],
1913 pro_left_trigger[point * 2 + 1] + (right_pressed ? 2 : 0));
1914 }
1915
1916 for (std::size_t point = 0; point < pro_body_top.size() / 2; ++point) {
1917 qbody_top[pro_body_top.size() - 1 - point] =
1918 center + QPointF(-pro_body_top[point * 2], pro_body_top[point * 2 + 1]);
1919 qbody_top[point] = center + QPointF(pro_body_top[point * 2], pro_body_top[point * 2 + 1]);
1920 }
1921
1922 // Pro body detail
1923 p.setPen(colors.outline);
1924 p.setBrush(colors.primary);
1925 DrawPolygon(p, qbody_top);
1926
1927 // Left trigger
1928 p.setBrush(left_pressed ? colors.highlight : colors.button);
1929 DrawPolygon(p, qleft_trigger);
1930
1931 // Right trigger
1932 p.setBrush(right_pressed ? colors.highlight : colors.button);
1933 DrawPolygon(p, qright_trigger);
1934}
1935
1936void PlayerControlPreview::DrawGCTriggers(QPainter& p, const QPointF center, bool left_pressed,
1937 bool right_pressed) {
1938 std::array<QPointF, left_gc_trigger.size() / 2> qleft_trigger;
1939 std::array<QPointF, left_gc_trigger.size() / 2> qright_trigger;
1940
1941 for (std::size_t point = 0; point < left_gc_trigger.size() / 2; ++point) {
1942 qleft_trigger[point] =
1943 center + QPointF(left_gc_trigger[point * 2],
1944 left_gc_trigger[point * 2 + 1] + (left_pressed ? 10 : 0));
1945 qright_trigger[point] =
1946 center + QPointF(-left_gc_trigger[point * 2],
1947 left_gc_trigger[point * 2 + 1] + (right_pressed ? 10 : 0));
1948 }
1949
1950 // Left trigger
1951 p.setPen(colors.outline);
1952 p.setBrush(left_pressed ? colors.highlight : colors.button);
1953 DrawPolygon(p, qleft_trigger);
1954
1955 // Right trigger
1956 p.setBrush(right_pressed ? colors.highlight : colors.button);
1957 DrawPolygon(p, qright_trigger);
1958
1959 // Draw L text
1960 p.setPen(colors.transparent);
1961 p.setBrush(colors.font);
1962 DrawSymbol(p, center + QPointF(-132, -119 + (left_pressed ? 10 : 0)), Symbol::L, 1.7f);
1963
1964 // Draw R text
1965 p.setPen(colors.transparent);
1966 p.setBrush(colors.font);
1967 DrawSymbol(p, center + QPointF(121.5f, -119 + (right_pressed ? 10 : 0)), Symbol::R, 1.7f);
1968}
1969
1970void PlayerControlPreview::DrawHandheldTriggers(QPainter& p, const QPointF center,
1971 bool left_pressed, bool right_pressed) {
1972 std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
1973 std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
1974
1975 for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) {
1976 qleft_trigger[point] =
1977 center + QPointF(left_joycon_trigger[point * 2],
1978 left_joycon_trigger[point * 2 + 1] + (left_pressed ? 0.5f : 0));
1979 qright_trigger[point] =
1980 center + QPointF(-left_joycon_trigger[point * 2],
1981 left_joycon_trigger[point * 2 + 1] + (right_pressed ? 0.5f : 0));
1982 }
1983
1984 // Left trigger
1985 p.setPen(colors.outline);
1986 p.setBrush(left_pressed ? colors.highlight : colors.button);
1987 DrawPolygon(p, qleft_trigger);
1988
1989 // Right trigger
1990 p.setBrush(right_pressed ? colors.highlight : colors.button);
1991 DrawPolygon(p, qright_trigger);
1992}
1993
1994void PlayerControlPreview::DrawDualTriggers(QPainter& p, const QPointF center, bool left_pressed,
1995 bool right_pressed) {
1996 std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
1997 std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
1998 constexpr float size = 1.62f;
1999 constexpr float offset = 210.6f;
2000 for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) {
2001 qleft_trigger[point] =
2002 center + QPointF(left_joycon_trigger[point * 2] * size + offset,
2003 left_joycon_trigger[point * 2 + 1] * size + (left_pressed ? 0.5f : 0));
2004 qright_trigger[point] = center + QPointF(-left_joycon_trigger[point * 2] * size - offset,
2005 left_joycon_trigger[point * 2 + 1] * size +
2006 (right_pressed ? 0.5f : 0));
2007 }
2008
2009 // Left trigger
2010 p.setPen(colors.outline);
2011 p.setBrush(left_pressed ? colors.highlight : colors.button);
2012 DrawPolygon(p, qleft_trigger);
2013
2014 // Right trigger
2015 p.setBrush(right_pressed ? colors.highlight : colors.button);
2016 DrawPolygon(p, qright_trigger);
2017}
2018
2019void PlayerControlPreview::DrawDualTriggersTopView(QPainter& p, const QPointF center,
2020 bool left_pressed, bool right_pressed) {
2021 std::array<QPointF, left_joystick_L_topview.size() / 2> qleft_trigger;
2022 std::array<QPointF, left_joystick_L_topview.size() / 2> qright_trigger;
2023 constexpr float size = 0.9f;
2024
2025 for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) {
2026 qleft_trigger[point] = center + QPointF(left_joystick_L_topview[point * 2] * size - 50,
2027 left_joystick_L_topview[point * 2 + 1] * size - 52);
2028 }
2029 for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) {
2030 qright_trigger[point] =
2031 center + QPointF(-left_joystick_L_topview[point * 2] * size + 50,
2032 left_joystick_L_topview[point * 2 + 1] * size - 52);
2033 }
2034
2035 p.setPen(colors.outline);
2036 p.setBrush(left_pressed ? colors.highlight : colors.button);
2037 DrawPolygon(p, qleft_trigger);
2038 p.setBrush(right_pressed ? colors.highlight : colors.button);
2039 DrawPolygon(p, qright_trigger);
2040
2041 // Draw L text
2042 p.setPen(colors.transparent);
2043 p.setBrush(colors.font2);
2044 DrawSymbol(p, center + QPointF(-183, -84), Symbol::L, 1.0f);
2045
2046 // Draw R text
2047 p.setPen(colors.transparent);
2048 p.setBrush(colors.font2);
2049 DrawSymbol(p, center + QPointF(177, -84), Symbol::R, 1.0f);
2050}
2051
2052void PlayerControlPreview::DrawDualZTriggersTopView(QPainter& p, const QPointF center,
2053 bool left_pressed, bool right_pressed) {
2054 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qleft_trigger;
2055 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qright_trigger;
2056 constexpr float size = 0.9f;
2057
2058 for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) {
2059 qleft_trigger[point] =
2060 center + QPointF(left_joystick_ZL_topview[point * 2] * size - 52,
2061 left_joystick_ZL_topview[point * 2 + 1] * size - 52);
2062 }
2063 for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) {
2064 qright_trigger[point] =
2065 center + QPointF(-left_joystick_ZL_topview[point * 2] * size + 52,
2066 left_joystick_ZL_topview[point * 2 + 1] * size - 52);
2067 }
2068
2069 p.setPen(colors.outline);
2070 p.setBrush(left_pressed ? colors.highlight : colors.button);
2071 DrawPolygon(p, qleft_trigger);
2072 p.setBrush(right_pressed ? colors.highlight : colors.button);
2073 DrawPolygon(p, qright_trigger);
2074
2075 // Draw ZL text
2076 p.setPen(colors.transparent);
2077 p.setBrush(colors.font2);
2078 DrawSymbol(p, center + QPointF(-180, -113), Symbol::ZL, 1.0f);
2079
2080 // Draw ZR text
2081 p.setPen(colors.transparent);
2082 p.setBrush(colors.font2);
2083 DrawSymbol(p, center + QPointF(180, -113), Symbol::ZR, 1.0f);
2084}
2085
2086void PlayerControlPreview::DrawLeftTriggers(QPainter& p, const QPointF center, bool left_pressed) {
2087 std::array<QPointF, left_joycon_trigger.size() / 2> qleft_trigger;
2088 constexpr float size = 1.78f;
2089 constexpr float offset = 311.5f;
2090
2091 for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) {
2092 qleft_trigger[point] = center + QPointF(left_joycon_trigger[point * 2] * size + offset,
2093 left_joycon_trigger[point * 2 + 1] * size -
2094 (left_pressed ? 0.5f : 1.0f));
2095 }
2096
2097 p.setPen(colors.outline);
2098 p.setBrush(left_pressed ? colors.highlight : colors.button);
2099 DrawPolygon(p, qleft_trigger);
2100}
2101
2102void PlayerControlPreview::DrawLeftZTriggers(QPainter& p, const QPointF center, bool left_pressed) {
2103 std::array<QPointF, left_joycon_sideview_zl.size() / 2> qleft_trigger;
2104 constexpr float size = 1.1115f;
2105 constexpr float offset2 = 335;
2106
2107 for (std::size_t point = 0; point < left_joycon_sideview_zl.size() / 2; ++point) {
2108 qleft_trigger[point] = center + QPointF(left_joycon_sideview_zl[point * 2] * size + offset2,
2109 left_joycon_sideview_zl[point * 2 + 1] * size +
2110 (left_pressed ? 1.5f : 1.0f));
2111 }
2112
2113 p.setPen(colors.outline);
2114 p.setBrush(left_pressed ? colors.highlight : colors.button);
2115 DrawPolygon(p, qleft_trigger);
2116 p.drawArc(center.x() + 158, center.y() + (left_pressed ? -203.5f : -204.0f), 77, 77, 225 * 16,
2117 44 * 16);
2118}
2119
2120void PlayerControlPreview::DrawLeftTriggersTopView(QPainter& p, const QPointF center,
2121 bool left_pressed) {
2122 std::array<QPointF, left_joystick_L_topview.size() / 2> qleft_trigger;
2123
2124 for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) {
2125 qleft_trigger[point] = center + QPointF(left_joystick_L_topview[point * 2],
2126 left_joystick_L_topview[point * 2 + 1]);
2127 }
2128
2129 p.setPen(colors.outline);
2130 p.setBrush(left_pressed ? colors.highlight : colors.button);
2131 DrawPolygon(p, qleft_trigger);
2132
2133 // Draw L text
2134 p.setPen(colors.transparent);
2135 p.setBrush(colors.font2);
2136 DrawSymbol(p, center + QPointF(-143, -36), Symbol::L, 1.0f);
2137}
2138
2139void PlayerControlPreview::DrawLeftZTriggersTopView(QPainter& p, const QPointF center,
2140 bool left_pressed) {
2141 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qleft_trigger;
2142
2143 for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) {
2144 qleft_trigger[point] = center + QPointF(left_joystick_ZL_topview[point * 2],
2145 left_joystick_ZL_topview[point * 2 + 1]);
2146 }
2147
2148 p.setPen(colors.outline);
2149 p.setBrush(left_pressed ? colors.highlight : colors.button);
2150 DrawPolygon(p, qleft_trigger);
2151
2152 // Draw ZL text
2153 p.setPen(colors.transparent);
2154 p.setBrush(colors.font2);
2155 DrawSymbol(p, center + QPointF(-140, -68), Symbol::ZL, 1.0f);
2156}
2157
2158void PlayerControlPreview::DrawRightTriggers(QPainter& p, const QPointF center,
2159 bool right_pressed) {
2160 std::array<QPointF, left_joycon_trigger.size() / 2> qright_trigger;
2161 constexpr float size = 1.78f;
2162 constexpr float offset = 311.5f;
2163
2164 for (std::size_t point = 0; point < left_joycon_trigger.size() / 2; ++point) {
2165 qright_trigger[point] = center + QPointF(-left_joycon_trigger[point * 2] * size - offset,
2166 left_joycon_trigger[point * 2 + 1] * size -
2167 (right_pressed ? 0.5f : 1.0f));
2168 }
2169
2170 p.setPen(colors.outline);
2171 p.setBrush(right_pressed ? colors.highlight : colors.button);
2172 DrawPolygon(p, qright_trigger);
2173}
2174
2175void PlayerControlPreview::DrawRightZTriggers(QPainter& p, const QPointF center,
2176 bool right_pressed) {
2177 std::array<QPointF, left_joycon_sideview_zl.size() / 2> qright_trigger;
2178 constexpr float size = 1.1115f;
2179 constexpr float offset2 = 335;
2180
2181 for (std::size_t point = 0; point < left_joycon_sideview_zl.size() / 2; ++point) {
2182 qright_trigger[point] =
2183 center +
2184 QPointF(-left_joycon_sideview_zl[point * 2] * size - offset2,
2185 left_joycon_sideview_zl[point * 2 + 1] * size + (right_pressed ? 0.5f : 0) + 1);
2186 }
2187
2188 p.setPen(colors.outline);
2189 p.setBrush(right_pressed ? colors.highlight : colors.button);
2190 DrawPolygon(p, qright_trigger);
2191 p.drawArc(center.x() - 236, center.y() + (right_pressed ? -203.5f : -204.0f), 77, 77, 271 * 16,
2192 44 * 16);
2193}
2194
2195void PlayerControlPreview::DrawRightTriggersTopView(QPainter& p, const QPointF center,
2196 bool right_pressed) {
2197 std::array<QPointF, left_joystick_L_topview.size() / 2> qright_trigger;
2198
2199 for (std::size_t point = 0; point < left_joystick_L_topview.size() / 2; ++point) {
2200 qright_trigger[point] = center + QPointF(-left_joystick_L_topview[point * 2],
2201 left_joystick_L_topview[point * 2 + 1]);
2202 }
2203
2204 p.setPen(colors.outline);
2205 p.setBrush(right_pressed ? colors.highlight : colors.button);
2206 DrawPolygon(p, qright_trigger);
2207
2208 // Draw R text
2209 p.setPen(colors.transparent);
2210 p.setBrush(colors.font2);
2211 DrawSymbol(p, center + QPointF(137, -36), Symbol::R, 1.0f);
2212}
2213
2214void PlayerControlPreview::DrawRightZTriggersTopView(QPainter& p, const QPointF center,
2215 bool right_pressed) {
2216 std::array<QPointF, left_joystick_ZL_topview.size() / 2> qright_trigger;
2217
2218 for (std::size_t point = 0; point < left_joystick_ZL_topview.size() / 2; ++point) {
2219 qright_trigger[point] = center + QPointF(-left_joystick_ZL_topview[point * 2],
2220 left_joystick_ZL_topview[point * 2 + 1]);
2221 }
2222
2223 p.setPen(colors.outline);
2224 p.setBrush(right_pressed ? colors.highlight : colors.button);
2225 DrawPolygon(p, qright_trigger);
2226
2227 // Draw ZR text
2228 p.setPen(colors.transparent);
2229 p.setBrush(colors.font2);
2230 DrawSymbol(p, center + QPointF(140, -68), Symbol::ZR, 1.0f);
2231}
2232
2233void PlayerControlPreview::DrawJoystick(QPainter& p, const QPointF center, float size,
2234 bool pressed) {
2235 const float radius1 = 13.0f * size;
2236 const float radius2 = 9.0f * size;
2237
2238 // Outer circle
2239 p.setPen(colors.outline);
2240 p.setBrush(pressed ? colors.highlight : colors.button);
2241 DrawCircle(p, center, radius1);
2242
2243 // Cross
2244 p.drawLine(center - QPoint(radius1, 0), center + QPoint(radius1, 0));
2245 p.drawLine(center - QPoint(0, radius1), center + QPoint(0, radius1));
2246
2247 // Inner circle
2248 p.setBrush(pressed ? colors.highlight2 : colors.button2);
2249 DrawCircle(p, center, radius2);
2250}
2251
2252void PlayerControlPreview::DrawJoystickSideview(QPainter& p, const QPointF center, float angle,
2253 float size, bool pressed) {
2254 QVector<QPointF> joystick;
2255 joystick.reserve(static_cast<int>(left_joystick_sideview.size() / 2));
2256
2257 for (std::size_t point = 0; point < left_joystick_sideview.size() / 2; ++point) {
2258 joystick.append(QPointF(left_joystick_sideview[point * 2] * size + (pressed ? 1 : 0),
2259 left_joystick_sideview[point * 2 + 1] * size - 1));
2260 }
2261
2262 // Rotate joystick
2263 QTransform t;
2264 t.translate(center.x(), center.y());
2265 t.rotate(18 * angle);
2266 QPolygonF p2 = t.map(QPolygonF(joystick));
2267
2268 // Draw joystick
2269 p.setPen(colors.outline);
2270 p.setBrush(pressed ? colors.highlight : colors.button);
2271 p.drawPolygon(p2);
2272 p.drawLine(p2.at(1), p2.at(30));
2273 p.drawLine(p2.at(32), p2.at(71));
2274}
2275
2276void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, bool pressed) {
2277 // Outer circle
2278 p.setPen(colors.outline);
2279 p.setBrush(pressed ? colors.highlight : colors.button);
2280 DrawCircle(p, center, 24.0f);
2281
2282 // Inner circle
2283 p.setBrush(pressed ? colors.highlight2 : colors.button2);
2284 DrawCircle(p, center, 17.0f);
2285}
2286
2287void PlayerControlPreview::DrawGCJoystick(QPainter& p, const QPointF center, bool pressed) {
2288 // Outer circle
2289 p.setPen(colors.outline);
2290 p.setBrush(pressed ? colors.highlight : colors.button);
2291 DrawCircle(p, center, 26.0f);
2292
2293 // Inner circle
2294 p.setBrush(pressed ? colors.highlight2 : colors.button2);
2295 DrawCircle(p, center, 19.0f);
2296 p.setBrush(colors.transparent);
2297 DrawCircle(p, center, 13.5f);
2298 DrawCircle(p, center, 7.5f);
2299}
2300
2301void PlayerControlPreview::DrawRawJoystick(QPainter& p, const QPointF center, const QPointF value,
2302 const Input::AnalogProperties properties) {
2303 constexpr float size = 45.0f;
2304 const float range = size * properties.range;
2305 const float deadzone = size * properties.deadzone;
2306
2307 // Max range zone circle
2308 p.setPen(colors.outline);
2309 p.setBrush(colors.transparent);
2310 QPen pen = p.pen();
2311 pen.setStyle(Qt::DotLine);
2312 p.setPen(pen);
2313 DrawCircle(p, center, range);
2314
2315 // Deadzone circle
2316 pen.setColor(colors.deadzone);
2317 p.setPen(pen);
2318 DrawCircle(p, center, deadzone);
2319
2320 // Dot pointer
2321 p.setPen(colors.indicator);
2322 p.setBrush(colors.indicator);
2323 DrawCircle(p, center + (value * range), 2);
2324}
2325
2326void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center, bool pressed, float width,
2327 float height, Direction direction, float radius) {
2328 p.setBrush(button_color);
2329 if (pressed) {
2330 switch (direction) {
2331 case Direction::Left:
2332 center.setX(center.x() - 1);
2333 break;
2334 case Direction::Right:
2335 center.setX(center.x() + 1);
2336 break;
2337 case Direction::Down:
2338 center.setY(center.y() + 1);
2339 break;
2340 case Direction::Up:
2341 center.setY(center.y() - 1);
2342 break;
2343 case Direction::None:
2344 break;
2345 }
2346 p.setBrush(colors.highlight);
2347 }
2348 QRectF rect = {center.x() - width, center.y() - height, width * 2.0f, height * 2.0f};
2349 p.drawRoundedRect(rect, radius, radius);
2350}
2351void PlayerControlPreview::DrawMinusButton(QPainter& p, const QPointF center, bool pressed,
2352 int button_size) {
2353 p.setPen(colors.outline);
2354 p.setBrush(pressed ? colors.highlight : colors.button);
2355 DrawRectangle(p, center, button_size, button_size / 3.0f);
2356}
2357void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center, bool pressed,
2358 int button_size) {
2359 // Draw outer line
2360 p.setPen(colors.outline);
2361 p.setBrush(pressed ? colors.highlight : colors.button);
2362 DrawRectangle(p, center, button_size, button_size / 3.0f);
2363 DrawRectangle(p, center, button_size / 3.0f, button_size);
2364
2365 // Scale down size
2366 button_size *= 0.88f;
2367
2368 // Draw inner color
2369 p.setPen(colors.transparent);
2370 DrawRectangle(p, center, button_size, button_size / 3.0f);
2371 DrawRectangle(p, center, button_size / 3.0f, button_size);
2372}
2373
2374void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center, bool pressed) {
2375 std::array<QPointF, gc_button_x.size() / 2> button_x;
2376
2377 for (std::size_t point = 0; point < gc_button_x.size() / 2; ++point) {
2378 button_x[point] = center + QPointF(gc_button_x[point * 2], gc_button_x[point * 2 + 1]);
2379 }
2380
2381 p.setPen(colors.outline);
2382 p.setBrush(pressed ? colors.highlight : colors.button);
2383 DrawPolygon(p, button_x);
2384}
2385
2386void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center, bool pressed) {
2387 std::array<QPointF, gc_button_y.size() / 2> button_x;
2388
2389 for (std::size_t point = 0; point < gc_button_y.size() / 2; ++point) {
2390 button_x[point] = center + QPointF(gc_button_y[point * 2], gc_button_y[point * 2 + 1]);
2391 }
2392
2393 p.setPen(colors.outline);
2394 p.setBrush(pressed ? colors.highlight : colors.button);
2395 DrawPolygon(p, button_x);
2396}
2397
2398void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center, bool pressed) {
2399 std::array<QPointF, gc_button_z.size() / 2> button_x;
2400
2401 for (std::size_t point = 0; point < gc_button_z.size() / 2; ++point) {
2402 button_x[point] = center + QPointF(gc_button_z[point * 2],
2403 gc_button_z[point * 2 + 1] + (pressed ? 1 : 0));
2404 }
2405
2406 p.setPen(colors.outline);
2407 p.setBrush(pressed ? colors.highlight : colors.button2);
2408 DrawPolygon(p, button_x);
2409}
2410
2411void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center, bool pressed,
2412 float button_size) {
2413 p.setBrush(button_color);
2414 if (pressed) {
2415 p.setBrush(colors.highlight);
2416 }
2417 p.drawEllipse(center, button_size, button_size);
2418}
2419
2420void PlayerControlPreview::DrawArrowButtonOutline(QPainter& p, const QPointF center, float size) {
2421 const std::size_t arrow_points = up_arrow_button.size() / 2;
2422 std::array<QPointF, (arrow_points - 1) * 4> arrow_button_outline;
2423
2424 for (std::size_t point = 0; point < arrow_points - 1; ++point) {
2425 arrow_button_outline[point] = center + QPointF(up_arrow_button[point * 2] * size,
2426 up_arrow_button[point * 2 + 1] * size);
2427 arrow_button_outline[(arrow_points - 1) * 2 - point - 1] =
2428 center +
2429 QPointF(up_arrow_button[point * 2 + 1] * size, up_arrow_button[point * 2] * size);
2430 arrow_button_outline[(arrow_points - 1) * 2 + point] =
2431 center +
2432 QPointF(-up_arrow_button[point * 2] * size, -up_arrow_button[point * 2 + 1] * size);
2433 arrow_button_outline[(arrow_points - 1) * 4 - point - 1] =
2434 center +
2435 QPointF(-up_arrow_button[point * 2 + 1] * size, -up_arrow_button[point * 2] * size);
2436 }
2437 // Draw arrow button outline
2438 p.setPen(colors.outline);
2439 p.setBrush(colors.transparent);
2440 DrawPolygon(p, arrow_button_outline);
2441}
2442
2443void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
2444 const Direction direction, bool pressed, float size) {
2445 std::array<QPointF, up_arrow_button.size() / 2> arrow_button;
2446 QPoint offset;
2447
2448 for (std::size_t point = 0; point < up_arrow_button.size() / 2; ++point) {
2449 switch (direction) {
2450 case Direction::Up:
2451 arrow_button[point] = center + QPointF(up_arrow_button[point * 2] * size,
2452 up_arrow_button[point * 2 + 1] * size);
2453 break;
2454 case Direction::Left:
2455 arrow_button[point] = center + QPointF(up_arrow_button[point * 2 + 1] * size,
2456 up_arrow_button[point * 2] * size);
2457 break;
2458 case Direction::Right:
2459 arrow_button[point] = center + QPointF(-up_arrow_button[point * 2 + 1] * size,
2460 up_arrow_button[point * 2] * size);
2461 break;
2462 case Direction::Down:
2463 arrow_button[point] = center + QPointF(up_arrow_button[point * 2] * size,
2464 -up_arrow_button[point * 2 + 1] * size);
2465 break;
2466 case Direction::None:
2467 break;
2468 }
2469 }
2470
2471 // Draw arrow button
2472 p.setPen(pressed ? colors.highlight : colors.button);
2473 p.setBrush(pressed ? colors.highlight : colors.button);
2474 DrawPolygon(p, arrow_button);
2475
2476 switch (direction) {
2477 case Direction::Up:
2478 offset = QPoint(0, -20 * size);
2479 break;
2480 case Direction::Left:
2481 offset = QPoint(-20 * size, 0);
2482 break;
2483 case Direction::Right:
2484 offset = QPoint(20 * size, 0);
2485 break;
2486 case Direction::Down:
2487 offset = QPoint(0, 20 * size);
2488 break;
2489 case Direction::None:
2490 offset = QPoint(0, 0);
2491 break;
2492 }
2493
2494 // Draw arrow icon
2495 p.setPen(colors.font2);
2496 p.setBrush(colors.font2);
2497 DrawArrow(p, center + offset, direction, size);
2498}
2499
2500void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center,
2501 const Direction direction, bool pressed) {
2502 std::array<QPointF, trigger_button.size() / 2> qtrigger_button;
2503 QPoint offset;
2504
2505 for (std::size_t point = 0; point < trigger_button.size() / 2; ++point) {
2506 switch (direction) {
2507 case Direction::Left:
2508 qtrigger_button[point] =
2509 center + QPointF(-trigger_button[point * 2], trigger_button[point * 2 + 1]);
2510 break;
2511 case Direction::Right:
2512 qtrigger_button[point] =
2513 center + QPointF(trigger_button[point * 2], trigger_button[point * 2 + 1]);
2514 break;
2515 case Direction::Up:
2516 case Direction::Down:
2517 case Direction::None:
2518 break;
2519 }
2520 }
2521
2522 // Draw arrow button
2523 p.setPen(colors.outline);
2524 p.setBrush(pressed ? colors.highlight : colors.button);
2525 DrawPolygon(p, qtrigger_button);
2526}
2527
2528void PlayerControlPreview::DrawSymbol(QPainter& p, const QPointF center, Symbol symbol,
2529 float icon_size) {
2530 std::array<QPointF, house.size() / 2> house_icon;
2531 std::array<QPointF, symbol_a.size() / 2> a_icon;
2532 std::array<QPointF, symbol_b.size() / 2> b_icon;
2533 std::array<QPointF, symbol_x.size() / 2> x_icon;
2534 std::array<QPointF, symbol_y.size() / 2> y_icon;
2535 std::array<QPointF, symbol_l.size() / 2> l_icon;
2536 std::array<QPointF, symbol_r.size() / 2> r_icon;
2537 std::array<QPointF, symbol_c.size() / 2> c_icon;
2538 std::array<QPointF, symbol_zl.size() / 2> zl_icon;
2539 std::array<QPointF, symbol_sl.size() / 2> sl_icon;
2540 std::array<QPointF, symbol_zr.size() / 2> zr_icon;
2541 std::array<QPointF, symbol_sr.size() / 2> sr_icon;
2542 switch (symbol) {
2543 case Symbol::House:
2544 for (std::size_t point = 0; point < house.size() / 2; ++point) {
2545 house_icon[point] = center + QPointF(house[point * 2] * icon_size,
2546 (house[point * 2 + 1] - 0.025f) * icon_size);
2547 }
2548 p.drawPolygon(house_icon.data(), static_cast<int>(house_icon.size()));
2549 break;
2550 case Symbol::A:
2551 for (std::size_t point = 0; point < symbol_a.size() / 2; ++point) {
2552 a_icon[point] = center + QPointF(symbol_a[point * 2] * icon_size,
2553 symbol_a[point * 2 + 1] * icon_size);
2554 }
2555 p.drawPolygon(a_icon.data(), static_cast<int>(a_icon.size()));
2556 break;
2557 case Symbol::B:
2558 for (std::size_t point = 0; point < symbol_b.size() / 2; ++point) {
2559 b_icon[point] = center + QPointF(symbol_b[point * 2] * icon_size,
2560 symbol_b[point * 2 + 1] * icon_size);
2561 }
2562 p.drawPolygon(b_icon.data(), static_cast<int>(b_icon.size()));
2563 break;
2564 case Symbol::X:
2565 for (std::size_t point = 0; point < symbol_x.size() / 2; ++point) {
2566 x_icon[point] = center + QPointF(symbol_x[point * 2] * icon_size,
2567 symbol_x[point * 2 + 1] * icon_size);
2568 }
2569 p.drawPolygon(x_icon.data(), static_cast<int>(x_icon.size()));
2570 break;
2571 case Symbol::Y:
2572 for (std::size_t point = 0; point < symbol_y.size() / 2; ++point) {
2573 y_icon[point] = center + QPointF(symbol_y[point * 2] * icon_size,
2574 (symbol_y[point * 2 + 1] - 1.0f) * icon_size);
2575 }
2576 p.drawPolygon(y_icon.data(), static_cast<int>(y_icon.size()));
2577 break;
2578 case Symbol::L:
2579 for (std::size_t point = 0; point < symbol_l.size() / 2; ++point) {
2580 l_icon[point] = center + QPointF(symbol_l[point * 2] * icon_size,
2581 (symbol_l[point * 2 + 1] - 1.0f) * icon_size);
2582 }
2583 p.drawPolygon(l_icon.data(), static_cast<int>(l_icon.size()));
2584 break;
2585 case Symbol::R:
2586 for (std::size_t point = 0; point < symbol_r.size() / 2; ++point) {
2587 r_icon[point] = center + QPointF(symbol_r[point * 2] * icon_size,
2588 (symbol_r[point * 2 + 1] - 1.0f) * icon_size);
2589 }
2590 p.drawPolygon(r_icon.data(), static_cast<int>(r_icon.size()));
2591 break;
2592 case Symbol::C:
2593 for (std::size_t point = 0; point < symbol_c.size() / 2; ++point) {
2594 c_icon[point] = center + QPointF(symbol_c[point * 2] * icon_size,
2595 (symbol_c[point * 2 + 1] - 1.0f) * icon_size);
2596 }
2597 p.drawPolygon(c_icon.data(), static_cast<int>(c_icon.size()));
2598 break;
2599 case Symbol::ZL:
2600 for (std::size_t point = 0; point < symbol_zl.size() / 2; ++point) {
2601 zl_icon[point] = center + QPointF(symbol_zl[point * 2] * icon_size,
2602 symbol_zl[point * 2 + 1] * icon_size);
2603 }
2604 p.drawPolygon(zl_icon.data(), static_cast<int>(zl_icon.size()));
2605 break;
2606 case Symbol::SL:
2607 for (std::size_t point = 0; point < symbol_sl.size() / 2; ++point) {
2608 sl_icon[point] = center + QPointF(symbol_sl[point * 2] * icon_size,
2609 symbol_sl[point * 2 + 1] * icon_size);
2610 }
2611 p.drawPolygon(sl_icon.data(), static_cast<int>(sl_icon.size()));
2612 break;
2613 case Symbol::ZR:
2614 for (std::size_t point = 0; point < symbol_zr.size() / 2; ++point) {
2615 zr_icon[point] = center + QPointF(symbol_zr[point * 2] * icon_size,
2616 symbol_zr[point * 2 + 1] * icon_size);
2617 }
2618 p.drawPolygon(zr_icon.data(), static_cast<int>(zr_icon.size()));
2619 break;
2620 case Symbol::SR:
2621 for (std::size_t point = 0; point < symbol_sr.size() / 2; ++point) {
2622 sr_icon[point] = center + QPointF(symbol_sr[point * 2] * icon_size,
2623 symbol_sr[point * 2 + 1] * icon_size);
2624 }
2625 p.drawPolygon(sr_icon.data(), static_cast<int>(sr_icon.size()));
2626 break;
2627 }
2628}
2629
2630void PlayerControlPreview::DrawArrow(QPainter& p, const QPointF center, const Direction direction,
2631 float size) {
2632
2633 std::array<QPointF, up_arrow_symbol.size() / 2> arrow_symbol;
2634
2635 for (std::size_t point = 0; point < up_arrow_symbol.size() / 2; ++point) {
2636 switch (direction) {
2637 case Direction::Up:
2638 arrow_symbol[point] = center + QPointF(up_arrow_symbol[point * 2] * size,
2639 up_arrow_symbol[point * 2 + 1] * size);
2640 break;
2641 case Direction::Left:
2642 arrow_symbol[point] = center + QPointF(up_arrow_symbol[point * 2 + 1] * size,
2643 up_arrow_symbol[point * 2] * size);
2644 break;
2645 case Direction::Right:
2646 arrow_symbol[point] = center + QPointF(-up_arrow_symbol[point * 2 + 1] * size,
2647 up_arrow_symbol[point * 2] * size);
2648 break;
2649 case Direction::Down:
2650 arrow_symbol[point] = center + QPointF(up_arrow_symbol[point * 2] * size,
2651 -up_arrow_symbol[point * 2 + 1] * size);
2652 break;
2653 case Direction::None:
2654 break;
2655 }
2656 }
2657
2658 DrawPolygon(p, arrow_symbol);
2659}
2660
2661template <size_t N>
2662void PlayerControlPreview::DrawPolygon(QPainter& p, const std::array<QPointF, N>& polygon) {
2663 p.drawPolygon(polygon.data(), static_cast<int>(polygon.size()));
2664}
2665
2666void PlayerControlPreview::DrawCircle(QPainter& p, const QPointF center, float size) {
2667 p.drawEllipse(center, size, size);
2668}
2669
2670void PlayerControlPreview::DrawRectangle(QPainter& p, const QPointF center, float width,
2671 float height) {
2672 const QRectF rect = QRectF(center.x() - (width / 2), center.y() - (height / 2), width, height);
2673 p.drawRect(rect);
2674}
2675void PlayerControlPreview::DrawRoundRectangle(QPainter& p, const QPointF center, float width,
2676 float height, float round) {
2677 const QRectF rect = QRectF(center.x() - (width / 2), center.y() - (height / 2), width, height);
2678 p.drawRoundedRect(rect, round, round);
2679}
2680
2681void PlayerControlPreview::DrawText(QPainter& p, const QPointF center, float text_size,
2682 const QString& text) {
2683 SetTextFont(p, text_size);
2684 const QFontMetrics fm(p.font());
2685 const QPointF offset = {fm.horizontalAdvance(text) / 2.0f, -text_size / 2.0f};
2686 p.drawText(center - offset, text);
2687}
2688
2689void PlayerControlPreview::SetTextFont(QPainter& p, float text_size, const QString& font_family) {
2690 QFont font = p.font();
2691 font.setPointSizeF(text_size);
2692 font.setFamily(font_family);
2693 p.setFont(font);
2694}
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
new file mode 100644
index 000000000..39565f795
--- /dev/null
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -0,0 +1,192 @@
1// Copyright 2020 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 <array>
8#include <QFrame>
9#include <QPointer>
10#include "core/frontend/input.h"
11#include "core/settings.h"
12
13class QLabel;
14
15using AnalogParam = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
16using ButtonParam = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
17
18// Widget for representing controller animations
19class PlayerControlPreview : public QFrame {
20 Q_OBJECT
21
22public:
23 explicit PlayerControlPreview(QWidget* parent);
24 ~PlayerControlPreview() override;
25
26 void SetPlayerInput(std::size_t index, const ButtonParam& buttons_param,
27 const AnalogParam& analogs_param);
28 void SetPlayerInputRaw(std::size_t index, const Settings::ButtonsRaw buttons_,
29 Settings::AnalogsRaw analogs_);
30 void SetConnectedStatus(bool checked);
31 void SetControllerType(Settings::ControllerType type);
32 void BeginMappingButton(std::size_t button_id);
33 void BeginMappingAnalog(std::size_t button_id);
34 void EndMapping();
35 void UpdateInput();
36
37protected:
38 void paintEvent(QPaintEvent* event) override;
39
40private:
41 enum class Direction : std::size_t {
42 None,
43 Up,
44 Right,
45 Down,
46 Left,
47 };
48
49 enum class Symbol {
50 House,
51 A,
52 B,
53 X,
54 Y,
55 L,
56 R,
57 C,
58 SL,
59 ZL,
60 ZR,
61 SR,
62 };
63
64 struct AxisValue {
65 QPointF value{};
66 QPointF raw_value{};
67 Input::AnalogProperties properties{};
68 int size{};
69 QPoint offset{};
70 bool active{};
71 };
72
73 struct LedPattern {
74 bool position1;
75 bool position2;
76 bool position3;
77 bool position4;
78 };
79
80 struct ColorMapping {
81 QColor outline{};
82 QColor primary{};
83 QColor left{};
84 QColor right{};
85 QColor button{};
86 QColor button2{};
87 QColor font{};
88 QColor font2{};
89 QColor highlight{};
90 QColor highlight2{};
91 QColor transparent{};
92 QColor indicator{};
93 QColor led_on{};
94 QColor led_off{};
95 QColor slider{};
96 QColor slider_button{};
97 QColor slider_arrow{};
98 QColor deadzone{};
99 };
100
101 static LedPattern GetColorPattern(std::size_t index, bool player_on);
102 void UpdateColors();
103
104 // Draw controller functions
105 void DrawHandheldController(QPainter& p, QPointF center);
106 void DrawDualController(QPainter& p, QPointF center);
107 void DrawLeftController(QPainter& p, QPointF center);
108 void DrawRightController(QPainter& p, QPointF center);
109 void DrawProController(QPainter& p, QPointF center);
110 void DrawGCController(QPainter& p, QPointF center);
111
112 // Draw body functions
113 void DrawHandheldBody(QPainter& p, QPointF center);
114 void DrawDualBody(QPainter& p, QPointF center);
115 void DrawLeftBody(QPainter& p, QPointF center);
116 void DrawRightBody(QPainter& p, QPointF center);
117 void DrawProBody(QPainter& p, QPointF center);
118 void DrawGCBody(QPainter& p, QPointF center);
119
120 // Draw triggers functions
121 void DrawProTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
122 void DrawGCTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
123 void DrawHandheldTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
124 void DrawDualTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
125 void DrawDualTriggersTopView(QPainter& p, QPointF center, bool left_pressed,
126 bool right_pressed);
127 void DrawDualZTriggersTopView(QPainter& p, QPointF center, bool left_pressed,
128 bool right_pressed);
129 void DrawLeftTriggers(QPainter& p, QPointF center, bool left_pressed);
130 void DrawLeftZTriggers(QPainter& p, QPointF center, bool left_pressed);
131 void DrawLeftTriggersTopView(QPainter& p, QPointF center, bool left_pressed);
132 void DrawLeftZTriggersTopView(QPainter& p, QPointF center, bool left_pressed);
133 void DrawRightTriggers(QPainter& p, QPointF center, bool right_pressed);
134 void DrawRightZTriggers(QPainter& p, QPointF center, bool right_pressed);
135 void DrawRightTriggersTopView(QPainter& p, QPointF center, bool right_pressed);
136 void DrawRightZTriggersTopView(QPainter& p, QPointF center, bool right_pressed);
137
138 // Draw joystick functions
139 void DrawJoystick(QPainter& p, QPointF center, float size, bool pressed);
140 void DrawJoystickSideview(QPainter& p, QPointF center, float angle, float size, bool pressed);
141 void DrawRawJoystick(QPainter& p, QPointF center, const QPointF value,
142 const Input::AnalogProperties properties);
143 void DrawProJoystick(QPainter& p, QPointF center, bool pressed);
144 void DrawGCJoystick(QPainter& p, QPointF center, bool pressed);
145
146 // Draw button functions
147 void DrawCircleButton(QPainter& p, QPointF center, bool pressed, float button_size);
148 void DrawRoundButton(QPainter& p, QPointF center, bool pressed, float width, float height,
149 Direction direction = Direction::None, float radius = 2);
150 void DrawMinusButton(QPainter& p, QPointF center, bool pressed, int button_size);
151 void DrawPlusButton(QPainter& p, QPointF center, bool pressed, int button_size);
152 void DrawGCButtonX(QPainter& p, QPointF center, bool pressed);
153 void DrawGCButtonY(QPainter& p, QPointF center, bool pressed);
154 void DrawGCButtonZ(QPainter& p, QPointF center, bool pressed);
155 void DrawArrowButtonOutline(QPainter& p, const QPointF center, float size = 1.0f);
156 void DrawArrowButton(QPainter& p, QPointF center, Direction direction, bool pressed,
157 float size = 1.0f);
158 void DrawTriggerButton(QPainter& p, QPointF center, Direction direction, bool pressed);
159
160 // Draw icon functions
161 void DrawSymbol(QPainter& p, QPointF center, Symbol symbol, float icon_size);
162 void DrawArrow(QPainter& p, QPointF center, Direction direction, float size);
163
164 // Draw primitive types
165 template <size_t N>
166 void DrawPolygon(QPainter& p, const std::array<QPointF, N>& polygon);
167 void DrawCircle(QPainter& p, QPointF center, float size);
168 void DrawRectangle(QPainter& p, QPointF center, float width, float height);
169 void DrawRoundRectangle(QPainter& p, QPointF center, float width, float height, float round);
170 void DrawText(QPainter& p, QPointF center, float text_size, const QString& text);
171 void SetTextFont(QPainter& p, float text_size,
172 const QString& font_family = QStringLiteral("sans-serif"));
173
174 using ButtonArray =
175 std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::BUTTON_NS_END>;
176 using StickArray =
177 std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>;
178
179 bool mapping_active{};
180 int blink_counter{};
181 QColor button_color{};
182 ColorMapping colors{};
183 std::array<QColor, 4> led_color{};
184 ButtonArray buttons{};
185 StickArray sticks{};
186 std::size_t player_index{};
187 std::size_t button_mapping_index{Settings::NativeButton::BUTTON_NS_END};
188 std::size_t analog_mapping_index{Settings::NativeAnalog::NUM_STICKS_HID};
189 std::array<AxisValue, Settings::NativeAnalog::NUM_STICKS_HID> axis_values{};
190 std::array<bool, Settings::NativeButton::NumButtons> button_values{};
191 Settings::ControllerType controller_type{Settings::ControllerType::ProController};
192};
diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp
new file mode 100644
index 000000000..85724a8f3
--- /dev/null
+++ b/src/yuzu/debugger/controller.cpp
@@ -0,0 +1,66 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <QAction>
6#include <QLayout>
7#include <QString>
8#include "core/settings.h"
9#include "yuzu/configuration/configure_input_player_widget.h"
10#include "yuzu/debugger/controller.h"
11
12ControllerDialog::ControllerDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) {
13 setObjectName(QStringLiteral("Controller"));
14 setWindowTitle(tr("Controller P1"));
15 resize(500, 350);
16 setMinimumSize(500, 350);
17 // Remove the "?" button from the titlebar and enable the maximize button
18 setWindowFlags((windowFlags() & ~Qt::WindowContextHelpButtonHint) |
19 Qt::WindowMaximizeButtonHint);
20
21 widget = new PlayerControlPreview(this);
22 refreshConfiguration();
23 QLayout* layout = new QVBoxLayout(this);
24 layout->setContentsMargins(0, 0, 0, 0);
25 layout->addWidget(widget);
26 setLayout(layout);
27
28 // Configure focus so that widget is focusable and the dialog automatically forwards focus to
29 // it.
30 setFocusProxy(widget);
31 widget->setFocusPolicy(Qt::StrongFocus);
32 widget->setFocus();
33}
34
35void ControllerDialog::refreshConfiguration() {
36 const auto& players = Settings::values.players.GetValue();
37 constexpr std::size_t player = 0;
38 widget->SetPlayerInputRaw(player, players[player].buttons, players[player].analogs);
39 widget->SetConnectedStatus(players[player].connected);
40 widget->SetControllerType(players[player].controller_type);
41}
42
43QAction* ControllerDialog::toggleViewAction() {
44 if (toggle_view_action == nullptr) {
45 toggle_view_action = new QAction(windowTitle(), this);
46 toggle_view_action->setCheckable(true);
47 toggle_view_action->setChecked(isVisible());
48 connect(toggle_view_action, &QAction::toggled, this, &ControllerDialog::setVisible);
49 }
50
51 return toggle_view_action;
52}
53
54void ControllerDialog::showEvent(QShowEvent* ev) {
55 if (toggle_view_action) {
56 toggle_view_action->setChecked(isVisible());
57 }
58 QWidget::showEvent(ev);
59}
60
61void ControllerDialog::hideEvent(QHideEvent* ev) {
62 if (toggle_view_action) {
63 toggle_view_action->setChecked(isVisible());
64 }
65 QWidget::hideEvent(ev);
66}
diff --git a/src/yuzu/debugger/controller.h b/src/yuzu/debugger/controller.h
new file mode 100644
index 000000000..c54750070
--- /dev/null
+++ b/src/yuzu/debugger/controller.h
@@ -0,0 +1,31 @@
1// Copyright 2015 Citra 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 <QWidget>
8
9class QAction;
10class QHideEvent;
11class QShowEvent;
12class PlayerControlPreview;
13
14class ControllerDialog : public QWidget {
15 Q_OBJECT
16
17public:
18 explicit ControllerDialog(QWidget* parent = nullptr);
19
20 /// Returns a QAction that can be used to toggle visibility of this dialog.
21 QAction* toggleViewAction();
22 void refreshConfiguration();
23
24protected:
25 void showEvent(QShowEvent* ev) override;
26 void hideEvent(QHideEvent* ev) override;
27
28private:
29 QAction* toggle_view_action = nullptr;
30 PlayerControlPreview* widget;
31};
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 0e5156dcc..3bca6277b 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -13,11 +13,11 @@
13#include "core/arm/arm_interface.h" 13#include "core/arm/arm_interface.h"
14#include "core/core.h" 14#include "core/core.h"
15#include "core/hle/kernel/handle_table.h" 15#include "core/hle/kernel/handle_table.h"
16#include "core/hle/kernel/k_readable_event.h"
16#include "core/hle/kernel/k_scheduler.h" 17#include "core/hle/kernel/k_scheduler.h"
17#include "core/hle/kernel/k_synchronization_object.h" 18#include "core/hle/kernel/k_synchronization_object.h"
18#include "core/hle/kernel/k_thread.h" 19#include "core/hle/kernel/k_thread.h"
19#include "core/hle/kernel/process.h" 20#include "core/hle/kernel/process.h"
20#include "core/hle/kernel/readable_event.h"
21#include "core/hle/kernel/svc_common.h" 21#include "core/hle/kernel/svc_common.h"
22#include "core/hle/kernel/svc_types.h" 22#include "core/hle/kernel/svc_types.h"
23#include "core/memory.h" 23#include "core/memory.h"
@@ -193,7 +193,7 @@ std::unique_ptr<WaitTreeSynchronizationObject> WaitTreeSynchronizationObject::ma
193 const Kernel::KSynchronizationObject& object) { 193 const Kernel::KSynchronizationObject& object) {
194 switch (object.GetHandleType()) { 194 switch (object.GetHandleType()) {
195 case Kernel::HandleType::ReadableEvent: 195 case Kernel::HandleType::ReadableEvent:
196 return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::ReadableEvent&>(object)); 196 return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::KReadableEvent&>(object));
197 case Kernel::HandleType::Thread: 197 case Kernel::HandleType::Thread:
198 return std::make_unique<WaitTreeThread>(static_cast<const Kernel::KThread&>(object)); 198 return std::make_unique<WaitTreeThread>(static_cast<const Kernel::KThread&>(object));
199 default: 199 default:
@@ -373,7 +373,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
373 return list; 373 return list;
374} 374}
375 375
376WaitTreeEvent::WaitTreeEvent(const Kernel::ReadableEvent& object) 376WaitTreeEvent::WaitTreeEvent(const Kernel::KReadableEvent& object)
377 : WaitTreeSynchronizationObject(object) {} 377 : WaitTreeSynchronizationObject(object) {}
378WaitTreeEvent::~WaitTreeEvent() = default; 378WaitTreeEvent::~WaitTreeEvent() = default;
379 379
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h
index b202c5567..3da2fdfd2 100644
--- a/src/yuzu/debugger/wait_tree.h
+++ b/src/yuzu/debugger/wait_tree.h
@@ -18,9 +18,9 @@ class EmuThread;
18 18
19namespace Kernel { 19namespace Kernel {
20class HandleTable; 20class HandleTable;
21class KReadableEvent;
21class KSynchronizationObject; 22class KSynchronizationObject;
22class KThread; 23class KThread;
23class ReadableEvent;
24} // namespace Kernel 24} // namespace Kernel
25 25
26class WaitTreeThread; 26class WaitTreeThread;
@@ -142,7 +142,7 @@ public:
142class WaitTreeEvent : public WaitTreeSynchronizationObject { 142class WaitTreeEvent : public WaitTreeSynchronizationObject {
143 Q_OBJECT 143 Q_OBJECT
144public: 144public:
145 explicit WaitTreeEvent(const Kernel::ReadableEvent& object); 145 explicit WaitTreeEvent(const Kernel::KReadableEvent& object);
146 ~WaitTreeEvent() override; 146 ~WaitTreeEvent() override;
147}; 147};
148 148
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 886e6e9d2..ef92c25bc 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -109,6 +109,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
109#include "yuzu/configuration/config.h" 109#include "yuzu/configuration/config.h"
110#include "yuzu/configuration/configure_dialog.h" 110#include "yuzu/configuration/configure_dialog.h"
111#include "yuzu/debugger/console.h" 111#include "yuzu/debugger/console.h"
112#include "yuzu/debugger/controller.h"
112#include "yuzu/debugger/profiler.h" 113#include "yuzu/debugger/profiler.h"
113#include "yuzu/debugger/wait_tree.h" 114#include "yuzu/debugger/wait_tree.h"
114#include "yuzu/discord.h" 115#include "yuzu/discord.h"
@@ -688,6 +689,11 @@ void GMainWindow::InitializeDebugWidgets() {
688 addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget); 689 addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget);
689 waitTreeWidget->hide(); 690 waitTreeWidget->hide();
690 debug_menu->addAction(waitTreeWidget->toggleViewAction()); 691 debug_menu->addAction(waitTreeWidget->toggleViewAction());
692
693 controller_dialog = new ControllerDialog(this);
694 controller_dialog->hide();
695 debug_menu->addAction(controller_dialog->toggleViewAction());
696
691 connect(this, &GMainWindow::EmulationStarting, waitTreeWidget, 697 connect(this, &GMainWindow::EmulationStarting, waitTreeWidget,
692 &WaitTreeWidget::OnEmulationStarting); 698 &WaitTreeWidget::OnEmulationStarting);
693 connect(this, &GMainWindow::EmulationStopping, waitTreeWidget, 699 connect(this, &GMainWindow::EmulationStopping, waitTreeWidget,
@@ -2336,6 +2342,7 @@ void GMainWindow::OnConfigure() {
2336 } 2342 }
2337 2343
2338 configure_dialog.ApplyConfiguration(); 2344 configure_dialog.ApplyConfiguration();
2345 controller_dialog->refreshConfiguration();
2339 InitializeHotkeys(); 2346 InitializeHotkeys();
2340 if (UISettings::values.theme != old_theme) { 2347 if (UISettings::values.theme != old_theme) {
2341 UpdateUITheme(); 2348 UpdateUITheme();
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 31788ea62..04d37d4ae 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -27,6 +27,7 @@ class GRenderWindow;
27class LoadingScreen; 27class LoadingScreen;
28class MicroProfileDialog; 28class MicroProfileDialog;
29class ProfilerWidget; 29class ProfilerWidget;
30class ControllerDialog;
30class QLabel; 31class QLabel;
31class QPushButton; 32class QPushButton;
32class QProgressDialog; 33class QProgressDialog;
@@ -313,6 +314,7 @@ private:
313 ProfilerWidget* profilerWidget; 314 ProfilerWidget* profilerWidget;
314 MicroProfileDialog* microProfileDialog; 315 MicroProfileDialog* microProfileDialog;
315 WaitTreeWidget* waitTreeWidget; 316 WaitTreeWidget* waitTreeWidget;
317 ControllerDialog* controller_dialog;
316 318
317 QAction* actions_recent_files[max_recent_files_item]; 319 QAction* actions_recent_files[max_recent_files_item];
318 320
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
index a103b04bd..deddea9ee 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
@@ -59,29 +59,17 @@ private:
59bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() { 59bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() {
60 std::vector<std::string_view> unsupported_ext; 60 std::vector<std::string_view> unsupported_ext;
61 61
62 if (!GLAD_GL_ARB_buffer_storage)
63 unsupported_ext.push_back("ARB_buffer_storage");
64 if (!GLAD_GL_ARB_direct_state_access)
65 unsupported_ext.push_back("ARB_direct_state_access");
66 if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev)
67 unsupported_ext.push_back("ARB_vertex_type_10f_11f_11f_rev");
68 if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge)
69 unsupported_ext.push_back("ARB_texture_mirror_clamp_to_edge");
70 if (!GLAD_GL_ARB_multi_bind)
71 unsupported_ext.push_back("ARB_multi_bind");
72 if (!GLAD_GL_ARB_clip_control)
73 unsupported_ext.push_back("ARB_clip_control");
74
75 // Extensions required to support some texture formats. 62 // Extensions required to support some texture formats.
76 if (!GLAD_GL_EXT_texture_compression_s3tc) 63 if (!GLAD_GL_EXT_texture_compression_s3tc) {
77 unsupported_ext.push_back("EXT_texture_compression_s3tc"); 64 unsupported_ext.push_back("EXT_texture_compression_s3tc");
78 if (!GLAD_GL_ARB_texture_compression_rgtc) 65 }
66 if (!GLAD_GL_ARB_texture_compression_rgtc) {
79 unsupported_ext.push_back("ARB_texture_compression_rgtc"); 67 unsupported_ext.push_back("ARB_texture_compression_rgtc");
80 if (!GLAD_GL_ARB_depth_buffer_float) 68 }
81 unsupported_ext.push_back("ARB_depth_buffer_float");
82 69
83 for (const auto& extension : unsupported_ext) 70 for (const auto& extension : unsupported_ext) {
84 LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", extension); 71 LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", extension);
72 }
85 73
86 return unsupported_ext.empty(); 74 return unsupported_ext.empty();
87} 75}
@@ -89,7 +77,7 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() {
89EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, bool fullscreen) 77EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, bool fullscreen)
90 : EmuWindow_SDL2{input_subsystem} { 78 : EmuWindow_SDL2{input_subsystem} {
91 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); 79 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
92 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); 80 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
93 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); 81 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
94 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 82 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
95 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); 83 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);