Annotation of hatari/src/joy.c, revision 1.1.1.8

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.