aboutsummaryrefslogtreecommitdiff
path: root/src/parsec/isdl_joy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/parsec/isdl_joy.cpp')
-rw-r--r--src/parsec/isdl_joy.cpp574
1 files changed, 574 insertions, 0 deletions
diff --git a/src/parsec/isdl_joy.cpp b/src/parsec/isdl_joy.cpp
new file mode 100644
index 0000000..e2d4df9
--- /dev/null
+++ b/src/parsec/isdl_joy.cpp
@@ -0,0 +1,574 @@
+/*
+ * PARSEC - Joystick Functions
+ *
+ * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:39 $
+ *
+ * Orginally written by:
+ * Copyright (c) Clemens Beer <cbx@parsec.org> 1999
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+// compilation flags/debug support
+#include "config.h"
+
+#if !defined ( DISABLE_JOYSTICK_CODE ) // TODO: Disabled for now.
+
+// C library
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "debug.h"
+
+
+// general definitions
+#include "general.h"
+#include "objstruc.h"
+
+// global externals
+#include "globals.h"
+
+
+// subsystem headers
+#include "inp_defs.h"
+
+// local module header
+#include "isdl_joy.h"
+
+// proprietary headers
+#include "con_aux.h"
+#include "con_int.h"
+#include "keycodes.h"
+
+
+// flags
+#define JOY_AKC_SUPPORT
+
+
+
+// ----------------------------------------------------------------------------
+//
+#define NAME_LENGTH 128
+
+
+// maximum number of joystick devices we support ------------------------------
+//
+#define MAX_JOYSTICK_DEVICES 4
+
+
+// joystick device name -------------------------------------------------------
+//
+//#define JOY_DEVICENAME_STRING "/dev/js%d"
+
+
+// external variables ---------------------------------------------------------
+//
+extern int isdl_bHasThrottle; // indicates, the joystick has a throttle
+extern int isdl_bHasRudder; // indicates, the joystick has a rudder
+extern joystate_s JoyState; // generic joystick data
+
+
+// string constants -----------------------------------------------------------
+//
+static char joystick_disabled[] = "Joystick code is disabled.\n";
+
+
+// module local variables -----------------------------------------------------
+//
+SDL_Joystick* isdl_joyHandle; // handle to the open joystick
+byte isdl_NumAxes; // number of axes for this joystick
+byte isdl_NumButtons; // number of buttons for this joystick
+
+int isdl_nJoystickFound = 0; // number of joysticks found
+
+// Joystick deadzones, in terms of SDL joystick range (-32768..32768)
+static int isdl_joyDeadZone_Min[4] = { -5, -5, -5, -5 };
+static int isdl_joyDeadZone_Max[4] = { 5, 5, 5, 5 };
+
+
+// initialize joystick device -------------------------------------------------
+//
+void ISDL_JoyInitHandler()
+{
+ SDL_InitSubSystem(SDL_INIT_JOYSTICK);
+ isdl_nJoystickFound = SDL_NumJoysticks();
+ MSGOUT("isdl_joy: Found %d joysticks.\n", isdl_nJoystickFound);
+ if(isdl_nJoystickFound > 0)
+ {
+ //TODO: Implement support for more than one stick when we have more flexible input layer stuff
+ MSGOUT("isdl_joy: ... but we don't care, because Parsec only has one JoyState\n");
+ isdl_joyHandle = SDL_JoystickOpen(0);
+ isdl_NumAxes = SDL_JoystickNumAxes(isdl_joyHandle);
+ isdl_NumButtons = SDL_JoystickNumButtons(isdl_joyHandle);
+ isdl_NumButtons = isdl_NumButtons > 32 ? 32 : isdl_NumButtons;
+ MSGOUT("isdl_joy: Joystick%d has %d axes and %d buttons\n", 0, isdl_NumAxes, isdl_NumButtons);
+ QueryJoystick = TRUE;
+ JoystickDisabled = FALSE;
+ }
+}
+
+/* //TODO: Remove old ass linux-specific code
+PRIVATE
+int ILm_JoyInit()
+{
+ if ( il_InitJoyDone )
+ return 1;
+ char szDeviceName[ 64 ];
+
+ // try to open one of the joystick devices
+ int nDevice = 0;
+ for( nDevice = 0; ( il_fd < 0 ) && ( nDevice < MAX_JOYSTICK_DEVICES ); nDevice++ ) {
+ sprintf( szDeviceName, JOY_DEVICENAME_STRING, nDevice );
+
+ il_fd = open( szDeviceName, O_RDONLY );
+ }
+
+ if ( il_fd < 0 ) {
+ // disable joystick, if no device could be opened
+ il_bDisableJoystick = TRUE;
+ } else {
+ // query number of axes, buttons, driver version and joystick name
+ ioctl( il_fd, JSIOCGVERSION, &il_version);
+ ioctl( il_fd, JSIOCGAXES, &isdl_NumAxes);
+ ioctl( il_fd, JSIOCGBUTTONS, &isdl_NumButtons);
+ ioctl( il_fd, JSIOCGNAME( NAME_LENGTH ),il_JoyName);
+
+ // sanety check, as JoyState _ONLY_ :) has 32 buttons defined
+ if( isdl_NumButtons > 32 )
+ isdl_NumButtons = 32;
+
+ MSGOUT("Using %s with %d axes and %d buttons. (Driver version %d.%d.%d on /dev/js%d)\n",
+ il_JoyName, isdl_NumAxes, isdl_NumButtons, il_version >> 16, (il_version >> 8) & 0xff, il_version & 0xff, nDevice);
+
+ //FIXME: eventually we should also support the 0.x driver version, which uses polling
+
+ // set the number of found joysticks
+ isdl_nJoystickFound = 1;
+
+ // set flags for querying the rudder/throttle
+ il_bHasRudder = isdl_NumAxes > 2;
+ il_bHasThrottle = isdl_NumAxes > 3;
+
+ // calculate the ranges
+ il_joyRange_X = JOY_DEVICE_RANGE;
+ il_joyRange_Y = JOY_DEVICE_RANGE;
+ il_joyRange_Z = JOY_DEVICE_RANGE;
+ il_joyRange_R = JOY_DEVICE_RANGE;
+
+ // calculate the dead zones
+ il_joyDeadZone_Min_X = JOY_DEVICE_MIN + ( il_joyRange_X / 2 ) - ( il_joyRange_X / 8 );
+ il_joyDeadZone_Max_X = JOY_DEVICE_MIN + ( il_joyRange_X / 2 ) + ( il_joyRange_X / 8 );
+
+ il_joyDeadZone_Min_Y = JOY_DEVICE_MIN + ( il_joyRange_Y / 2 ) - ( il_joyRange_Y / 8 );
+ il_joyDeadZone_Max_Y = JOY_DEVICE_MIN + ( il_joyRange_Y / 2 ) + ( il_joyRange_Y / 8 );
+
+ il_joyDeadZone_Min_Z = JOY_DEVICE_MIN + ( il_joyRange_Z / 2 ) - ( il_joyRange_Z / 8 );
+ il_joyDeadZone_Max_Z = JOY_DEVICE_MIN + ( il_joyRange_Z / 2 ) + ( il_joyRange_Z / 8 );
+
+ il_joyDeadZone_Min_R = JOY_DEVICE_MIN + ( il_joyRange_R / 2 ) - ( il_joyRange_R / 8 );
+ il_joyDeadZone_Max_R = JOY_DEVICE_MIN + ( il_joyRange_R / 2 ) + ( il_joyRange_R / 8 );
+
+
+ // and set the joystick device in non-blocking mode
+ fcntl(il_fd, F_SETFL, O_NONBLOCK);
+ }
+
+ isdl_nJoystickFound = SDL_NumJoysticks();
+ MSGOUT("isdl_joy: Found %d joysticks.\n", isdl_nJoystickFound);
+
+ il_InitJoyDone = TRUE;
+
+ return 1;
+}
+*/
+
+// close joystick device ------------------------------------------------------
+//
+void ISDL_JoyKillHandler()
+{
+ for (int i = 0; i < isdl_nJoystickFound; i++)
+ {
+#if SDL_VERSION_ATLEAST(2,0,0)
+ // TODO: implement
+#else
+ if (SDL_JoystickOpened(i))
+#endif
+ //SDL_JoystickClose(isdl_joyHandle[i]);
+ SDL_JoystickClose(isdl_joyHandle);
+ }
+}
+
+/* //TODO: Remove old ass linux-specific code
+PRIVATE
+int ILm_JoyExit()
+{
+ if ( !il_InitJoyDone )
+ return 1;
+
+ il_InitJoyDone = FALSE;
+
+ // close the joystick device
+ close( il_fd );
+
+ return 1;
+}
+*/
+
+// simulate assignable keypresses bound to specific joystick buttons ----------
+//
+/*
+PRIVATE
+void ILm_HandleAssignableButtonKeys( dword joy_button_changed )
+{
+
+#ifdef JOY_AKC_SUPPORT
+
+ // additional key mappings table
+ keyaddition_s *kap = KeyAdditional->table;
+ ASSERT( KeyAdditional->size >= 0 );
+ ASSERT( KeyAdditional->size <= KEY_ADDITIONS_MAX );
+
+ // check the additional assignments
+ for ( int aid = KeyAdditional->size - 1; aid >= 0; aid-- ) {
+
+ // skip non-joystick akcs
+ if ( ( kap[ aid ].code & ~AKC_JOY_FLAG ) == 0 )
+ continue;
+
+ // fetch button id by masking out flag
+ dword button = kap[ aid ].code & ~AKC_JOY_FLAG;
+ printf("derp! aid: %d button:%d\n", aid, button);
+ //ASSERT( ( button >= 0 ) && ( button <= 31 ) );
+ if(! (( button >= 0 ) && ( button <= 31 )) )
+ continue;
+
+ // check button changed
+ if ( joy_button_changed & ( 1 << button ) ) {
+
+ //NOTE:
+ // the actual execution of the mapped command will be
+ // done by CON_KMAP::ExecBoundKeyCommands(). this
+ // function only simulates some kind of special keys
+ // using codes that cannot occur via the keyboard.
+
+ // set the state flag
+ kap[ aid ].state = JoyState.Buttons[ button ];
+ }
+ }
+
+#endif // JOY_AKC_SUPPORT
+
+}
+*/
+
+// axes swapping flags --------------------------------------------------------
+//
+static int isdl_swap_axes01 = FALSE;
+static int isdl_swap_axes23 = FALSE;
+
+
+// set value for joystick axis x ----------------------------------------------
+//
+/*PRIVATE
+void ILm_JoyAxisX( Sint16 value )
+{
+ // check against dead zone
+ if ( ( (dword)value < il_joyDeadZone_Min_X ) || ( (dword)value > il_joyDeadZone_Max_X ) ) {
+ JoyState.X = JOY_X_MIN + int( float( value - JOY_DEVICE_MIN ) /
+ float( il_joyRange_X ) * ( JOY_X_RANGE ) );
+ } else {
+ JoyState.X = JOY_X_ZERO;
+ }
+}
+
+
+// set value for joystick axis y ----------------------------------------------
+//
+PRIVATE
+void ILm_JoyAxisY( Sint16 value )
+{
+ // check against dead zone
+ if ( ( (dword)value < il_joyDeadZone_Min_Y ) || ( (dword)value > il_joyDeadZone_Max_Y ) ) {
+ JoyState.Y = JOY_Y_MIN + int( float( value - JOY_DEVICE_MIN ) /
+ float( il_joyRange_Y ) * ( JOY_Y_RANGE ) );
+ } else {
+ JoyState.Y = JOY_Y_ZERO;
+ }
+}
+
+
+// set value for joystick axis z (throttle) -----------------------------------
+//
+PRIVATE
+void ILm_JoyAxisZ( Sint16 value )
+{
+ // NOTE: no dead zone check for the throttle
+ JoyState.Z = JOY_THROTTLE_MIN + int( float( value - JOY_DEVICE_MIN ) /
+ float( il_joyRange_Z ) * ( JOY_THROTTLE_RANGE ) );
+}
+
+
+// set value for joystick axis r (rudder) -------------------------------------
+//
+PRIVATE
+void ILm_JoyAxisR( Sint16 value )
+{
+ if ( ( (dword)value < il_joyDeadZone_Min_R ) || ( (dword)value > il_joyDeadZone_Max_R ) ) {
+ JoyState.Rz = JOY_RUDDER_MIN + int( float( value - JOY_DEVICE_MIN ) /
+ float( il_joyRange_R ) * ( JOY_RUDDER_RANGE ) );
+ } else {
+ JoyState.Rz = JOY_RUDDER_ZERO;
+ }
+ } */
+
+// apply deadzones ------------------------------------------------------------
+//
+PRIVATE
+int ISDL_ApplyDZ(int value, int axis)
+{
+ if ( value > isdl_joyDeadZone_Min[axis] &&
+ value < isdl_joyDeadZone_Max[axis] )
+ return 0;
+ else
+ return value;
+}
+
+
+// read current joystick state ( positions and buttons ) ----------------------
+//
+void ISDL_JoyCollect()
+{
+ if ( !QueryJoystick )
+ return;
+
+ joystate_s _OldJoyState = JoyState; // Save previous JoyState to detect changes
+
+ // Read Axes
+ if (isdl_NumAxes >= 2)
+ {
+ if(isdl_swap_axes01)
+ {
+ JoyState.X = ISDL_ApplyDZ(SDL_JoystickGetAxis(isdl_joyHandle, 1), 1) / JOY_Y_DIV;
+ JoyState.Y = ISDL_ApplyDZ(SDL_JoystickGetAxis(isdl_joyHandle, 0), 0) / JOY_X_DIV;
+ }
+ else
+ {
+ JoyState.X = ISDL_ApplyDZ(SDL_JoystickGetAxis(isdl_joyHandle, 0), 0) / JOY_X_DIV;
+ JoyState.Y = ISDL_ApplyDZ(SDL_JoystickGetAxis(isdl_joyHandle, 1), 1) / JOY_Y_DIV;
+ }
+ }
+ if (isdl_NumAxes >= 3)
+ {
+ if(isdl_swap_axes23)
+ {
+ JoyState.Rz = ISDL_ApplyDZ(SDL_JoystickGetAxis(isdl_joyHandle, 2), 2) / JOY_RUDDER_DIV;
+ isdl_bHasRudder = TRUE;
+ }
+ else
+ {
+ // Do not apply deadzones to throttle
+ JoyState.Z = SDL_JoystickGetAxis(isdl_joyHandle, 2) / JOY_THROTTLE_DIV + JOY_THROTTLE_OFF;
+ isdl_bHasThrottle = TRUE;
+ }
+ }
+ if (isdl_NumAxes >= 4)
+ {
+ if(isdl_swap_axes23)
+ {
+ // Do not apply deadzones to throttle
+ JoyState.Z = SDL_JoystickGetAxis(isdl_joyHandle, 3) / JOY_THROTTLE_DIV + JOY_THROTTLE_OFF;
+ isdl_bHasThrottle = TRUE;
+ }
+ else
+ {
+ JoyState.Rz = ISDL_ApplyDZ(SDL_JoystickGetAxis(isdl_joyHandle, 3), 3) / JOY_RUDDER_DIV;
+ isdl_bHasRudder = TRUE;
+ }
+ }
+
+ // Read buttons
+ keyaddition_s *kap = KeyAdditional->table;
+ ASSERT( KeyAdditional->size >= 0 );
+ ASSERT( KeyAdditional->size <= KEY_ADDITIONS_MAX );
+ for (int button = 0; button < isdl_NumButtons; button++) {
+ JoyState.Buttons[button] = SDL_JoystickGetButton(isdl_joyHandle, button);
+
+#ifdef JOY_AKC_SUPPORT
+ if ( _OldJoyState.Buttons[button] != JoyState.Buttons[button]) {
+ for (int aid = 1; aid < KeyAdditional->size; aid++) {
+ if (kap[aid].code == ((dword)button | (dword)AKC_JOY_FLAG)) {
+ kap[aid].state = (JoyState.Buttons[button] ? TRUE : FALSE);
+ }
+ }
+ }
+#endif // JOY_AKC_SUPPORT
+ }
+/*
+ // Fake AKC_ keys for joystick buttons that fit in it
+
+ if ( AUX_ENABLE_JOYSTICK_BINDING ) {
+
+ int mask = 0x0001;
+ int joy_button_changed = 0x0000;
+
+ // check which buttons have changed
+ for ( int nButton = 0; nButton < isdl_NumButtons; nButton++ ) {
+
+ // check for button changed
+ joy_button_changed |= ( _OldJoyState.Buttons[ nButton ] != JoyState.Buttons[ nButton ] ) ? mask : 0;
+
+ mask = mask << 1;
+ }
+
+ ILm_HandleAssignableButtonKeys( joy_button_changed );
+ }
+*/
+ // Confused yet? Me too...
+}
+
+/* //TODO: Remove ancient Linux-specific joystick code.
+PRIVATE
+int ILm_ReadJoystickData()
+{
+ if ( !QueryJoystick )
+ return FALSE;
+ struct js_event js;
+
+#ifdef JOY_AKC_SUPPORT
+
+ joystate_s _OldJoyState;
+
+ if ( AUX_ENABLE_JOYSTICK_BINDING ) {
+ // copy the previous joystate;
+ memcpy( &_OldJoyState, &JoyState, sizeof( joystate_s ) );
+ }
+
+#endif // JOY_AKC_SUPPORT
+
+ // read in all the pending joystick events
+ while ( read( il_fd, &js, sizeof( struct js_event ) ) == sizeof( struct js_event ) ) {
+
+ switch ( js.type & ~JS_EVENT_INIT ) {
+
+ case JS_EVENT_BUTTON:
+ JoyState.Buttons[ js.number ] = js.value ? 0x80 : 0x00;
+ break;
+
+ case JS_EVENT_AXIS:
+ switch ( js.number ) {
+
+ case 0:
+ if ( !isdl_swap_axes01 ) {
+ ILm_JoyAxisX( js.value );
+ } else {
+ ILm_JoyAxisY( js.value );
+ }
+ break;
+
+ case 1:
+ if ( !isdl_swap_axes01 ) {
+ ILm_JoyAxisY( js.value );
+ } else {
+ ILm_JoyAxisX( js.value );
+ }
+ break;
+
+ case 2:
+ if ( !isdl_swap_axes23 ) {
+ ILm_JoyAxisZ( js.value );
+ } else {
+ ILm_JoyAxisR( js.value );
+ }
+ break;
+
+ case 3:
+ if ( !isdl_swap_axes23 ) {
+ ILm_JoyAxisR( js.value );
+ } else {
+ ILm_JoyAxisZ( js.value );
+ }
+ break;
+ }
+ break;
+ }
+
+// MSGOUT( "Event: type %d, time %d, number %d, value %d\n",
+// js.type, js.time, js.number, js.value);
+ }
+
+#ifdef JOY_AKC_SUPPORT
+
+ if ( AUX_ENABLE_JOYSTICK_BINDING ) {
+
+ int mask = 0x0001;
+ int joy_button_changed = 0x0000;
+
+ // check which buttons have changed
+ for ( int nButton = 0; nButton < isdl_NumButtons; nButton++ ) {
+
+ // check for button changed
+ joy_button_changed |= ( _OldJoyState.Buttons[ nButton ] != JoyState.Buttons[ nButton ] ) ? mask : 0;
+
+ mask = mask << 1;
+ }
+
+ ILm_HandleAssignableButtonKeys( joy_button_changed );
+ }
+
+#endif // JOY_AKC_SUPPORT
+
+ // check for error condition while reading
+ if ( errno != EAGAIN ) {
+ MSGOUT( "error reading from joystick." );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+*/
+
+
+
+// registration table for joystick config flags -------------------------------
+//
+int_command_s il_joy_int_commands[] = {
+
+ { 0x01, "isdl.swap_joyaxes_01" , 0, 1, &isdl_swap_axes01, NULL, NULL },
+ { 0x01, "isdl.swap_joyaxes_23" , 0, 1, &isdl_swap_axes23, NULL, NULL },
+ { 0x01, "isdl.deadzone_min_axis_0", -32768, 0, &isdl_joyDeadZone_Min[0], NULL, NULL },
+ { 0x01, "isdl.deadzone_min_axis_1", -32768, 0, &isdl_joyDeadZone_Min[1], NULL, NULL },
+ { 0x01, "isdl.deadzone_min_axis_2", -32768, 0, &isdl_joyDeadZone_Min[2], NULL, NULL },
+ { 0x01, "isdl.deadzone_min_axis_3", -32768, 0, &isdl_joyDeadZone_Min[3], NULL, NULL },
+ { 0x01, "isdl.deadzone_max_axis_0", 0, 32767, &isdl_joyDeadZone_Max[0], NULL, NULL },
+ { 0x01, "isdl.deadzone_max_axis_1", 0, 32767, &isdl_joyDeadZone_Max[1], NULL, NULL },
+ { 0x01, "isdl.deadzone_max_axis_2", 0, 32767, &isdl_joyDeadZone_Max[2], NULL, NULL },
+ { 0x01, "isdl.deadzone_max_axis_3", 0, 32767, &isdl_joyDeadZone_Max[3], NULL, NULL },
+
+};
+
+#define NUM_IL_JOY_INT_COMMANDS CALC_NUM_ARRAY_ENTRIES( il_joy_int_commands )
+
+
+// module registration function -----------------------------------------------
+//
+REGISTER_MODULE( IL_JOY )
+{
+ // register joystick config flags
+ for ( unsigned int curcmd = 0; curcmd < NUM_IL_JOY_INT_COMMANDS; curcmd++ ) {
+ CON_RegisterIntCommand( &il_joy_int_commands[ curcmd ] );
+ }
+}
+
+#endif