shithub: choc

Download patch

ref: a9be9d879ad141ba6f0153bbf7e823256495065b
parent: 797a9a563b2e90849bc6eb79169a9381896eeb15
author: Simon Howard <fraggle@gmail.com>
date: Mon Apr 28 16:22:08 EDT 2014

joystick: Add support for "button axes".

Some gamepads, notably the PS3 SIXAXIS controller, provide the D-pad
not as a pair of axes, but rather as four separate buttons. Define a
special axis numbering scheme that packs two button numbers into a
single number, and allow an axis to be defined this way.

--- a/src/i_joystick.c
+++ b/src/i_joystick.c
@@ -82,10 +82,27 @@
     }
 }
 
-void I_InitJoystick(void)
+static boolean IsValidAxis(int axis)
 {
     int num_axes;
 
+    if (axis < 0)
+    {
+        return true;
+    }
+
+    if (IS_BUTTON_AXIS(axis))
+    {
+        return true;
+    }
+
+    num_axes = SDL_JoystickNumAxes(joystick);
+
+    return axis < num_axes;
+}
+
+void I_InitJoystick(void)
+{
     if (!usejoystick)
     {
         return;
@@ -115,11 +132,9 @@
         return;
     }
 
-    num_axes = SDL_JoystickNumAxes(joystick);
-
-    if (joystick_x_axis >= num_axes
-     || joystick_y_axis >= num_axes
-     || joystick_strafe_axis >= num_axes)
+    if (!IsValidAxis(joystick_x_axis)
+     || !IsValidAxis(joystick_y_axis)
+     || !IsValidAxis(joystick_strafe_axis))
     {
         printf("I_InitJoystick: Invalid joystick axis for joystick #%i "
                "(run joystick setup again)\n",
@@ -172,16 +187,34 @@
         return 0;
     }
 
-    result = SDL_JoystickGetAxis(joystick, axis);
+    // Is this a button axis? If so, we need to handle it specially.
 
-    if (invert)
+    if (IS_BUTTON_AXIS(axis))
     {
-        result = -result;
-    }
+        result = 0;
 
-    if (result < DEAD_ZONE && result > -DEAD_ZONE)
+        if (SDL_JoystickGetButton(joystick, BUTTON_AXIS_NEG(axis)))
+        {
+            result -= 32767;
+        }
+        if (SDL_JoystickGetButton(joystick, BUTTON_AXIS_POS(axis)))
+        {
+            result += 32767;
+        }
+    }
+    else
     {
-        result = 0;
+        result = SDL_JoystickGetAxis(joystick, axis);
+
+        if (invert)
+        {
+            result = -result;
+        }
+
+        if (result < DEAD_ZONE && result > -DEAD_ZONE)
+        {
+            result = 0;
+        }
     }
 
     return result;
--- a/src/i_joystick.h
+++ b/src/i_joystick.h
@@ -27,6 +27,24 @@
 #ifndef __I_JOYSTICK__
 #define __I_JOYSTICK__
 
+// If this bit is set in a configuration file axis value, the axis is
+// not actually a joystick axis, but instead is a "button axis". This
+// means that instead of reading an SDL joystick axis, we read the
+// state of two buttons to get the axis value. This is needed for eg.
+// the PS3 SIXAXIS controller, where the D-pad buttons register as
+// buttons, not as two axes.
+#define BUTTON_AXIS 0x10000
+
+// Query whether a given axis value describes a button axis.
+#define IS_BUTTON_AXIS(axis) ((axis) >= 0 && ((axis) & BUTTON_AXIS) != 0)
+
+// Get the individual buttons from a button axis value.
+#define BUTTON_AXIS_NEG(axis)  ((axis) & 0xff)
+#define BUTTON_AXIS_POS(axis)  (((axis) >> 8) & 0xff)
+
+// Create a button axis value from two button values.
+#define CREATE_BUTTON_AXIS(neg, pos) (BUTTON_AXIS | (neg) | ((pos) << 8))
+
 void I_InitJoystick(void);
 void I_ShutdownJoystick(void);
 void I_UpdateJoystick(void);