summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar german2021-02-06 11:53:25 -0600
committerGravatar german2021-02-07 22:59:46 -0600
commita994a404676feed8c812e66edf3d055af8bc10e4 (patch)
tree7121e41fed6dffd6a81a4fab7d2ab1a480bf2c9c /src/core
parentMerge pull request #5339 from german77/interactive (diff)
downloadyuzu-a994a404676feed8c812e66edf3d055af8bc10e4.tar.gz
yuzu-a994a404676feed8c812e66edf3d055af8bc10e4.tar.xz
yuzu-a994a404676feed8c812e66edf3d055af8bc10e4.zip
hid: Implement GC controller
Diffstat (limited to 'src/core')
-rw-r--r--src/core/frontend/applets/controller.h1
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp63
-rw-r--r--src/core/hle/service/hid/controllers/npad.h26
3 files changed, 89 insertions, 1 deletions
diff --git a/src/core/frontend/applets/controller.h b/src/core/frontend/applets/controller.h
index dff71d8d9..b0626a0f9 100644
--- a/src/core/frontend/applets/controller.h
+++ b/src/core/frontend/applets/controller.h
@@ -31,6 +31,7 @@ struct ControllerParameters {
31 bool allow_dual_joycons{}; 31 bool allow_dual_joycons{};
32 bool allow_left_joycon{}; 32 bool allow_left_joycon{};
33 bool allow_right_joycon{}; 33 bool allow_right_joycon{};
34 bool allow_gamecube_controller{};
34}; 35};
35 36
36class ControllerApplet { 37class ControllerApplet {
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index dbf198345..70b9f3824 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -21,6 +21,7 @@
21 21
22namespace Service::HID { 22namespace Service::HID {
23constexpr s32 HID_JOYSTICK_MAX = 0x7fff; 23constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
24constexpr s32 HID_TRIGGER_MAX = 0x7fff;
24[[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff; 25[[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
25constexpr std::size_t NPAD_OFFSET = 0x9A00; 26constexpr std::size_t NPAD_OFFSET = 0x9A00;
26constexpr u32 BATTERY_FULL = 2; 27constexpr u32 BATTERY_FULL = 2;
@@ -48,6 +49,8 @@ Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad(
48 return NPadControllerType::JoyRight; 49 return NPadControllerType::JoyRight;
49 case Settings::ControllerType::Handheld: 50 case Settings::ControllerType::Handheld:
50 return NPadControllerType::Handheld; 51 return NPadControllerType::Handheld;
52 case Settings::ControllerType::GameCube:
53 return NPadControllerType::GameCube;
51 default: 54 default:
52 UNREACHABLE(); 55 UNREACHABLE();
53 return NPadControllerType::ProController; 56 return NPadControllerType::ProController;
@@ -67,6 +70,8 @@ Settings::ControllerType Controller_NPad::MapNPadToSettingsType(
67 return Settings::ControllerType::RightJoycon; 70 return Settings::ControllerType::RightJoycon;
68 case NPadControllerType::Handheld: 71 case NPadControllerType::Handheld:
69 return Settings::ControllerType::Handheld; 72 return Settings::ControllerType::Handheld;
73 case NPadControllerType::GameCube:
74 return Settings::ControllerType::GameCube;
70 default: 75 default:
71 UNREACHABLE(); 76 UNREACHABLE();
72 return Settings::ControllerType::ProController; 77 return Settings::ControllerType::ProController;
@@ -209,6 +214,13 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
209 controller.assignment_mode = NpadAssignments::Single; 214 controller.assignment_mode = NpadAssignments::Single;
210 controller.footer_type = AppletFooterUiType::JoyRightHorizontal; 215 controller.footer_type = AppletFooterUiType::JoyRightHorizontal;
211 break; 216 break;
217 case NPadControllerType::GameCube:
218 controller.style_set.gamecube.Assign(1);
219 // The GC Controller behaves like a wired Pro Controller
220 controller.device_type.fullkey.Assign(1);
221 controller.system_properties.is_vertical.Assign(1);
222 controller.system_properties.use_plus.Assign(1);
223 break;
212 case NPadControllerType::Pokeball: 224 case NPadControllerType::Pokeball:
213 controller.style_set.palma.Assign(1); 225 controller.style_set.palma.Assign(1);
214 controller.device_type.palma.Assign(1); 226 controller.device_type.palma.Assign(1);
@@ -259,6 +271,7 @@ void Controller_NPad::OnInit() {
259 style.joycon_right.Assign(1); 271 style.joycon_right.Assign(1);
260 style.joycon_dual.Assign(1); 272 style.joycon_dual.Assign(1);
261 style.fullkey.Assign(1); 273 style.fullkey.Assign(1);
274 style.gamecube.Assign(1);
262 style.palma.Assign(1); 275 style.palma.Assign(1);
263 } 276 }
264 277
@@ -339,6 +352,7 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
339 auto& pad_state = npad_pad_states[controller_idx].pad_states; 352 auto& pad_state = npad_pad_states[controller_idx].pad_states;
340 auto& lstick_entry = npad_pad_states[controller_idx].l_stick; 353 auto& lstick_entry = npad_pad_states[controller_idx].l_stick;
341 auto& rstick_entry = npad_pad_states[controller_idx].r_stick; 354 auto& rstick_entry = npad_pad_states[controller_idx].r_stick;
355 auto& trigger_entry = npad_trigger_states[controller_idx];
342 const auto& button_state = buttons[controller_idx]; 356 const auto& button_state = buttons[controller_idx];
343 const auto& analog_state = sticks[controller_idx]; 357 const auto& analog_state = sticks[controller_idx];
344 const auto [stick_l_x_f, stick_l_y_f] = 358 const auto [stick_l_x_f, stick_l_y_f] =
@@ -404,6 +418,17 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
404 pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus()); 418 pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
405 pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus()); 419 pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
406 } 420 }
421
422 if (controller_type == NPadControllerType::GameCube) {
423 trigger_entry.l_analog = static_cast<s32>(
424 button_state[ZL - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0);
425 trigger_entry.r_analog = static_cast<s32>(
426 button_state[ZR - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0);
427 pad_state.zl.Assign(false);
428 pad_state.zr.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
429 pad_state.l.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
430 pad_state.r.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
431 }
407} 432}
408 433
409void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 434void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
@@ -418,6 +443,11 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
418 &npad.joy_left_states, &npad.joy_right_states, &npad.palma_states, 443 &npad.joy_left_states, &npad.joy_right_states, &npad.palma_states,
419 &npad.system_ext_states}; 444 &npad.system_ext_states};
420 445
446 // There is the posibility to have more controllers with analog triggers
447 const std::array<TriggerGeneric*, 1> controller_triggers{
448 &npad.gc_trigger_states,
449 };
450
421 for (auto* main_controller : controller_npads) { 451 for (auto* main_controller : controller_npads) {
422 main_controller->common.entry_count = 16; 452 main_controller->common.entry_count = 16;
423 main_controller->common.total_entry_count = 17; 453 main_controller->common.total_entry_count = 17;
@@ -435,6 +465,21 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
435 cur_entry.timestamp2 = cur_entry.timestamp; 465 cur_entry.timestamp2 = cur_entry.timestamp;
436 } 466 }
437 467
468 for (auto* analog_trigger : controller_triggers) {
469 analog_trigger->entry_count = 16;
470 analog_trigger->total_entry_count = 17;
471
472 const auto& last_entry = analog_trigger->trigger[analog_trigger->last_entry_index];
473
474 analog_trigger->timestamp = core_timing.GetCPUTicks();
475 analog_trigger->last_entry_index = (analog_trigger->last_entry_index + 1) % 17;
476
477 auto& cur_entry = analog_trigger->trigger[analog_trigger->last_entry_index];
478
479 cur_entry.timestamp = last_entry.timestamp + 1;
480 cur_entry.timestamp2 = cur_entry.timestamp;
481 }
482
438 const auto& controller_type = connected_controllers[i].type; 483 const auto& controller_type = connected_controllers[i].type;
439 484
440 if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) { 485 if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
@@ -444,6 +489,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
444 489
445 RequestPadStateUpdate(npad_index); 490 RequestPadStateUpdate(npad_index);
446 auto& pad_state = npad_pad_states[npad_index]; 491 auto& pad_state = npad_pad_states[npad_index];
492 auto& trigger_state = npad_trigger_states[npad_index];
447 493
448 auto& main_controller = 494 auto& main_controller =
449 npad.fullkey_states.npad[npad.fullkey_states.common.last_entry_index]; 495 npad.fullkey_states.npad[npad.fullkey_states.common.last_entry_index];
@@ -456,6 +502,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
456 auto& pokeball_entry = npad.palma_states.npad[npad.palma_states.common.last_entry_index]; 502 auto& pokeball_entry = npad.palma_states.npad[npad.palma_states.common.last_entry_index];
457 auto& libnx_entry = 503 auto& libnx_entry =
458 npad.system_ext_states.npad[npad.system_ext_states.common.last_entry_index]; 504 npad.system_ext_states.npad[npad.system_ext_states.common.last_entry_index];
505 auto& trigger_entry =
506 npad.gc_trigger_states.trigger[npad.gc_trigger_states.last_entry_index];
459 507
460 libnx_entry.connection_status.raw = 0; 508 libnx_entry.connection_status.raw = 0;
461 libnx_entry.connection_status.is_connected.Assign(1); 509 libnx_entry.connection_status.is_connected.Assign(1);
@@ -524,6 +572,18 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
524 572
525 libnx_entry.connection_status.is_right_connected.Assign(1); 573 libnx_entry.connection_status.is_right_connected.Assign(1);
526 break; 574 break;
575 case NPadControllerType::GameCube:
576 main_controller.connection_status.raw = 0;
577 main_controller.connection_status.is_connected.Assign(1);
578 main_controller.connection_status.is_wired.Assign(1);
579 main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
580 main_controller.pad.l_stick = pad_state.l_stick;
581 main_controller.pad.r_stick = pad_state.r_stick;
582 trigger_entry.l_analog = trigger_state.l_analog;
583 trigger_entry.r_analog = trigger_state.r_analog;
584
585 libnx_entry.connection_status.is_wired.Assign(1);
586 break;
527 case NPadControllerType::Pokeball: 587 case NPadControllerType::Pokeball:
528 pokeball_entry.connection_status.raw = 0; 588 pokeball_entry.connection_status.raw = 0;
529 pokeball_entry.connection_status.is_connected.Assign(1); 589 pokeball_entry.connection_status.is_connected.Assign(1);
@@ -674,6 +734,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
674 right_sixaxis_entry.orientation = motion_devices[1].orientation; 734 right_sixaxis_entry.orientation = motion_devices[1].orientation;
675 } 735 }
676 break; 736 break;
737 case NPadControllerType::GameCube:
677 case NPadControllerType::Pokeball: 738 case NPadControllerType::Pokeball:
678 break; 739 break;
679 } 740 }
@@ -1135,6 +1196,8 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
1135 return style.joycon_left; 1196 return style.joycon_left;
1136 case NPadControllerType::JoyRight: 1197 case NPadControllerType::JoyRight:
1137 return style.joycon_right; 1198 return style.joycon_right;
1199 case NPadControllerType::GameCube:
1200 return style.gamecube;
1138 case NPadControllerType::Pokeball: 1201 case NPadControllerType::Pokeball:
1139 return style.palma; 1202 return style.palma;
1140 default: 1203 default:
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 48bab988c..bc2e6779d 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -51,6 +51,7 @@ public:
51 JoyDual, 51 JoyDual,
52 JoyLeft, 52 JoyLeft,
53 JoyRight, 53 JoyRight,
54 GameCube,
54 Pokeball, 55 Pokeball,
55 }; 56 };
56 57
@@ -60,6 +61,7 @@ public:
60 JoyconDual = 5, 61 JoyconDual = 5,
61 JoyconLeft = 6, 62 JoyconLeft = 6,
62 JoyconRight = 7, 63 JoyconRight = 7,
64 GameCube = 8,
63 Pokeball = 9, 65 Pokeball = 9,
64 MaxNpadType = 10, 66 MaxNpadType = 10,
65 }; 67 };
@@ -389,6 +391,25 @@ private:
389 }; 391 };
390 static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size"); 392 static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size");
391 393
394 struct TriggerState {
395 s64_le timestamp{};
396 s64_le timestamp2{};
397 s32_le l_analog{};
398 s32_le r_analog{};
399 };
400 static_assert(sizeof(TriggerState) == 0x18, "TriggerState is an invalid size");
401
402 struct TriggerGeneric {
403 INSERT_PADDING_BYTES(0x4);
404 s64_le timestamp;
405 INSERT_PADDING_BYTES(0x4);
406 s64_le total_entry_count;
407 s64_le last_entry_index;
408 s64_le entry_count;
409 std::array<TriggerState, 17> trigger{};
410 };
411 static_assert(sizeof(TriggerGeneric) == 0x1C8, "TriggerGeneric is an invalid size");
412
392 struct NPadSystemProperties { 413 struct NPadSystemProperties {
393 union { 414 union {
394 s64_le raw{}; 415 s64_le raw{};
@@ -509,7 +530,9 @@ private:
509 AppletFooterUiType footer_type; 530 AppletFooterUiType footer_type;
510 // nfc_states needs to be checked switchbrew does not match with HW 531 // nfc_states needs to be checked switchbrew does not match with HW
511 NfcXcdHandle nfc_states; 532 NfcXcdHandle nfc_states;
512 INSERT_PADDING_BYTES(0xdef); 533 INSERT_PADDING_BYTES(0x8); // Mutex
534 TriggerGeneric gc_trigger_states;
535 INSERT_PADDING_BYTES(0xc1f);
513 }; 536 };
514 static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size"); 537 static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size");
515 538
@@ -560,6 +583,7 @@ private:
560 f32 sixaxis_fusion_parameter2{}; 583 f32 sixaxis_fusion_parameter2{};
561 bool sixaxis_at_rest{true}; 584 bool sixaxis_at_rest{true};
562 std::array<ControllerPad, 10> npad_pad_states{}; 585 std::array<ControllerPad, 10> npad_pad_states{};
586 std::array<TriggerState, 10> npad_trigger_states{};
563 bool is_in_lr_assignment_mode{false}; 587 bool is_in_lr_assignment_mode{false};
564 Core::System& system; 588 Core::System& system;
565}; 589};