src/joystick/os2/SDL_sysjoystick.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 29 May 2006 04:04:35 +0000
branchSDL-1.3
changeset 1668 4da1ee79c9af
parent 1662 782fd950bd46
permissions -rw-r--r--
more tweaking indent options
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #ifdef SDL_JOYSTICK_OS2
    25 
    26 /* OS/2 Joystick driver, contributed by Daniel Caetano */
    27 
    28 #include <mem.h>
    29 
    30 #define INCL_DOSDEVICES
    31 #define INCL_DOSDEVIOCTL
    32 #define INCL_DOSMEMMGR
    33 #include <os2.h>
    34 #include "joyos2.h"
    35 
    36 #include "SDL_joystick.h"
    37 #include "SDL_events.h"
    38 #include "../SDL_sysjoystick.h"
    39 #include "../SDL_joystick_c.h"
    40 
    41 HFILE hJoyPort = NULL;          /* Joystick GAME$ Port Address */
    42 #define MAX_JOYSTICKS	2       /* Maximum of two joysticks */
    43 #define MAX_AXES	4       /* each joystick can have up to 4 axes */
    44 #define MAX_BUTTONS	8       /* 8 buttons */
    45 #define MAX_HATS	0       /* 0 hats - OS/2 doesn't support it */
    46 #define MAX_BALLS	0       /* and 0 balls - OS/2 doesn't support it */
    47 #define AXIS_MIN -32768         /* minimum value for axes coordinate */
    48 #define AXIS_MAX 32767          /* maximum value for axes coordinate */
    49 #define MAX_JOYNAME	128     /* Joystick name may have 128 characters */
    50 /* limit axes to 256 possible positions to filter out noise */
    51 #define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/256)
    52 /* Calc Button Flag for buttons A to D */
    53 #define JOY_BUTTON_FLAG(n) (1<<n)
    54 
    55 /* Joystick data... hold information about detected devices */
    56 typedef struct SYS_JoyData_s
    57 {
    58     Sint8 id;                   // Device ID
    59     char szDeviceName[MAX_JOYNAME];     // Device Name
    60     char axes;                  // Number of axes
    61     char buttons;               // Number of buttons
    62     char hats;                  // Number of buttons
    63     char balls;                 // Number of buttons
    64     int axes_min[MAX_AXES];     // minimum callibration value for axes
    65     int axes_med[MAX_AXES];     // medium callibration value for axes
    66     int axes_max[MAX_AXES];     // maximum callibration value for axes
    67     int buttoncalc[4];          // Used for buttons 5, 6, 7 and 8.
    68 } SYS_JoyData_t, *SYS_JoyData_p;
    69 
    70 SYS_JoyData_t SYS_JoyData[MAX_JOYSTICKS];
    71 
    72 
    73 /* Structure used to convert data from OS/2 driver format to SDL format */
    74 struct joystick_hwdata
    75 {
    76     Sint8 id;
    77     struct _transaxes
    78     {
    79         int offset;             /* Center Offset */
    80         float scale1;           /* Center to left/up Scale */
    81         float scale2;           /* Center to right/down Scale */
    82     } transaxes[MAX_AXES];
    83 };
    84 
    85 /* Structure used to get values from Joystick Environment Variable */
    86 struct _joycfg
    87 {
    88     char name[MAX_JOYNAME];
    89     unsigned int axes;
    90     unsigned int buttons;
    91     unsigned int hats;
    92     unsigned int balls;
    93 };
    94 
    95 /* OS/2 Implementation Function Prototypes */
    96 APIRET joyPortOpen(HFILE * hGame);
    97 void joyPortClose(HFILE * hGame);
    98 int joyGetData(char *joyenv, char *name, char stopchar, size_t maxchars);
    99 int joyGetEnv(struct _joycfg *joydata);
   100 
   101 
   102 
   103 /************************************************************************/
   104 /* Function to scan the system for joysticks.									*/
   105 /* This function should set SDL_numjoysticks to the number of available	*/
   106 /* joysticks.  Joystick 0 should be the system default joystick.			*/
   107 /* It should return 0, or -1 on an unrecoverable fatal error.				*/
   108 /************************************************************************/
   109 int
   110 SDL_SYS_JoystickInit(void)
   111 {
   112     APIRET rc;                  /* Generic OS/2 return code */
   113     GAME_PORT_STRUCT stJoyStatus;       /* Joystick Status Structure */
   114     GAME_PARM_STRUCT stGameParms;       /* Joystick Parameter Structure */
   115     GAME_CALIB_STRUCT stGameCalib;      /* Calibration Struct */
   116     ULONG ulDataLen;            /* Size of data */
   117     ULONG ulLastTick;           /* Tick Counter for timing operations */
   118     Uint8 maxdevs;              /* Maximum number of devices */
   119     Uint8 numdevs;              /* Number of present devices */
   120     Uint8 maxbut;               /* Maximum number of buttons... */
   121     Uint8 i;                    /* Temporary Count Vars */
   122     Uint8 ucNewJoystickMask;    /* Mask for Joystick Detection */
   123     struct _joycfg joycfg;      /* Joy Configuration from envvar */
   124 
   125 
   126 /* Get Max Number of Devices */
   127     rc = joyPortOpen(&hJoyPort);        /* Open GAME$ port */
   128     if (rc != 0)
   129         return 0;               /* Cannot open... report no joystick */
   130     ulDataLen = sizeof(stGameParms);
   131     rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_PARMS, NULL, 0, NULL, &stGameParms, ulDataLen, &ulDataLen);     /* Ask device info */
   132     if (rc != 0) {
   133         joyPortClose(&hJoyPort);
   134         SDL_SetError("Could not read joystick port.");
   135         return -1;
   136     }
   137     if (stGameParms.useA != 0)
   138         maxdevs++;
   139     if (stGameParms.useB != 0)
   140         maxdevs++;
   141     if (maxdevs > MAX_JOYSTICKS)
   142         maxdevs = MAX_JOYSTICKS;
   143 
   144 /* Defines min/max axes values (callibration) */
   145     ulDataLen = sizeof(stGameCalib);
   146     rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_CALIB,
   147                      NULL, 0, NULL, &stGameCalib, ulDataLen, &ulDataLen);
   148     if (rc != 0) {
   149         joyPortClose(&hJoyPort);
   150         SDL_SetError("Could not read callibration data.");
   151         return -1;
   152     }
   153 
   154 /* Determine how many joysticks are active */
   155     numdevs = 0;                /* Points no device */
   156     ucNewJoystickMask = 0x0F;   /* read all 4 joystick axis */
   157     ulDataLen = sizeof(ucNewJoystickMask);
   158     rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_RESET,
   159                      &ucNewJoystickMask, ulDataLen, &ulDataLen, NULL, 0,
   160                      NULL);
   161     if (rc == 0) {
   162         ulDataLen = sizeof(stJoyStatus);
   163         rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_GET,
   164                          NULL, 0, NULL, &stJoyStatus, ulDataLen, &ulDataLen);
   165         if (rc != 0) {
   166             joyPortClose(&hJoyPort);
   167             SDL_SetError("Could not call joystick port.");
   168             return -1;
   169         }
   170         ulLastTick = stJoyStatus.ulJs_Ticks;
   171         while (stJoyStatus.ulJs_Ticks == ulLastTick) {
   172             rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_GET,
   173                              NULL, 0, NULL, &stJoyStatus, ulDataLen,
   174                              &ulDataLen);
   175         }
   176         if ((stJoyStatus.ucJs_JoyStickMask & 0x03) > 0)
   177             numdevs++;
   178         if (((stJoyStatus.ucJs_JoyStickMask >> 2) & 0x03) > 0)
   179             numdevs++;
   180     }
   181 
   182     if (numdevs > maxdevs)
   183         numdevs = maxdevs;
   184 
   185 /* If *any* joystick was detected... Let's configure SDL for them */
   186     if (numdevs > 0) {
   187         /* Verify if it is a "user defined" joystick */
   188         if (joyGetEnv(&joycfg)) {
   189             GAME_3POS_STRUCT *axis[4];
   190             axis[0] = &stGameCalib.Ax;
   191             axis[1] = &stGameCalib.Ay;
   192             axis[2] = &stGameCalib.Bx;
   193             axis[3] = &stGameCalib.By;
   194             /* Say it has one device only (user defined is always one device only) */
   195             numdevs = 1;
   196             /* Define Device 0 as... */
   197             SYS_JoyData[0].id = 0;
   198             /* Define Number of Axes... up to 4 */
   199             if (joycfg.axes > MAX_AXES)
   200                 joycfg.axes = MAX_AXES;
   201             SYS_JoyData[0].axes = joycfg.axes;
   202             /* Define number of buttons... 8 if 2 axes, 6 if 3 axes and 4 if 4 axes */
   203             maxbut = MAX_BUTTONS;
   204             if (joycfg.axes > 2)
   205                 maxbut -= ((joycfg.axes - 2) << 1);     /* MAX_BUTTONS - 2*(axes-2) */
   206             if (joycfg.buttons > maxbut)
   207                 joycfg.buttons = maxbut;
   208             SYS_JoyData[0].buttons = joycfg.buttons;
   209             /* Define number of hats */
   210             if (joycfg.hats > MAX_HATS)
   211                 joycfg.hats = MAX_HATS;
   212             SYS_JoyData[0].hats = joycfg.hats;
   213             /* Define number of balls */
   214             if (joycfg.balls > MAX_BALLS)
   215                 joycfg.balls = MAX_BALLS;
   216             SYS_JoyData[0].balls = joycfg.balls;
   217             /* Initialize Axes Callibration Values */
   218             for (i = 0; i < joycfg.axes; i++) {
   219                 SYS_JoyData[0].axes_min[i] = axis[i]->lower;
   220                 SYS_JoyData[0].axes_med[i] = axis[i]->centre;
   221                 SYS_JoyData[0].axes_max[i] = axis[i]->upper;
   222             }
   223             /* Initialize Buttons 5 to 8 structures */
   224             if (joycfg.buttons >= 5)
   225                 SYS_JoyData[0].buttoncalc[0] =
   226                     ((axis[2]->lower + axis[3]->centre) >> 1);
   227             if (joycfg.buttons >= 6)
   228                 SYS_JoyData[0].buttoncalc[1] =
   229                     ((axis[3]->lower + axis[3]->centre) >> 1);
   230             if (joycfg.buttons >= 7)
   231                 SYS_JoyData[0].buttoncalc[2] =
   232                     ((axis[2]->upper + axis[3]->centre) >> 1);
   233             if (joycfg.buttons >= 8)
   234                 SYS_JoyData[0].buttoncalc[3] =
   235                     ((axis[3]->upper + axis[3]->centre) >> 1);
   236             /* Intialize Joystick Name */
   237             SDL_strlcpy(SYS_JoyData[0].szDeviceName, joycfg.name,
   238                         SDL_arraysize(SYS_JoyData[0].szDeviceName));
   239         }
   240         /* Default Init ... autoconfig */
   241         else {
   242             /* if two devices were detected... configure as Joy1 4 axis and Joy2 2 axis */
   243             if (numdevs == 2) {
   244                 /* Define Device 0 as 4 axes, 4 buttons */
   245                 SYS_JoyData[0].id = 0;
   246                 SYS_JoyData[0].axes = 4;
   247                 SYS_JoyData[0].buttons = 4;
   248                 SYS_JoyData[0].hats = 0;
   249                 SYS_JoyData[0].balls = 0;
   250                 SYS_JoyData[0].axes_min[0] = stGameCalib.Ax.lower;
   251                 SYS_JoyData[0].axes_med[0] = stGameCalib.Ax.centre;
   252                 SYS_JoyData[0].axes_max[0] = stGameCalib.Ax.upper;
   253                 SYS_JoyData[0].axes_min[1] = stGameCalib.Ay.lower;
   254                 SYS_JoyData[0].axes_med[1] = stGameCalib.Ay.centre;
   255                 SYS_JoyData[0].axes_max[1] = stGameCalib.Ay.upper;
   256                 SYS_JoyData[0].axes_min[2] = stGameCalib.Bx.lower;
   257                 SYS_JoyData[0].axes_med[2] = stGameCalib.Bx.centre;
   258                 SYS_JoyData[0].axes_max[2] = stGameCalib.Bx.upper;
   259                 SYS_JoyData[0].axes_min[3] = stGameCalib.By.lower;
   260                 SYS_JoyData[0].axes_med[3] = stGameCalib.By.centre;
   261                 SYS_JoyData[0].axes_max[3] = stGameCalib.By.upper;
   262                 /* Define Device 1 as 2 axes, 2 buttons */
   263                 SYS_JoyData[1].id = 1;
   264                 SYS_JoyData[1].axes = 2;
   265                 SYS_JoyData[1].buttons = 2;
   266                 SYS_JoyData[1].hats = 0;
   267                 SYS_JoyData[1].balls = 0;
   268                 SYS_JoyData[1].axes_min[0] = stGameCalib.Bx.lower;
   269                 SYS_JoyData[1].axes_med[0] = stGameCalib.Bx.centre;
   270                 SYS_JoyData[1].axes_max[0] = stGameCalib.Bx.upper;
   271                 SYS_JoyData[1].axes_min[1] = stGameCalib.By.lower;
   272                 SYS_JoyData[1].axes_med[1] = stGameCalib.By.centre;
   273                 SYS_JoyData[1].axes_max[1] = stGameCalib.By.upper;
   274             }
   275             /* One joystick only? */
   276             else {
   277                 /* If it is joystick A... */
   278                 if ((stJoyStatus.ucJs_JoyStickMask & 0x03) > 0) {
   279                     /* Define Device 0 as 2 axes, 4 buttons */
   280                     SYS_JoyData[0].id = 0;
   281                     SYS_JoyData[0].axes = 2;
   282                     SYS_JoyData[0].buttons = 4;
   283                     SYS_JoyData[0].hats = 0;
   284                     SYS_JoyData[0].balls = 0;
   285                     SYS_JoyData[0].axes_min[0] = stGameCalib.Ax.lower;
   286                     SYS_JoyData[0].axes_med[0] = stGameCalib.Ax.centre;
   287                     SYS_JoyData[0].axes_max[0] = stGameCalib.Ax.upper;
   288                     SYS_JoyData[0].axes_min[1] = stGameCalib.Ay.lower;
   289                     SYS_JoyData[0].axes_med[1] = stGameCalib.Ay.centre;
   290                     SYS_JoyData[0].axes_max[1] = stGameCalib.Ay.upper;
   291                 }
   292                 /* If not, it is joystick B */
   293                 else {
   294                     /* Define Device 1 as 2 axes, 2 buttons */
   295                     SYS_JoyData[0].id = 1;
   296                     SYS_JoyData[0].axes = 2;
   297                     SYS_JoyData[0].buttons = 2;
   298                     SYS_JoyData[0].hats = 0;
   299                     SYS_JoyData[0].balls = 0;
   300                     SYS_JoyData[0].axes_min[0] = stGameCalib.Bx.lower;
   301                     SYS_JoyData[0].axes_med[0] = stGameCalib.Bx.centre;
   302                     SYS_JoyData[0].axes_max[0] = stGameCalib.Bx.upper;
   303                     SYS_JoyData[0].axes_min[1] = stGameCalib.By.lower;
   304                     SYS_JoyData[0].axes_med[1] = stGameCalib.By.centre;
   305                     SYS_JoyData[0].axes_max[1] = stGameCalib.By.upper;
   306                 }
   307             }
   308             /* Hack to define Joystick Port Names */
   309             if (numdevs > maxdevs)
   310                 numdevs = maxdevs;
   311             for (i = 0; i < numdevs; i++)
   312                 SDL_snprintf(SYS_JoyData[i].szDeviceName,
   313                              SDL_arraysize(SYS_JoyData[i].szDeviceName),
   314                              "Default Joystick %c", 'A' + SYS_JoyData[i].id);
   315 
   316         }
   317     }
   318 /* Return the number of devices found */
   319     return (numdevs);
   320 }
   321 
   322 
   323 /***********************************************************/
   324 /* Function to get the device-dependent name of a joystick */
   325 /***********************************************************/
   326 const char *
   327 SDL_SYS_JoystickName(int index)
   328 {
   329 /* No need to verify if device exists, already done in upper layer */
   330     return (SYS_JoyData[index].szDeviceName);
   331 }
   332 
   333 
   334 
   335 /******************************************************************************/
   336 /* Function to open a joystick for use.													*/
   337 /* The joystick to open is specified by the index field of the joystick.		*/
   338 /* This should fill the nbuttons and naxes fields of the joystick structure.	*/
   339 /* It returns 0, or -1 if there is an error.												*/
   340 /******************************************************************************/
   341 int
   342 SDL_SYS_JoystickOpen(SDL_Joystick * joystick)
   343 {
   344     int index;                  /* Index shortcut for index in joystick structure */
   345     int i;                      /* Generic Counter */
   346 
   347 /* allocate memory for system specific hardware data */
   348     joystick->hwdata =
   349         (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata));
   350     if (joystick->hwdata == NULL) {
   351         SDL_OutOfMemory();
   352         return (-1);
   353     }
   354 /* Reset Hardware Data */
   355     SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
   356 
   357 /* ShortCut Pointer */
   358     index = joystick->index;
   359 /* Define offsets and scales for all axes */
   360     joystick->hwdata->id = SYS_JoyData[index].id;
   361     for (i = 0; i < MAX_AXES; ++i) {
   362         if ((i < 2) || i < SYS_JoyData[index].axes) {
   363             joystick->hwdata->transaxes[i].offset =
   364                 ((AXIS_MAX + AXIS_MIN) >> 1) - SYS_JoyData[index].axes_med[i];
   365             //joystick->hwdata->transaxes[i].scale = (float)((AXIS_MAX - AXIS_MIN)/(SYS_JoyData[index].axes_max[i]-SYS_JoyData[index].axes_min[i]));
   366             joystick->hwdata->transaxes[i].scale1 =
   367                 (float) abs((AXIS_MIN / SYS_JoyData[index].axes_min[i]));
   368             joystick->hwdata->transaxes[i].scale2 =
   369                 (float) abs((AXIS_MAX / SYS_JoyData[index].axes_max[i]));
   370         } else {
   371             joystick->hwdata->transaxes[i].offset = 0;
   372             //joystick->hwdata->transaxes[i].scale = 1.0; /* Just in case */
   373             joystick->hwdata->transaxes[i].scale1 = 1.0;        /* Just in case */
   374             joystick->hwdata->transaxes[i].scale2 = 1.0;        /* Just in case */
   375         }
   376     }
   377 
   378 /* fill nbuttons, naxes, and nhats fields */
   379     joystick->nbuttons = SYS_JoyData[index].buttons;
   380     joystick->naxes = SYS_JoyData[index].axes;
   381 /* joystick->nhats = SYS_JoyData[index].hats; */
   382     joystick->nhats = 0;        /* No support for hats at this time */
   383 /* joystick->nballs = SYS_JoyData[index].balls; */
   384     joystick->nballs = 0;       /* No support for balls at this time */
   385     return 0;
   386 }
   387 
   388 
   389 
   390 /***************************************************************************/
   391 /* Function to update the state of a joystick - called as a device poll.	*/
   392 /* This function shouldn't update the joystick structure directly,			*/
   393 /* but instead should call SDL_PrivateJoystick*() to deliver events			*/
   394 /* and update joystick device state.													*/
   395 /***************************************************************************/
   396 void
   397 SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
   398 {
   399     APIRET rc;                  /* Generic OS/2 return code */
   400     int index;                  /* index shortcurt to joystick index */
   401     int i;                      /* Generic counter */
   402     int normbut;                /* Number of buttons reported by joystick */
   403     int corr;                   /* Correction for button names */
   404     Sint16 value, change;       /* Values used to update axis values */
   405     struct _transaxes *transaxes;       /* Shortcut for Correction structure */
   406     Uint32 pos[MAX_AXES];       /* Vector to inform the Axis status */
   407     ULONG ulDataLen;            /* Size of data */
   408     GAME_STATUS_STRUCT stGameStatus;    /* Joystick Status Structure */
   409 
   410     ulDataLen = sizeof(stGameStatus);
   411     rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_STATUS,
   412                      NULL, 0, NULL, &stGameStatus, ulDataLen, &ulDataLen);
   413     if (rc != 0) {
   414         SDL_SetError("Could not read joystick status.");
   415         return;                 /* Could not read data */
   416     }
   417 
   418 /* Shortcut pointer */
   419     index = joystick->index;
   420 /* joystick motion events */
   421 
   422     if (SYS_JoyData[index].id == 0) {
   423         pos[0] = stGameStatus.curdata.A.x;
   424         pos[1] = stGameStatus.curdata.A.y;
   425         if (SYS_JoyData[index].axes >= 3)
   426             pos[2] = stGameStatus.curdata.B.x;
   427         else
   428             pos[2] = 0;
   429         if (SYS_JoyData[index].axes >= 4)
   430             pos[3] = stGameStatus.curdata.B.y;
   431         else
   432             pos[3] = 0;
   433         pos[4] = 0;             /* OS/2 basic drivers do not support more than 4 axes joysticks */
   434         pos[5] = 0;
   435     } else if (SYS_JoyData[index].id == 1) {
   436         pos[0] = stGameStatus.curdata.B.x;
   437         pos[1] = stGameStatus.curdata.B.y;
   438         pos[2] = 0;
   439         pos[3] = 0;
   440         pos[4] = 0;
   441         pos[5] = 0;
   442     }
   443 
   444 /* Corrects the movements using the callibration */
   445     transaxes = joystick->hwdata->transaxes;
   446     for (i = 0; i < joystick->naxes; i++) {
   447         value = pos[i] + transaxes[i].offset;
   448         if (value < 0) {
   449             value *= transaxes[i].scale1;
   450             if (value > 0)
   451                 value = AXIS_MIN;
   452         } else {
   453             value *= transaxes[i].scale2;
   454             if (value < 0)
   455                 value = AXIS_MAX;
   456         }
   457         change = (value - joystick->axes[i]);
   458         if ((change < -JOY_AXIS_THRESHOLD) || (change > JOY_AXIS_THRESHOLD)) {
   459             SDL_PrivateJoystickAxis(joystick, (Uint8) i, (Sint16) value);
   460         }
   461     }
   462 
   463 /* joystick button A to D events */
   464     if (SYS_JoyData[index].id == 1)
   465         corr = 2;
   466     else
   467         corr = 0;
   468     normbut = 4;                /* Number of normal buttons */
   469     if (joystick->nbuttons < normbut)
   470         normbut = joystick->nbuttons;
   471     for (i = corr; (i - corr) < normbut; ++i) {
   472         /*
   473            Button A: 1110 0000
   474            Button B: 1101 0000
   475            Button C: 1011 0000
   476            Button D: 0111 0000
   477          */
   478         if ((~stGameStatus.curdata.butMask) >> 4 & JOY_BUTTON_FLAG(i)) {
   479             if (!joystick->buttons[i - corr]) {
   480                 SDL_PrivateJoystickButton(joystick, (Uint8) (i - corr),
   481                                           SDL_PRESSED);
   482             }
   483         } else {
   484             if (joystick->buttons[i - corr]) {
   485                 SDL_PrivateJoystickButton(joystick, (Uint8) (i - corr),
   486                                           SDL_RELEASED);
   487             }
   488         }
   489     }
   490 
   491 /* Joystick button E to H buttons */
   492     /*
   493        Button E: Axis 2 X Left
   494        Button F: Axis 2 Y Up
   495        Button G: Axis 2 X Right
   496        Button H: Axis 2 Y Down
   497      */
   498     if (joystick->nbuttons >= 5) {
   499         if (stGameStatus.curdata.B.x < SYS_JoyData[index].buttoncalc[0])
   500             SDL_PrivateJoystickButton(joystick, (Uint8) 4, SDL_PRESSED);
   501         else
   502             SDL_PrivateJoystickButton(joystick, (Uint8) 4, SDL_RELEASED);
   503     }
   504     if (joystick->nbuttons >= 6) {
   505         if (stGameStatus.curdata.B.y < SYS_JoyData[index].buttoncalc[1])
   506             SDL_PrivateJoystickButton(joystick, (Uint8) 5, SDL_PRESSED);
   507         else
   508             SDL_PrivateJoystickButton(joystick, (Uint8) 5, SDL_RELEASED);
   509     }
   510     if (joystick->nbuttons >= 7) {
   511         if (stGameStatus.curdata.B.x > SYS_JoyData[index].buttoncalc[2])
   512             SDL_PrivateJoystickButton(joystick, (Uint8) 6, SDL_PRESSED);
   513         else
   514             SDL_PrivateJoystickButton(joystick, (Uint8) 6, SDL_RELEASED);
   515     }
   516     if (joystick->nbuttons >= 8) {
   517         if (stGameStatus.curdata.B.y > SYS_JoyData[index].buttoncalc[3])
   518             SDL_PrivateJoystickButton(joystick, (Uint8) 7, SDL_PRESSED);
   519         else
   520             SDL_PrivateJoystickButton(joystick, (Uint8) 7, SDL_RELEASED);
   521     }
   522 
   523 /* joystick hat events */
   524 /* Not Supported under OS/2 */
   525 /* joystick ball events */
   526 /* Not Supported under OS/2 */
   527 }
   528 
   529 
   530 
   531 /******************************************/
   532 /* Function to close a joystick after use */
   533 /******************************************/
   534 void
   535 SDL_SYS_JoystickClose(SDL_Joystick * joystick)
   536 {
   537     if (joystick->hwdata != NULL) {
   538         /* free system specific hardware data */
   539         SDL_free(joystick->hwdata);
   540     }
   541 }
   542 
   543 
   544 
   545 /********************************************************************/
   546 /* Function to perform any system-specific joystick related cleanup */
   547 /********************************************************************/
   548 void
   549 SDL_SYS_JoystickQuit(void)
   550 {
   551     joyPortClose(&hJoyPort);
   552 }
   553 
   554 
   555 
   556 /************************/
   557 /************************/
   558 /* OS/2 Implementations */
   559 /************************/
   560 /************************/
   561 
   562 
   563 /*****************************************/
   564 /* Open Joystick Port, if not opened yet */
   565 /*****************************************/
   566 APIRET
   567 joyPortOpen(HFILE * hGame)
   568 {
   569     APIRET rc;                  /* Generic Return Code */
   570     ULONG ulAction;             /* ? */
   571     ULONG ulVersion;            /* Version of joystick driver */
   572     ULONG ulDataLen;            /* Size of version data */
   573 
   574 /* Verifies if joyport is not already open... */
   575     if (*hGame != NULL)
   576         return 0;
   577 /* Open GAME$ for read */
   578     rc = DosOpen((PSZ) GAMEPDDNAME, hGame, &ulAction, 0, FILE_READONLY,
   579                  FILE_OPEN, OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, NULL);
   580     if (rc != 0) {
   581         SDL_SetError("Could not open Joystick Port.");
   582         return -1;
   583     }
   584 
   585 /* Get Joystick Driver Version... must be 2.0 or higher */
   586     ulVersion = 0;
   587     ulDataLen = sizeof(ulVersion);
   588     rc = DosDevIOCtl(*hGame, IOCTL_CAT_USER, GAME_GET_VERSION,
   589                      NULL, 0, NULL, &ulVersion, ulDataLen, &ulDataLen);
   590     if (rc != 0) {
   591         joyPortClose(hGame);
   592         SDL_SetError("Could not get Joystick Driver version.");
   593         return -1;
   594     }
   595     if (ulVersion < GAME_VERSION) {
   596         joyPortClose(hGame);
   597         SDL_SetError
   598             ("Driver too old. At least IBM driver version 2.0 required.");
   599         return -1;
   600     }
   601     return 0;
   602 }
   603 
   604 
   605 
   606 /****************************/
   607 /* Close JoyPort, if opened */
   608 /****************************/
   609 void
   610 joyPortClose(HFILE * hGame)
   611 {
   612     if (*hGame != NULL)
   613         DosClose(*hGame);
   614     *hGame = NULL;
   615 }
   616 
   617 
   618 
   619 /***************************/
   620 /* Get SDL Joystick EnvVar */
   621 /***************************/
   622 int
   623 joyGetEnv(struct _joycfg *joydata)
   624 {
   625     char *joyenv;               /* Pointer to tested character */
   626     char tempnumber[5];         /* Temporary place to put numeric texts */
   627 
   628     joyenv = SDL_getenv("SDL_OS2_JOYSTICK");
   629     if (joyenv == NULL)
   630         return 0;
   631 /* Joystick Environment is defined! */
   632     while (*joyenv == ' ' && *joyenv != 0)
   633         joyenv++;               /* jump spaces... */
   634 /* If the string name starts with '... get if fully */
   635     if (*joyenv == '\'')
   636         joyenv +=
   637             joyGetData(++joyenv, joydata->name, '\'', sizeof(joydata->name));
   638 /* If not, get it until the next space */
   639     else if (*joyenv == '\"')
   640         joyenv +=
   641             joyGetData(++joyenv, joydata->name, '\"', sizeof(joydata->name));
   642     else
   643         joyenv +=
   644             joyGetData(joyenv, joydata->name, ' ', sizeof(joydata->name));
   645 /* Now get the number of axes */
   646     while (*joyenv == ' ' && *joyenv != 0)
   647         joyenv++;               /* jump spaces... */
   648     joyenv += joyGetData(joyenv, tempnumber, ' ', sizeof(tempnumber));
   649     joydata->axes = atoi(tempnumber);
   650 /* Now get the number of buttons */
   651     while (*joyenv == ' ' && *joyenv != 0)
   652         joyenv++;               /* jump spaces... */
   653     joyenv += joyGetData(joyenv, tempnumber, ' ', sizeof(tempnumber));
   654     joydata->buttons = atoi(tempnumber);
   655 /* Now get the number of hats */
   656     while (*joyenv == ' ' && *joyenv != 0)
   657         joyenv++;               /* jump spaces... */
   658     joyenv += joyGetData(joyenv, tempnumber, ' ', sizeof(tempnumber));
   659     joydata->hats = atoi(tempnumber);
   660 /* Now get the number of balls */
   661     while (*joyenv == ' ' && *joyenv != 0)
   662         joyenv++;               /* jump spaces... */
   663     joyenv += joyGetData(joyenv, tempnumber, ' ', sizeof(tempnumber));
   664     joydata->balls = atoi(tempnumber);
   665     return 1;
   666 }
   667 
   668 
   669 
   670 /************************************************************************/
   671 /* Get a text from in the string starting in joyenv until it finds		*/
   672 /* the stopchar or maxchars is reached. The result is placed in name.	*/
   673 /************************************************************************/
   674 int
   675 joyGetData(char *joyenv, char *name, char stopchar, size_t maxchars)
   676 {
   677     char *nameptr;              /* Pointer to the selected character */
   678     int chcnt = 0;              /* Count how many characters where copied */
   679 
   680     nameptr = name;
   681     while (*joyenv != stopchar && *joyenv != 0) {
   682         if (nameptr < (name + (maxchars - 1))) {
   683             *nameptr = *joyenv; /* Only copy if smaller than maximum */
   684             nameptr++;
   685         }
   686         chcnt++;
   687         joyenv++;
   688     }
   689     if (*joyenv == stopchar) {
   690         joyenv++;               /* Jump stopchar */
   691         chcnt++;
   692     }
   693     *nameptr = 0;               /* Mark last byte */
   694     return chcnt;
   695 }
   696 
   697 #endif /* SDL_JOYSTICK_OS2 */
   698 /* vi: set ts=4 sw=4 expandtab: */