Skip to content

Commit 72bd319

Browse files
committed
New gamepad types
1 parent c1d4376 commit 72bd319

8 files changed

Lines changed: 1016 additions & 679 deletions

File tree

include/SDL3/SDL_gamepad.h

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,15 @@ typedef struct SDL_Gamepad SDL_Gamepad;
103103
* Standard gamepad types.
104104
*
105105
* This type does not necessarily map to first-party controllers from
106-
* Microsoft/Sony/Nintendo; in many cases, third-party controllers can report
106+
* Microsoft/Sony/Nintendo/etc.; in many cases, third-party controllers can report
107107
* as these, either because they were designed for a specific console, or they
108108
* simply most closely match that console's controllers (does it have A/B/X/Y
109109
* buttons or X/O/Square/Triangle? Does it have a touchpad? etc).
110+
*
111+
* PSX and PS2 controllers should be classified as PS3.
112+
*
113+
* Sega Saturn controllers should be classified as Sega Genesis.
114+
*
110115
*/
111116
typedef enum SDL_GamepadType
112117
{
@@ -123,6 +128,9 @@ typedef enum SDL_GamepadType
123128
SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR,
124129
SDL_GAMEPAD_TYPE_GAMECUBE,
125130
SDL_GAMEPAD_TYPE_STEAM,
131+
SDL_GAMEPAD_TYPE_N64,
132+
SDL_GAMEPAD_TYPE_WII,
133+
SDL_GAMEPAD_TYPE_SEGA_GENESIS,
126134
SDL_GAMEPAD_TYPE_COUNT
127135
} SDL_GamepadType;
128136

@@ -136,15 +144,25 @@ typedef enum SDL_GamepadType
136144
* would be A/X/B/Y, for PlayStation controllers this would be
137145
* Cross/Circle/Square/Triangle.
138146
*
147+
* Gamepads which use a Sega Genesis-style layout (3 button or 6-button both)
148+
* should map the bottom (or only) row to South, East, and Right Trigger, and
149+
* the top row to West, North, and Right Button. L and R, if present, should
150+
* be mapped to Left Button and Left Trigger respectively.
151+
*
139152
* For controllers that don't use a diamond pattern for the face buttons, the
140153
* south/east/west/north buttons indicate the buttons labeled A, B, C, D, or
141154
* 1, 2, 3, 4, or for controllers that aren't labeled, they are the primary,
142155
* secondary, etc. buttons.
143156
*
144157
* The activate action is often the south button and the cancel action is
145-
* often the east button, but in some regions this is reversed, so your game
146-
* should allow remapping actions based on user preferences.
147-
*
158+
* often the east button, but in some regions and on some gamepads this is reversed,
159+
* so your game should allow remapping actions based on user preferences, and you should
160+
* check the gamepad type and region for the default mapping.
161+
*
162+
* On some controllers, what would conventionally be considered buttons are instead
163+
* considered axes by SDL, such as the R and C buttons on the genesis controller,
164+
* or the ZL and ZR buttons on the Switch Pro controller.
165+
*
148166
* You can query the labels for the face buttons using
149167
* SDL_GetGamepadButtonLabel()
150168
*
@@ -732,6 +750,7 @@ extern SDL_DECLSPEC SDL_GamepadType SDLCALL SDL_GetGamepadTypeForID(SDL_Joystick
732750
* \since This function is available since SDL 3.2.0.
733751
*
734752
* \sa SDL_GetGamepadTypeForID
753+
* \sa SDL_GetGamepadStringForType
735754
* \sa SDL_GetGamepads
736755
* \sa SDL_GetRealGamepadType
737756
*/
@@ -893,6 +912,7 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetGamepadPath(SDL_Gamepad *gamepad
893912
* \since This function is available since SDL 3.2.0.
894913
*
895914
* \sa SDL_GetGamepadTypeForID
915+
* \sa SDL_GetGamepadStringForType
896916
*/
897917
extern SDL_DECLSPEC SDL_GamepadType SDLCALL SDL_GetGamepadType(SDL_Gamepad *gamepad);
898918

@@ -1367,7 +1387,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetGamepadButton(SDL_Gamepad *gamepad, SDL_
13671387
*
13681388
* \param type the type of gamepad to check.
13691389
* \param button a button index (one of the SDL_GamepadButton values).
1370-
* \returns the SDL_GamepadButtonLabel enum corresponding to the button label.
1390+
* \returns the SDL_GamepadButtonLabel enum corresponding to the button label, or SDL_GAMEPAD_BUTTON_LABEL_UNKNOWN.
13711391
*
13721392
* \threadsafety It is safe to call this function from any thread.
13731393
*
@@ -1380,9 +1400,10 @@ extern SDL_DECLSPEC SDL_GamepadButtonLabel SDLCALL SDL_GetGamepadButtonLabelForT
13801400
/**
13811401
* Get the label of a button on a gamepad.
13821402
*
1403+
*
13831404
* \param gamepad a gamepad.
13841405
* \param button a button index (one of the SDL_GamepadButton values).
1385-
* \returns the SDL_GamepadButtonLabel enum corresponding to the button label.
1406+
* \returns the SDL_GamepadButtonLabel enum corresponding to the button label, or SDL_GAMEPAD_BUTTON_LABEL_UNKNOWN.
13861407
*
13871408
* \threadsafety It is safe to call this function from any thread.
13881409
*

src/joystick/SDL_gamepad.c

Lines changed: 217 additions & 218 deletions
Large diffs are not rendered by default.

src/joystick/SDL_gamepad_db.h

Lines changed: 436 additions & 435 deletions
Large diffs are not rendered by default.

src/joystick/SDL_joystick.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3079,12 +3079,11 @@ SDL_GamepadType SDL_GetGamepadTypeFromVIDPID(Uint16 vendor, Uint16 product, cons
30793079
(product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT ||
30803080
product == USB_PRODUCT_NINTENDO_SWITCH2_JOYCON_RIGHT)) {
30813081
if (name && SDL_strstr(name, "NES Controller") != NULL) {
3082-
// We don't have a type for the Nintendo Online NES Controller
3083-
type = SDL_GAMEPAD_TYPE_STANDARD;
3082+
/* TODO -- NES gamepad type */
3083+
type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO;
30843084
} else {
30853085
type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT;
30863086
}
3087-
30883087
} else if (vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP) {
30893088
if (name && SDL_strstr(name, "(L)") != NULL) {
30903089
type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT;
@@ -3098,10 +3097,19 @@ SDL_GamepadType SDL_GetGamepadTypeFromVIDPID(Uint16 vendor, Uint16 product, cons
30983097
(product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR ||
30993098
product == USB_PRODUCT_NINTENDO_SWITCH2_JOYCON_PAIR)) {
31003099
type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR;
3101-
3100+
} else if (vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_N64_CONTROLLER) {
3101+
type = SDL_GAMEPAD_TYPE_N64;
3102+
} else if (vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_SNES_CONTROLLER) {
3103+
/* TODO -- SNES gamepad type */
3104+
type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO;
3105+
} else if (vendor == USB_VENDOR_NINTENDO && product == USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER) {
3106+
type = SDL_GAMEPAD_TYPE_SEGA_GENESIS;
3107+
} else if (vendor == USB_VENDOR_NINTENDO &&
3108+
(product == USB_PRODUCT_NINTENDO_WII_REMOTE ||
3109+
product == USB_PRODUCT_NINTENDO_WII_REMOTE2)) {
3110+
type = SDL_GAMEPAD_TYPE_WII;
31023111
} else if (forUI && SDL_IsJoystickGameCube(vendor, product)) {
31033112
type = SDL_GAMEPAD_TYPE_GAMECUBE;
3104-
31053113
} else {
31063114
switch (GuessControllerType(vendor, product)) {
31073115
case k_eControllerType_XBox360Controller:

src/joystick/hidapi/SDL_hidapi_sinput.c

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -411,13 +411,7 @@ static void DeviceDynamicEncodingSetup(SDL_HIDAPI_Device *device)
411411
break;
412412
}
413413

414-
int version = analogStyle;
415-
version = (version * (int)SINPUT_BUMPERSTYLE_MAX) + bumperStyle;
416-
version = (version * (int)SINPUT_TRIGGERSTYLE_MAX) + triggerStyle;
417-
version = (version * (int)SINPUT_PADDLESTYLE_MAX) + paddleStyle;
418-
version = (version * (int)SINPUT_METASTYLE_MAX) + metaStyle;
419-
version = (version * (int)SINPUT_TOUCHSTYLE_MAX) + touchStyle;
420-
version = (version * (int)SINPUT_MISCSTYLE_MAX) + miscStyle;
414+
Uint16 version = SINPUT_PACK_VERSION(miscStyle, touchStyle, metaStyle, paddleStyle, triggerStyle, bumperStyle, analogStyle);
421415

422416
// Overwrite our button usage masks
423417
// with our sanitized masks
@@ -426,8 +420,6 @@ static void DeviceDynamicEncodingSetup(SDL_HIDAPI_Device *device)
426420
ctx->usage_masks[2] = mask[2];
427421
ctx->usage_masks[3] = mask[3];
428422

429-
version = SDL_clamp(version, 0, UINT16_MAX);
430-
431423
// Overwrite 'Version' field of the GUID data
432424
device->guid.data[12] = (Uint8)(version & 0xFF);
433425
device->guid.data[13] = (Uint8)(version >> 8);
@@ -460,10 +452,12 @@ static void ProcessSDLFeaturesResponse(SDL_HIDAPI_Device *device, Uint8 *data)
460452
// The gamepad type represents a style of gamepad that most closely
461453
// resembles the gamepad in question (Button style, button layout)
462454
SDL_GamepadType type = SDL_GAMEPAD_TYPE_UNKNOWN;
463-
type = (SDL_GamepadType)SDL_clamp(data[4], SDL_GAMEPAD_TYPE_UNKNOWN, SDL_GAMEPAD_TYPE_COUNT);
455+
if (data[4] < SDL_GAMEPAD_TYPE_COUNT) {
456+
type = (SDL_GamepadType)data[4];
457+
}
464458
device->type = type;
465459

466-
// The 3 MSB represent a button layout style SDL_GamepadFaceStyle
460+
// The 3 MSB represent a face button layout style
467461
// The 5 LSB represent a device sub-type
468462
device->guid.data[15] = data[5];
469463

src/joystick/hidapi/SDL_hidapi_sinput.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,15 @@ typedef struct
9090
Uint16 touch_style;
9191
Uint16 misc_style;
9292
} SDL_SInputStyles_t;
93+
94+
/* Pack the seven style enums into a single Uint16
95+
* (can fit in the version field of the GUID) */
96+
#define SINPUT_PACK_VERSION(misc, touch, meta, paddle, trigger, bumper, analog) \
97+
((Uint16)((((((( \
98+
(analog)) * SINPUT_BUMPERSTYLE_MAX + \
99+
(bumper)) * SINPUT_TRIGGERSTYLE_MAX + \
100+
(trigger)) * SINPUT_PADDLESTYLE_MAX + \
101+
(paddle)) * SINPUT_METASTYLE_MAX + \
102+
(meta)) * SINPUT_TOUCHSTYLE_MAX + \
103+
(touch)) * SINPUT_MISCSTYLE_MAX + \
104+
(misc)))

test/gamepadutils.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3622,7 +3622,6 @@ char *SetMappingName(char *mapping, const char *name)
36223622
return RecreateMapping(&parts, mapping);
36233623
}
36243624

3625-
36263625
const char *GetGamepadTypeString(SDL_GamepadType type)
36273626
{
36283627
switch (type) {
@@ -3636,6 +3635,12 @@ const char *GetGamepadTypeString(SDL_GamepadType type)
36363635
return "PS4";
36373636
case SDL_GAMEPAD_TYPE_PS5:
36383637
return "PS5";
3638+
case SDL_GAMEPAD_TYPE_N64:
3639+
return "N64";
3640+
case SDL_GAMEPAD_TYPE_GAMECUBE:
3641+
return "GameCube";
3642+
case SDL_GAMEPAD_TYPE_WII:
3643+
return "Wii";
36393644
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO:
36403645
return "Nintendo Switch";
36413646
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT:
@@ -3644,12 +3649,14 @@ const char *GetGamepadTypeString(SDL_GamepadType type)
36443649
return "Joy-Con (R)";
36453650
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
36463651
return "Joy-Con Pair";
3647-
case SDL_GAMEPAD_TYPE_GAMECUBE:
3648-
return "GameCube";
36493652
case SDL_GAMEPAD_TYPE_STEAM:
36503653
return "Steam";
3654+
case SDL_GAMEPAD_TYPE_SEGA_GENESIS:
3655+
return "Sega Genesis";
3656+
case SDL_GAMEPAD_TYPE_STANDARD:
3657+
return "Standard";
36513658
default:
3652-
return "";
3659+
return "(unknown)";
36533660
}
36543661
}
36553662

0 commit comments

Comments
 (0)