|
|
1.1 root 1: /*
1.1.1.4 root 2: Hatari - joy.c
1.1 root 3:
1.1.1.4 root 4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: Joystick routines.
1.1 root 8:
1.1.1.6 ! root 9: NOTE: The ST uses the joystick port 1 as the default controller.
1.1 root 10: */
1.1.1.6 ! root 11: char Joy_rcsid[] = "Hatari $Id: joy.c,v 1.8 2005/10/05 14:14:35 thothy Exp $";
1.1 root 12:
13: #include <SDL.h>
14:
15: #include "main.h"
16: #include "configuration.h"
17: #include "dialog.h"
1.1.1.6 ! root 18: #include "ioMem.h"
1.1 root 19: #include "joy.h"
1.1.1.5 root 20: #include "log.h"
1.1.1.2 root 21: #include "video.h"
1.1 root 22:
1.1.1.2 root 23: #define JOY_BUTTON1 1
24: #define JOY_BUTTON2 2
1.1 root 25:
1.1.1.2 root 26:
1.1.1.6 ! root 27: SDL_Joystick *sdlJoystick[6] = /* SDL's joystick structures */
! 28: {
! 29: NULL, NULL, NULL, NULL, NULL, NULL
! 30: };
! 31: BOOL bJoystickWorking[6] = /* Is joystick plugged in and working? */
! 32: {
! 33: FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
! 34: };
! 35:
! 36: int JoystickSpaceBar = FALSE; /* State of space-bar on joystick button 2 */
! 37: static Uint8 nJoyKeyEmu[6];
! 38: Uint16 nSteJoySelect;
1.1 root 39:
40:
41: /*-----------------------------------------------------------------------*/
42: /*
1.1.1.3 root 43: This function initialises the (real) joysticks.
1.1 root 44: */
45: void Joy_Init(void)
46: {
1.1.1.6 ! root 47: int i, nPadsConnected;
! 48:
! 49: /* Initialise SDL's joystick subsystem: */
! 50: if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
! 51: {
! 52: Log_Printf(LOG_ERROR, "Could not init joysticks: %s\n", SDL_GetError());
! 53: return;
! 54: }
! 55:
! 56: /* Scan joystick connection array for working joysticks */
! 57: nPadsConnected = SDL_NumJoysticks();
! 58: for (i = 0; i < nPadsConnected && i < 6; i++)
! 59: {
! 60: /* Open the joystick for use */
! 61: sdlJoystick[i] = SDL_JoystickOpen(i);
! 62: /* Is joystick ok? */
! 63: if (sdlJoystick[i] != NULL)
! 64: {
! 65: /* Set as working */
! 66: bJoystickWorking[i] = TRUE;
! 67: Log_Printf(LOG_DEBUG, "Joystick %i: %s\n", i, SDL_JoystickName(i));
! 68: }
! 69: }
! 70:
! 71: /* OK, do we have any working joysticks? */
! 72: if (!bJoystickWorking[0])
! 73: {
! 74: /* No, so if first time install need to set cursor emulation */
! 75: if (bFirstTimeInstall)
! 76: ConfigureParams.Joysticks.Joy[1].nJoystickMode = JOYSTICK_KEYBOARD;
! 77: }
1.1.1.2 root 78:
1.1.1.6 ! root 79: JoystickSpaceBar = FALSE;
1.1 root 80: }
81:
82:
1.1.1.2 root 83: /*-----------------------------------------------------------------------*/
1.1 root 84: /*
1.1.1.6 ! root 85: Read details from joystick using SDL calls
! 86: NOTE ID is that of SDL
! 87: */
! 88: static BOOL Joy_ReadJoystick(int nSdlJoyID, JOYREADING *pJoyReading)
! 89: {
! 90: /* Joystick is OK, read position */
! 91: pJoyReading->XPos = SDL_JoystickGetAxis(sdlJoystick[nSdlJoyID], 0);
! 92: pJoyReading->YPos = SDL_JoystickGetAxis(sdlJoystick[nSdlJoyID], 1);
! 93: /* Sets bit #0 if button #1 is pressed: */
! 94: pJoyReading->Buttons = SDL_JoystickGetButton(sdlJoystick[nSdlJoyID], 0);
! 95: /* Sets bit #1 if button #2 is pressed: */
! 96: if (SDL_JoystickGetButton(sdlJoystick[nSdlJoyID], 1))
! 97: pJoyReading->Buttons |= JOY_BUTTON2;
! 98:
! 99: return TRUE;
1.1 root 100: }
101:
1.1.1.2 root 102:
103: /*-----------------------------------------------------------------------*/
1.1 root 104: /*
1.1.1.6 ! root 105: Read PC joystick and return ST format byte, i.e. lower 4 bits direction
! 106: and top bit fire.
! 107: NOTE : ID 0 is Joystick 0/Mouse and ID 1 is Joystick 1 (default),
! 108: ID 2 and 3 are STE joypads and ID 4 and 5 are parport joysticks.
1.1 root 109: */
1.1.1.6 ! root 110: Uint8 Joy_GetStickData(int nStJoyId)
1.1 root 111: {
1.1.1.6 ! root 112: Uint8 nData = 0;
! 113: JOYREADING JoyReading;
! 114: int nSdlJoyId;
! 115:
! 116: nSdlJoyId = ConfigureParams.Joysticks.Joy[nStJoyId].nJoyId;
! 117:
! 118: /* Are we emulating the joystick via the keyboard? */
! 119: if (ConfigureParams.Joysticks.Joy[nStJoyId].nJoystickMode == JOYSTICK_KEYBOARD)
! 120: {
! 121: /* If holding 'SHIFT' we actually want cursor key movement, so ignore any of this */
! 122: if ( !(SDL_GetModState()&(KMOD_LSHIFT|KMOD_RSHIFT)) )
! 123: {
! 124: nData = nJoyKeyEmu[nStJoyId];
! 125: }
! 126: }
! 127: else if (ConfigureParams.Joysticks.Joy[nStJoyId].nJoystickMode == JOYSTICK_REALSTICK
! 128: && bJoystickWorking[nSdlJoyId])
! 129: {
! 130: /* Use real joystick for emulation */
! 131: if (!Joy_ReadJoystick(nSdlJoyId, &JoyReading))
! 132: {
! 133: /* Something is wrong, we cannot read the joystick */
! 134: bJoystickWorking[nSdlJoyId] = FALSE;
! 135: return 0;
! 136: }
! 137:
! 138: /* Directions */
! 139: if (JoyReading.YPos <= JOYRANGE_UP_VALUE)
! 140: nData |= 0x01;
! 141: else if (JoyReading.YPos >= JOYRANGE_DOWN_VALUE)
! 142: nData |= 0x02;
! 143: if (JoyReading.XPos <= JOYRANGE_LEFT_VALUE)
! 144: nData |= 0x04;
! 145: else if (JoyReading.XPos >= JOYRANGE_RIGHT_VALUE)
! 146: nData |= 0x08;
! 147:
! 148: /* PC Joystick button 1 is set as ST joystick button */
! 149: if (JoyReading.Buttons & JOY_BUTTON1)
! 150: nData |= 0x80;
! 151:
! 152: /* Enable PC Joystick button 2 to mimick space bar (For XenonII, Flying Shark etc...) */
! 153: if (nStJoyId == JOYID_JOYSTICK1 && (JoyReading.Buttons & JOY_BUTTON2))
! 154: {
! 155: /* Only press 'space bar' if not in NULL state */
! 156: if (!JoystickSpaceBar)
! 157: {
! 158: /* Press, ikbd will send packets and de-press */
! 159: JoystickSpaceBar = JOYSTICK_SPACE_DOWN;
! 160: }
! 161: }
! 162: }
! 163:
! 164: /* Ignore fire button every 8 frames if enabled autofire (for both cursor emulation and joystick) */
! 165: if (ConfigureParams.Joysticks.Joy[nStJoyId].bEnableAutoFire)
! 166: {
! 167: if ((nVBLs&0x7)<4)
! 168: nData &= ~0x80; /* Remove top bit! */
! 169: }
! 170:
! 171: return nData;
1.1 root 172: }
173:
1.1.1.2 root 174:
175: /*-----------------------------------------------------------------------*/
1.1 root 176: /*
1.1.1.6 ! root 177: Get the fire button states.
! 178: Note: More than one fire buttons are only supported for real joystick,
! 179: not for keyboard emulation!
! 180: */
! 181: static int Joy_GetFireButtons(int nStJoyId)
! 182: {
! 183: int nButtons = 0;
! 184: int nSdlJoyId;
! 185: int i, nMaxButtons;
! 186:
! 187: nSdlJoyId = ConfigureParams.Joysticks.Joy[nStJoyId].nJoyId;
! 188:
! 189: /* Are we emulating the joystick via the keyboard? */
! 190: if (ConfigureParams.Joysticks.Joy[nStJoyId].nJoystickMode == JOYSTICK_KEYBOARD)
! 191: {
! 192: if (nJoyKeyEmu[nStJoyId] & 0x80)
! 193: {
! 194: nButtons |= 1;
! 195: }
! 196: }
! 197: else if (ConfigureParams.Joysticks.Joy[nStJoyId].nJoystickMode == JOYSTICK_REALSTICK
! 198: && bJoystickWorking[nSdlJoyId])
! 199: {
! 200: nMaxButtons = SDL_JoystickNumButtons(sdlJoystick[nSdlJoyId]);
! 201: if (nMaxButtons > 17)
! 202: nMaxButtons = 17;
! 203: /* Now read all fire buttons and set a bit for each pressed button: */
! 204: for (i = 0; i < nMaxButtons; i++)
! 205: {
! 206: if (SDL_JoystickGetButton(sdlJoystick[nSdlJoyId], i))
! 207: {
! 208: nButtons |= (1 << i);
! 209: }
! 210: }
! 211: }
1.1.1.2 root 212:
1.1.1.6 ! root 213: return nButtons;
1.1 root 214: }
215:
1.1.1.2 root 216:
217: /*-----------------------------------------------------------------------*/
1.1 root 218: /*
219: Toggle cursor emulation
220: */
221: void Joy_ToggleCursorEmulation(void)
222: {
1.1.1.6 ! root 223: /* Toggle joystick 1 keyboard emulation */
! 224: if (ConfigureParams.Joysticks.Joy[1].nJoystickMode != JOYSTICK_DISABLED)
! 225: {
! 226: if (ConfigureParams.Joysticks.Joy[1].nJoystickMode == JOYSTICK_REALSTICK)
! 227: ConfigureParams.Joysticks.Joy[1].nJoystickMode = JOYSTICK_KEYBOARD;
! 228: else
! 229: ConfigureParams.Joysticks.Joy[1].nJoystickMode = JOYSTICK_REALSTICK;
! 230: }
! 231: }
! 232:
! 233:
! 234: /*-----------------------------------------------------------------------*/
! 235: /*
! 236: A key has been pressed down, check if we use it for joystick emulation
! 237: via keyboard.
! 238: */
! 239: BOOL Joy_KeyDown(int symkey, int modkey)
! 240: {
! 241: int i;
! 242:
! 243: for (i = 0; i < 6; i++)
! 244: {
! 245: if (ConfigureParams.Joysticks.Joy[i].nJoystickMode == JOYSTICK_KEYBOARD
! 246: && !(modkey & KMOD_SHIFT))
! 247: {
! 248: if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeUp)
! 249: {
! 250: nJoyKeyEmu[i] |= 1;
! 251: return TRUE;
! 252: }
! 253: else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeDown)
! 254: {
! 255: nJoyKeyEmu[i] |= 2;
! 256: return TRUE;
! 257: }
! 258: else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeLeft)
! 259: {
! 260: nJoyKeyEmu[i] |= 4;
! 261: return TRUE;
! 262: }
! 263: else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeRight)
! 264: {
! 265: nJoyKeyEmu[i] |= 8;
! 266: return TRUE;
! 267: }
! 268: else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeFire)
! 269: {
! 270: nJoyKeyEmu[i] |= 0x80;
! 271: return TRUE;
! 272: }
! 273: }
! 274: }
! 275:
! 276: return FALSE;
! 277: }
! 278:
! 279:
! 280: /*-----------------------------------------------------------------------*/
! 281: /*
! 282: A key has been released, check if we use it for joystick emulation
! 283: via keyboard.
! 284: */
! 285: BOOL Joy_KeyUp(int symkey, int modkey)
! 286: {
! 287: int i;
! 288:
! 289: for (i = 0; i < 6; i++)
! 290: {
! 291: if (ConfigureParams.Joysticks.Joy[i].nJoystickMode == JOYSTICK_KEYBOARD
! 292: && !(modkey & KMOD_SHIFT))
! 293: {
! 294: if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeUp)
! 295: {
! 296: nJoyKeyEmu[i] &= ~1;
! 297: return TRUE;
! 298: }
! 299: else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeDown)
! 300: {
! 301: nJoyKeyEmu[i] &= ~2;
! 302: return TRUE;
! 303: }
! 304: else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeLeft)
! 305: {
! 306: nJoyKeyEmu[i] &= ~4;
! 307: return TRUE;
! 308: }
! 309: else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeRight)
! 310: {
! 311: nJoyKeyEmu[i] &= ~8;
! 312: return TRUE;
! 313: }
! 314: else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeFire)
! 315: {
! 316: nJoyKeyEmu[i] &= ~0x80;
! 317: return TRUE;
! 318: }
! 319: }
! 320: }
! 321:
! 322: return FALSE;
! 323: }
! 324:
! 325:
! 326: /*-----------------------------------------------------------------------*/
! 327: /*
! 328: Read from STE joypad buttons register (0xff9200)
! 329: */
! 330: void Joy_StePadButtons_ReadWord(void)
! 331: {
! 332: Uint16 nData = 0xffff;
! 333:
! 334: if (ConfigureParams.Joysticks.Joy[JOYID_STEPADA].nJoystickMode != JOYSTICK_DISABLED
! 335: && (nSteJoySelect & 0x0f) != 0x0f)
! 336: {
! 337: int nButtons = Joy_GetFireButtons(JOYID_STEPADA);
! 338: if (!(nSteJoySelect & 0x1))
! 339: {
! 340: if (nButtons & 0x01) /* Fire button A pressed? */
! 341: nData &= ~2;
! 342: if (nButtons & 0x10) /* Fire button PAUSE pressed? */
! 343: nData &= ~1;
! 344: }
! 345: else if (!(nSteJoySelect & 0x2))
! 346: {
! 347: if (nButtons & 0x02) /* Fire button B pressed? */
! 348: nData &= ~2;
! 349: }
! 350: else if (!(nSteJoySelect & 0x4))
! 351: {
! 352: if (nButtons & 0x04) /* Fire button C pressed? */
! 353: nData &= ~2;
! 354: }
! 355: else if (!(nSteJoySelect & 0x8))
! 356: {
! 357: if (nButtons & 0x01) /* Fire button OPTION pressed? */
! 358: nData &= ~2;
! 359: }
! 360: }
! 361:
! 362: if (ConfigureParams.Joysticks.Joy[JOYID_STEPADB].nJoystickMode != JOYSTICK_DISABLED
! 363: && (nSteJoySelect & 0xf0) != 0xf0)
! 364: {
! 365: int nButtons = Joy_GetFireButtons(JOYID_STEPADB);
! 366: if (!(nSteJoySelect & 0x10))
! 367: {
! 368: if (nButtons & 0x01) /* Fire button A pressed? */
! 369: nData &= ~8;
! 370: if (nButtons & 0x10) /* Fire button PAUSE pressed? */
! 371: nData &= ~4;
! 372: }
! 373: else if (!(nSteJoySelect & 0x20))
! 374: {
! 375: if (nButtons & 0x02) /* Fire button B pressed? */
! 376: nData &= ~8;
! 377: }
! 378: else if (!(nSteJoySelect & 0x40))
! 379: {
! 380: if (nButtons & 0x04) /* Fire button C pressed? */
! 381: nData &= ~8;
! 382: }
! 383: else if (!(nSteJoySelect & 0x80))
! 384: {
! 385: if (nButtons & 0x08) /* Fire button OPTION pressed? */
! 386: nData &= ~8;
! 387: }
! 388: }
! 389:
! 390: IoMem_WriteWord(0xff9200, nData);
1.1 root 391: }
1.1.1.2 root 392:
1.1.1.6 ! root 393:
! 394: /*-----------------------------------------------------------------------*/
! 395: /*
! 396: Read from STE joypad direction/buttons register (0xff9202)
! 397: */
! 398: void Joy_StePadMulti_ReadWord(void)
! 399: {
! 400: Uint8 nData = 0xff;
! 401:
! 402: if (ConfigureParams.Joysticks.Joy[JOYID_STEPADA].nJoystickMode != JOYSTICK_DISABLED
! 403: && (nSteJoySelect & 0x0f) != 0x0f)
! 404: {
! 405: nData &= 0xf0;
! 406: if (!(nSteJoySelect & 0x1))
! 407: {
! 408: nData |= ~Joy_GetStickData(JOYID_STEPADA) & 0x0f;
! 409: }
! 410: else if (!(nSteJoySelect & 0x2))
! 411: {
! 412: nData |= ~(Joy_GetFireButtons(JOYID_STEPADA) >> 13) & 0x0f;
! 413: }
! 414: else if (!(nSteJoySelect & 0x4))
! 415: {
! 416: nData |= ~(Joy_GetFireButtons(JOYID_STEPADA) >> 9) & 0x0f;
! 417: }
! 418: else if (!(nSteJoySelect & 0x8))
! 419: {
! 420: nData |= ~(Joy_GetFireButtons(JOYID_STEPADA) >> 5) & 0x0f;
! 421: }
! 422: }
! 423:
! 424: if (ConfigureParams.Joysticks.Joy[JOYID_STEPADB].nJoystickMode != JOYSTICK_DISABLED
! 425: && (nSteJoySelect & 0xf0) != 0xf0)
! 426: {
! 427: nData &= 0x0f;
! 428: if (!(nSteJoySelect & 0x10))
! 429: {
! 430: nData |= ~Joy_GetStickData(JOYID_STEPADB) << 4;
! 431: }
! 432: else if (!(nSteJoySelect & 0x20))
! 433: {
! 434: nData |= ~(Joy_GetFireButtons(JOYID_STEPADB) >> 13) & 0x0f;
! 435: }
! 436: else if (!(nSteJoySelect & 0x40))
! 437: {
! 438: nData |= ~(Joy_GetFireButtons(JOYID_STEPADB) >> 9) & 0x0f;
! 439: }
! 440: else if (!(nSteJoySelect & 0x80))
! 441: {
! 442: nData |= ~(Joy_GetFireButtons(JOYID_STEPADB) >> 5) & 0x0f;
! 443: }
! 444: }
! 445:
! 446: IoMem_WriteWord(0xff9202, (nData << 8) | 0x0ff);
! 447: }
! 448:
! 449:
! 450: /*-----------------------------------------------------------------------*/
! 451: /*
! 452: Write to STE joypad selection register (0xff9202)
! 453: */
! 454: void Joy_StePadMulti_WriteWord(void)
! 455: {
! 456: nSteJoySelect = IoMem_ReadWord(0xff9202);
! 457: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.