Skip to content

New gamepad types, and "type:" db field - #15970

Open
nstbayless wants to merge 9 commits into
libsdl-org:mainfrom
nstbayless:new-gamepad-types-take-2
Open

New gamepad types, and "type:" db field#15970
nstbayless wants to merge 9 commits into
libsdl-org:mainfrom
nstbayless:new-gamepad-types-take-2

Conversation

@nstbayless

@nstbayless nstbayless commented Jul 10, 2026

Copy link
Copy Markdown
  • I confirm that I am the author of this code and release it to the SDL project under the Zlib license. This contribution does not contain code from other sources, including code generated by a Large Language Model ("AI").

The gamepad db lacks a good way to actually indicate the gamepad's type (e.g. switchpro, ps5, ...). With this PR, it's now part of the db format (e.g. type:switchpro). If type: is omitted it will still use the same checks as before to determine the type.

Changes

The database parsing remains backward-compatible -- the (confusingly-named) USE_BUTTON_LABELS hint is still respected. However, I removed support for face: since it seems like these were not documented nor used anywhere, not even in the larger SDL gamepad db, except essentially as a private way for SInput controllers to squeeze some additional info through the db string. (SInput now uses the new type: field instead for that information.)

Also adds these gamepad types: n64, wii, and genesis. These are common but very different kinds of gamepads to anything else in the list, so I think it's important they have their own label.

This is part of a longer effort to make it easier for application developers to implement standardized support for button labels and confirm/cancel/etc/actions easier, which vary from gamepad to gamepad.

Existing Issue(s)

@nstbayless nstbayless changed the title New gamepad types New gamepad types, and "type:" db field Jul 10, 2026
Comment thread src/joystick/SDL_gamepad.c Outdated
Comment thread src/joystick/SDL_gamepad_db.h Outdated
Comment thread src/joystick/SDL_gamepad_db.h
Comment thread src/joystick/SDL_joystick.c Outdated
@nstbayless
nstbayless force-pushed the new-gamepad-types-take-2 branch from 72bd319 to 286513f Compare July 11, 2026 17:32
@nstbayless

nstbayless commented Jul 11, 2026

Copy link
Copy Markdown
Author
  • Added comments explaining that the gamepad types have certain minimum requirements
  • restored hint: to the db entries that used them
  • SInput now falls back to SNES or NES if it doesn't meet the requirements for switch pro
  • No such system for SInput gamecube and sony yet... do we really need one though? How likely is it for a SInput gamepad to report gamecube button layout but not have all gamecube features?

If we're concerned about sony-labelled gamepads which don't satisfy the minimum requirements for any specific playstation gamepads, I'm thinking it might be sensible to add hint:USE_SONY_LABELS to the db entries for such sinput devices.

@slouken

slouken commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator
  • Added comments explaining that the gamepad types have certain minimum requirements
  • restored hint: to the db entries that used them
  • SInput now falls back to SNES or NES if it doesn't meet the requirements for switch pro
  • No such system for SInput gamecube and sony yet... do we really need one though? How likely is it for a SInput gamepad to report gamecube button layout but not have all gamecube features?

I have an SInput gamepad that is gamecube form factor, but it has all the features.

If we're concerned about sony-labelled gamepads which don't satisfy the minimum requirements for any specific playstation gamepads, I'm thinking it might be sensible to add hint:USE_SONY_LABELS to the db entries for such sinput devices.

That was what the face enumeration was for. :)

@nstbayless

Copy link
Copy Markdown
Author

I have an SInput gamepad that is gamecube form factor, but it has all the features.

I was wondering about controllers which are missing features.

That was what the face enumeration was for. :)

The problem with this is that it doesn't feed into SDL_GetGamepadButtonLabelForType, which takes only the gamepad type as an argument. I can restore the "face:" entry in the db for SInput controllers, but it won't actually affect how SDL determines face button labels.

@slouken

slouken commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

The problem with this is that it doesn't feed into SDL_GetGamepadButtonLabelForType, which takes only the gamepad type as an argument. I can restore the "face:" entry in the db for SInput controllers, but it won't actually affect how SDL determines face button labels.

Yeah, I'm not sure what to do here.

@nstbayless

Copy link
Copy Markdown
Author

I'm not sure what to do here.

I'm leaning toward adding SDL_GAMEPAD_TYPE_STANDARD_SONY and SDL_GAMEPAD_TYPE_STANDARD_AXBY as new gamepad types, which imply nothing about the gamepad except for the face button labels. Maybe SDL_GAMEPAD_TYPE_STANDARD_BAYX too if SDL_GAMEPAD_TYPE_NES would be too weird as the fallback.

The alternative is to say that SDL_GAMEPAD_TYPE_GAMECUBE and SDL_GAMEPAD_TYPE_PS3 or something have no actual minimum requirements and imply only button labels. Maybe for switchpro as well.

@slouken

slouken commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

I'm leaning toward adding SDL_GAMEPAD_TYPE_STANDARD_SONY and SDL_GAMEPAD_TYPE_STANDARD_AXBY as new gamepad types, which imply nothing about the gamepad except for the face button labels.

Yeah, that seems reasonable to me.

@nstbayless

Copy link
Copy Markdown
Author

If at some point we want gamepads to support custom labels, such unusual SInput gamepads could use that system too.

@nstbayless
nstbayless force-pushed the new-gamepad-types-take-2 branch from 286513f to 762b00c Compare July 14, 2026 16:52
@nstbayless
nstbayless force-pushed the new-gamepad-types-take-2 branch from 762b00c to 636f333 Compare July 14, 2026 17:02
@nstbayless

Copy link
Copy Markdown
Author

Added type:sony, type:axby, type:bayx. Ready for a new review now I think.

Comment thread include/SDL3/SDL_gamepad.h
Comment thread include/SDL3/SDL_gamepad.h Outdated
Comment thread include/SDL3/SDL_gamepad.h Outdated
SDL_GAMEPAD_TYPE_GAMECUBE,
SDL_GAMEPAD_TYPE_GAMECUBE, /**< At least A/X/B/Y, d-pad, one bumper, two sticks, two analog triggers, start */
SDL_GAMEPAD_TYPE_STEAM,
SDL_GAMEPAD_TYPE_STANDARD_BAYX, /**< A non-specific gamepad with B/A/Y/X face button layout */

@slouken slouken Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SDL_GAMEPAD_TYPE_STANDARD_BAYX, /**< A non-specific gamepad with B/A/Y/X face button layout */
SDL_GAMEPAD_TYPE_STANDARD_BAYX, /**< A non-specific gamepad with Nintendo Switch Pro style (B/A/Y/X) face button layout */

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could equally say SNES style

Comment thread include/SDL3/SDL_gamepad.h Outdated
Comment thread include/SDL3/SDL_gamepad.h Outdated
Comment thread include/SDL3/SDL_gamepad.h Outdated
Comment on lines +136 to +138
SDL_GAMEPAD_TYPE_N64,
SDL_GAMEPAD_TYPE_WII,
SDL_GAMEPAD_TYPE_SEGA_GENESIS,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Descriptive comments here, similar to above?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Genesis and Wii okay. But N64 doesn't have a clear mapping scheme -- SDL gamepad DB doesn't define one, for example. And the "obvious" thing (map c-stick to right stick) is deficient (doesn't support holding left-C and right-C simultaneously). I'd rather leave this unspecified in this PR for now than risk doing damage by introducing a bad standard here.

Also... it's quite astonishing that Genesis maps L and R to LB and LT respectively instead of to LB and RB. But I guess that can't be fixed at this point.

Comment thread src/joystick/SDL_gamepad.c Outdated
SDL_strlcat(mapping_string, "back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b11,paddle2:b13,paddle4:b15,", sizeof(mapping_string));
SDL_strlcat(mapping_string, "back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b11,paddle2:b13,paddle4:b15,type:joyconleft,", sizeof(mapping_string));
} else {
SDL_strlcat(mapping_string, "a:b0,b:b1,guide:b5,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,paddle1:b12,paddle3:b14,", sizeof(mapping_string));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add the button label hints here? Conceptually this is a way to let older code know that this is BAYX face button layout.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, good point. I forgot that this mapping string might not stay private.

Comment thread src/joystick/SDL_gamepad.c Outdated
if (SDL_IsJoystickSteamController(vendor, product)) {
// Steam controllers have 2 back paddle buttons
SDL_strlcat(mapping_string, "paddle1:b11,paddle2:b12,", sizeof(mapping_string));
SDL_strlcat(mapping_string, "paddle1:b11,paddle2:b12", sizeof(mapping_string));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For historical reasons, the mappings must have a trailing comma.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to add ",type:steam," here?

@nstbayless nstbayless Aug 14, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. But I don't understand what a "steam" controller is. The documentation is unclear. Am I right to assume that it includes steam deck, the original steam controller, and steam controller 2? Even though the original steam controller has a very different layout?

Does "steam" refer to any controller under Steam Input? (I believe underlying controller type is opaque through SI but I could be mistaken.)

Comment thread src/joystick/SDL_gamepad.c
Comment thread src/joystick/SDL_gamepad.c
Comment thread src/joystick/SDL_gamepad.c Outdated
Comment thread src/joystick/SDL_gamepad.c Outdated
case SDL_GAMEPAD_TYPE_NES:
case SDL_GAMEPAD_TYPE_SNES:
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO:
// TODO: confirm joycon label conventions

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that on the Switch, horizontal joycon button labels usually look like this (screenshot from retroarch) rather than actually using "A"/"B" etc.:

image

We can still report this as "A"/"B" for but I'm unsure what the "right" thing to do is.

Comment thread src/joystick/SDL_gamepad.c Outdated
Comment thread src/joystick/SDL_gamepad_db.h Outdated
"030000000d0f00008700000000000000,HORI Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"030000000d0f00006e00000000000000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"030000000d0f00006600000000000000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"030000000d0f00008800000000000000,HORI Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,type:sony,",

@slouken slouken Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically this should be type:ps3 and the one below this is type:ps4, but this is probably fine for arcade sticks.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They don't match the form factor of a PS3/PS4 controller. Well, we can come down on this issue more cleanly in a future PR?

Comment thread src/joystick/SDL_gamepad_db.h Outdated
@@ -877,7 +878,7 @@ static const char *s_GamepadMappings[] = {
"0000000050535669746120436f6e7400,PSVita Controller,crc:d598,a:b2,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b3,y:b0,",
#endif
#ifdef SDL_JOYSTICK_N3DS
"000000004e696e74656e646f20334400,Nintendo 3DS,crc:3210,a:b1,b:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b11,rightx:a2,righty:a3,start:b3,x:b7,y:b6,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"000000004e696e74656e646f20334400,Nintendo 3DS,crc:3210,a:b1,b:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b11,rightx:a2,righty:a3,start:b3,x:b7,y:b6,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,type:bayx",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't gone through this exhaustively, but I assume that you made sure everything using hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1 has some form of BAYX type and every controller with some form of BAYX type has that hint? Also the same for the gamecube hint?

You should be careful, because if there are entries for BAYX controllers without the hint, they may actually be mapping face buttons as ABXY.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that you made sure everything using hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1 has some form of BAYX type and every controller with some form of BAYX type has that hint?

This seems like a job for a unit test that will fail the build if we get this wrong in future?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree.

Comment thread test/gamepadutils.c
@slouken

slouken commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

In general this is looking good. Lots of feedback above. @sezero, can you review once the feedback is addressed?

@sezero

sezero commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

@sezero, can you review

The whole thing is rather alien to me, and I couldn't read it
in entirety, but this change:

-    int version = analogStyle;
-    version = (version * (int)SINPUT_BUMPERSTYLE_MAX) + bumperStyle;
-    version = (version * (int)SINPUT_TRIGGERSTYLE_MAX) + triggerStyle;
-    version = (version * (int)SINPUT_PADDLESTYLE_MAX) + paddleStyle;
-    version = (version * (int)SINPUT_METASTYLE_MAX) + metaStyle;
-    version = (version * (int)SINPUT_TOUCHSTYLE_MAX) + touchStyle;
-    version = (version * (int)SINPUT_MISCSTYLE_MAX) + miscStyle;
+    Uint16 version = SINPUT_PACK_VERSION(miscStyle, touchStyle, metaStyle, paddleStyle, triggerStyle, bumperStyle, analogStyle);

/****/

+/* Pack SInput style values into a single Uint16
+ * (can fit in the version field of the GUID) */
+#define SINPUT_PACK_VERSION(misc, touch, meta, paddle, trigger, bumper, analog) \
+    ((Uint16)(((((((                                                            \
+        (analog)) * SINPUT_BUMPERSTYLE_MAX +                                    \
+        (bumper)) * SINPUT_TRIGGERSTYLE_MAX +                                   \
+        (trigger)) * SINPUT_PADDLESTYLE_MAX +                                   \
+        (paddle)) * SINPUT_METASTYLE_MAX +                                      \
+        (meta)) * SINPUT_TOUCHSTYLE_MAX +                                       \
+        (touch)) * SINPUT_MISCSTYLE_MAX +                                       \
+        (misc)))

... unless I'm missing something, doesn't seem to yield the same vale before:
Intentional, I assume?

nstbayless and others added 2 commits July 14, 2026 14:53
Co-authored-by: Sam Lantinga <slouken@libsdl.org>
Co-authored-by: Sam Lantinga <slouken@libsdl.org>
@nstbayless

Copy link
Copy Markdown
Author

... unless I'm missing something, doesn't seem to yield the same vale before: Intentional, I assume?

I'm not sure I see how it's different.

Comment thread include/SDL3/SDL_gamepad.h Outdated
@nstbayless
nstbayless force-pushed the new-gamepad-types-take-2 branch from ed26da2 to 909c187 Compare August 14, 2026 20:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants