diff options
| author | 2020-07-22 10:39:53 -0400 | |
|---|---|---|
| committer | 2020-08-26 02:32:32 -0400 | |
| commit | f0fac0c7fb6f7dd9fe81747b3369767c8c9e7d01 (patch) | |
| tree | 4438688a9b9b4bc015985f2df1a731de57fe50db /src/core/hle | |
| parent | Merge pull request #4582 from lioncash/xbyak (diff) | |
| download | yuzu-f0fac0c7fb6f7dd9fe81747b3369767c8c9e7d01.tar.gz yuzu-f0fac0c7fb6f7dd9fe81747b3369767c8c9e7d01.tar.xz yuzu-f0fac0c7fb6f7dd9fe81747b3369767c8c9e7d01.zip | |
Project Mjölnir: Part 1
Co-authored-by: James Rowe <jroweboy@gmail.com>
Co-authored-by: Its-Rei <kupfel@gmail.com>
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.cpp | 213 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.h | 11 | ||||
| -rw-r--r-- | src/core/hle/service/hid/hid.cpp | 14 |
3 files changed, 111 insertions, 127 deletions
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 0e7794dc7..82e11b169 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -24,6 +24,7 @@ constexpr s32 HID_JOYSTICK_MAX = 0x7fff; | |||
| 24 | constexpr std::size_t NPAD_OFFSET = 0x9A00; | 24 | constexpr std::size_t NPAD_OFFSET = 0x9A00; |
| 25 | constexpr u32 BATTERY_FULL = 2; | 25 | constexpr u32 BATTERY_FULL = 2; |
| 26 | constexpr u32 MAX_NPAD_ID = 7; | 26 | constexpr u32 MAX_NPAD_ID = 7; |
| 27 | constexpr std::size_t HANDHELD_INDEX = 8; | ||
| 27 | constexpr std::array<u32, 10> npad_id_list{ | 28 | constexpr std::array<u32, 10> npad_id_list{ |
| 28 | 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, | 29 | 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, |
| 29 | }; | 30 | }; |
| @@ -33,19 +34,41 @@ enum class JoystickId : std::size_t { | |||
| 33 | Joystick_Right, | 34 | Joystick_Right, |
| 34 | }; | 35 | }; |
| 35 | 36 | ||
| 36 | static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type) { | 37 | Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad( |
| 38 | Settings::ControllerType type) { | ||
| 37 | switch (type) { | 39 | switch (type) { |
| 38 | case Settings::ControllerType::ProController: | 40 | case Settings::ControllerType::ProController: |
| 39 | return Controller_NPad::NPadControllerType::ProController; | 41 | return NPadControllerType::ProController; |
| 40 | case Settings::ControllerType::DualJoycon: | 42 | case Settings::ControllerType::DualJoyconDetached: |
| 41 | return Controller_NPad::NPadControllerType::JoyDual; | 43 | return NPadControllerType::JoyDual; |
| 42 | case Settings::ControllerType::LeftJoycon: | 44 | case Settings::ControllerType::LeftJoycon: |
| 43 | return Controller_NPad::NPadControllerType::JoyLeft; | 45 | return NPadControllerType::JoyLeft; |
| 44 | case Settings::ControllerType::RightJoycon: | 46 | case Settings::ControllerType::RightJoycon: |
| 45 | return Controller_NPad::NPadControllerType::JoyRight; | 47 | return NPadControllerType::JoyRight; |
| 48 | case Settings::ControllerType::Handheld: | ||
| 49 | return NPadControllerType::Handheld; | ||
| 46 | default: | 50 | default: |
| 47 | UNREACHABLE(); | 51 | UNREACHABLE(); |
| 48 | return Controller_NPad::NPadControllerType::JoyDual; | 52 | return NPadControllerType::ProController; |
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | Settings::ControllerType Controller_NPad::MapNPadToSettingsType( | ||
| 57 | Controller_NPad::NPadControllerType type) { | ||
| 58 | switch (type) { | ||
| 59 | case NPadControllerType::ProController: | ||
| 60 | return Settings::ControllerType::ProController; | ||
| 61 | case NPadControllerType::JoyDual: | ||
| 62 | return Settings::ControllerType::DualJoyconDetached; | ||
| 63 | case NPadControllerType::JoyLeft: | ||
| 64 | return Settings::ControllerType::LeftJoycon; | ||
| 65 | case NPadControllerType::JoyRight: | ||
| 66 | return Settings::ControllerType::RightJoycon; | ||
| 67 | case NPadControllerType::Handheld: | ||
| 68 | return Settings::ControllerType::Handheld; | ||
| 69 | default: | ||
| 70 | UNREACHABLE(); | ||
| 71 | return Settings::ControllerType::ProController; | ||
| 49 | } | 72 | } |
| 50 | } | 73 | } |
| 51 | 74 | ||
| @@ -60,9 +83,9 @@ std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) { | |||
| 60 | case 6: | 83 | case 6: |
| 61 | case 7: | 84 | case 7: |
| 62 | return npad_id; | 85 | return npad_id; |
| 63 | case 8: | 86 | case HANDHELD_INDEX: |
| 64 | case NPAD_HANDHELD: | 87 | case NPAD_HANDHELD: |
| 65 | return 8; | 88 | return HANDHELD_INDEX; |
| 66 | case 9: | 89 | case 9: |
| 67 | case NPAD_UNKNOWN: | 90 | case NPAD_UNKNOWN: |
| 68 | return 9; | 91 | return 9; |
| @@ -83,7 +106,7 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { | |||
| 83 | case 6: | 106 | case 6: |
| 84 | case 7: | 107 | case 7: |
| 85 | return static_cast<u32>(index); | 108 | return static_cast<u32>(index); |
| 86 | case 8: | 109 | case HANDHELD_INDEX: |
| 87 | return NPAD_HANDHELD; | 110 | return NPAD_HANDHELD; |
| 88 | case 9: | 111 | case 9: |
| 89 | return NPAD_UNKNOWN; | 112 | return NPAD_UNKNOWN; |
| @@ -96,25 +119,35 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { | |||
| 96 | Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} | 119 | Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} |
| 97 | Controller_NPad::~Controller_NPad() = default; | 120 | Controller_NPad::~Controller_NPad() = default; |
| 98 | 121 | ||
| 99 | void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { | 122 | void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { |
| 100 | const auto controller_type = connected_controllers[controller_idx].type; | 123 | const auto controller_type = connected_controllers[controller_idx].type; |
| 101 | auto& controller = shared_memory_entries[controller_idx]; | 124 | auto& controller = shared_memory_entries[controller_idx]; |
| 102 | if (controller_type == NPadControllerType::None) { | 125 | if (controller_type == NPadControllerType::None) { |
| 126 | styleset_changed_events[controller_idx].writable->Signal(); | ||
| 103 | return; | 127 | return; |
| 104 | } | 128 | } |
| 105 | controller.joy_styles.raw = 0; // Zero out | 129 | controller.joy_styles.raw = 0; // Zero out |
| 106 | controller.device_type.raw = 0; | 130 | controller.device_type.raw = 0; |
| 131 | controller.properties.raw = 0; | ||
| 107 | switch (controller_type) { | 132 | switch (controller_type) { |
| 108 | case NPadControllerType::None: | 133 | case NPadControllerType::None: |
| 109 | UNREACHABLE(); | 134 | UNREACHABLE(); |
| 110 | break; | 135 | break; |
| 136 | case NPadControllerType::ProController: | ||
| 137 | controller.joy_styles.pro_controller.Assign(1); | ||
| 138 | controller.device_type.pro_controller.Assign(1); | ||
| 139 | controller.properties.is_vertical.Assign(1); | ||
| 140 | controller.properties.use_plus.Assign(1); | ||
| 141 | controller.properties.use_minus.Assign(1); | ||
| 142 | controller.pad_assignment = NPadAssignments::Single; | ||
| 143 | break; | ||
| 111 | case NPadControllerType::Handheld: | 144 | case NPadControllerType::Handheld: |
| 112 | controller.joy_styles.handheld.Assign(1); | 145 | controller.joy_styles.handheld.Assign(1); |
| 113 | controller.device_type.handheld.Assign(1); | 146 | controller.device_type.handheld.Assign(1); |
| 114 | controller.pad_assignment = NPadAssignments::Dual; | ||
| 115 | controller.properties.is_vertical.Assign(1); | 147 | controller.properties.is_vertical.Assign(1); |
| 116 | controller.properties.use_plus.Assign(1); | 148 | controller.properties.use_plus.Assign(1); |
| 117 | controller.properties.use_minus.Assign(1); | 149 | controller.properties.use_minus.Assign(1); |
| 150 | controller.pad_assignment = NPadAssignments::Dual; | ||
| 118 | break; | 151 | break; |
| 119 | case NPadControllerType::JoyDual: | 152 | case NPadControllerType::JoyDual: |
| 120 | controller.joy_styles.joycon_dual.Assign(1); | 153 | controller.joy_styles.joycon_dual.Assign(1); |
| @@ -144,14 +177,6 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { | |||
| 144 | controller.device_type.pokeball.Assign(1); | 177 | controller.device_type.pokeball.Assign(1); |
| 145 | controller.pad_assignment = NPadAssignments::Single; | 178 | controller.pad_assignment = NPadAssignments::Single; |
| 146 | break; | 179 | break; |
| 147 | case NPadControllerType::ProController: | ||
| 148 | controller.joy_styles.pro_controller.Assign(1); | ||
| 149 | controller.device_type.pro_controller.Assign(1); | ||
| 150 | controller.properties.is_vertical.Assign(1); | ||
| 151 | controller.properties.use_plus.Assign(1); | ||
| 152 | controller.properties.use_minus.Assign(1); | ||
| 153 | controller.pad_assignment = NPadAssignments::Single; | ||
| 154 | break; | ||
| 155 | } | 180 | } |
| 156 | 181 | ||
| 157 | controller.single_color_error = ColorReadError::ReadOk; | 182 | controller.single_color_error = ColorReadError::ReadOk; |
| @@ -192,36 +217,25 @@ void Controller_NPad::OnInit() { | |||
| 192 | style.pokeball.Assign(1); | 217 | style.pokeball.Assign(1); |
| 193 | } | 218 | } |
| 194 | 219 | ||
| 195 | std::transform( | 220 | std::transform(Settings::values.players.begin(), Settings::values.players.end(), |
| 196 | Settings::values.players.begin(), Settings::values.players.end(), | 221 | connected_controllers.begin(), [](const Settings::PlayerInput& player) { |
| 197 | connected_controllers.begin(), [](const Settings::PlayerInput& player) { | 222 | return ControllerHolder{MapSettingsTypeToNPad(player.controller_type), |
| 198 | return ControllerHolder{MapSettingsTypeToNPad(player.type), player.connected}; | 223 | player.connected}; |
| 199 | }); | 224 | }); |
| 200 | |||
| 201 | std::stable_partition(connected_controllers.begin(), connected_controllers.begin() + 8, | ||
| 202 | [](const ControllerHolder& holder) { return holder.is_connected; }); | ||
| 203 | 225 | ||
| 204 | // Account for handheld | 226 | // Account for handheld |
| 205 | if (connected_controllers[8].is_connected) | 227 | if (connected_controllers[HANDHELD_INDEX].is_connected) { |
| 206 | connected_controllers[8].type = NPadControllerType::Handheld; | 228 | connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld; |
| 229 | } | ||
| 207 | 230 | ||
| 208 | supported_npad_id_types.resize(npad_id_list.size()); | 231 | supported_npad_id_types.resize(npad_id_list.size()); |
| 209 | std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), | 232 | std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), |
| 210 | npad_id_list.size() * sizeof(u32)); | 233 | npad_id_list.size() * sizeof(u32)); |
| 211 | 234 | ||
| 212 | // Add a default dual joycon controller if none are present. | ||
| 213 | if (std::none_of(connected_controllers.begin(), connected_controllers.end(), | ||
| 214 | [](const ControllerHolder& controller) { return controller.is_connected; })) { | ||
| 215 | supported_npad_id_types.resize(npad_id_list.size()); | ||
| 216 | std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), | ||
| 217 | npad_id_list.size() * sizeof(u32)); | ||
| 218 | AddNewController(NPadControllerType::JoyDual); | ||
| 219 | } | ||
| 220 | |||
| 221 | for (std::size_t i = 0; i < connected_controllers.size(); ++i) { | 235 | for (std::size_t i = 0; i < connected_controllers.size(); ++i) { |
| 222 | const auto& controller = connected_controllers[i]; | 236 | const auto& controller = connected_controllers[i]; |
| 223 | if (controller.is_connected) { | 237 | if (controller.is_connected) { |
| 224 | AddNewControllerAt(controller.type, IndexToNPad(i)); | 238 | AddNewControllerAt(controller.type, i); |
| 225 | } | 239 | } |
| 226 | } | 240 | } |
| 227 | } | 241 | } |
| @@ -309,8 +323,9 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { | |||
| 309 | 323 | ||
| 310 | void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, | 324 | void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, |
| 311 | std::size_t data_len) { | 325 | std::size_t data_len) { |
| 312 | if (!IsControllerActivated()) | 326 | if (!IsControllerActivated()) { |
| 313 | return; | 327 | return; |
| 328 | } | ||
| 314 | for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { | 329 | for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { |
| 315 | auto& npad = shared_memory_entries[i]; | 330 | auto& npad = shared_memory_entries[i]; |
| 316 | const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, | 331 | const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, |
| @@ -365,6 +380,14 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* | |||
| 365 | case NPadControllerType::None: | 380 | case NPadControllerType::None: |
| 366 | UNREACHABLE(); | 381 | UNREACHABLE(); |
| 367 | break; | 382 | break; |
| 383 | case NPadControllerType::ProController: | ||
| 384 | main_controller.connection_status.raw = 0; | ||
| 385 | main_controller.connection_status.IsConnected.Assign(1); | ||
| 386 | main_controller.connection_status.IsWired.Assign(1); | ||
| 387 | main_controller.pad.pad_states.raw = pad_state.pad_states.raw; | ||
| 388 | main_controller.pad.l_stick = pad_state.l_stick; | ||
| 389 | main_controller.pad.r_stick = pad_state.r_stick; | ||
| 390 | break; | ||
| 368 | case NPadControllerType::Handheld: | 391 | case NPadControllerType::Handheld: |
| 369 | handheld_entry.connection_status.raw = 0; | 392 | handheld_entry.connection_status.raw = 0; |
| 370 | handheld_entry.connection_status.IsWired.Assign(1); | 393 | handheld_entry.connection_status.IsWired.Assign(1); |
| @@ -378,22 +401,19 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* | |||
| 378 | break; | 401 | break; |
| 379 | case NPadControllerType::JoyDual: | 402 | case NPadControllerType::JoyDual: |
| 380 | dual_entry.connection_status.raw = 0; | 403 | dual_entry.connection_status.raw = 0; |
| 381 | 404 | dual_entry.connection_status.IsConnected.Assign(1); | |
| 382 | dual_entry.connection_status.IsLeftJoyConnected.Assign(1); | 405 | dual_entry.connection_status.IsLeftJoyConnected.Assign(1); |
| 383 | dual_entry.connection_status.IsRightJoyConnected.Assign(1); | 406 | dual_entry.connection_status.IsRightJoyConnected.Assign(1); |
| 384 | dual_entry.connection_status.IsConnected.Assign(1); | ||
| 385 | |||
| 386 | libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); | ||
| 387 | libnx_entry.connection_status.IsRightJoyConnected.Assign(1); | ||
| 388 | libnx_entry.connection_status.IsConnected.Assign(1); | ||
| 389 | |||
| 390 | dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 407 | dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; |
| 391 | dual_entry.pad.l_stick = pad_state.l_stick; | 408 | dual_entry.pad.l_stick = pad_state.l_stick; |
| 392 | dual_entry.pad.r_stick = pad_state.r_stick; | 409 | dual_entry.pad.r_stick = pad_state.r_stick; |
| 410 | |||
| 411 | libnx_entry.connection_status.IsConnected.Assign(1); | ||
| 412 | libnx_entry.connection_status.IsLeftJoyConnected.Assign(1); | ||
| 413 | libnx_entry.connection_status.IsRightJoyConnected.Assign(1); | ||
| 393 | break; | 414 | break; |
| 394 | case NPadControllerType::JoyLeft: | 415 | case NPadControllerType::JoyLeft: |
| 395 | left_entry.connection_status.raw = 0; | 416 | left_entry.connection_status.raw = 0; |
| 396 | |||
| 397 | left_entry.connection_status.IsConnected.Assign(1); | 417 | left_entry.connection_status.IsConnected.Assign(1); |
| 398 | left_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 418 | left_entry.pad.pad_states.raw = pad_state.pad_states.raw; |
| 399 | left_entry.pad.l_stick = pad_state.l_stick; | 419 | left_entry.pad.l_stick = pad_state.l_stick; |
| @@ -401,7 +421,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* | |||
| 401 | break; | 421 | break; |
| 402 | case NPadControllerType::JoyRight: | 422 | case NPadControllerType::JoyRight: |
| 403 | right_entry.connection_status.raw = 0; | 423 | right_entry.connection_status.raw = 0; |
| 404 | |||
| 405 | right_entry.connection_status.IsConnected.Assign(1); | 424 | right_entry.connection_status.IsConnected.Assign(1); |
| 406 | right_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 425 | right_entry.pad.pad_states.raw = pad_state.pad_states.raw; |
| 407 | right_entry.pad.l_stick = pad_state.l_stick; | 426 | right_entry.pad.l_stick = pad_state.l_stick; |
| @@ -409,23 +428,12 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* | |||
| 409 | break; | 428 | break; |
| 410 | case NPadControllerType::Pokeball: | 429 | case NPadControllerType::Pokeball: |
| 411 | pokeball_entry.connection_status.raw = 0; | 430 | pokeball_entry.connection_status.raw = 0; |
| 412 | |||
| 413 | pokeball_entry.connection_status.IsConnected.Assign(1); | 431 | pokeball_entry.connection_status.IsConnected.Assign(1); |
| 414 | pokeball_entry.connection_status.IsWired.Assign(1); | 432 | pokeball_entry.connection_status.IsWired.Assign(1); |
| 415 | |||
| 416 | pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; | 433 | pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; |
| 417 | pokeball_entry.pad.l_stick = pad_state.l_stick; | 434 | pokeball_entry.pad.l_stick = pad_state.l_stick; |
| 418 | pokeball_entry.pad.r_stick = pad_state.r_stick; | 435 | pokeball_entry.pad.r_stick = pad_state.r_stick; |
| 419 | break; | 436 | break; |
| 420 | case NPadControllerType::ProController: | ||
| 421 | main_controller.connection_status.raw = 0; | ||
| 422 | |||
| 423 | main_controller.connection_status.IsConnected.Assign(1); | ||
| 424 | main_controller.connection_status.IsWired.Assign(1); | ||
| 425 | main_controller.pad.pad_states.raw = pad_state.pad_states.raw; | ||
| 426 | main_controller.pad.l_stick = pad_state.l_stick; | ||
| 427 | main_controller.pad.r_stick = pad_state.r_stick; | ||
| 428 | break; | ||
| 429 | } | 437 | } |
| 430 | 438 | ||
| 431 | // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate | 439 | // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate |
| @@ -453,26 +461,6 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { | |||
| 453 | supported_npad_id_types.clear(); | 461 | supported_npad_id_types.clear(); |
| 454 | supported_npad_id_types.resize(length / sizeof(u32)); | 462 | supported_npad_id_types.resize(length / sizeof(u32)); |
| 455 | std::memcpy(supported_npad_id_types.data(), data, length); | 463 | std::memcpy(supported_npad_id_types.data(), data, length); |
| 456 | for (std::size_t i = 0; i < connected_controllers.size(); i++) { | ||
| 457 | auto& controller = connected_controllers[i]; | ||
| 458 | if (!controller.is_connected) { | ||
| 459 | continue; | ||
| 460 | } | ||
| 461 | const auto requested_controller = | ||
| 462 | i <= MAX_NPAD_ID ? MapSettingsTypeToNPad(Settings::values.players[i].type) | ||
| 463 | : NPadControllerType::Handheld; | ||
| 464 | if (!IsControllerSupported(requested_controller)) { | ||
| 465 | const auto is_handheld = requested_controller == NPadControllerType::Handheld; | ||
| 466 | if (is_handheld) { | ||
| 467 | controller.type = NPadControllerType::None; | ||
| 468 | controller.is_connected = false; | ||
| 469 | AddNewController(requested_controller); | ||
| 470 | } else { | ||
| 471 | controller.type = requested_controller; | ||
| 472 | InitNewlyAddedControler(i); | ||
| 473 | } | ||
| 474 | } | ||
| 475 | } | ||
| 476 | } | 464 | } |
| 477 | 465 | ||
| 478 | void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { | 466 | void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { |
| @@ -504,7 +492,7 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, | |||
| 504 | const std::vector<Vibration>& vibrations) { | 492 | const std::vector<Vibration>& vibrations) { |
| 505 | LOG_DEBUG(Service_HID, "(STUBBED) called"); | 493 | LOG_DEBUG(Service_HID, "(STUBBED) called"); |
| 506 | 494 | ||
| 507 | if (!can_controllers_vibrate) { | 495 | if (!Settings::values.vibration_enabled || !can_controllers_vibrate) { |
| 508 | return; | 496 | return; |
| 509 | } | 497 | } |
| 510 | for (std::size_t i = 0; i < controller_ids.size(); i++) { | 498 | for (std::size_t i = 0; i < controller_ids.size(); i++) { |
| @@ -517,8 +505,6 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, | |||
| 517 | } | 505 | } |
| 518 | 506 | ||
| 519 | std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { | 507 | std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { |
| 520 | // TODO(ogniK): Figure out the best time to signal this event. This event seems that it should | ||
| 521 | // be signalled at least once, and signaled after a new controller is connected? | ||
| 522 | const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; | 508 | const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)]; |
| 523 | return styleset_event.readable; | 509 | return styleset_event.readable; |
| 524 | } | 510 | } |
| @@ -527,43 +513,43 @@ Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { | |||
| 527 | return last_processed_vibration; | 513 | return last_processed_vibration; |
| 528 | } | 514 | } |
| 529 | 515 | ||
| 530 | void Controller_NPad::AddNewController(NPadControllerType controller) { | 516 | void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) { |
| 531 | controller = DecideBestController(controller); | 517 | UpdateControllerAt(controller, npad_index, true); |
| 532 | if (controller == NPadControllerType::Handheld) { | 518 | } |
| 533 | connected_controllers[8] = {controller, true}; | 519 | |
| 534 | InitNewlyAddedControler(8); | 520 | void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, |
| 535 | return; | 521 | bool connected) { |
| 536 | } | 522 | if (!connected) { |
| 537 | const auto pos = | 523 | DisconnectNPad(IndexToNPad(npad_index)); |
| 538 | std::find_if(connected_controllers.begin(), connected_controllers.end() - 2, | ||
| 539 | [](const ControllerHolder& holder) { return !holder.is_connected; }); | ||
| 540 | if (pos == connected_controllers.end() - 2) { | ||
| 541 | LOG_ERROR(Service_HID, "Cannot connect any more controllers!"); | ||
| 542 | return; | 524 | return; |
| 543 | } | 525 | } |
| 544 | const auto controller_id = std::distance(connected_controllers.begin(), pos); | ||
| 545 | connected_controllers[controller_id] = {controller, true}; | ||
| 546 | InitNewlyAddedControler(controller_id); | ||
| 547 | } | ||
| 548 | 526 | ||
| 549 | void Controller_NPad::AddNewControllerAt(NPadControllerType controller, u32 npad_id) { | ||
| 550 | controller = DecideBestController(controller); | ||
| 551 | if (controller == NPadControllerType::Handheld) { | 527 | if (controller == NPadControllerType::Handheld) { |
| 552 | connected_controllers[NPadIdToIndex(NPAD_HANDHELD)] = {controller, true}; | 528 | Settings::values.players[HANDHELD_INDEX].controller_type = |
| 553 | InitNewlyAddedControler(NPadIdToIndex(NPAD_HANDHELD)); | 529 | MapNPadToSettingsType(controller); |
| 530 | Settings::values.players[HANDHELD_INDEX].connected = true; | ||
| 531 | connected_controllers[HANDHELD_INDEX] = {controller, true}; | ||
| 532 | InitNewlyAddedController(HANDHELD_INDEX); | ||
| 554 | return; | 533 | return; |
| 555 | } | 534 | } |
| 556 | 535 | ||
| 557 | connected_controllers[NPadIdToIndex(npad_id)] = {controller, true}; | 536 | Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller); |
| 558 | InitNewlyAddedControler(NPadIdToIndex(npad_id)); | 537 | Settings::values.players[npad_index].connected = true; |
| 559 | } | 538 | connected_controllers[npad_index] = {controller, true}; |
| 560 | 539 | InitNewlyAddedController(npad_index); | |
| 561 | void Controller_NPad::ConnectNPad(u32 npad_id) { | ||
| 562 | connected_controllers[NPadIdToIndex(npad_id)].is_connected = true; | ||
| 563 | } | 540 | } |
| 564 | 541 | ||
| 565 | void Controller_NPad::DisconnectNPad(u32 npad_id) { | 542 | void Controller_NPad::DisconnectNPad(u32 npad_id) { |
| 566 | connected_controllers[NPadIdToIndex(npad_id)].is_connected = false; | 543 | const auto npad_index = NPadIdToIndex(npad_id); |
| 544 | connected_controllers[npad_index].is_connected = false; | ||
| 545 | Settings::values.players[npad_index].connected = false; | ||
| 546 | |||
| 547 | auto& controller = shared_memory_entries[npad_index]; | ||
| 548 | controller.joy_styles.raw = 0; // Zero out | ||
| 549 | controller.device_type.raw = 0; | ||
| 550 | controller.properties.raw = 0; | ||
| 551 | |||
| 552 | styleset_changed_events[npad_index].writable->Signal(); | ||
| 567 | } | 553 | } |
| 568 | 554 | ||
| 569 | void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { | 555 | void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { |
| @@ -599,8 +585,8 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) { | |||
| 599 | 585 | ||
| 600 | std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type); | 586 | std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type); |
| 601 | 587 | ||
| 602 | InitNewlyAddedControler(npad_index_1); | 588 | AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1); |
| 603 | InitNewlyAddedControler(npad_index_2); | 589 | AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2); |
| 604 | 590 | ||
| 605 | return true; | 591 | return true; |
| 606 | } | 592 | } |
| @@ -628,7 +614,6 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { | |||
| 628 | case 7: | 614 | case 7: |
| 629 | return LedPattern{0, 1, 1, 0}; | 615 | return LedPattern{0, 1, 1, 0}; |
| 630 | default: | 616 | default: |
| 631 | UNIMPLEMENTED_MSG("Unhandled npad_id {}", npad_id); | ||
| 632 | return LedPattern{0, 0, 0, 0}; | 617 | return LedPattern{0, 0, 0, 0}; |
| 633 | } | 618 | } |
| 634 | } | 619 | } |
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 5d4c58a43..75ce5b731 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -118,10 +118,11 @@ public: | |||
| 118 | std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; | 118 | std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; |
| 119 | Vibration GetLastVibration() const; | 119 | Vibration GetLastVibration() const; |
| 120 | 120 | ||
| 121 | void AddNewController(NPadControllerType controller); | 121 | // Adds a new controller at an index. |
| 122 | void AddNewControllerAt(NPadControllerType controller, u32 npad_id); | 122 | void AddNewControllerAt(NPadControllerType controller, std::size_t npad_index); |
| 123 | // Adds a new controller at an index with connection status. | ||
| 124 | void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); | ||
| 123 | 125 | ||
| 124 | void ConnectNPad(u32 npad_id); | ||
| 125 | void DisconnectNPad(u32 npad_id); | 126 | void DisconnectNPad(u32 npad_id); |
| 126 | void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); | 127 | void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); |
| 127 | GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; | 128 | GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; |
| @@ -141,6 +142,8 @@ public: | |||
| 141 | // Specifically for cheat engine and other features. | 142 | // Specifically for cheat engine and other features. |
| 142 | u32 GetAndResetPressState(); | 143 | u32 GetAndResetPressState(); |
| 143 | 144 | ||
| 145 | static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type); | ||
| 146 | static Settings::ControllerType MapNPadToSettingsType(Controller_NPad::NPadControllerType type); | ||
| 144 | static std::size_t NPadIdToIndex(u32 npad_id); | 147 | static std::size_t NPadIdToIndex(u32 npad_id); |
| 145 | static u32 IndexToNPad(std::size_t index); | 148 | static u32 IndexToNPad(std::size_t index); |
| 146 | 149 | ||
| @@ -309,7 +312,7 @@ private: | |||
| 309 | bool is_connected; | 312 | bool is_connected; |
| 310 | }; | 313 | }; |
| 311 | 314 | ||
| 312 | void InitNewlyAddedControler(std::size_t controller_idx); | 315 | void InitNewlyAddedController(std::size_t controller_idx); |
| 313 | bool IsControllerSupported(NPadControllerType controller) const; | 316 | bool IsControllerSupported(NPadControllerType controller) const; |
| 314 | NPadControllerType DecideBestController(NPadControllerType priority) const; | 317 | NPadControllerType DecideBestController(NPadControllerType priority) const; |
| 315 | void RequestPadStateUpdate(u32 npad_id); | 318 | void RequestPadStateUpdate(u32 npad_id); |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 1e95b7580..33416b5dd 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -38,11 +38,9 @@ | |||
| 38 | namespace Service::HID { | 38 | namespace Service::HID { |
| 39 | 39 | ||
| 40 | // Updating period for each HID device. | 40 | // Updating period for each HID device. |
| 41 | // TODO(ogniK): Find actual polling rate of hid | 41 | // HID is polled every 15ms, this value was derived from |
| 42 | constexpr auto pad_update_ns = std::chrono::nanoseconds{1000000000 / 66}; | 42 | // https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet |
| 43 | [[maybe_unused]] constexpr auto accelerometer_update_ns = | 43 | constexpr auto pad_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.6Hz) |
| 44 | std::chrono::nanoseconds{1000000000 / 100}; | ||
| 45 | [[maybe_unused]] constexpr auto gyroscope_update_ticks = std::chrono::nanoseconds{1000000000 / 100}; | ||
| 46 | constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; | 44 | constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; |
| 47 | 45 | ||
| 48 | IAppletResource::IAppletResource(Core::System& system) | 46 | IAppletResource::IAppletResource(Core::System& system) |
| @@ -845,8 +843,7 @@ void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { | |||
| 845 | void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { | 843 | void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { |
| 846 | IPC::RequestParser rp{ctx}; | 844 | IPC::RequestParser rp{ctx}; |
| 847 | const auto can_vibrate{rp.Pop<bool>()}; | 845 | const auto can_vibrate{rp.Pop<bool>()}; |
| 848 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 846 | Settings::values.vibration_enabled = can_vibrate; |
| 849 | .SetVibrationEnabled(can_vibrate); | ||
| 850 | 847 | ||
| 851 | LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); | 848 | LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); |
| 852 | 849 | ||
| @@ -859,8 +856,7 @@ void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) { | |||
| 859 | 856 | ||
| 860 | IPC::ResponseBuilder rb{ctx, 3}; | 857 | IPC::ResponseBuilder rb{ctx, 3}; |
| 861 | rb.Push(RESULT_SUCCESS); | 858 | rb.Push(RESULT_SUCCESS); |
| 862 | rb.Push( | 859 | rb.Push(Settings::values.vibration_enabled); |
| 863 | applet_resource->GetController<Controller_NPad>(HidController::NPad).IsVibrationEnabled()); | ||
| 864 | } | 860 | } |
| 865 | 861 | ||
| 866 | void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | 862 | void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { |