shithub: choc

Download patch

ref: 8659cfd6409dcf093fc6d89e89bd38da391ba009
parent: 242fa1ee46f90f451c625e90f16927e13030c0a0
author: Simon Howard <fraggle@gmail.com>
date: Tue Apr 29 19:45:29 EDT 2014

setup: Detect and ignore bad joystick axes.

In some cases a joystick axis can be "stuck" and have a large
uncentered value. These must be detected and ignored, otherwise the
axis can be chosen during calibration instead of the user's actual
desired axis.

--- a/src/setup/joystick.c
+++ b/src/setup/joystick.c
@@ -62,6 +62,15 @@
 
 static int calibrate_button = -1;
 
+// "Bad" joystick axes. Sometimes an axis can be stuck or "bad". An
+// example I found is that if you unplug the nunchuck extension from
+// a Wii remote, the axes from the nunchuck can be stuck at one of
+// the maximum values. These have to be ignored, so when we ask the
+// user to center the joystick, we look for bad axes that are not
+// close to zero.
+
+static boolean *bad_axis = NULL;
+
 // Which joystick axis to use for horizontal movement, and whether to
 // invert the direction:
 
@@ -301,6 +310,11 @@
 
     for (i=0; i<SDL_JoystickNumAxes(joystick); ++i)
     {
+        if (bad_axis[i])
+        {
+            continue;
+        }
+
         axis_value = SDL_JoystickGetAxis(joystick, i);
 
         if (abs(axis_value) > best_value)
@@ -406,6 +420,31 @@
     }
 }
 
+static void IdentifyBadAxes(void)
+{
+    SDL_Joystick *joystick;
+    int i, val;
+
+    free(bad_axis);
+
+    joystick = all_joysticks[joystick_index];
+    bad_axis = calloc(SDL_JoystickNumAxes(joystick), sizeof(boolean));
+
+    // Look for uncentered axes.
+
+    for (i = 0; i < SDL_JoystickNumAxes(joystick); ++i)
+    {
+        val = SDL_JoystickGetAxis(joystick, i);
+
+        bad_axis[i] = abs(val) > (32768 / 5);
+
+        if (bad_axis[i])
+        {
+            printf("Ignoring uncentered joystick axis #%i: %i\n", i, val);
+        }
+    }
+}
+
 static int CalibrationEventCallback(SDL_Event *event, void *user_data)
 {
     boolean advance;
@@ -422,6 +461,7 @@
     {
         joystick_index = event->jbutton.which;
         calibrate_button = event->jbutton.button;
+        IdentifyBadAxes();
 
         // Advance to next stage.
         calibrate_stage = CALIBRATE_LEFT;