We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 4547

Summary: Fix GameController axis polling incorrect values
Product: SDL Reporter: Jimb Esser <wasteland>
Component: joystickAssignee: Sam Lantinga <slouken>
Status: RESOLVED FIXED QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2    
Version: HG 2.1   
Hardware: x86   
OS: Windows 10   
Attachments: Patch

Description Jimb Esser 2019-03-12 21:51:31 UTC
Created attachment 3695 [details]
Patch

If a GameController has one axis with the negative and positive bound to two different things, the polling API returns incorrect results.  The events generated are correct.

Simplest way to reproduce is an XBox 360 controller with XInput disabled and an valid controller mapping.  Add the following two lines to the top of main() in testgamecontroller.c:
* SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "0");
* SDL_SetHint(SDL_HINT_GAMECONTROLLERCONFIG, "030000005e0400008e02000000000000,XBox360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3"); // From https://github.com/gabomdq/SDL_GameControllerDB/

Run `testgamecontroller 0`, depress the Left Trigger.  See the log indicates only events on left trigger, but visually the Right Trigger also lights up.

Fix here: https://github.com/Jimbly/SDL/commit/5d8ec3cc2a36b4a8336e484f61bedb1e9599b366
Patch also attached.

This makes SDL_GameControllerGetAxis behave more similarly to HandleJoystickAxis in that a binding for which the value is out of range provides no output, allowing another binding to instead return a value (or 0, if no appropriate bindings are found).


More generally than the negative/positive binding issue this fixes, it seems SDL_GameControllerGetAxis() might also return slightly different results than the events if you have two bindings simultaneously valid - the events will have fired whatever value happened last, and the polling will return whatever binding happens to be first in the list.  Seems a simpler architecture (solving both issues) would be for HandleJoystickAxis to just save the 6 axis values when modified (exactly when events are fired) and SDL_GameControllerGetAxis() just returns those values, instead of iterating the bindings in a slightly different manner.
Comment 1 Sam Lantinga 2019-03-17 01:14:24 UTC
Thanks, your patch is added:
https://hg.libsdl.org/SDL/rev/76caa6065d50

I agree with your analysis of the logic there. Do you want to provide a tested patch that makes that change?

Thanks!
Comment 2 Jimb Esser 2019-03-17 16:34:40 UTC
Sure.  Not super high priority, so will wait until I have a little more bandwidth, but will put it on my to-do list.