diff options
Diffstat (limited to 'src/input_common/gcadapter/gc_adapter.cpp')
| -rw-r--r-- | src/input_common/gcadapter/gc_adapter.cpp | 134 |
1 files changed, 116 insertions, 18 deletions
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp index 74759ea7d..c95feb0d7 100644 --- a/src/input_common/gcadapter/gc_adapter.cpp +++ b/src/input_common/gcadapter/gc_adapter.cpp | |||
| @@ -4,13 +4,24 @@ | |||
| 4 | 4 | ||
| 5 | #include <chrono> | 5 | #include <chrono> |
| 6 | #include <thread> | 6 | #include <thread> |
| 7 | |||
| 8 | #ifdef _MSC_VER | ||
| 9 | #pragma warning(push) | ||
| 10 | #pragma warning(disable : 4200) // nonstandard extension used : zero-sized array in struct/union | ||
| 11 | #endif | ||
| 7 | #include <libusb.h> | 12 | #include <libusb.h> |
| 13 | #ifdef _MSC_VER | ||
| 14 | #pragma warning(pop) | ||
| 15 | #endif | ||
| 16 | |||
| 8 | #include "common/logging/log.h" | 17 | #include "common/logging/log.h" |
| 18 | #include "common/param_package.h" | ||
| 9 | #include "input_common/gcadapter/gc_adapter.h" | 19 | #include "input_common/gcadapter/gc_adapter.h" |
| 20 | #include "input_common/settings.h" | ||
| 10 | 21 | ||
| 11 | namespace GCAdapter { | 22 | namespace GCAdapter { |
| 12 | 23 | ||
| 13 | /// Used to loop through and assign button in poller | 24 | // Used to loop through and assign button in poller |
| 14 | constexpr std::array<PadButton, 12> PadButtonArray{ | 25 | constexpr std::array<PadButton, 12> PadButtonArray{ |
| 15 | PadButton::PAD_BUTTON_LEFT, PadButton::PAD_BUTTON_RIGHT, PadButton::PAD_BUTTON_DOWN, | 26 | PadButton::PAD_BUTTON_LEFT, PadButton::PAD_BUTTON_RIGHT, PadButton::PAD_BUTTON_DOWN, |
| 16 | PadButton::PAD_BUTTON_UP, PadButton::PAD_TRIGGER_Z, PadButton::PAD_TRIGGER_R, | 27 | PadButton::PAD_BUTTON_UP, PadButton::PAD_TRIGGER_Z, PadButton::PAD_TRIGGER_R, |
| @@ -18,6 +29,18 @@ constexpr std::array<PadButton, 12> PadButtonArray{ | |||
| 18 | PadButton::PAD_BUTTON_X, PadButton::PAD_BUTTON_Y, PadButton::PAD_BUTTON_START, | 29 | PadButton::PAD_BUTTON_X, PadButton::PAD_BUTTON_Y, PadButton::PAD_BUTTON_START, |
| 19 | }; | 30 | }; |
| 20 | 31 | ||
| 32 | static void PadToState(const GCPadStatus& pad, GCState& out_state) { | ||
| 33 | for (const auto& button : PadButtonArray) { | ||
| 34 | const auto button_key = static_cast<u16>(button); | ||
| 35 | const auto button_value = (pad.button & button_key) != 0; | ||
| 36 | out_state.buttons.insert_or_assign(static_cast<s32>(button_key), button_value); | ||
| 37 | } | ||
| 38 | |||
| 39 | for (std::size_t i = 0; i < pad.axis_values.size(); ++i) { | ||
| 40 | out_state.axes.insert_or_assign(static_cast<u32>(i), pad.axis_values[i]); | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 21 | Adapter::Adapter() { | 44 | Adapter::Adapter() { |
| 22 | if (usb_adapter_handle != nullptr) { | 45 | if (usb_adapter_handle != nullptr) { |
| 23 | return; | 46 | return; |
| @@ -67,17 +90,17 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad | |||
| 67 | 90 | ||
| 68 | for (std::size_t i = 0; i < b1_buttons.size(); ++i) { | 91 | for (std::size_t i = 0; i < b1_buttons.size(); ++i) { |
| 69 | if ((b1 & (1U << i)) != 0) { | 92 | if ((b1 & (1U << i)) != 0) { |
| 70 | pad.button |= static_cast<u16>(b1_buttons[i]); | 93 | pad.button = static_cast<u16>(pad.button | static_cast<u16>(b1_buttons[i])); |
| 71 | } | 94 | } |
| 72 | } | 95 | } |
| 73 | 96 | ||
| 74 | for (std::size_t j = 0; j < b2_buttons.size(); ++j) { | 97 | for (std::size_t j = 0; j < b2_buttons.size(); ++j) { |
| 75 | if ((b2 & (1U << j)) != 0) { | 98 | if ((b2 & (1U << j)) != 0) { |
| 76 | pad.button |= static_cast<u16>(b2_buttons[j]); | 99 | pad.button = static_cast<u16>(pad.button | static_cast<u16>(b2_buttons[j])); |
| 77 | } | 100 | } |
| 78 | } | 101 | } |
| 79 | for (PadAxes axis : axes) { | 102 | for (PadAxes axis : axes) { |
| 80 | const std::size_t index = static_cast<std::size_t>(axis); | 103 | const auto index = static_cast<std::size_t>(axis); |
| 81 | pad.axis_values[index] = adapter_payload[offset + 3 + index]; | 104 | pad.axis_values[index] = adapter_payload[offset + 3 + index]; |
| 82 | } | 105 | } |
| 83 | 106 | ||
| @@ -89,17 +112,6 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad | |||
| 89 | return pad; | 112 | return pad; |
| 90 | } | 113 | } |
| 91 | 114 | ||
| 92 | void Adapter::PadToState(const GCPadStatus& pad, GCState& state) { | ||
| 93 | for (const auto& button : PadButtonArray) { | ||
| 94 | const u16 button_value = static_cast<u16>(button); | ||
| 95 | state.buttons.insert_or_assign(button_value, pad.button & button_value); | ||
| 96 | } | ||
| 97 | |||
| 98 | for (size_t i = 0; i < pad.axis_values.size(); ++i) { | ||
| 99 | state.axes.insert_or_assign(static_cast<u8>(i), pad.axis_values[i]); | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | void Adapter::Read() { | 115 | void Adapter::Read() { |
| 104 | LOG_DEBUG(Input, "GC Adapter Read() thread started"); | 116 | LOG_DEBUG(Input, "GC Adapter Read() thread started"); |
| 105 | 117 | ||
| @@ -239,7 +251,7 @@ void Adapter::GetGCEndpoint(libusb_device* device) { | |||
| 239 | const libusb_interface_descriptor* interface = &interfaceContainer->altsetting[i]; | 251 | const libusb_interface_descriptor* interface = &interfaceContainer->altsetting[i]; |
| 240 | for (u8 e = 0; e < interface->bNumEndpoints; e++) { | 252 | for (u8 e = 0; e < interface->bNumEndpoints; e++) { |
| 241 | const libusb_endpoint_descriptor* endpoint = &interface->endpoint[e]; | 253 | const libusb_endpoint_descriptor* endpoint = &interface->endpoint[e]; |
| 242 | if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) { | 254 | if ((endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) != 0) { |
| 243 | input_endpoint = endpoint->bEndpointAddress; | 255 | input_endpoint = endpoint->bEndpointAddress; |
| 244 | } else { | 256 | } else { |
| 245 | output_endpoint = endpoint->bEndpointAddress; | 257 | output_endpoint = endpoint->bEndpointAddress; |
| @@ -283,7 +295,93 @@ void Adapter::Reset() { | |||
| 283 | } | 295 | } |
| 284 | } | 296 | } |
| 285 | 297 | ||
| 286 | bool Adapter::DeviceConnected(std::size_t port) { | 298 | std::vector<Common::ParamPackage> Adapter::GetInputDevices() const { |
| 299 | std::vector<Common::ParamPackage> devices; | ||
| 300 | for (std::size_t port = 0; port < state.size(); ++port) { | ||
| 301 | if (!DeviceConnected(port)) { | ||
| 302 | continue; | ||
| 303 | } | ||
| 304 | std::string name = fmt::format("Gamecube Controller {}", port); | ||
| 305 | devices.emplace_back(Common::ParamPackage{ | ||
| 306 | {"class", "gcpad"}, | ||
| 307 | {"display", std::move(name)}, | ||
| 308 | {"port", std::to_string(port)}, | ||
| 309 | }); | ||
| 310 | } | ||
| 311 | return devices; | ||
| 312 | } | ||
| 313 | |||
| 314 | InputCommon::ButtonMapping Adapter::GetButtonMappingForDevice( | ||
| 315 | const Common::ParamPackage& params) const { | ||
| 316 | // This list is missing ZL/ZR since those are not considered buttons. | ||
| 317 | // We will add those afterwards | ||
| 318 | // This list also excludes any button that can't be really mapped | ||
| 319 | static constexpr std::array<std::pair<Settings::NativeButton::Values, PadButton>, 12> | ||
| 320 | switch_to_gcadapter_button = { | ||
| 321 | std::pair{Settings::NativeButton::A, PadButton::PAD_BUTTON_A}, | ||
| 322 | {Settings::NativeButton::B, PadButton::PAD_BUTTON_B}, | ||
| 323 | {Settings::NativeButton::X, PadButton::PAD_BUTTON_X}, | ||
| 324 | {Settings::NativeButton::Y, PadButton::PAD_BUTTON_Y}, | ||
| 325 | {Settings::NativeButton::Plus, PadButton::PAD_BUTTON_START}, | ||
| 326 | {Settings::NativeButton::DLeft, PadButton::PAD_BUTTON_LEFT}, | ||
| 327 | {Settings::NativeButton::DUp, PadButton::PAD_BUTTON_UP}, | ||
| 328 | {Settings::NativeButton::DRight, PadButton::PAD_BUTTON_RIGHT}, | ||
| 329 | {Settings::NativeButton::DDown, PadButton::PAD_BUTTON_DOWN}, | ||
| 330 | {Settings::NativeButton::SL, PadButton::PAD_TRIGGER_L}, | ||
| 331 | {Settings::NativeButton::SR, PadButton::PAD_TRIGGER_R}, | ||
| 332 | {Settings::NativeButton::R, PadButton::PAD_TRIGGER_Z}, | ||
| 333 | }; | ||
| 334 | if (!params.Has("port")) { | ||
| 335 | return {}; | ||
| 336 | } | ||
| 337 | |||
| 338 | InputCommon::ButtonMapping mapping{}; | ||
| 339 | for (const auto& [switch_button, gcadapter_button] : switch_to_gcadapter_button) { | ||
| 340 | Common::ParamPackage button_params({{"engine", "gcpad"}}); | ||
| 341 | button_params.Set("port", params.Get("port", 0)); | ||
| 342 | button_params.Set("button", static_cast<int>(gcadapter_button)); | ||
| 343 | mapping.insert_or_assign(switch_button, std::move(button_params)); | ||
| 344 | } | ||
| 345 | |||
| 346 | // Add the missing bindings for ZL/ZR | ||
| 347 | static constexpr std::array<std::pair<Settings::NativeButton::Values, PadAxes>, 2> | ||
| 348 | switch_to_gcadapter_axis = { | ||
| 349 | std::pair{Settings::NativeButton::ZL, PadAxes::TriggerLeft}, | ||
| 350 | {Settings::NativeButton::ZR, PadAxes::TriggerRight}, | ||
| 351 | }; | ||
| 352 | for (const auto& [switch_button, gcadapter_axis] : switch_to_gcadapter_axis) { | ||
| 353 | Common::ParamPackage button_params({{"engine", "gcpad"}}); | ||
| 354 | button_params.Set("port", params.Get("port", 0)); | ||
| 355 | button_params.Set("button", static_cast<int>(PadButton::PAD_STICK)); | ||
| 356 | button_params.Set("axis", static_cast<int>(gcadapter_axis)); | ||
| 357 | mapping.insert_or_assign(switch_button, std::move(button_params)); | ||
| 358 | } | ||
| 359 | return mapping; | ||
| 360 | } | ||
| 361 | |||
| 362 | InputCommon::AnalogMapping Adapter::GetAnalogMappingForDevice( | ||
| 363 | const Common::ParamPackage& params) const { | ||
| 364 | if (!params.Has("port")) { | ||
| 365 | return {}; | ||
| 366 | } | ||
| 367 | |||
| 368 | InputCommon::AnalogMapping mapping = {}; | ||
| 369 | Common::ParamPackage left_analog_params; | ||
| 370 | left_analog_params.Set("engine", "gcpad"); | ||
| 371 | left_analog_params.Set("port", params.Get("port", 0)); | ||
| 372 | left_analog_params.Set("axis_x", static_cast<int>(PadAxes::StickX)); | ||
| 373 | left_analog_params.Set("axis_y", static_cast<int>(PadAxes::StickY)); | ||
| 374 | mapping.insert_or_assign(Settings::NativeAnalog::LStick, std::move(left_analog_params)); | ||
| 375 | Common::ParamPackage right_analog_params; | ||
| 376 | right_analog_params.Set("engine", "gcpad"); | ||
| 377 | right_analog_params.Set("port", params.Get("port", 0)); | ||
| 378 | right_analog_params.Set("axis_x", static_cast<int>(PadAxes::SubstickX)); | ||
| 379 | right_analog_params.Set("axis_y", static_cast<int>(PadAxes::SubstickY)); | ||
| 380 | mapping.insert_or_assign(Settings::NativeAnalog::RStick, std::move(right_analog_params)); | ||
| 381 | return mapping; | ||
| 382 | } | ||
| 383 | |||
| 384 | bool Adapter::DeviceConnected(std::size_t port) const { | ||
| 287 | return adapter_controllers_status[port] != ControllerTypes::None; | 385 | return adapter_controllers_status[port] != ControllerTypes::None; |
| 288 | } | 386 | } |
| 289 | 387 | ||
| @@ -322,7 +420,7 @@ const std::array<GCState, 4>& Adapter::GetPadState() const { | |||
| 322 | return state; | 420 | return state; |
| 323 | } | 421 | } |
| 324 | 422 | ||
| 325 | int Adapter::GetOriginValue(int port, int axis) const { | 423 | int Adapter::GetOriginValue(u32 port, u32 axis) const { |
| 326 | return origin_status[port].axis_values[axis]; | 424 | return origin_status[port].axis_values[axis]; |
| 327 | } | 425 | } |
| 328 | 426 | ||