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