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

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

unix.superglobalmegacorp.com

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