-
Notifications
You must be signed in to change notification settings - Fork 5
Description
I'm willing to help extend the solution to find the fix.
I've just built sdl3, installed it locally then build and run the c file, with the following output:
$ ./get-controller-config
Joystick 0: Steam Deck
To use this controller in Silksong, set the following environment variable when running the game:
SDL_GAMECONTROLLERCONFIG='03000000de2800000512000000036800,Steam Deck Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b11,paddle1:b12,paddle2:b13,paddle3:b14,paddle4:b15,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,'
For example, Steam launch options would be:
SDL_GAMECONTROLLERCONFIG='03000000de2800000512000000036800,Steam Deck Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b11,paddle1:b12,paddle2:b13,paddle3:b14,paddle4:b15,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,' %command%
Joystick 1: 8BitDo Ultimate 2 Wireless Controller for PC
To use this controller in Silksong, set the following environment variable when running the game:
SDL_GAMECONTROLLERCONFIG='03000000c82d00000b31000014016800,*,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,crc:cdb5,platform:Linux,'
For example, Steam launch options would be:
SDL_GAMECONTROLLERCONFIG='03000000c82d00000b31000014016800,*,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,crc:cdb5,platform:Linux,' %command%But unfortunately, after setting that as steam launch, the controller doesn't work at all regardless. Tried enabling/disabling steam input with no change as well (and yes, NativeInput is set to 0 too :( )
I saw the example code in the repo and that it has the controller name in it, while this output has *. I also replaced * with 8BitDo Ultimate 2 Wireless Controller for PC which is my controller's name, but no success.
Asking AI also replied with this, which I tried, re-built, but also no success, but posting here just in case:
Looking at the C code and the output, I can identify the problem. The code has a critical logic error in how it modifies the GUID string in the mapping.
The Problem
The code attempts to zero out CRC bytes by modifying the mapping string directly, but this approach has several issues:
- Wrong target: The code is trying to modify bytes 2-4 of the
mappingstring (which is the entire gamepad configuration string like"03000000c82d00000b31000014016800,*,a:b0,b:b1..."), not the GUID portion within it. - String immutability: In SDL3,
SDL_GetGamepadMappingForGUID()now returns aconst char*(notchar*) as part of the SDL_GetStringRule changes. This means the returned string should not be modified directly. - Invalid approach: The loop
for (size_t guid_byte = 2; guid_byte < 4; guid_byte++)is modifying positions 4-7 of the mapping string (which would be part of"0300..."at the start), but this isn't correctly targeting the GUID bytes.
The Fix
The code needs to:
- Extract the GUID portion from the mapping string (the first part before the comma)
- Zero out bytes 4-7 (indices 4-7 in the hex string, representing GUID bytes 2-3)
- Reconstruct the mapping string with the modified GUID
Here's the corrected version:
char* mapping = SDL_GetGamepadMappingForGUID(guid);
if (mapping == NULL) {
fprintf(stderr, "\tNo mapping available for this controller\n");
SDL_CloseJoystick(joystick);
continue;
}
// Find the first comma (end of GUID portion)
char* comma = strchr(mapping, ',');
if (comma == NULL) {
fprintf(stderr, "\tInvalid mapping format\n");
SDL_free(mapping);
SDL_CloseJoystick(joystick);
continue;
}
// Create a modified mapping string with zeroed CRC bytes
size_t guid_len = comma - mapping;
char* modified_mapping = malloc(strlen(mapping) + 1);
strcpy(modified_mapping, mapping);
// Zero out bytes at positions 4-7 (GUID bytes 2-3, which are the CRC)
modified_mapping[^4] = '0';
modified_mapping[^5] = '0';
modified_mapping[^6] = '0';
modified_mapping[^7] = '0';
printf("\tTo use this controller in Silksong, set the following environment variable when running the game:\n\n");
printf("\tSDL_GAMECONTROLLERCONFIG='%s'\n\n", modified_mapping);
printf("\tFor example, Steam launch options would be:\n\n");
printf("\tSDL_GAMECONTROLLERCONFIG='%s' %%command%%\n\n", modified_mapping);
free(modified_mapping);
SDL_CloseJoystick(joystick);
SDL_free(mapping);The original code was modifying the wrong positions in the string, which is why the generated mapping strings weren't working for Silksong.