summaryrefslogtreecommitdiff
path: root/src/input_common/gcadapter/gc_adapter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/gcadapter/gc_adapter.cpp')
-rw-r--r--src/input_common/gcadapter/gc_adapter.cpp134
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
11namespace GCAdapter { 22namespace GCAdapter {
12 23
13/// Used to loop through and assign button in poller 24// Used to loop through and assign button in poller
14constexpr std::array<PadButton, 12> PadButtonArray{ 25constexpr 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
32static 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
21Adapter::Adapter() { 44Adapter::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
92void 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
103void Adapter::Read() { 115void 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
286bool Adapter::DeviceConnected(std::size_t port) { 298std::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
314InputCommon::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
362InputCommon::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
384bool 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
325int Adapter::GetOriginValue(int port, int axis) const { 423int 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