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

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: }

unix.superglobalmegacorp.com

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