From cb70e972e3e7db7b5a543e69e5d6db60ab193733 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 1 Feb 2024 20:15:01 -0800 Subject: [PATCH] Added miscellaneous gamepad buttons for additional macro buttons on some controllers --- include/SDL3/SDL_gamepad.h | 5 ++++- src/joystick/SDL_gamepad.c | 18 ++++++++++++------ src/joystick/SDL_joystick_c.h | 3 +++ src/joystick/hidapi/SDL_hidapi_stadia.c | 4 ++-- src/joystick/virtual/SDL_virtualjoystick.c | 20 ++++++++++++++++++++ test/gamepadutils.c | 3 +++ test/testcontroller.c | 6 +++++- 7 files changed, 49 insertions(+), 10 deletions(-) diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h index 035ac9d47..b2eb44589 100644 --- a/include/SDL3/SDL_gamepad.h +++ b/include/SDL3/SDL_gamepad.h @@ -113,12 +113,15 @@ typedef enum SDL_GAMEPAD_BUTTON_DPAD_DOWN, SDL_GAMEPAD_BUTTON_DPAD_LEFT, SDL_GAMEPAD_BUTTON_DPAD_RIGHT, - SDL_GAMEPAD_BUTTON_MISC1, /* Additional button (e.g. Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button) */ + SDL_GAMEPAD_BUTTON_MISC1, /* Additional button (e.g. Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button, Google Stadia capture button) */ SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, /* Upper or primary paddle, under your right hand (e.g. Xbox Elite paddle P1) */ SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, /* Upper or primary paddle, under your left hand (e.g. Xbox Elite paddle P3) */ SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, /* Lower or secondary paddle, under your right hand (e.g. Xbox Elite paddle P2) */ SDL_GAMEPAD_BUTTON_LEFT_PADDLE2, /* Lower or secondary paddle, under your left hand (e.g. Xbox Elite paddle P4) */ SDL_GAMEPAD_BUTTON_TOUCHPAD, /* PS4/PS5 touchpad button */ + SDL_GAMEPAD_BUTTON_MISC2, /* Additional button */ + SDL_GAMEPAD_BUTTON_MISC3, /* Additional button */ + SDL_GAMEPAD_BUTTON_MISC4, /* Additional button */ SDL_GAMEPAD_BUTTON_MAX } SDL_GamepadButton; diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index c699dbc9c..02c422151 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -790,14 +790,14 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_JoystickGUID guid SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string)); } else if (SDL_IsJoystickGoogleStadiaController(vendor, product)) { /* The Google Stadia controller has a share button and a Google Assistant button */ - SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string)); + SDL_strlcat(mapping_string, "misc1:b11,misc2:b12", sizeof(mapping_string)); } else if (SDL_IsJoystickNVIDIASHIELDController(vendor, product)) { /* The NVIDIA SHIELD controller has a share button between back and start buttons */ SDL_strlcat(mapping_string, "misc1:b11,", sizeof(mapping_string)); if (product == USB_PRODUCT_NVIDIA_SHIELD_CONTROLLER_V103) { - /* The original SHIELD controller has a touchpad as well */ - SDL_strlcat(mapping_string, "touchpad:b12,", sizeof(mapping_string)); + /* The original SHIELD controller has a touchpad and plus/minus buttons as well */ + SDL_strlcat(mapping_string, "touchpad:b12,misc2:b13,misc3:b14", sizeof(mapping_string)); } } else if (SDL_IsJoystickPS4(vendor, product)) { /* PS4 controllers have an additional touchpad button */ @@ -805,7 +805,7 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_JoystickGUID guid } else if (SDL_IsJoystickPS5(vendor, product)) { /* PS5 controllers have a microphone button and an additional touchpad button */ SDL_strlcat(mapping_string, "touchpad:b11,misc1:b12,", sizeof(mapping_string)); - /* DualSense Edge controllers have paddles */ + /* DualSense Edge controllers have paddles and a microphone button */ if (SDL_IsJoystickDualSenseEdge(vendor, product)) { SDL_strlcat(mapping_string, "paddle1:b16,paddle2:b15,paddle3:b14,paddle4:b13,", sizeof(mapping_string)); } @@ -1085,7 +1085,10 @@ static const char *map_StringForGamepadButton[] = { "paddle2", "paddle3", "paddle4", - "touchpad" + "touchpad", + "misc2", + "misc3", + "misc4" }; SDL_COMPILE_TIME_ASSERT(map_StringForGamepadButton, SDL_arraysize(map_StringForGamepadButton) == SDL_GAMEPAD_BUTTON_MAX); @@ -1518,7 +1521,7 @@ static char *SDL_PrivateGetGamepadMappingFromMappingString(const char *pMapping) /* Trim whitespace */ length = SDL_strlen(result); - while (SDL_isspace(result[length - 1])) { + while (length > 0 && SDL_isspace(result[length - 1])) { --length; } result[length] = '\0'; @@ -1751,6 +1754,9 @@ static GamepadMapping_t *SDL_PrivateGenerateAutomaticGamepadMapping(const char * SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "dpleft", &raw_map->dpleft); SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "dpright", &raw_map->dpright); SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "misc1", &raw_map->misc1); + SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "misc2", &raw_map->misc2); + SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "misc3", &raw_map->misc3); + SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "misc4", &raw_map->misc4); /* Keep using paddle1-4 in the generated mapping so that it can be * reused with SDL2 */ SDL_PrivateAppendToMappingString(mapping, sizeof(mapping), "paddle1", &raw_map->right_paddle1); diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 95ab4f71e..14fe0ce72 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -212,6 +212,9 @@ typedef struct SDL_GamepadMapping SDL_InputMapping dpleft; SDL_InputMapping dpright; SDL_InputMapping misc1; + SDL_InputMapping misc2; + SDL_InputMapping misc3; + SDL_InputMapping misc4; SDL_InputMapping right_paddle1; SDL_InputMapping left_paddle1; SDL_InputMapping right_paddle2; diff --git a/src/joystick/hidapi/SDL_hidapi_stadia.c b/src/joystick/hidapi/SDL_hidapi_stadia.c index 0d7dd83f0..5f284b209 100644 --- a/src/joystick/hidapi/SDL_hidapi_stadia.c +++ b/src/joystick/hidapi/SDL_hidapi_stadia.c @@ -33,7 +33,7 @@ enum { - SDL_GAMEPAD_BUTTON_STADIA_SHARE = 11, + SDL_GAMEPAD_BUTTON_STADIA_CAPTURE = 11, SDL_GAMEPAD_BUTTON_STADIA_GOOGLE_ASSISTANT, SDL_GAMEPAD_NUM_STADIA_BUTTONS, }; @@ -218,7 +218,7 @@ static void HIDAPI_DriverStadia_HandleStatePacket(SDL_Joystick *joystick, SDL_Dr SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, (data[2] & 0x10) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, (data[2] & 0x20) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, (data[2] & 0x80) ? SDL_PRESSED : SDL_RELEASED); - SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STADIA_SHARE, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED); + SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STADIA_CAPTURE, (data[2] & 0x01) ? SDL_PRESSED : SDL_RELEASED); SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STADIA_GOOGLE_ASSISTANT, (data[2] & 0x02) ? SDL_PRESSED : SDL_RELEASED); } diff --git a/src/joystick/virtual/SDL_virtualjoystick.c b/src/joystick/virtual/SDL_virtualjoystick.c index d756f368d..80177fbdb 100644 --- a/src/joystick/virtual/SDL_virtualjoystick.c +++ b/src/joystick/virtual/SDL_virtualjoystick.c @@ -682,6 +682,26 @@ static SDL_bool VIRTUAL_JoystickGetGamepadMapping(int device_index, SDL_GamepadM out->left_paddle2.target = current_button++; } + if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_TOUCHPAD))) { + out->touchpad.kind = EMappingKind_Button; + out->touchpad.target = current_button++; + } + + if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_MISC2))) { + out->misc2.kind = EMappingKind_Button; + out->misc2.target = current_button++; + } + + if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_MISC3))) { + out->misc3.kind = EMappingKind_Button; + out->misc3.target = current_button++; + } + + if (current_button < hwdata->desc.nbuttons && (hwdata->desc.button_mask & (1 << SDL_GAMEPAD_BUTTON_MISC4))) { + out->misc4.kind = EMappingKind_Button; + out->misc4.target = current_button++; + } + if (current_axis < hwdata->desc.naxes && (hwdata->desc.axis_mask & (1 << SDL_GAMEPAD_AXIS_LEFTX))) { out->leftx.kind = EMappingKind_Axis; out->leftx.target = current_axis++; diff --git a/test/gamepadutils.c b/test/gamepadutils.c index 656c9970a..43b98aeb2 100644 --- a/test/gamepadutils.c +++ b/test/gamepadutils.c @@ -649,6 +649,9 @@ static const char *gamepad_button_names[] = { "Right Paddle 2", "Left Paddle 2", "Touchpad", + "Misc2", + "Misc3", + "Misc4", }; SDL_COMPILE_TIME_ASSERT(gamepad_button_names, SDL_arraysize(gamepad_button_names) == SDL_GAMEPAD_BUTTON_MAX); diff --git a/test/testcontroller.c b/test/testcontroller.c index 16908afbb..ab695b0ff 100644 --- a/test/testcontroller.c +++ b/test/testcontroller.c @@ -35,7 +35,7 @@ #define BUTTON_MARGIN 16 #define BUTTON_PADDING 12 #define GAMEPAD_WIDTH 512 -#define GAMEPAD_HEIGHT 480 +#define GAMEPAD_HEIGHT 560 #define SCREEN_WIDTH (PANEL_WIDTH + PANEL_SPACING + GAMEPAD_WIDTH + PANEL_SPACING + PANEL_WIDTH) #define SCREEN_HEIGHT (TITLE_HEIGHT + GAMEPAD_HEIGHT) @@ -782,6 +782,10 @@ static const char *GetBindingInstruction(void) return "Press the lower paddle under your left hand"; case SDL_GAMEPAD_BUTTON_TOUCHPAD: return "Press down on the touchpad"; + case SDL_GAMEPAD_BUTTON_MISC2: + case SDL_GAMEPAD_BUTTON_MISC3: + case SDL_GAMEPAD_BUTTON_MISC4: + return "Press any additional button not already bound"; case SDL_GAMEPAD_ELEMENT_AXIS_LEFTX_NEGATIVE: return "Move the left thumbstick to the left"; case SDL_GAMEPAD_ELEMENT_AXIS_LEFTX_POSITIVE: