| 1 | /* |
| 2 | SDL - Simple DirectMedia Layer |
| 3 | Copyright (C) 1997-2009 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 SDL_SYS_JoystickInit(void) |
| 110 | { |
| 111 | APIRET rc; /* Generic OS/2 return code */ |
| 112 | GAME_PORT_STRUCT stJoyStatus; /* Joystick Status Structure */ |
| 113 | GAME_PARM_STRUCT stGameParms; /* Joystick Parameter Structure */ |
| 114 | GAME_CALIB_STRUCT stGameCalib; /* Calibration Struct */ |
| 115 | ULONG ulDataLen; /* Size of data */ |
| 116 | ULONG ulLastTick; /* Tick Counter for timing operations */ |
| 117 | Uint8 maxdevs; /* Maximum number of devices */ |
| 118 | Uint8 numdevs; /* Number of present devices */ |
| 119 | Uint8 maxbut; /* Maximum number of buttons... */ |
| 120 | Uint8 i; /* Temporary Count Vars */ |
| 121 | Uint8 ucNewJoystickMask; /* Mask for Joystick Detection */ |
| 122 | struct _joycfg joycfg; /* Joy Configuration from envvar */ |
| 123 | |
| 124 | |
| 125 | /* Get Max Number of Devices */ |
| 126 | rc = joyPortOpen(&hJoyPort); /* Open GAME$ port */ |
| 127 | if (rc != 0) return 0; /* Cannot open... report no joystick */ |
| 128 | ulDataLen = sizeof(stGameParms); |
| 129 | rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_PARMS, |
| 130 | NULL, 0, NULL, &stGameParms, ulDataLen, &ulDataLen); /* Ask device info */ |
| 131 | if (rc != 0) |
| 132 | { |
| 133 | joyPortClose(&hJoyPort); |
| 134 | SDL_SetError("Could not read joystick port."); |
| 135 | return -1; |
| 136 | } |
| 137 | if (stGameParms.useA != 0) maxdevs++; |
| 138 | if (stGameParms.useB != 0) maxdevs++; |
| 139 | if ( maxdevs > MAX_JOYSTICKS ) maxdevs = MAX_JOYSTICKS; |
| 140 | |
| 141 | /* Defines min/max axes values (callibration) */ |
| 142 | ulDataLen = sizeof(stGameCalib); |
| 143 | rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_CALIB, |
| 144 | NULL, 0, NULL, &stGameCalib, ulDataLen, &ulDataLen); |
| 145 | if (rc != 0) |
| 146 | { |
| 147 | joyPortClose(&hJoyPort); |
| 148 | SDL_SetError("Could not read callibration data."); |
| 149 | return -1; |
| 150 | } |
| 151 | |
| 152 | /* Determine how many joysticks are active */ |
| 153 | numdevs = 0; /* Points no device */ |
| 154 | ucNewJoystickMask = 0x0F; /* read all 4 joystick axis */ |
| 155 | ulDataLen = sizeof(ucNewJoystickMask); |
| 156 | rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_RESET, |
| 157 | &ucNewJoystickMask, ulDataLen, &ulDataLen, NULL, 0, NULL); |
| 158 | if (rc == 0) |
| 159 | { |
| 160 | ulDataLen = sizeof(stJoyStatus); |
| 161 | rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_GET, |
| 162 | NULL, 0, NULL, &stJoyStatus, ulDataLen, &ulDataLen); |
| 163 | if (rc != 0) |
| 164 | { |
| 165 | joyPortClose(&hJoyPort); |
| 166 | SDL_SetError("Could not call joystick port."); |
| 167 | return -1; |
| 168 | } |
| 169 | ulLastTick = stJoyStatus.ulJs_Ticks; |
| 170 | while (stJoyStatus.ulJs_Ticks == ulLastTick) |
| 171 | { |
| 172 | rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_GET, |
| 173 | NULL, 0, NULL, &stJoyStatus, ulDataLen, &ulDataLen); |
| 174 | } |
| 175 | if ((stJoyStatus.ucJs_JoyStickMask & 0x03) > 0) numdevs++; |
| 176 | if (((stJoyStatus.ucJs_JoyStickMask >> 2) & 0x03) > 0) numdevs++; |
| 177 | } |
| 178 | |
| 179 | if (numdevs>maxdevs) numdevs=maxdevs; |
| 180 | |
| 181 | /* If *any* joystick was detected... Let's configure SDL for them */ |
| 182 | if (numdevs > 0) |
| 183 | { |
| 184 | /* Verify if it is a "user defined" joystick */ |
| 185 | if (joyGetEnv(&joycfg)) |
| 186 | { |
| 187 | GAME_3POS_STRUCT * axis[4]; |
| 188 | axis[0] = &stGameCalib.Ax; |
| 189 | axis[1] = &stGameCalib.Ay; |
| 190 | axis[2] = &stGameCalib.Bx; |
| 191 | axis[3] = &stGameCalib.By; |
| 192 | /* Say it has one device only (user defined is always one device only) */ |
| 193 | numdevs = 1; |
| 194 | /* Define Device 0 as... */ |
| 195 | SYS_JoyData[0].id=0; |
| 196 | /* Define Number of Axes... up to 4 */ |
| 197 | if (joycfg.axes>MAX_AXES) joycfg.axes = MAX_AXES; |
| 198 | SYS_JoyData[0].axes = joycfg.axes; |
| 199 | /* Define number of buttons... 8 if 2 axes, 6 if 3 axes and 4 if 4 axes */ |
| 200 | maxbut = MAX_BUTTONS; |
| 201 | if (joycfg.axes>2) maxbut-=((joycfg.axes-2)<<1); /* MAX_BUTTONS - 2*(axes-2) */ |
| 202 | if (joycfg.buttons > maxbut) joycfg.buttons = maxbut; |
| 203 | SYS_JoyData[0].buttons = joycfg.buttons; |
| 204 | /* Define number of hats */ |
| 205 | if (joycfg.hats > MAX_HATS) joycfg.hats = MAX_HATS; |
| 206 | SYS_JoyData[0].hats = joycfg.hats; |
| 207 | /* Define number of balls */ |
| 208 | if (joycfg.balls > MAX_BALLS) joycfg.balls = MAX_BALLS; |
| 209 | SYS_JoyData[0].balls = joycfg.balls; |
| 210 | /* Initialize Axes Callibration Values */ |
| 211 | for (i=0; i<joycfg.axes; i++) |
| 212 | { |
| 213 | SYS_JoyData[0].axes_min[i] = axis[i]->lower; |
| 214 | SYS_JoyData[0].axes_med[i] = axis[i]->centre; |
| 215 | SYS_JoyData[0].axes_max[i] = axis[i]->upper; |
| 216 | } |
| 217 | /* Initialize Buttons 5 to 8 structures */ |
| 218 | if (joycfg.buttons>=5) SYS_JoyData[0].buttoncalc[0]=((axis[2]->lower+axis[3]->centre)>>1); |
| 219 | if (joycfg.buttons>=6) SYS_JoyData[0].buttoncalc[1]=((axis[3]->lower+axis[3]->centre)>>1); |
| 220 | if (joycfg.buttons>=7) SYS_JoyData[0].buttoncalc[2]=((axis[2]->upper+axis[3]->centre)>>1); |
| 221 | if (joycfg.buttons>=8) SYS_JoyData[0].buttoncalc[3]=((axis[3]->upper+axis[3]->centre)>>1); |
| 222 | /* Intialize Joystick Name */ |
| 223 | SDL_strlcpy (SYS_JoyData[0].szDeviceName,joycfg.name, SDL_arraysize(SYS_JoyData[0].szDeviceName)); |
| 224 | } |
| 225 | /* Default Init ... autoconfig */ |
| 226 | else |
| 227 | { |
| 228 | /* if two devices were detected... configure as Joy1 4 axis and Joy2 2 axis */ |
| 229 | if (numdevs==2) |
| 230 | { |
| 231 | /* Define Device 0 as 4 axes, 4 buttons */ |
| 232 | SYS_JoyData[0].id=0; |
| 233 | SYS_JoyData[0].axes = 4; |
| 234 | SYS_JoyData[0].buttons = 4; |
| 235 | SYS_JoyData[0].hats = 0; |
| 236 | SYS_JoyData[0].balls = 0; |
| 237 | SYS_JoyData[0].axes_min[0] = stGameCalib.Ax.lower; |
| 238 | SYS_JoyData[0].axes_med[0] = stGameCalib.Ax.centre; |
| 239 | SYS_JoyData[0].axes_max[0] = stGameCalib.Ax.upper; |
| 240 | SYS_JoyData[0].axes_min[1] = stGameCalib.Ay.lower; |
| 241 | SYS_JoyData[0].axes_med[1] = stGameCalib.Ay.centre; |
| 242 | SYS_JoyData[0].axes_max[1] = stGameCalib.Ay.upper; |
| 243 | SYS_JoyData[0].axes_min[2] = stGameCalib.Bx.lower; |
| 244 | SYS_JoyData[0].axes_med[2] = stGameCalib.Bx.centre; |
| 245 | SYS_JoyData[0].axes_max[2] = stGameCalib.Bx.upper; |
| 246 | SYS_JoyData[0].axes_min[3] = stGameCalib.By.lower; |
| 247 | SYS_JoyData[0].axes_med[3] = stGameCalib.By.centre; |
| 248 | SYS_JoyData[0].axes_max[3] = stGameCalib.By.upper; |
| 249 | /* Define Device 1 as 2 axes, 2 buttons */ |
| 250 | SYS_JoyData[1].id=1; |
| 251 | SYS_JoyData[1].axes = 2; |
| 252 | SYS_JoyData[1].buttons = 2; |
| 253 | SYS_JoyData[1].hats = 0; |
| 254 | SYS_JoyData[1].balls = 0; |
| 255 | SYS_JoyData[1].axes_min[0] = stGameCalib.Bx.lower; |
| 256 | SYS_JoyData[1].axes_med[0] = stGameCalib.Bx.centre; |
| 257 | SYS_JoyData[1].axes_max[0] = stGameCalib.Bx.upper; |
| 258 | SYS_JoyData[1].axes_min[1] = stGameCalib.By.lower; |
| 259 | SYS_JoyData[1].axes_med[1] = stGameCalib.By.centre; |
| 260 | SYS_JoyData[1].axes_max[1] = stGameCalib.By.upper; |
| 261 | } |
| 262 | /* One joystick only? */ |
| 263 | else |
| 264 | { |
| 265 | /* If it is joystick A... */ |
| 266 | if ((stJoyStatus.ucJs_JoyStickMask & 0x03) > 0) |
| 267 | { |
| 268 | /* Define Device 0 as 2 axes, 4 buttons */ |
| 269 | SYS_JoyData[0].id=0; |
| 270 | SYS_JoyData[0].axes = 2; |
| 271 | SYS_JoyData[0].buttons = 4; |
| 272 | SYS_JoyData[0].hats = 0; |
| 273 | SYS_JoyData[0].balls = 0; |
| 274 | SYS_JoyData[0].axes_min[0] = stGameCalib.Ax.lower; |
| 275 | SYS_JoyData[0].axes_med[0] = stGameCalib.Ax.centre; |
| 276 | SYS_JoyData[0].axes_max[0] = stGameCalib.Ax.upper; |
| 277 | SYS_JoyData[0].axes_min[1] = stGameCalib.Ay.lower; |
| 278 | SYS_JoyData[0].axes_med[1] = stGameCalib.Ay.centre; |
| 279 | SYS_JoyData[0].axes_max[1] = stGameCalib.Ay.upper; |
| 280 | } |
| 281 | /* If not, it is joystick B */ |
| 282 | else |
| 283 | { |
| 284 | /* Define Device 1 as 2 axes, 2 buttons */ |
| 285 | SYS_JoyData[0].id=1; |
| 286 | SYS_JoyData[0].axes = 2; |
| 287 | SYS_JoyData[0].buttons = 2; |
| 288 | SYS_JoyData[0].hats = 0; |
| 289 | SYS_JoyData[0].balls = 0; |
| 290 | SYS_JoyData[0].axes_min[0] = stGameCalib.Bx.lower; |
| 291 | SYS_JoyData[0].axes_med[0] = stGameCalib.Bx.centre; |
| 292 | SYS_JoyData[0].axes_max[0] = stGameCalib.Bx.upper; |
| 293 | SYS_JoyData[0].axes_min[1] = stGameCalib.By.lower; |
| 294 | SYS_JoyData[0].axes_med[1] = stGameCalib.By.centre; |
| 295 | SYS_JoyData[0].axes_max[1] = stGameCalib.By.upper; |
| 296 | } |
| 297 | } |
| 298 | /* Hack to define Joystick Port Names */ |
| 299 | if ( numdevs > maxdevs ) numdevs = maxdevs; |
| 300 | for (i=0; i<numdevs; i++) |
| 301 | SDL_snprintf (SYS_JoyData[i].szDeviceName, SDL_arraysize(SYS_JoyData[i].szDeviceName), "Default Joystick %c", 'A'+SYS_JoyData[i].id); |
| 302 | |
| 303 | } |
| 304 | } |
| 305 | /* Return the number of devices found */ |
| 306 | return(numdevs); |
| 307 | } |
| 308 | |
| 309 | |
| 310 | /***********************************************************/ |
| 311 | /* Function to get the device-dependent name of a joystick */ |
| 312 | /***********************************************************/ |
| 313 | const char *SDL_SYS_JoystickName(int index) |
| 314 | { |
| 315 | /* No need to verify if device exists, already done in upper layer */ |
| 316 | return(SYS_JoyData[index].szDeviceName); |
| 317 | } |
| 318 | |
| 319 | |
| 320 | |
| 321 | /******************************************************************************/ |
| 322 | /* Function to open a joystick for use. */ |
| 323 | /* The joystick to open is specified by the index field of the joystick. */ |
| 324 | /* This should fill the nbuttons and naxes fields of the joystick structure. */ |
| 325 | /* It returns 0, or -1 if there is an error. */ |
| 326 | /******************************************************************************/ |
| 327 | int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) |
| 328 | { |
| 329 | int index; /* Index shortcut for index in joystick structure */ |
| 330 | int i; /* Generic Counter */ |
| 331 | |
| 332 | /* allocate memory for system specific hardware data */ |
| 333 | joystick->hwdata = (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata)); |
| 334 | if (joystick->hwdata == NULL) |
| 335 | { |
| 336 | SDL_OutOfMemory(); |
| 337 | return(-1); |
| 338 | } |
| 339 | /* Reset Hardware Data */ |
| 340 | SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); |
| 341 | |
| 342 | /* ShortCut Pointer */ |
| 343 | index = joystick->index; |
| 344 | /* Define offsets and scales for all axes */ |
| 345 | joystick->hwdata->id = SYS_JoyData[index].id; |
| 346 | for ( i = 0; i < MAX_AXES; ++i ) |
| 347 | { |
| 348 | if ( (i<2) || i < SYS_JoyData[index].axes ) |
| 349 | { |
| 350 | joystick->hwdata->transaxes[i].offset = ((AXIS_MAX + AXIS_MIN)>>1) - SYS_JoyData[index].axes_med[i]; |
| 351 | //joystick->hwdata->transaxes[i].scale = (float)((AXIS_MAX - AXIS_MIN)/(SYS_JoyData[index].axes_max[i]-SYS_JoyData[index].axes_min[i])); |
| 352 | joystick->hwdata->transaxes[i].scale1 = (float)abs((AXIS_MIN/SYS_JoyData[index].axes_min[i])); |
| 353 | joystick->hwdata->transaxes[i].scale2 = (float)abs((AXIS_MAX/SYS_JoyData[index].axes_max[i])); |
| 354 | } |
| 355 | else |
| 356 | { |
| 357 | joystick->hwdata->transaxes[i].offset = 0; |
| 358 | //joystick->hwdata->transaxes[i].scale = 1.0; /* Just in case */ |
| 359 | joystick->hwdata->transaxes[i].scale1 = 1.0; /* Just in case */ |
| 360 | joystick->hwdata->transaxes[i].scale2 = 1.0; /* Just in case */ |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | /* fill nbuttons, naxes, and nhats fields */ |
| 365 | joystick->nbuttons = SYS_JoyData[index].buttons; |
| 366 | joystick->naxes = SYS_JoyData[index].axes; |
| 367 | /* joystick->nhats = SYS_JoyData[index].hats; */ |
| 368 | joystick->nhats = 0; /* No support for hats at this time */ |
| 369 | /* joystick->nballs = SYS_JoyData[index].balls; */ |
| 370 | joystick->nballs = 0; /* No support for balls at this time */ |
| 371 | return 0; |
| 372 | } |
| 373 | |
| 374 | |
| 375 | |
| 376 | /***************************************************************************/ |
| 377 | /* Function to update the state of a joystick - called as a device poll. */ |
| 378 | /* This function shouldn't update the joystick structure directly, */ |
| 379 | /* but instead should call SDL_PrivateJoystick*() to deliver events */ |
| 380 | /* and update joystick device state. */ |
| 381 | /***************************************************************************/ |
| 382 | void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) |
| 383 | { |
| 384 | APIRET rc; /* Generic OS/2 return code */ |
| 385 | int index; /* index shortcurt to joystick index */ |
| 386 | int i; /* Generic counter */ |
| 387 | int normbut; /* Number of buttons reported by joystick */ |
| 388 | int corr; /* Correction for button names */ |
| 389 | Sint16 value, change; /* Values used to update axis values */ |
| 390 | struct _transaxes *transaxes; /* Shortcut for Correction structure */ |
| 391 | Uint32 pos[MAX_AXES]; /* Vector to inform the Axis status */ |
| 392 | ULONG ulDataLen; /* Size of data */ |
| 393 | GAME_STATUS_STRUCT stGameStatus; /* Joystick Status Structure */ |
| 394 | |
| 395 | ulDataLen = sizeof(stGameStatus); |
| 396 | rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_STATUS, |
| 397 | NULL, 0, NULL, &stGameStatus, ulDataLen, &ulDataLen); |
| 398 | if (rc != 0) |
| 399 | { |
| 400 | SDL_SetError("Could not read joystick status."); |
| 401 | return; /* Could not read data */ |
| 402 | } |
| 403 | |
| 404 | /* Shortcut pointer */ |
| 405 | index = joystick->index; |
| 406 | /* joystick motion events */ |
| 407 | |
| 408 | if (SYS_JoyData[index].id == 0) |
| 409 | { |
| 410 | pos[0] = stGameStatus.curdata.A.x; |
| 411 | pos[1] = stGameStatus.curdata.A.y; |
| 412 | if (SYS_JoyData[index].axes >= 3) pos[2] = stGameStatus.curdata.B.x; |
| 413 | else pos[2]=0; |
| 414 | if (SYS_JoyData[index].axes >= 4) pos[3] = stGameStatus.curdata.B.y; |
| 415 | else pos[3]=0; |
| 416 | pos[4]=0; /* OS/2 basic drivers do not support more than 4 axes joysticks */ |
| 417 | pos[5]=0; |
| 418 | } |
| 419 | else if (SYS_JoyData[index].id == 1) |
| 420 | { |
| 421 | pos[0] = stGameStatus.curdata.B.x; |
| 422 | pos[1] = stGameStatus.curdata.B.y; |
| 423 | pos[2]=0; |
| 424 | pos[3]=0; |
| 425 | pos[4]=0; |
| 426 | pos[5]=0; |
| 427 | } |
| 428 | |
| 429 | /* Corrects the movements using the callibration */ |
| 430 | transaxes = joystick->hwdata->transaxes; |
| 431 | for (i = 0; i < joystick->naxes; i++) |
| 432 | { |
| 433 | value = pos[i] + transaxes[i].offset; |
| 434 | if (value<0) |
| 435 | { |
| 436 | value*=transaxes[i].scale1; |
| 437 | if (value>0) value = AXIS_MIN; |
| 438 | } |
| 439 | else |
| 440 | { |
| 441 | value*=transaxes[i].scale2; |
| 442 | if (value<0) value = AXIS_MAX; |
| 443 | } |
| 444 | change = (value - joystick->axes[i]); |
| 445 | if ( (change < -JOY_AXIS_THRESHOLD) || (change > JOY_AXIS_THRESHOLD) ) |
| 446 | { |
| 447 | SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)value); |
| 448 | } |
| 449 | } |
| 450 | |
| 451 | /* joystick button A to D events */ |
| 452 | if (SYS_JoyData[index].id == 1) corr = 2; |
| 453 | else corr = 0; |
| 454 | normbut=4; /* Number of normal buttons */ |
| 455 | if (joystick->nbuttons<normbut) normbut = joystick->nbuttons; |
| 456 | for ( i = corr; (i-corr) < normbut; ++i ) |
| 457 | { |
| 458 | /* |
| 459 | Button A: 1110 0000 |
| 460 | Button B: 1101 0000 |
| 461 | Button C: 1011 0000 |
| 462 | Button D: 0111 0000 |
| 463 | */ |
| 464 | if ( (~stGameStatus.curdata.butMask)>>4 & JOY_BUTTON_FLAG(i) ) |
| 465 | { |
| 466 | if ( ! joystick->buttons[i-corr] ) |
| 467 | { |
| 468 | SDL_PrivateJoystickButton(joystick, (Uint8)(i-corr), SDL_PRESSED); |
| 469 | } |
| 470 | } |
| 471 | else |
| 472 | { |
| 473 | if ( joystick->buttons[i-corr] ) |
| 474 | { |
| 475 | SDL_PrivateJoystickButton(joystick, (Uint8)(i-corr), SDL_RELEASED); |
| 476 | } |
| 477 | } |
| 478 | } |
| 479 | |
| 480 | /* Joystick button E to H buttons */ |
| 481 | /* |
| 482 | Button E: Axis 2 X Left |
| 483 | Button F: Axis 2 Y Up |
| 484 | Button G: Axis 2 X Right |
| 485 | Button H: Axis 2 Y Down |
| 486 | */ |
| 487 | if (joystick->nbuttons>=5) |
| 488 | { |
| 489 | if (stGameStatus.curdata.B.x < SYS_JoyData[index].buttoncalc[0]) SDL_PrivateJoystickButton(joystick, (Uint8)4, SDL_PRESSED); |
| 490 | else SDL_PrivateJoystickButton(joystick, (Uint8)4, SDL_RELEASED); |
| 491 | } |
| 492 | if (joystick->nbuttons>=6) |
| 493 | { |
| 494 | if (stGameStatus.curdata.B.y < SYS_JoyData[index].buttoncalc[1]) SDL_PrivateJoystickButton(joystick, (Uint8)5, SDL_PRESSED); |
| 495 | else SDL_PrivateJoystickButton(joystick, (Uint8)5, SDL_RELEASED); |
| 496 | } |
| 497 | if (joystick->nbuttons>=7) |
| 498 | { |
| 499 | if (stGameStatus.curdata.B.x > SYS_JoyData[index].buttoncalc[2]) SDL_PrivateJoystickButton(joystick, (Uint8)6, SDL_PRESSED); |
| 500 | else SDL_PrivateJoystickButton(joystick, (Uint8)6, SDL_RELEASED); |
| 501 | } |
| 502 | if (joystick->nbuttons>=8) |
| 503 | { |
| 504 | if (stGameStatus.curdata.B.y > SYS_JoyData[index].buttoncalc[3]) SDL_PrivateJoystickButton(joystick, (Uint8)7, SDL_PRESSED); |
| 505 | else SDL_PrivateJoystickButton(joystick, (Uint8)7, SDL_RELEASED); |
| 506 | } |
| 507 | |
| 508 | /* joystick hat events */ |
| 509 | /* Not Supported under OS/2 */ |
| 510 | /* joystick ball events */ |
| 511 | /* Not Supported under OS/2 */ |
| 512 | } |
| 513 | |
| 514 | |
| 515 | |
| 516 | /******************************************/ |
| 517 | /* Function to close a joystick after use */ |
| 518 | /******************************************/ |
| 519 | void SDL_SYS_JoystickClose(SDL_Joystick *joystick) |
| 520 | { |
| 521 | if (joystick->hwdata != NULL) |
| 522 | { |
| 523 | /* free system specific hardware data */ |
| 524 | SDL_free(joystick->hwdata); |
| 525 | } |
| 526 | } |
| 527 | |
| 528 | |
| 529 | |
| 530 | /********************************************************************/ |
| 531 | /* Function to perform any system-specific joystick related cleanup */ |
| 532 | /********************************************************************/ |
| 533 | void SDL_SYS_JoystickQuit(void) |
| 534 | { |
| 535 | joyPortClose(&hJoyPort); |
| 536 | } |
| 537 | |
| 538 | |
| 539 | |
| 540 | /************************/ |
| 541 | /************************/ |
| 542 | /* OS/2 Implementations */ |
| 543 | /************************/ |
| 544 | /************************/ |
| 545 | |
| 546 | |
| 547 | /*****************************************/ |
| 548 | /* Open Joystick Port, if not opened yet */ |
| 549 | /*****************************************/ |
| 550 | APIRET joyPortOpen(HFILE * hGame) |
| 551 | { |
| 552 | APIRET rc; /* Generic Return Code */ |
| 553 | ULONG ulAction; /* ? */ |
| 554 | ULONG ulVersion; /* Version of joystick driver */ |
| 555 | ULONG ulDataLen; /* Size of version data */ |
| 556 | |
| 557 | /* Verifies if joyport is not already open... */ |
| 558 | if (*hGame != NULL) return 0; |
| 559 | /* Open GAME$ for read */ |
| 560 | rc = DosOpen((PSZ)GAMEPDDNAME, hGame, &ulAction, 0, FILE_READONLY, |
| 561 | FILE_OPEN, OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, NULL); |
| 562 | if (rc != 0) |
| 563 | { |
| 564 | SDL_SetError("Could not open Joystick Port."); |
| 565 | return -1; |
| 566 | } |
| 567 | |
| 568 | /* Get Joystick Driver Version... must be 2.0 or higher */ |
| 569 | ulVersion = 0; |
| 570 | ulDataLen = sizeof(ulVersion); |
| 571 | rc = DosDevIOCtl( *hGame, IOCTL_CAT_USER, GAME_GET_VERSION, |
| 572 | NULL, 0, NULL, &ulVersion, ulDataLen, &ulDataLen); |
| 573 | if (rc != 0) |
| 574 | { |
| 575 | joyPortClose(hGame); |
| 576 | SDL_SetError("Could not get Joystick Driver version."); |
| 577 | return -1; |
| 578 | } |
| 579 | if (ulVersion < GAME_VERSION) |
| 580 | { |
| 581 | joyPortClose(hGame); |
| 582 | SDL_SetError("Driver too old. At least IBM driver version 2.0 required."); |
| 583 | return -1; |
| 584 | } |
| 585 | return 0; |
| 586 | } |
| 587 | |
| 588 | |
| 589 | |
| 590 | /****************************/ |
| 591 | /* Close JoyPort, if opened */ |
| 592 | /****************************/ |
| 593 | void joyPortClose(HFILE * hGame) |
| 594 | { |
| 595 | if (*hGame != NULL) DosClose(*hGame); |
| 596 | *hGame = NULL; |
| 597 | } |
| 598 | |
| 599 | |
| 600 | |
| 601 | /***************************/ |
| 602 | /* Get SDL Joystick EnvVar */ |
| 603 | /***************************/ |
| 604 | int joyGetEnv(struct _joycfg * joydata) |
| 605 | { |
| 606 | char *joyenv; /* Pointer to tested character */ |
| 607 | char tempnumber[5]; /* Temporary place to put numeric texts */ |
| 608 | |
| 609 | joyenv = SDL_getenv("SDL_OS2_JOYSTICK"); |
| 610 | if (joyenv == NULL) return 0; |
| 611 | /* Joystick Environment is defined! */ |
| 612 | while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */ |
| 613 | /* If the string name starts with '... get if fully */ |
| 614 | if (*joyenv=='\'') joyenv+=joyGetData(++joyenv,joydata->name,'\'',sizeof(joydata->name)); |
| 615 | /* If not, get it until the next space */ |
| 616 | else if (*joyenv=='\"') joyenv+=joyGetData(++joyenv,joydata->name,'\"',sizeof(joydata->name)); |
| 617 | else joyenv+=joyGetData(joyenv,joydata->name,' ',sizeof(joydata->name)); |
| 618 | /* Now get the number of axes */ |
| 619 | while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */ |
| 620 | joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber)); |
| 621 | joydata->axes = atoi(tempnumber); |
| 622 | /* Now get the number of buttons */ |
| 623 | while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */ |
| 624 | joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber)); |
| 625 | joydata->buttons = atoi(tempnumber); |
| 626 | /* Now get the number of hats */ |
| 627 | while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */ |
| 628 | joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber)); |
| 629 | joydata->hats = atoi(tempnumber); |
| 630 | /* Now get the number of balls */ |
| 631 | while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */ |
| 632 | joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber)); |
| 633 | joydata->balls = atoi(tempnumber); |
| 634 | return 1; |
| 635 | } |
| 636 | |
| 637 | |
| 638 | |
| 639 | /************************************************************************/ |
| 640 | /* Get a text from in the string starting in joyenv until it finds */ |
| 641 | /* the stopchar or maxchars is reached. The result is placed in name. */ |
| 642 | /************************************************************************/ |
| 643 | int joyGetData(char *joyenv, char *name, char stopchar, size_t maxchars) |
| 644 | { |
| 645 | char *nameptr; /* Pointer to the selected character */ |
| 646 | int chcnt=0; /* Count how many characters where copied */ |
| 647 | |
| 648 | nameptr=name; |
| 649 | while (*joyenv!=stopchar && *joyenv!=0) |
| 650 | { |
| 651 | if (nameptr<(name+(maxchars-1))) |
| 652 | { |
| 653 | *nameptr = *joyenv; /* Only copy if smaller than maximum */ |
| 654 | nameptr++; |
| 655 | } |
| 656 | chcnt++; |
| 657 | joyenv++; |
| 658 | } |
| 659 | if (*joyenv==stopchar) |
| 660 | { |
| 661 | joyenv++; /* Jump stopchar */ |
| 662 | chcnt++; |
| 663 | } |
| 664 | *nameptr = 0; /* Mark last byte */ |
| 665 | return chcnt; |
| 666 | } |
| 667 | |
| 668 | #endif /* SDL_JOYSTICK_OS2 */ |