summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar David Marcec2018-10-20 15:07:18 +1100
committerGravatar David Marcec2018-10-20 15:07:18 +1100
commita03600ba28698ba2c9a7ded20c6da1c22986bf9e (patch)
treefeb7ad14772b04bd0de3cdcff429f6beb84b778f /src
parentMerge pull request #1501 from ReinUsesLisp/half-float (diff)
downloadyuzu-a03600ba28698ba2c9a7ded20c6da1c22986bf9e.tar.gz
yuzu-a03600ba28698ba2c9a7ded20c6da1c22986bf9e.tar.xz
yuzu-a03600ba28698ba2c9a7ded20c6da1c22986bf9e.zip
Added auto controller switching to supported controllers and single joycon button rotation
This is a subset of the better-hid-2 changes, this fixes input in various games which don't support dual joycons. This pr will search for the next best controller which is supported by the current game
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp191
-rw-r--r--src/core/hle/service/hid/controllers/npad.h2
2 files changed, 189 insertions, 4 deletions
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index b26593b4f..b06e65a77 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -26,7 +26,11 @@ constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
26constexpr s32 HID_JOYSTICK_MIN = -0x7fff; 26constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
27constexpr std::size_t NPAD_OFFSET = 0x9A00; 27constexpr std::size_t NPAD_OFFSET = 0x9A00;
28constexpr u32 BATTERY_FULL = 2; 28constexpr u32 BATTERY_FULL = 2;
29 29constexpr u32 NPAD_HANDHELD = 32;
30constexpr u32 NPAD_UNKNOWN = 16; // TODO(ogniK): What is this?
31constexpr u32 MAX_NPAD_ID = 7;
32constexpr Controller_NPad::NPadControllerType PREFERRED_CONTROLLER =
33 Controller_NPad::NPadControllerType::JoyDual;
30constexpr std::array<u32, 10> npad_id_list{ 34constexpr std::array<u32, 10> npad_id_list{
31 0, 1, 2, 3, 4, 5, 6, 7, 32, 16, 35 0, 1, 2, 3, 4, 5, 6, 7, 32, 16,
32}; 36};
@@ -121,7 +125,7 @@ void Controller_NPad::OnInit() {
121 supported_npad_id_types.resize(npad_id_list.size()); 125 supported_npad_id_types.resize(npad_id_list.size());
122 std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), 126 std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
123 npad_id_list.size() * sizeof(u32)); 127 npad_id_list.size() * sizeof(u32));
124 AddNewController(NPadControllerType::JoyDual); 128 AddNewController(PREFERRED_CONTROLLER);
125 } 129 }
126} 130}
127 131
@@ -218,6 +222,51 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) {
218 rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX); 222 rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
219 rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX); 223 rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
220 224
225 if (controller_type == NPadControllerType::JoyLeft ||
226 controller_type == NPadControllerType::JoyRight) {
227 if (npad.properties.is_horizontal) {
228 ControllerPadState state{};
229 AnalogPosition temp_lstick_entry{};
230 AnalogPosition temp_rstick_entry{};
231 if (controller_type == NPadControllerType::JoyLeft) {
232 state.d_down.Assign(pad_state.d_left.Value());
233 state.d_left.Assign(pad_state.d_up.Value());
234 state.d_right.Assign(pad_state.d_down.Value());
235 state.d_up.Assign(pad_state.d_right.Value());
236 state.l.Assign(pad_state.l.Value() | pad_state.sl.Value());
237 state.r.Assign(pad_state.r.Value() | pad_state.sr.Value());
238
239 state.zl.Assign(pad_state.zl.Value());
240 state.plus.Assign(pad_state.minus.Value());
241
242 temp_lstick_entry = lstick_entry;
243 temp_rstick_entry = rstick_entry;
244 std::swap(temp_lstick_entry.x, temp_lstick_entry.y);
245 std::swap(temp_rstick_entry.x, temp_rstick_entry.y);
246 temp_lstick_entry.y *= -1;
247 } else if (controller_type == NPadControllerType::JoyRight) {
248 state.x.Assign(pad_state.a.Value());
249 state.a.Assign(pad_state.b.Value());
250 state.b.Assign(pad_state.y.Value());
251 state.y.Assign(pad_state.b.Value());
252
253 state.l.Assign(pad_state.l.Value() | pad_state.sl.Value());
254 state.r.Assign(pad_state.r.Value() | pad_state.sr.Value());
255 state.zr.Assign(pad_state.zr.Value());
256 state.plus.Assign(pad_state.plus.Value());
257
258 temp_lstick_entry = lstick_entry;
259 temp_rstick_entry = rstick_entry;
260 std::swap(temp_lstick_entry.x, temp_lstick_entry.y);
261 std::swap(temp_rstick_entry.x, temp_rstick_entry.y);
262 temp_rstick_entry.x *= -1;
263 }
264 pad_state.raw = state.raw;
265 lstick_entry = temp_lstick_entry;
266 rstick_entry = temp_rstick_entry;
267 }
268 }
269
221 auto& main_controller = 270 auto& main_controller =
222 npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index]; 271 npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index];
223 auto& handheld_entry = 272 auto& handheld_entry =
@@ -320,6 +369,16 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) {
320 supported_npad_id_types.clear(); 369 supported_npad_id_types.clear();
321 supported_npad_id_types.resize(length / sizeof(u32)); 370 supported_npad_id_types.resize(length / sizeof(u32));
322 std::memcpy(supported_npad_id_types.data(), data, length); 371 std::memcpy(supported_npad_id_types.data(), data, length);
372 for (std::size_t i = 0; i < connected_controllers.size(); i++) {
373 auto& controller = connected_controllers[i];
374 if (!controller.is_connected) {
375 continue;
376 }
377 if (!IsControllerSupported(PREFERRED_CONTROLLER)) {
378 controller.type = DecideBestController(PREFERRED_CONTROLLER);
379 InitNewlyAddedControler(i);
380 }
381 }
323} 382}
324 383
325void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { 384void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
@@ -351,11 +410,11 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
351 for (std::size_t i = 0; i < controller_ids.size(); i++) { 410 for (std::size_t i = 0; i < controller_ids.size(); i++) {
352 std::size_t controller_pos = i; 411 std::size_t controller_pos = i;
353 // Handheld controller conversion 412 // Handheld controller conversion
354 if (controller_pos == 32) { 413 if (controller_pos == NPAD_HANDHELD) {
355 controller_pos = 8; 414 controller_pos = 8;
356 } 415 }
357 // Unknown controller conversion 416 // Unknown controller conversion
358 if (controller_pos == 16) { 417 if (controller_pos == NPAD_UNKNOWN) {
359 controller_pos = 9; 418 controller_pos = 9;
360 } 419 }
361 if (connected_controllers[controller_pos].is_connected) { 420 if (connected_controllers[controller_pos].is_connected) {
@@ -433,4 +492,128 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
433void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { 492void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
434 can_controllers_vibrate = can_vibrate; 493 can_controllers_vibrate = can_vibrate;
435} 494}
495
496bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const {
497 const bool support_handheld =
498 std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), NPAD_HANDHELD) !=
499 supported_npad_id_types.end();
500 if (controller == NPadControllerType::Handheld) {
501 // Handheld is not even a supported type, lets stop here
502 if (!support_handheld) {
503 return false;
504 }
505 // Handheld should not be supported in docked mode
506 if (Settings::values.use_docked_mode) {
507 return false;
508 }
509
510 return true;
511 }
512 if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
513 [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
514 switch (controller) {
515 case NPadControllerType::ProController:
516 return style.pro_controller;
517 case NPadControllerType::JoyDual:
518 return style.joycon_dual;
519 case NPadControllerType::JoyLeft:
520 return style.joycon_left;
521 case NPadControllerType::JoyRight:
522 return style.joycon_right;
523 case NPadControllerType::Pokeball:
524 return style.pokeball;
525 default:
526 return false;
527 }
528 }
529 return false;
530}
531
532Controller_NPad::NPadControllerType Controller_NPad::DecideBestController(
533 NPadControllerType priority) const {
534 if (IsControllerSupported(priority)) {
535 return priority;
536 }
537 const auto is_docked = Settings::values.use_docked_mode;
538 if (is_docked && priority == NPadControllerType::Handheld) {
539 priority = NPadControllerType::JoyDual;
540 if (IsControllerSupported(priority)) {
541 return priority;
542 }
543 }
544 std::vector<NPadControllerType> priority_list;
545 switch (priority) {
546 case NPadControllerType::ProController:
547 priority_list.push_back(NPadControllerType::JoyDual);
548 if (!is_docked) {
549 priority_list.push_back(NPadControllerType::Handheld);
550 }
551 priority_list.push_back(NPadControllerType::JoyLeft);
552 priority_list.push_back(NPadControllerType::JoyRight);
553 priority_list.push_back(NPadControllerType::Pokeball);
554 break;
555 case NPadControllerType::Handheld:
556 priority_list.push_back(NPadControllerType::JoyDual);
557 priority_list.push_back(NPadControllerType::ProController);
558 priority_list.push_back(NPadControllerType::JoyLeft);
559 priority_list.push_back(NPadControllerType::JoyRight);
560 priority_list.push_back(NPadControllerType::Pokeball);
561 break;
562 case NPadControllerType::JoyDual:
563 if (!is_docked) {
564 priority_list.push_back(NPadControllerType::Handheld);
565 }
566 priority_list.push_back(NPadControllerType::ProController);
567 priority_list.push_back(NPadControllerType::JoyLeft);
568 priority_list.push_back(NPadControllerType::JoyRight);
569 priority_list.push_back(NPadControllerType::Pokeball);
570 break;
571 case NPadControllerType::JoyLeft:
572 priority_list.push_back(NPadControllerType::JoyRight);
573 priority_list.push_back(NPadControllerType::JoyDual);
574 if (!is_docked) {
575 priority_list.push_back(NPadControllerType::Handheld);
576 }
577 priority_list.push_back(NPadControllerType::ProController);
578 priority_list.push_back(NPadControllerType::Pokeball);
579 break;
580 case NPadControllerType::JoyRight:
581 priority_list.push_back(NPadControllerType::JoyLeft);
582 priority_list.push_back(NPadControllerType::JoyDual);
583 if (!is_docked) {
584 priority_list.push_back(NPadControllerType::Handheld);
585 }
586 priority_list.push_back(NPadControllerType::ProController);
587 priority_list.push_back(NPadControllerType::Pokeball);
588 break;
589 case NPadControllerType::Pokeball:
590 priority_list.push_back(NPadControllerType::JoyLeft);
591 priority_list.push_back(NPadControllerType::JoyRight);
592 priority_list.push_back(NPadControllerType::JoyDual);
593 if (!is_docked) {
594 priority_list.push_back(NPadControllerType::Handheld);
595 }
596 priority_list.push_back(NPadControllerType::ProController);
597 break;
598 default:
599 priority_list.push_back(NPadControllerType::JoyDual);
600 if (!is_docked) {
601 priority_list.push_back(NPadControllerType::Handheld);
602 }
603 priority_list.push_back(NPadControllerType::ProController);
604 priority_list.push_back(NPadControllerType::JoyLeft);
605 priority_list.push_back(NPadControllerType::JoyRight);
606 priority_list.push_back(NPadControllerType::JoyDual);
607 }
608
609 const auto iter = std::find_if(priority_list.begin(), priority_list.end(),
610 [this](auto type) { return IsControllerSupported(type); });
611 if (iter == priority_list.end()) {
612 UNIMPLEMENTED_MSG("Could not find supported controller!");
613 return priority;
614 }
615
616 return *iter;
617}
618
436} // namespace Service::HID 619} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 7c0f93acf..ac86985ff 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -283,5 +283,7 @@ private:
283 bool can_controllers_vibrate{true}; 283 bool can_controllers_vibrate{true};
284 284
285 void InitNewlyAddedControler(std::size_t controller_idx); 285 void InitNewlyAddedControler(std::size_t controller_idx);
286 bool IsControllerSupported(NPadControllerType controller) const;
287 NPadControllerType DecideBestController(NPadControllerType priority) const;
286}; 288};
287} // namespace Service::HID 289} // namespace Service::HID