diff --git a/WhatsNew.txt b/WhatsNew.txt index 37a001cfb..1870f5679 100644 --- a/WhatsNew.txt +++ b/WhatsNew.txt @@ -1,6 +1,14 @@ This is a list of major changes in SDL's version history. +--------------------------------------------------------------------------- +2.26.0: +--------------------------------------------------------------------------- + +General: +* Added SDL_GetJoystickGUIDInfo() to get device information encoded in a joystick GUID + + --------------------------------------------------------------------------- 2.24.0: --------------------------------------------------------------------------- diff --git a/include/SDL_joystick.h b/include/SDL_joystick.h index b27a750e9..d3243ecba 100644 --- a/include/SDL_joystick.h +++ b/include/SDL_joystick.h @@ -647,6 +647,21 @@ extern DECLSPEC void SDLCALL SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, ch */ extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetGUIDFromString(const char *pchGUID); +/** + * Get the device information encoded in a SDL_JoystickGUID structure + * + * \param guid the SDL_JoystickGUID you wish to get info about + * \param vendor A pointer filled in with the device VID, or 0 if not available + * \param product A pointer filled in with the device PID, or 0 if not available + * \param version A pointer filled in with the device version, or 0 if not available + * \param crc A pointer filled in with a CRC used to distinguish different products with the same VID/PID, or 0 if not available + * + * \since This function is available since SDL 2.26.0. + * + * \sa SDL_JoystickGetDeviceGUID + */ +extern DECLSPEC void SDLCALL SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version, Uint16 *crc16); + /** * Get the status of a specified joystick. * diff --git a/src/dynapi/SDL2.exports b/src/dynapi/SDL2.exports index 1faa894dc..d25b8f721 100644 --- a/src/dynapi/SDL2.exports +++ b/src/dynapi/SDL2.exports @@ -859,3 +859,4 @@ ++'_SDL_ResetHint'.'SDL2.dll'.'SDL_ResetHint' ++'_SDL_crc16'.'SDL2.dll'.'SDL_crc16' ++'_SDL_GetWindowSizeInPixels'.'SDL2.dll'.'SDL_GetWindowSizeInPixels' +++'_SDL_GetJoystickGUIDInfo'.'SDL2.dll'.'SDL_GetJoystickGUIDInfo' diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index cabb7cd84..4b68f1ab4 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -885,3 +885,4 @@ #define SDL_ResetHint SDL_ResetHint_REAL #define SDL_crc16 SDL_crc16_REAL #define SDL_GetWindowSizeInPixels SDL_GetWindowSizeInPixels_REAL +#define SDL_GetJoystickGUIDInfo SDL_GetJoystickGUIDInfo_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 9b6919ce5..b8ecadbcf 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -968,3 +968,4 @@ SDL_DYNAPI_PROC(int,SDL_GetRectDisplayIndex,(const SDL_Rect *a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_ResetHint,(const char *a),(a),return) SDL_DYNAPI_PROC(Uint16,SDL_crc16,(Uint16 a, const void *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_GetWindowSizeInPixels,(SDL_Window *a, int *b, int *c),(a,b,c),) +SDL_DYNAPI_PROC(void,SDL_GetJoystickGUIDInfo,(SDL_JoystickGUID a, Uint16 *b, Uint16 *c, Uint16 *d, Uint16 *e),(a,b,c,d,e),) diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c index c188023e6..34998a3cd 100644 --- a/src/joystick/SDL_gamecontroller.c +++ b/src/joystick/SDL_gamecontroller.c @@ -664,21 +664,23 @@ static ControllerMapping_t *SDL_CreateMappingForWGIController(SDL_JoystickGUID g static ControllerMapping_t *SDL_PrivateGetControllerMappingForGUID(SDL_JoystickGUID guid, SDL_bool exact_match) { ControllerMapping_t *mapping; - SDL_JoystickGUID zero_crc_guid; + Uint16 crc; - /* First check for exact match */ + SDL_GetJoystickGUIDInfo(guid, NULL, NULL, NULL, &crc); + if (crc) { + /* Clear the CRC from the GUID for matching */ + SDL_SetJoystickGUIDCRC(&guid, 0); + } for (mapping = s_pSupportedControllers; mapping; mapping = mapping->next) { if (SDL_memcmp(&guid, &mapping->guid, sizeof(guid)) == 0) { - return mapping; - } - } - - /* Now check for match with no CRC */ - SDL_memcpy(&zero_crc_guid, &guid, sizeof(guid)); - zero_crc_guid.data[2] = 0; - zero_crc_guid.data[3] = 0; - for (mapping = s_pSupportedControllers; mapping; mapping = mapping->next) { - if (SDL_memcmp(&zero_crc_guid, &mapping->guid, sizeof(guid)) == 0) { + /* Check to see if the CRC matches */ + const char *crc_string = SDL_strstr(mapping->mapping, "crc:"); + if (crc_string) { + Uint16 mapping_crc = (Uint16)SDL_strtol(crc_string + 4, NULL, 16); + if (crc != mapping_crc) { + continue; + } + } return mapping; } } @@ -1098,6 +1100,7 @@ SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, const char *mappingString, char *pchName; char *pchMapping; ControllerMapping_t *pControllerMapping; + Uint16 crc; pchName = SDL_PrivateGetControllerNameFromMappingString(mappingString); if (!pchName) { @@ -1112,6 +1115,38 @@ SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, const char *mappingString, return NULL; } + /* Fix up the GUID and the mapping with the CRC, if needed */ + SDL_GetJoystickGUIDInfo(jGUID, NULL, NULL, NULL, &crc); + if (crc) { + /* Make sure the mapping has the CRC */ + char *new_mapping; + char *crc_end = ""; + char *crc_string = SDL_strstr(pchMapping, "crc:"); + if (crc_string) { + crc_end = SDL_strchr(crc_string, ','); + if (crc_end) { + ++crc_end; + } else { + crc_end = ""; + } + *crc_string = '\0'; + } + + if (SDL_asprintf(&new_mapping, "%scrc:%.4x,%s", pchMapping, crc, crc_end) >= 0) { + SDL_free(pchMapping); + pchMapping = new_mapping; + } + } else { + /* Make sure the GUID has the CRC, for matching purposes */ + char *crc_string = SDL_strstr(pchMapping, "crc:"); + if (crc_string) { + crc = (Uint16)SDL_strtol(crc_string + 4, NULL, 16); + if (crc) { + SDL_SetJoystickGUIDCRC(&jGUID, crc); + } + } + } + pControllerMapping = SDL_PrivateGetControllerMappingForGUID(jGUID, SDL_TRUE); if (pControllerMapping) { /* Only overwrite the mapping if the priority is the same or higher. */ @@ -1137,6 +1172,10 @@ SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, const char *mappingString, SDL_OutOfMemory(); return NULL; } + /* Clear the CRC, we've already added it to the mapping */ + if (crc) { + SDL_SetJoystickGUIDCRC(&jGUID, 0); + } pControllerMapping->guid = jGUID; pControllerMapping->name = pchName; pControllerMapping->mapping = pchMapping; diff --git a/src/joystick/SDL_gamecontrollerdb.h b/src/joystick/SDL_gamecontrollerdb.h index 40b73c2b4..181e688a3 100644 --- a/src/joystick/SDL_gamecontrollerdb.h +++ b/src/joystick/SDL_gamecontrollerdb.h @@ -132,7 +132,6 @@ static const char *s_ControllerMappings [] = "03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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:b1,", "03000000852100000201000000000000,FF-GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,", "030000000d0f00002700000000000000,FIGHTING STICK V3,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,", - "78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,", "03000000151900004000000000000000,Flydigi Vader 2,a:b11,b:b10,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,leftstick:b1,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b0,righttrigger:b4,rightx:a3,righty:a4,start:b2,x:b9,y:b8,", "03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,", "03000000790000000600000000000000,G-Shark GS-GP702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,", @@ -213,7 +212,6 @@ static const char *s_ControllerMappings [] = "030000002a0600001024000000000000,Matricom,a:b0,b:b1,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:a3,righty:a4,start:b9,x:b2,y:b3,", "03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,", "03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,", - "030000008f0e00001330000000000000,Mayflash N64 controller adapter PC043,a:b1,b:b2,start:b9,leftshoulder:b6,rightshoulder:b7,guide:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,", "0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,", "03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,", @@ -510,7 +508,7 @@ static const char *s_ControllerMappings [] = "03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,", #endif -#ifdef SDL_JOYSTICK_LINUX +#if SDL_JOYSTICK_LINUX "xinput,*,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", @@ -919,7 +917,7 @@ static const char *s_ControllerMappings [] = "0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", #endif -#if defined(SDL_JOYSTICK_MFI) +#if SDL_JOYSTICK_MFI "05000000ac050000010000004f066d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,", "05000000ac05000001000000cf076d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,", "05000000ac05000001000000df076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", @@ -947,17 +945,17 @@ static const char *s_ControllerMappings [] = "050000005e040000e0020000df070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,", "050000005e040000e0020000ff070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,", #endif -#if defined(SDL_JOYSTICK_EMSCRIPTEN) +#if SDL_JOYSTICK_EMSCRIPTEN "default,Standard Gamepad,a:b0,b:b1,back:b8,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b16,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", #endif -#if defined(SDL_JOYSTICK_VITA) - "50535669746120436f6e74726f6c6c65,PSVita Controller,a:b2,b:b1,back:b10,dpdown:b6,dpleft:b7,dpright:b9,dpup:b8,leftshoulder:b4,leftstick:b14,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,", +#if SDL_JOYSTICK_PS2 + "0000000050533220436f6e74726f6c00,PS2 Controller,crc:87ed,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", #endif -#if defined(SDL_JOYSTICK_PSP) - "505350206275696c74696e206a6f7970,PSP builtin joypad,a:b2,b:b1,back:b10,dpdown:b6,dpleft:b7,dpright:b9,dpup:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,", +#if SDL_JOYSTICK_PSP + "00000000505350206275696c74696e00,PSP builtin joypad,crc:86bb,a:b2,b:b1,back:b10,dpdown:b6,dpleft:b7,dpright:b9,dpup:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,", #endif -#if defined(SDL_JOYSTICK_PS2) - "50533220436f6e74726f6c6c65720000,PS2 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", +#if SDL_JOYSTICK_VITA + "0000000050535669746120436f6e7400,PSVita Controller,crc:98d5,a:b2,b:b1,back:b10,dpdown:b6,dpleft:b7,dpright:b9,dpup:b8,leftshoulder:b4,leftstick:b14,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,", #endif "hidapi,*,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", NULL diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index a71e7a0a9..49bd2f0b7 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -1984,11 +1984,7 @@ SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 product, Uint16 version /* We only need 16 bits for each of these; space them out to fill 128. */ /* Byteswap so devices get same GUID on little/big endian platforms. */ *guid16++ = SDL_SwapLE16(bus); -#if 1 - *guid16++ = 0; -#else *guid16++ = SDL_SwapLE16(SDL_crc16(0, name, SDL_strlen(name))); -#endif if (vendor && product) { *guid16++ = SDL_SwapLE16(vendor); @@ -2017,6 +2013,14 @@ SDL_CreateJoystickGUIDForName(const char *name) return SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_UNKNOWN, 0, 0, 0, name, 0, 0); } +void +SDL_SetJoystickGUIDCRC(SDL_JoystickGUID *guid, Uint16 crc) +{ + Uint16 *guid16 = (Uint16 *)guid->data; + + guid16[1] = SDL_SwapLE16(crc); +} + SDL_GameControllerType SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product, const char *name, SDL_bool forUI) { diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index b1ee5a47f..ca72a1d75 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -54,9 +54,6 @@ extern SDL_bool SDL_GetDriverAndJoystickIndex(int device_index, struct _SDL_Joys /* Function to return the device index for a joystick ID, or -1 if not found */ extern int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id); -/* Function to extract information from an SDL joystick GUID */ -extern void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version, Uint16 *crc16); - /* Function to standardize the name for a controller This should be freed with SDL_free() when no longer needed */ @@ -68,6 +65,9 @@ extern SDL_JoystickGUID SDL_CreateJoystickGUID(Uint16 bus, Uint16 vendor, Uint16 /* Function to create a GUID for a joystick based on the name, with no VID/PID information */ extern SDL_JoystickGUID SDL_CreateJoystickGUIDForName(const char *name); +/* Function to set the CRC field of a joystick GUID */ +extern void SDL_SetJoystickGUIDCRC(SDL_JoystickGUID *guid, Uint16 crc); + /* Function to return the type of a controller */ extern SDL_GameControllerType SDL_GetJoystickGameControllerTypeFromVIDPID(Uint16 vendor, Uint16 product, const char *name, SDL_bool forUI); extern SDL_GameControllerType SDL_GetJoystickGameControllerTypeFromGUID(SDL_JoystickGUID guid, const char *name); diff --git a/src/joystick/sort_controllers.py b/src/joystick/sort_controllers.py index df04241bb..af2421f59 100755 --- a/src/joystick/sort_controllers.py +++ b/src/joystick/sort_controllers.py @@ -13,6 +13,7 @@ controllers = [] controller_guids = {} conditionals = [] split_pattern = re.compile(r'([^"]*")([^,]*,)([^,]*,)([^"]*)(".*)') +guid_crc_pattern = re.compile(r'^([0-9a-zA-Z]{4})([0-9a-zA-Z]{4})([0-9a-zA-Z]{24},)$') def find_element(prefix, bindings): i=0 @@ -31,38 +32,54 @@ def save_controller(line): if (bindings[0] == ""): bindings.pop(0) - pos=find_element("sdk", bindings) + crc = "" + pos = find_element("crc:", bindings) + if pos >= 0: + crc = bindings[pos] + "," + bindings.pop(pos) + + # Look for CRC embedded in the GUID and convert to crc element + crc_match = guid_crc_pattern.match(entry[1]) + if crc_match and crc_match.group(2) != '0000': + print("Extracting CRC from GUID of " + entry[2]) + entry[1] = crc_match.group(1) + '0000' + crc_match.group(3) + crc = "crc:" + crc_match.group(2) + "," + + pos = find_element("sdk", bindings) if pos >= 0: bindings.append(bindings.pop(pos)) - pos=find_element("hint:", bindings) + pos = find_element("hint:", bindings) if pos >= 0: bindings.append(bindings.pop(pos)) + entry.extend(crc) entry.extend(",".join(bindings) + ",") entry.append(match.group(5)) controllers.append(entry) + entry_id = entry[1] + entry[3] if ',sdk' in line or ',hint:' in line: - conditionals.append(entry[1]) + conditionals.append(entry_id) def write_controllers(): global controllers global controller_guids # Check for duplicates for entry in controllers: - if (entry[1] in controller_guids and entry[1] not in conditionals): + entry_id = entry[1] + entry[3] + if (entry_id in controller_guids and entry_id not in conditionals): current_name = entry[2] - existing_name = controller_guids[entry[1]][2] + existing_name = controller_guids[entry_id][2] print("Warning: entry '%s' is duplicate of entry '%s'" % (current_name, existing_name)) if (not current_name.startswith("(DUPE)")): entry[2] = f"(DUPE) {current_name}" if (not existing_name.startswith("(DUPE)")): - controller_guids[entry[1]][2] = f"(DUPE) {existing_name}" + controller_guids[entry_id][2] = f"(DUPE) {existing_name}" - controller_guids[entry[1]] = entry + controller_guids[entry_id] = entry for entry in sorted(controllers, key=lambda entry: f"{entry[2]}-{entry[1]}"): line = "".join(entry) + "\n" diff --git a/test/controllermap.c b/test/controllermap.c index 429125a19..7fb5f687b 100644 --- a/test/controllermap.c +++ b/test/controllermap.c @@ -558,6 +558,8 @@ WatchJoystick(SDL_Joystick * joystick) } if (s_bBindingComplete) { + SDL_JoystickGUID guid; + Uint16 crc; char mapping[1024]; char trimmed_name[128]; char *spot; @@ -576,13 +578,28 @@ WatchJoystick(SDL_Joystick * joystick) } /* Initialize mapping with GUID and name */ - SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), mapping, SDL_arraysize(mapping)); + guid = SDL_JoystickGetGUID(joystick); + SDL_GetJoystickGUIDInfo(guid, NULL, NULL, NULL, &crc); + if (crc) { + /* Clear the CRC from the GUID for the mapping */ + guid.data[2] = 0; + guid.data[3] = 0; + } + SDL_JoystickGetGUIDString(guid, mapping, SDL_arraysize(mapping)); SDL_strlcat(mapping, ",", SDL_arraysize(mapping)); SDL_strlcat(mapping, trimmed_name, SDL_arraysize(mapping)); SDL_strlcat(mapping, ",", SDL_arraysize(mapping)); SDL_strlcat(mapping, "platform:", SDL_arraysize(mapping)); SDL_strlcat(mapping, SDL_GetPlatform(), SDL_arraysize(mapping)); SDL_strlcat(mapping, ",", SDL_arraysize(mapping)); + if (crc) { + char crc_string[5]; + + SDL_strlcat(mapping, "crc:", SDL_arraysize(mapping)); + SDL_snprintf(crc_string, sizeof(crc_string), "%.4x", crc); + SDL_strlcat(mapping, crc_string, SDL_arraysize(mapping)); + SDL_strlcat(mapping, ",", SDL_arraysize(mapping)); + } for (iIndex = 0; iIndex < SDL_arraysize(s_arrBindings); ++iIndex) { SDL_GameControllerExtendedBind *pBinding = &s_arrBindings[iIndex];