Commit 8aaf945b2fd7a1125deeb6626215219180a041a1

Sam Lantinga 2019-11-28T11:44:15

Fixed mapping controllers that have axes that start at -32768 and then snap to 0 at the first input report

diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index ba6d2b3..96a3b89 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -833,43 +833,49 @@ int
 SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
 {
     int posted;
+    SDL_JoystickAxisInfo *info;
 
     /* Make sure we're not getting garbage or duplicate events */
     if (axis >= joystick->naxes) {
         return 0;
     }
-    if (!joystick->axes[axis].has_initial_value) {
-        joystick->axes[axis].initial_value = value;
-        joystick->axes[axis].value = value;
-        joystick->axes[axis].zero = value;
-        joystick->axes[axis].has_initial_value = SDL_TRUE;
+
+    info = &joystick->axes[axis];
+    if (!info->has_initial_value ||
+        (!info->has_second_value && info->initial_value == -32768 && value == 0)) {
+        info->initial_value = value;
+        info->value = value;
+        info->zero = value;
+        info->has_initial_value = SDL_TRUE;
+    } else {
+        info->has_second_value = SDL_TRUE;
     }
-    if (value == joystick->axes[axis].value) {
+    if (value == info->value) {
         return 0;
     }
-    if (!joystick->axes[axis].sent_initial_value) {
+    if (!info->sent_initial_value) {
         /* Make sure we don't send motion until there's real activity on this axis */
         const int MAX_ALLOWED_JITTER = SDL_JOYSTICK_AXIS_MAX / 80;  /* ShanWan PS3 controller needed 96 */
-        if (SDL_abs(value - joystick->axes[axis].value) <= MAX_ALLOWED_JITTER) {
+        if (SDL_abs(value - info->value) <= MAX_ALLOWED_JITTER) {
             return 0;
         }
-        joystick->axes[axis].sent_initial_value = SDL_TRUE;
-        joystick->axes[axis].value = value; /* Just so we pass the check above */
-        SDL_PrivateJoystickAxis(joystick, axis, joystick->axes[axis].initial_value);
+        info->sent_initial_value = SDL_TRUE;
+        info->value = value; /* Just so we pass the check above */
+        SDL_PrivateJoystickAxis(joystick, axis, info->initial_value);
     }
 
     /* We ignore events if we don't have keyboard focus, except for centering
      * events.
      */
     if (SDL_PrivateJoystickShouldIgnoreEvent()) {
-        if ((value > joystick->axes[axis].zero && value >= joystick->axes[axis].value) ||
-            (value < joystick->axes[axis].zero && value <= joystick->axes[axis].value)) {
+        if ((value > info->zero && value >= info->value) ||
+            (value < info->zero && value <= info->value)) {
             return 0;
         }
     }
 
     /* Update internal joystick state */
-    joystick->axes[axis].value = value;
+    info->value = value;
 
     /* Post the event, if desired */
     posted = 0;
diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h
index 8f57523..4ea0c80 100644
--- a/src/joystick/SDL_sysjoystick.h
+++ b/src/joystick/SDL_sysjoystick.h
@@ -35,6 +35,7 @@ typedef struct _SDL_JoystickAxisInfo
     Sint16 value;               /* Current axis state */
     Sint16 zero;                /* Zero point on the axis (-32768 for triggers) */
     SDL_bool has_initial_value; /* Whether we've seen a value on the axis yet */
+    SDL_bool has_second_value;  /* Whether we've seen a second value on the axis yet */
     SDL_bool sent_initial_value; /* Whether we've sent the initial axis value */
 } SDL_JoystickAxisInfo;
 
diff --git a/test/controllermap.c b/test/controllermap.c
index 40c3518..0f7de70 100644
--- a/test/controllermap.c
+++ b/test/controllermap.c
@@ -413,13 +413,6 @@ WatchJoystick(SDL_Joystick * joystick)
 
     s_nNumAxes = SDL_JoystickNumAxes(joystick);
     s_arrAxisState = (AxisState *)SDL_calloc(s_nNumAxes, sizeof(*s_arrAxisState));
-    for (iIndex = 0; iIndex < s_nNumAxes; ++iIndex) {
-        AxisState *pAxisState = &s_arrAxisState[iIndex];
-        Sint16 nInitialValue;
-        pAxisState->m_bMoving = SDL_JoystickGetAxisInitialState(joystick, iIndex, &nInitialValue);
-        pAxisState->m_nStartingValue = nInitialValue;
-        pAxisState->m_nFarthestValue = nInitialValue;
-    }
 
     /* Loop, getting joystick events! */
     while (!done && !s_bBindingComplete) {
@@ -472,9 +465,10 @@ WatchJoystick(SDL_Joystick * joystick)
                     int nValue = event.jaxis.value;
                     int nCurrentDistance, nFarthestDistance;
                     if (!pAxisState->m_bMoving) {
-                        pAxisState->m_bMoving = SDL_TRUE;
-                        pAxisState->m_nStartingValue = nValue;
-                        pAxisState->m_nFarthestValue = nValue;
+                        Sint16 nInitialValue;
+                        pAxisState->m_bMoving = SDL_JoystickGetAxisInitialState(joystick, event.jaxis.axis, &nInitialValue);
+                        pAxisState->m_nStartingValue = nInitialValue;
+                        pAxisState->m_nFarthestValue = nInitialValue;
                     }
                     nCurrentDistance = SDL_abs(nValue - pAxisState->m_nStartingValue);
                     nFarthestDistance = SDL_abs(pAxisState->m_nFarthestValue - pAxisState->m_nStartingValue);