diff options
| author | 2021-02-06 11:53:25 -0600 | |
|---|---|---|
| committer | 2021-02-07 22:59:46 -0600 | |
| commit | a994a404676feed8c812e66edf3d055af8bc10e4 (patch) | |
| tree | 7121e41fed6dffd6a81a4fab7d2ab1a480bf2c9c /src/core | |
| parent | Merge pull request #5339 from german77/interactive (diff) | |
| download | yuzu-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.h | 1 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.cpp | 63 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.h | 26 |
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 | ||
| 36 | class ControllerApplet { | 37 | class 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 | ||
| 22 | namespace Service::HID { | 22 | namespace Service::HID { |
| 23 | constexpr s32 HID_JOYSTICK_MAX = 0x7fff; | 23 | constexpr s32 HID_JOYSTICK_MAX = 0x7fff; |
| 24 | constexpr s32 HID_TRIGGER_MAX = 0x7fff; | ||
| 24 | [[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff; | 25 | [[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff; |
| 25 | constexpr std::size_t NPAD_OFFSET = 0x9A00; | 26 | constexpr std::size_t NPAD_OFFSET = 0x9A00; |
| 26 | constexpr u32 BATTERY_FULL = 2; | 27 | constexpr 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 | ||
| 409 | void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, | 434 | void 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 | }; |