summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/ring_buffer.h21
-rw-r--r--src/core/hle/kernel/k_address_arbiter.cpp84
-rw-r--r--src/core/hle/service/am/applets/controller.cpp2
-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.cpp208
-rw-r--r--src/core/hle/service/hid/controllers/npad.h189
-rw-r--r--src/core/hle/service/hid/controllers/xpad.h70
-rw-r--r--src/core/hle/service/hid/hid.cpp20
-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/ns/pl_u.cpp9
-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/bootmanager.cpp31
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp2
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp26
22 files changed, 485 insertions, 292 deletions
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/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp
index f2f497dc4..d0e90fd60 100644
--- a/src/core/hle/kernel/k_address_arbiter.cpp
+++ b/src/core/hle/kernel/k_address_arbiter.cpp
@@ -118,9 +118,10 @@ 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 123 return Svc::ResultInvalidCurrentMemory;
124 }
124 if (user_value != value) { 125 if (user_value != value) {
125 return Svc::ResultInvalidState; 126 return Svc::ResultInvalidState;
126 } 127 }
@@ -146,61 +147,34 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
146 // Perform signaling. 147 // Perform signaling.
147 s32 num_waiters{}; 148 s32 num_waiters{};
148 { 149 {
149 KScopedSchedulerLock sl(kernel); 150 [[maybe_unused]] const KScopedSchedulerLock sl(kernel);
150 151
151 auto it = thread_tree.nfind_light({addr, -1}); 152 auto it = thread_tree.nfind_light({addr, -1});
152 // Determine the updated value. 153 // Determine the updated value.
153 s32 new_value{}; 154 s32 new_value{};
154 if (/*GetTargetFirmware() >= TargetFirmware_7_0_0*/ true) { 155 if (count <= 0) {
155 if (count <= 0) { 156 if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) {
156 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { 157 new_value = value - 2;
157 new_value = value - 2;
158 } else {
159 new_value = value + 1;
160 }
161 } else { 158 } else {
162 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { 159 new_value = value + 1;
163 auto tmp_it = it;
164 s32 tmp_num_waiters{};
165 while ((++tmp_it != thread_tree.end()) &&
166 (tmp_it->GetAddressArbiterKey() == addr)) {
167 if ((tmp_num_waiters++) >= count) {
168 break;
169 }
170 }
171
172 if (tmp_num_waiters < count) {
173 new_value = value - 1;
174 } else {
175 new_value = value;
176 }
177 } else {
178 new_value = value + 1;
179 }
180 } 160 }
181 } else { 161 } else {
182 if (count <= 0) { 162 if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) {
183 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
184 new_value = value - 1;
185 } else {
186 new_value = value + 1;
187 }
188 } else {
189 auto tmp_it = it; 163 auto tmp_it = it;
190 s32 tmp_num_waiters{}; 164 s32 tmp_num_waiters{};
191 while ((tmp_it != thread_tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && 165 while (++tmp_it != thread_tree.end() && tmp_it->GetAddressArbiterKey() == addr) {
192 (tmp_num_waiters < count + 1)) { 166 if (tmp_num_waiters++ >= count) {
193 ++tmp_num_waiters; 167 break;
194 ++tmp_it; 168 }
195 } 169 }
196 170
197 if (tmp_num_waiters == 0) { 171 if (tmp_num_waiters < count) {
198 new_value = value + 1;
199 } else if (tmp_num_waiters <= count) {
200 new_value = value - 1; 172 new_value = value - 1;
201 } else { 173 } else {
202 new_value = value; 174 new_value = value;
203 } 175 }
176 } else {
177 new_value = value + 1;
204 } 178 }
205 } 179 }
206 180
@@ -208,13 +182,15 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
208 s32 user_value{}; 182 s32 user_value{};
209 bool succeeded{}; 183 bool succeeded{};
210 if (value != new_value) { 184 if (value != new_value) {
211 succeeded = UpdateIfEqual(system, std::addressof(user_value), addr, value, new_value); 185 succeeded = UpdateIfEqual(system, &user_value, addr, value, new_value);
212 } else { 186 } else {
213 succeeded = ReadFromUser(system, std::addressof(user_value), addr); 187 succeeded = ReadFromUser(system, &user_value, addr);
214 } 188 }
215 189
216 R_UNLESS(succeeded, Svc::ResultInvalidCurrentMemory); 190 if (!succeeded) {
217 191 LOG_ERROR(Kernel, "Invalid current memory!");
192 return Svc::ResultInvalidCurrentMemory;
193 }
218 if (user_value != value) { 194 if (user_value != value) {
219 return Svc::ResultInvalidState; 195 return Svc::ResultInvalidState;
220 } 196 }
@@ -255,9 +231,9 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
255 s32 user_value{}; 231 s32 user_value{};
256 bool succeeded{}; 232 bool succeeded{};
257 if (decrement) { 233 if (decrement) {
258 succeeded = DecrementIfLessThan(system, std::addressof(user_value), addr, value); 234 succeeded = DecrementIfLessThan(system, &user_value, addr, value);
259 } else { 235 } else {
260 succeeded = ReadFromUser(system, std::addressof(user_value), addr); 236 succeeded = ReadFromUser(system, &user_value, addr);
261 } 237 }
262 238
263 if (!succeeded) { 239 if (!succeeded) {
@@ -278,7 +254,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
278 } 254 }
279 255
280 // Set the arbiter. 256 // Set the arbiter.
281 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); 257 cur_thread->SetAddressArbiter(&thread_tree, addr);
282 thread_tree.insert(*cur_thread); 258 thread_tree.insert(*cur_thread);
283 cur_thread->SetState(ThreadState::Waiting); 259 cur_thread->SetState(ThreadState::Waiting);
284 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); 260 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
@@ -299,7 +275,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
299 275
300 // Get the result. 276 // Get the result.
301 KSynchronizationObject* dummy{}; 277 KSynchronizationObject* dummy{};
302 return cur_thread->GetWaitResult(std::addressof(dummy)); 278 return cur_thread->GetWaitResult(&dummy);
303} 279}
304 280
305ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { 281ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
@@ -320,7 +296,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
320 296
321 // Read the value from userspace. 297 // Read the value from userspace.
322 s32 user_value{}; 298 s32 user_value{};
323 if (!ReadFromUser(system, std::addressof(user_value), addr)) { 299 if (!ReadFromUser(system, &user_value, addr)) {
324 slp.CancelSleep(); 300 slp.CancelSleep();
325 return Svc::ResultInvalidCurrentMemory; 301 return Svc::ResultInvalidCurrentMemory;
326 } 302 }
@@ -338,7 +314,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
338 } 314 }
339 315
340 // Set the arbiter. 316 // Set the arbiter.
341 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); 317 cur_thread->SetAddressArbiter(&thread_tree, addr);
342 thread_tree.insert(*cur_thread); 318 thread_tree.insert(*cur_thread);
343 cur_thread->SetState(ThreadState::Waiting); 319 cur_thread->SetState(ThreadState::Waiting);
344 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); 320 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
@@ -359,7 +335,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
359 335
360 // Get the result. 336 // Get the result.
361 KSynchronizationObject* dummy{}; 337 KSynchronizationObject* dummy{};
362 return cur_thread->GetWaitResult(std::addressof(dummy)); 338 return cur_thread->GetWaitResult(&dummy);
363} 339}
364 340
365} // namespace Kernel 341} // namespace Kernel
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/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 5794f417c..dbf198345 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -157,76 +157,83 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
157 styleset_changed_events[controller_idx]->GetWritableEvent()->Signal(); 157 styleset_changed_events[controller_idx]->GetWritableEvent()->Signal();
158 return; 158 return;
159 } 159 }
160 controller.joy_styles.raw = 0; // Zero out 160 controller.style_set.raw = 0; // Zero out
161 controller.device_type.raw = 0; 161 controller.device_type.raw = 0;
162 controller.properties.raw = 0; 162 controller.system_properties.raw = 0;
163 switch (controller_type) { 163 switch (controller_type) {
164 case NPadControllerType::None: 164 case NPadControllerType::None:
165 UNREACHABLE(); 165 UNREACHABLE();
166 break; 166 break;
167 case NPadControllerType::ProController: 167 case NPadControllerType::ProController:
168 controller.joy_styles.pro_controller.Assign(1); 168 controller.style_set.fullkey.Assign(1);
169 controller.device_type.pro_controller.Assign(1); 169 controller.device_type.fullkey.Assign(1);
170 controller.properties.is_vertical.Assign(1); 170 controller.system_properties.is_vertical.Assign(1);
171 controller.properties.use_plus.Assign(1); 171 controller.system_properties.use_plus.Assign(1);
172 controller.properties.use_minus.Assign(1); 172 controller.system_properties.use_minus.Assign(1);
173 controller.pad_assignment = NpadAssignments::Single; 173 controller.assignment_mode = NpadAssignments::Single;
174 controller.footer_type = AppletFooterUiType::SwitchProController;
174 break; 175 break;
175 case NPadControllerType::Handheld: 176 case NPadControllerType::Handheld:
176 controller.joy_styles.handheld.Assign(1); 177 controller.style_set.handheld.Assign(1);
177 controller.device_type.handheld.Assign(1); 178 controller.device_type.handheld_left.Assign(1);
178 controller.properties.is_vertical.Assign(1); 179 controller.device_type.handheld_right.Assign(1);
179 controller.properties.use_plus.Assign(1); 180 controller.system_properties.is_vertical.Assign(1);
180 controller.properties.use_minus.Assign(1); 181 controller.system_properties.use_plus.Assign(1);
181 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;
182 break; 185 break;
183 case NPadControllerType::JoyDual: 186 case NPadControllerType::JoyDual:
184 controller.joy_styles.joycon_dual.Assign(1); 187 controller.style_set.joycon_dual.Assign(1);
185 controller.device_type.joycon_left.Assign(1); 188 controller.device_type.joycon_left.Assign(1);
186 controller.device_type.joycon_right.Assign(1); 189 controller.device_type.joycon_right.Assign(1);
187 controller.properties.is_vertical.Assign(1); 190 controller.system_properties.is_vertical.Assign(1);
188 controller.properties.use_plus.Assign(1); 191 controller.system_properties.use_plus.Assign(1);
189 controller.properties.use_minus.Assign(1); 192 controller.system_properties.use_minus.Assign(1);
190 controller.pad_assignment = NpadAssignments::Dual; 193 controller.assignment_mode = NpadAssignments::Dual;
194 controller.footer_type = AppletFooterUiType::JoyDual;
191 break; 195 break;
192 case NPadControllerType::JoyLeft: 196 case NPadControllerType::JoyLeft:
193 controller.joy_styles.joycon_left.Assign(1); 197 controller.style_set.joycon_left.Assign(1);
194 controller.device_type.joycon_left.Assign(1); 198 controller.device_type.joycon_left.Assign(1);
195 controller.properties.is_horizontal.Assign(1); 199 controller.system_properties.is_horizontal.Assign(1);
196 controller.properties.use_minus.Assign(1); 200 controller.system_properties.use_minus.Assign(1);
197 controller.pad_assignment = NpadAssignments::Single; 201 controller.assignment_mode = NpadAssignments::Single;
202 controller.footer_type = AppletFooterUiType::JoyLeftHorizontal;
198 break; 203 break;
199 case NPadControllerType::JoyRight: 204 case NPadControllerType::JoyRight:
200 controller.joy_styles.joycon_right.Assign(1); 205 controller.style_set.joycon_right.Assign(1);
201 controller.device_type.joycon_right.Assign(1); 206 controller.device_type.joycon_right.Assign(1);
202 controller.properties.is_horizontal.Assign(1); 207 controller.system_properties.is_horizontal.Assign(1);
203 controller.properties.use_plus.Assign(1); 208 controller.system_properties.use_plus.Assign(1);
204 controller.pad_assignment = NpadAssignments::Single; 209 controller.assignment_mode = NpadAssignments::Single;
210 controller.footer_type = AppletFooterUiType::JoyRightHorizontal;
205 break; 211 break;
206 case NPadControllerType::Pokeball: 212 case NPadControllerType::Pokeball:
207 controller.joy_styles.pokeball.Assign(1); 213 controller.style_set.palma.Assign(1);
208 controller.device_type.pokeball.Assign(1); 214 controller.device_type.palma.Assign(1);
209 controller.pad_assignment = NpadAssignments::Single; 215 controller.assignment_mode = NpadAssignments::Single;
210 break; 216 break;
211 } 217 }
212 218
213 controller.single_color_error = ColorReadError::ReadOk; 219 controller.fullkey_color.attribute = ColorAttributes::Ok;
214 controller.single_color.body_color = 0; 220 controller.fullkey_color.fullkey.body = 0;
215 controller.single_color.button_color = 0; 221 controller.fullkey_color.fullkey.button = 0;
216 222
217 controller.dual_color_error = ColorReadError::ReadOk; 223 controller.joycon_color.attribute = ColorAttributes::Ok;
218 controller.left_color.body_color = 224 controller.joycon_color.left.body =
219 Settings::values.players.GetValue()[controller_idx].body_color_left; 225 Settings::values.players.GetValue()[controller_idx].body_color_left;
220 controller.left_color.button_color = 226 controller.joycon_color.left.button =
221 Settings::values.players.GetValue()[controller_idx].button_color_left; 227 Settings::values.players.GetValue()[controller_idx].button_color_left;
222 controller.right_color.body_color = 228 controller.joycon_color.right.body =
223 Settings::values.players.GetValue()[controller_idx].body_color_right; 229 Settings::values.players.GetValue()[controller_idx].body_color_right;
224 controller.right_color.button_color = 230 controller.joycon_color.right.button =
225 Settings::values.players.GetValue()[controller_idx].button_color_right; 231 Settings::values.players.GetValue()[controller_idx].button_color_right;
226 232
227 controller.battery_level[0] = BATTERY_FULL; 233 // TODO: Investigate when we should report all batery types
228 controller.battery_level[1] = BATTERY_FULL; 234 controller.battery_level_dual = BATTERY_FULL;
229 controller.battery_level[2] = BATTERY_FULL; 235 controller.battery_level_left = BATTERY_FULL;
236 controller.battery_level_right = BATTERY_FULL;
230 237
231 SignalStyleSetChangedEvent(IndexToNPad(controller_idx)); 238 SignalStyleSetChangedEvent(IndexToNPad(controller_idx));
232} 239}
@@ -251,8 +258,8 @@ void Controller_NPad::OnInit() {
251 style.joycon_left.Assign(1); 258 style.joycon_left.Assign(1);
252 style.joycon_right.Assign(1); 259 style.joycon_right.Assign(1);
253 style.joycon_dual.Assign(1); 260 style.joycon_dual.Assign(1);
254 style.pro_controller.Assign(1); 261 style.fullkey.Assign(1);
255 style.pokeball.Assign(1); 262 style.palma.Assign(1);
256 } 263 }
257 264
258 std::transform(Settings::values.players.GetValue().begin(), 265 std::transform(Settings::values.players.GetValue().begin(),
@@ -406,13 +413,10 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
406 } 413 }
407 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) {
408 auto& npad = shared_memory_entries[i]; 415 auto& npad = shared_memory_entries[i];
409 const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, 416 const std::array<NPadGeneric*, 7> controller_npads{
410 &npad.handheld_states, 417 &npad.fullkey_states, &npad.handheld_states, &npad.joy_dual_states,
411 &npad.dual_states, 418 &npad.joy_left_states, &npad.joy_right_states, &npad.palma_states,
412 &npad.left_joy_states, 419 &npad.system_ext_states};
413 &npad.right_joy_states,
414 &npad.pokeball_states,
415 &npad.libnx};
416 420
417 for (auto* main_controller : controller_npads) { 421 for (auto* main_controller : controller_npads) {
418 main_controller->common.entry_count = 16; 422 main_controller->common.entry_count = 16;
@@ -442,19 +446,19 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
442 auto& pad_state = npad_pad_states[npad_index]; 446 auto& pad_state = npad_pad_states[npad_index];
443 447
444 auto& main_controller = 448 auto& main_controller =
445 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];
446 auto& handheld_entry = 450 auto& handheld_entry =
447 npad.handheld_states.npad[npad.handheld_states.common.last_entry_index]; 451 npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
448 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];
449 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];
450 auto& right_entry = 454 auto& right_entry =
451 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];
452 auto& pokeball_entry = 456 auto& pokeball_entry = npad.palma_states.npad[npad.palma_states.common.last_entry_index];
453 npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index]; 457 auto& libnx_entry =
454 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];
455 459
456 libnx_entry.connection_status.raw = 0; 460 libnx_entry.connection_status.raw = 0;
457 libnx_entry.connection_status.IsConnected.Assign(1); 461 libnx_entry.connection_status.is_connected.Assign(1);
458 462
459 switch (controller_type) { 463 switch (controller_type) {
460 case NPadControllerType::None: 464 case NPadControllerType::None:
@@ -462,67 +466,67 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
462 break; 466 break;
463 case NPadControllerType::ProController: 467 case NPadControllerType::ProController:
464 main_controller.connection_status.raw = 0; 468 main_controller.connection_status.raw = 0;
465 main_controller.connection_status.IsConnected.Assign(1); 469 main_controller.connection_status.is_connected.Assign(1);
466 main_controller.connection_status.IsWired.Assign(1); 470 main_controller.connection_status.is_wired.Assign(1);
467 main_controller.pad.pad_states.raw = pad_state.pad_states.raw; 471 main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
468 main_controller.pad.l_stick = pad_state.l_stick; 472 main_controller.pad.l_stick = pad_state.l_stick;
469 main_controller.pad.r_stick = pad_state.r_stick; 473 main_controller.pad.r_stick = pad_state.r_stick;
470 474
471 libnx_entry.connection_status.IsWired.Assign(1); 475 libnx_entry.connection_status.is_wired.Assign(1);
472 break; 476 break;
473 case NPadControllerType::Handheld: 477 case NPadControllerType::Handheld:
474 handheld_entry.connection_status.raw = 0; 478 handheld_entry.connection_status.raw = 0;
475 handheld_entry.connection_status.IsConnected.Assign(1); 479 handheld_entry.connection_status.is_connected.Assign(1);
476 handheld_entry.connection_status.IsWired.Assign(1); 480 handheld_entry.connection_status.is_wired.Assign(1);
477 handheld_entry.connection_status.IsLeftJoyConnected.Assign(1); 481 handheld_entry.connection_status.is_left_connected.Assign(1);
478 handheld_entry.connection_status.IsRightJoyConnected.Assign(1); 482 handheld_entry.connection_status.is_right_connected.Assign(1);
479 handheld_entry.connection_status.IsLeftJoyWired.Assign(1); 483 handheld_entry.connection_status.is_left_wired.Assign(1);
480 handheld_entry.connection_status.IsRightJoyWired.Assign(1); 484 handheld_entry.connection_status.is_right_wired.Assign(1);
481 handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; 485 handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
482 handheld_entry.pad.l_stick = pad_state.l_stick; 486 handheld_entry.pad.l_stick = pad_state.l_stick;
483 handheld_entry.pad.r_stick = pad_state.r_stick; 487 handheld_entry.pad.r_stick = pad_state.r_stick;
484 488
485 libnx_entry.connection_status.IsWired.Assign(1); 489 libnx_entry.connection_status.is_wired.Assign(1);
486 libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); 490 libnx_entry.connection_status.is_left_connected.Assign(1);
487 libnx_entry.connection_status.IsRightJoyConnected.Assign(1); 491 libnx_entry.connection_status.is_right_connected.Assign(1);
488 libnx_entry.connection_status.IsLeftJoyWired.Assign(1); 492 libnx_entry.connection_status.is_left_wired.Assign(1);
489 libnx_entry.connection_status.IsRightJoyWired.Assign(1); 493 libnx_entry.connection_status.is_right_wired.Assign(1);
490 break; 494 break;
491 case NPadControllerType::JoyDual: 495 case NPadControllerType::JoyDual:
492 dual_entry.connection_status.raw = 0; 496 dual_entry.connection_status.raw = 0;
493 dual_entry.connection_status.IsConnected.Assign(1); 497 dual_entry.connection_status.is_connected.Assign(1);
494 dual_entry.connection_status.IsLeftJoyConnected.Assign(1); 498 dual_entry.connection_status.is_left_connected.Assign(1);
495 dual_entry.connection_status.IsRightJoyConnected.Assign(1); 499 dual_entry.connection_status.is_right_connected.Assign(1);
496 dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; 500 dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
497 dual_entry.pad.l_stick = pad_state.l_stick; 501 dual_entry.pad.l_stick = pad_state.l_stick;
498 dual_entry.pad.r_stick = pad_state.r_stick; 502 dual_entry.pad.r_stick = pad_state.r_stick;
499 503
500 libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); 504 libnx_entry.connection_status.is_left_connected.Assign(1);
501 libnx_entry.connection_status.IsRightJoyConnected.Assign(1); 505 libnx_entry.connection_status.is_right_connected.Assign(1);
502 break; 506 break;
503 case NPadControllerType::JoyLeft: 507 case NPadControllerType::JoyLeft:
504 left_entry.connection_status.raw = 0; 508 left_entry.connection_status.raw = 0;
505 left_entry.connection_status.IsConnected.Assign(1); 509 left_entry.connection_status.is_connected.Assign(1);
506 left_entry.connection_status.IsLeftJoyConnected.Assign(1); 510 left_entry.connection_status.is_left_connected.Assign(1);
507 left_entry.pad.pad_states.raw = pad_state.pad_states.raw; 511 left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
508 left_entry.pad.l_stick = pad_state.l_stick; 512 left_entry.pad.l_stick = pad_state.l_stick;
509 left_entry.pad.r_stick = pad_state.r_stick; 513 left_entry.pad.r_stick = pad_state.r_stick;
510 514
511 libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); 515 libnx_entry.connection_status.is_left_connected.Assign(1);
512 break; 516 break;
513 case NPadControllerType::JoyRight: 517 case NPadControllerType::JoyRight:
514 right_entry.connection_status.raw = 0; 518 right_entry.connection_status.raw = 0;
515 right_entry.connection_status.IsConnected.Assign(1); 519 right_entry.connection_status.is_connected.Assign(1);
516 right_entry.connection_status.IsRightJoyConnected.Assign(1); 520 right_entry.connection_status.is_right_connected.Assign(1);
517 right_entry.pad.pad_states.raw = pad_state.pad_states.raw; 521 right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
518 right_entry.pad.l_stick = pad_state.l_stick; 522 right_entry.pad.l_stick = pad_state.l_stick;
519 right_entry.pad.r_stick = pad_state.r_stick; 523 right_entry.pad.r_stick = pad_state.r_stick;
520 524
521 libnx_entry.connection_status.IsRightJoyConnected.Assign(1); 525 libnx_entry.connection_status.is_right_connected.Assign(1);
522 break; 526 break;
523 case NPadControllerType::Pokeball: 527 case NPadControllerType::Pokeball:
524 pokeball_entry.connection_status.raw = 0; 528 pokeball_entry.connection_status.raw = 0;
525 pokeball_entry.connection_status.IsConnected.Assign(1); 529 pokeball_entry.connection_status.is_connected.Assign(1);
526 pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; 530 pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
527 pokeball_entry.pad.l_stick = pad_state.l_stick; 531 pokeball_entry.pad.l_stick = pad_state.l_stick;
528 pokeball_entry.pad.r_stick = pad_state.r_stick; 532 pokeball_entry.pad.r_stick = pad_state.r_stick;
@@ -556,7 +560,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
556 } 560 }
557 561
558 const std::array<SixAxisGeneric*, 6> controller_sixaxes{ 562 const std::array<SixAxisGeneric*, 6> controller_sixaxes{
559 &npad.sixaxis_full, &npad.sixaxis_handheld, &npad.sixaxis_dual_left, 563 &npad.sixaxis_fullkey, &npad.sixaxis_handheld, &npad.sixaxis_dual_left,
560 &npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right, 564 &npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right,
561 }; 565 };
562 566
@@ -594,7 +598,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
594 } 598 }
595 599
596 auto& full_sixaxis_entry = 600 auto& full_sixaxis_entry =
597 npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index]; 601 npad.sixaxis_fullkey.sixaxis[npad.sixaxis_fullkey.common.last_entry_index];
598 auto& handheld_sixaxis_entry = 602 auto& handheld_sixaxis_entry =
599 npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index]; 603 npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index];
600 auto& dual_left_sixaxis_entry = 604 auto& dual_left_sixaxis_entry =
@@ -611,7 +615,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
611 UNREACHABLE(); 615 UNREACHABLE();
612 break; 616 break;
613 case NPadControllerType::ProController: 617 case NPadControllerType::ProController:
618 full_sixaxis_entry.attribute.raw = 0;
614 if (sixaxis_sensors_enabled && motions[i][0]) { 619 if (sixaxis_sensors_enabled && motions[i][0]) {
620 full_sixaxis_entry.attribute.is_connected.Assign(1);
615 full_sixaxis_entry.accel = motion_devices[0].accel; 621 full_sixaxis_entry.accel = motion_devices[0].accel;
616 full_sixaxis_entry.gyro = motion_devices[0].gyro; 622 full_sixaxis_entry.gyro = motion_devices[0].gyro;
617 full_sixaxis_entry.rotation = motion_devices[0].rotation; 623 full_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -619,7 +625,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
619 } 625 }
620 break; 626 break;
621 case NPadControllerType::Handheld: 627 case NPadControllerType::Handheld:
628 handheld_sixaxis_entry.attribute.raw = 0;
622 if (sixaxis_sensors_enabled && motions[i][0]) { 629 if (sixaxis_sensors_enabled && motions[i][0]) {
630 handheld_sixaxis_entry.attribute.is_connected.Assign(1);
623 handheld_sixaxis_entry.accel = motion_devices[0].accel; 631 handheld_sixaxis_entry.accel = motion_devices[0].accel;
624 handheld_sixaxis_entry.gyro = motion_devices[0].gyro; 632 handheld_sixaxis_entry.gyro = motion_devices[0].gyro;
625 handheld_sixaxis_entry.rotation = motion_devices[0].rotation; 633 handheld_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -627,8 +635,11 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
627 } 635 }
628 break; 636 break;
629 case NPadControllerType::JoyDual: 637 case NPadControllerType::JoyDual:
638 dual_left_sixaxis_entry.attribute.raw = 0;
639 dual_right_sixaxis_entry.attribute.raw = 0;
630 if (sixaxis_sensors_enabled && motions[i][0]) { 640 if (sixaxis_sensors_enabled && motions[i][0]) {
631 // Set motion for the left joycon 641 // Set motion for the left joycon
642 dual_left_sixaxis_entry.attribute.is_connected.Assign(1);
632 dual_left_sixaxis_entry.accel = motion_devices[0].accel; 643 dual_left_sixaxis_entry.accel = motion_devices[0].accel;
633 dual_left_sixaxis_entry.gyro = motion_devices[0].gyro; 644 dual_left_sixaxis_entry.gyro = motion_devices[0].gyro;
634 dual_left_sixaxis_entry.rotation = motion_devices[0].rotation; 645 dual_left_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -636,6 +647,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
636 } 647 }
637 if (sixaxis_sensors_enabled && motions[i][1]) { 648 if (sixaxis_sensors_enabled && motions[i][1]) {
638 // Set motion for the right joycon 649 // Set motion for the right joycon
650 dual_right_sixaxis_entry.attribute.is_connected.Assign(1);
639 dual_right_sixaxis_entry.accel = motion_devices[1].accel; 651 dual_right_sixaxis_entry.accel = motion_devices[1].accel;
640 dual_right_sixaxis_entry.gyro = motion_devices[1].gyro; 652 dual_right_sixaxis_entry.gyro = motion_devices[1].gyro;
641 dual_right_sixaxis_entry.rotation = motion_devices[1].rotation; 653 dual_right_sixaxis_entry.rotation = motion_devices[1].rotation;
@@ -643,7 +655,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
643 } 655 }
644 break; 656 break;
645 case NPadControllerType::JoyLeft: 657 case NPadControllerType::JoyLeft:
658 left_sixaxis_entry.attribute.raw = 0;
646 if (sixaxis_sensors_enabled && motions[i][0]) { 659 if (sixaxis_sensors_enabled && motions[i][0]) {
660 left_sixaxis_entry.attribute.is_connected.Assign(1);
647 left_sixaxis_entry.accel = motion_devices[0].accel; 661 left_sixaxis_entry.accel = motion_devices[0].accel;
648 left_sixaxis_entry.gyro = motion_devices[0].gyro; 662 left_sixaxis_entry.gyro = motion_devices[0].gyro;
649 left_sixaxis_entry.rotation = motion_devices[0].rotation; 663 left_sixaxis_entry.rotation = motion_devices[0].rotation;
@@ -651,7 +665,9 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
651 } 665 }
652 break; 666 break;
653 case NPadControllerType::JoyRight: 667 case NPadControllerType::JoyRight:
668 right_sixaxis_entry.attribute.raw = 0;
654 if (sixaxis_sensors_enabled && motions[i][1]) { 669 if (sixaxis_sensors_enabled && motions[i][1]) {
670 right_sixaxis_entry.attribute.is_connected.Assign(1);
655 right_sixaxis_entry.accel = motion_devices[1].accel; 671 right_sixaxis_entry.accel = motion_devices[1].accel;
656 right_sixaxis_entry.gyro = motion_devices[1].gyro; 672 right_sixaxis_entry.gyro = motion_devices[1].gyro;
657 right_sixaxis_entry.rotation = motion_devices[1].rotation; 673 right_sixaxis_entry.rotation = motion_devices[1].rotation;
@@ -717,8 +733,8 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode
717void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) { 733void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) {
718 const std::size_t npad_index = NPadIdToIndex(npad_id); 734 const std::size_t npad_index = NPadIdToIndex(npad_id);
719 ASSERT(npad_index < shared_memory_entries.size()); 735 ASSERT(npad_index < shared_memory_entries.size());
720 if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) { 736 if (shared_memory_entries[npad_index].assignment_mode != assignment_mode) {
721 shared_memory_entries[npad_index].pad_assignment = assignment_mode; 737 shared_memory_entries[npad_index].assignment_mode = assignment_mode;
722 } 738 }
723} 739}
724 740
@@ -926,9 +942,17 @@ void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
926 connected_controllers[npad_index].is_connected = false; 942 connected_controllers[npad_index].is_connected = false;
927 943
928 auto& controller = shared_memory_entries[npad_index]; 944 auto& controller = shared_memory_entries[npad_index];
929 controller.joy_styles.raw = 0; // Zero out 945 controller.style_set.raw = 0; // Zero out
930 controller.device_type.raw = 0; 946 controller.device_type.raw = 0;
931 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;
932 956
933 SignalStyleSetChangedEvent(IndexToNPad(npad_index)); 957 SignalStyleSetChangedEvent(IndexToNPad(npad_index));
934} 958}
@@ -1104,7 +1128,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
1104 [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) { 1128 [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
1105 switch (controller) { 1129 switch (controller) {
1106 case NPadControllerType::ProController: 1130 case NPadControllerType::ProController:
1107 return style.pro_controller; 1131 return style.fullkey;
1108 case NPadControllerType::JoyDual: 1132 case NPadControllerType::JoyDual:
1109 return style.joycon_dual; 1133 return style.joycon_dual;
1110 case NPadControllerType::JoyLeft: 1134 case NPadControllerType::JoyLeft:
@@ -1112,7 +1136,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
1112 case NPadControllerType::JoyRight: 1136 case NPadControllerType::JoyRight:
1113 return style.joycon_right; 1137 return style.joycon_right;
1114 case NPadControllerType::Pokeball: 1138 case NPadControllerType::Pokeball:
1115 return style.pokeball; 1139 return style.palma;
1116 default: 1140 default:
1117 return false; 1141 return false;
1118 } 1142 }
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 1a65b19f5..48bab988c 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -94,10 +94,10 @@ public:
94 }; 94 };
95 95
96 enum class NpadCommunicationMode : u64 { 96 enum class NpadCommunicationMode : u64 {
97 Unknown0 = 0, 97 Mode_5ms = 0,
98 Unknown1 = 1, 98 Mode_10ms = 1,
99 Unknown2 = 2, 99 Mode_15ms = 2,
100 Unknown3 = 3, 100 Default = 3,
101 }; 101 };
102 102
103 struct DeviceHandle { 103 struct DeviceHandle {
@@ -112,13 +112,18 @@ public:
112 union { 112 union {
113 u32_le raw{}; 113 u32_le raw{};
114 114
115 BitField<0, 1, u32> pro_controller; 115 BitField<0, 1, u32> fullkey;
116 BitField<1, 1, u32> handheld; 116 BitField<1, 1, u32> handheld;
117 BitField<2, 1, u32> joycon_dual; 117 BitField<2, 1, u32> joycon_dual;
118 BitField<3, 1, u32> joycon_left; 118 BitField<3, 1, u32> joycon_left;
119 BitField<4, 1, u32> joycon_right; 119 BitField<4, 1, u32> joycon_right;
120 120 BitField<5, 1, u32> gamecube;
121 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;
122 }; 127 };
123 }; 128 };
124 static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); 129 static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
@@ -242,12 +247,32 @@ private:
242 }; 247 };
243 static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); 248 static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
244 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
245 struct ControllerColor { 257 struct ControllerColor {
246 u32_le body_color; 258 u32_le body;
247 u32_le button_color; 259 u32_le button;
248 }; 260 };
249 static_assert(sizeof(ControllerColor) == 8, "ControllerColor is an invalid size"); 261 static_assert(sizeof(ControllerColor) == 8, "ControllerColor is an invalid size");
250 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
251 struct ControllerPadState { 276 struct ControllerPadState {
252 union { 277 union {
253 u64_le raw{}; 278 u64_le raw{};
@@ -289,6 +314,9 @@ private:
289 314
290 BitField<26, 1, u64> right_sl; 315 BitField<26, 1, u64> right_sl;
291 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;
292 }; 320 };
293 }; 321 };
294 static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size"); 322 static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size");
@@ -302,12 +330,12 @@ private:
302 struct ConnectionState { 330 struct ConnectionState {
303 union { 331 union {
304 u32_le raw{}; 332 u32_le raw{};
305 BitField<0, 1, u32> IsConnected; 333 BitField<0, 1, u32> is_connected;
306 BitField<1, 1, u32> IsWired; 334 BitField<1, 1, u32> is_wired;
307 BitField<2, 1, u32> IsLeftJoyConnected; 335 BitField<2, 1, u32> is_left_connected;
308 BitField<3, 1, u32> IsLeftJoyWired; 336 BitField<3, 1, u32> is_left_wired;
309 BitField<4, 1, u32> IsRightJoyConnected; 337 BitField<4, 1, u32> is_right_connected;
310 BitField<5, 1, u32> IsRightJoyWired; 338 BitField<5, 1, u32> is_right_wired;
311 }; 339 };
312 }; 340 };
313 static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size"); 341 static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size");
@@ -333,6 +361,15 @@ private:
333 }; 361 };
334 static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size"); 362 static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size");
335 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
336 struct SixAxisStates { 373 struct SixAxisStates {
337 s64_le timestamp{}; 374 s64_le timestamp{};
338 INSERT_PADDING_WORDS(2); 375 INSERT_PADDING_WORDS(2);
@@ -341,7 +378,8 @@ private:
341 Common::Vec3f gyro{}; 378 Common::Vec3f gyro{};
342 Common::Vec3f rotation{}; 379 Common::Vec3f rotation{};
343 std::array<Common::Vec3f, 3> orientation{}; 380 std::array<Common::Vec3f, 3> orientation{};
344 s64_le always_one{1}; 381 SixAxisAttributes attribute;
382 INSERT_PADDING_BYTES(4); // Reserved
345 }; 383 };
346 static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size"); 384 static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size");
347 385
@@ -351,32 +389,54 @@ private:
351 }; 389 };
352 static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size"); 390 static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size");
353 391
354 enum class ColorReadError : u32_le { 392 struct NPadSystemProperties {
355 ReadOk = 0,
356 ColorDoesntExist = 1,
357 NoController = 2,
358 };
359
360 struct NPadProperties {
361 union { 393 union {
362 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;
363 BitField<11, 1, s64> is_vertical; 403 BitField<11, 1, s64> is_vertical;
364 BitField<12, 1, s64> is_horizontal; 404 BitField<12, 1, s64> is_horizontal;
365 BitField<13, 1, s64> use_plus; 405 BitField<13, 1, s64> use_plus;
366 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;
367 }; 416 };
368 }; 417 };
418 static_assert(sizeof(NPadButtonProperties) == 0x4, "NPadButtonProperties is an invalid size");
369 419
370 struct NPadDevice { 420 struct NPadDevice {
371 union { 421 union {
372 u32_le raw{}; 422 u32_le raw{};
373 BitField<0, 1, s32> pro_controller; 423 BitField<0, 1, s32> fullkey;
374 BitField<1, 1, s32> handheld; 424 BitField<1, 1, s32> debug_pad;
375 BitField<2, 1, s32> handheld_left; 425 BitField<2, 1, s32> handheld_left;
376 BitField<3, 1, s32> handheld_right; 426 BitField<3, 1, s32> handheld_right;
377 BitField<4, 1, s32> joycon_left; 427 BitField<4, 1, s32> joycon_left;
378 BitField<5, 1, s32> joycon_right; 428 BitField<5, 1, s32> joycon_right;
379 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;
380 }; 440 };
381 }; 441 };
382 442
@@ -387,37 +447,69 @@ private:
387 std::array<Common::Vec3f, 3> orientation; 447 std::array<Common::Vec3f, 3> orientation;
388 }; 448 };
389 449
390 struct NPadEntry { 450 struct NfcXcdHandle {
391 NpadStyleSet joy_styles; 451 INSERT_PADDING_BYTES(0x60);
392 NpadAssignments pad_assignment; 452 };
453
454 struct AppletFooterUiAttributes {
455 INSERT_PADDING_BYTES(0x4);
456 };
393 457
394 ColorReadError single_color_error; 458 enum class AppletFooterUiType : u8 {
395 ControllerColor single_color; 459 None = 0,
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 };
396 481
397 ColorReadError dual_color_error; 482 struct NPadEntry {
398 ControllerColor left_color; 483 NpadStyleSet style_set;
399 ControllerColor right_color; 484 NpadAssignments assignment_mode;
485 FullKeyColor fullkey_color;
486 JoyconColor joycon_color;
400 487
401 NPadGeneric main_controller_states; 488 NPadGeneric fullkey_states;
402 NPadGeneric handheld_states; 489 NPadGeneric handheld_states;
403 NPadGeneric dual_states; 490 NPadGeneric joy_dual_states;
404 NPadGeneric left_joy_states; 491 NPadGeneric joy_left_states;
405 NPadGeneric right_joy_states; 492 NPadGeneric joy_right_states;
406 NPadGeneric pokeball_states; 493 NPadGeneric palma_states;
407 NPadGeneric libnx; // TODO(ogniK): Find out what this actually is, libnx seems to only be 494 NPadGeneric system_ext_states;
408 // relying on this for the time being 495 SixAxisGeneric sixaxis_fullkey;
409 SixAxisGeneric sixaxis_full;
410 SixAxisGeneric sixaxis_handheld; 496 SixAxisGeneric sixaxis_handheld;
411 SixAxisGeneric sixaxis_dual_left; 497 SixAxisGeneric sixaxis_dual_left;
412 SixAxisGeneric sixaxis_dual_right; 498 SixAxisGeneric sixaxis_dual_right;
413 SixAxisGeneric sixaxis_left; 499 SixAxisGeneric sixaxis_left;
414 SixAxisGeneric sixaxis_right; 500 SixAxisGeneric sixaxis_right;
415 NPadDevice device_type; 501 NPadDevice device_type;
416 NPadProperties properties; 502 INSERT_PADDING_BYTES(0x4); // reserved
417 INSERT_PADDING_WORDS(1); 503 NPadSystemProperties system_properties;
418 std::array<u32, 3> battery_level; 504 NPadButtonProperties button_properties;
419 INSERT_PADDING_BYTES(0x5c); 505 u32 battery_level_dual;
420 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);
421 }; 513 };
422 static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size"); 514 static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size");
423 515
@@ -453,8 +545,7 @@ private:
453 std::vector<u32> supported_npad_id_types{}; 545 std::vector<u32> supported_npad_id_types{};
454 NpadHoldType hold_type{NpadHoldType::Vertical}; 546 NpadHoldType hold_type{NpadHoldType::Vertical};
455 NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; 547 NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
456 // NpadCommunicationMode is unknown, default value is 1 548 NpadCommunicationMode communication_mode{NpadCommunicationMode::Default};
457 NpadCommunicationMode communication_mode{NpadCommunicationMode::Unknown1};
458 // Each controller should have their own styleset changed event 549 // Each controller should have their own styleset changed event
459 std::array<std::shared_ptr<Kernel::KEvent>, 10> styleset_changed_events; 550 std::array<std::shared_ptr<Kernel::KEvent>, 10> styleset_changed_events;
460 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;
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 dda33f2b4..51a010a55 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -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(
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/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/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 bb1f8491f..2cf95937e 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/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..b40d7c5e2 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -884,7 +884,7 @@ void ConfigureInputPlayer::SetConnectableControllers() {
884 index_controller_type_pairs.clear(); 884 index_controller_type_pairs.clear();
885 ui->comboControllerType->clear(); 885 ui->comboControllerType->clear();
886 886
887 if (enable_all || npad_style_set.pro_controller == 1) { 887 if (enable_all || npad_style_set.fullkey == 1) {
888 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), 888 index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
889 Settings::ControllerType::ProController); 889 Settings::ControllerType::ProController);
890 ui->comboControllerType->addItem(tr("Pro Controller")); 890 ui->comboControllerType->addItem(tr("Pro Controller"));
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);