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

1.1       root        1: /*
1.1.1.4   root        2:   Hatari - joy.c
1.1       root        3: 
1.1.1.14  root        4:   This file is distributed under the GNU General Public License, version 2
                      5:   or at your option any later version. Read the file gpl.txt for details.
1.1.1.4   root        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.12  root       20: #include "screen.h"
1.1.1.2   root       21: #include "video.h"
1.1.1.15  root       22: #include "statusbar.h"
1.1       root       23: 
1.1.1.16! root       24: #define JOY_DEBUG 0
        !            25: #if JOY_DEBUG
        !            26: #define Dprintf(a) printf a
        !            27: #else
        !            28: #define Dprintf(a)
        !            29: #endif
        !            30: 
1.1.1.2   root       31: #define JOY_BUTTON1  1
                     32: #define JOY_BUTTON2  2
1.1       root       33: 
1.1.1.14  root       34: typedef struct
                     35: {
                     36:        int XPos,YPos;                /* the actually read axis values in range of -32768...0...32767 */
                     37:        int XAxisID,YAxisID;          /* the IDs of the physical PC joystick's axis to be used to gain ST joystick axis input */
                     38:        int Buttons;                  /* JOY_BUTTON1 */
                     39: } JOYREADING;
                     40: 
                     41: typedef struct
                     42: {
                     43:     const char *SDLJoystickName;
                     44:     int XAxisID,YAxisID;           /* the IDs associated with a certain SDL joystick */
                     45: } JOYAXISMAPPING;
1.1.1.2   root       46: 
1.1.1.13  root       47: static SDL_Joystick *sdlJoystick[ JOYSTICK_COUNT ] =           /* SDL's joystick structures */
1.1.1.6   root       48: {
                     49:        NULL, NULL, NULL, NULL, NULL, NULL
                     50: };
1.1.1.7   root       51: 
1.1.1.13  root       52: /* Further explanation see JoyInit() */
1.1.1.14  root       53: static JOYAXISMAPPING const *sdlJoystickMapping[ JOYSTICK_COUNT ] =    /* references which axis are actually in use by the selected SDL joystick */
1.1.1.13  root       54: {
                     55:        NULL, NULL, NULL, NULL, NULL, NULL
                     56: };
                     57: 
                     58: static bool bJoystickWorking[ JOYSTICK_COUNT ] =               /* Is joystick plugged in and working? */
1.1.1.6   root       59: {
1.1.1.11  root       60:        false, false, false, false, false, false
1.1.1.13  root       61: };
1.1.1.6   root       62: 
1.1.1.11  root       63: int JoystickSpaceBar = false;           /* State of space-bar on joystick button 2 */
1.1.1.13  root       64: static Uint8 nJoyKeyEmu[ JOYSTICK_COUNT ];
1.1.1.7   root       65: static Uint16 nSteJoySelect;
1.1       root       66: 
                     67: 
1.1.1.16! root       68: /**
        !            69:  * Get joystick name
        !            70:  */
        !            71: const char *Joy_GetName(int id)
        !            72: {
        !            73: #if WITH_SDL2
        !            74:        return SDL_JoystickName(sdlJoystick[id]);
        !            75: #else
        !            76:        return SDL_JoystickName(id);
        !            77: #endif
        !            78: }
        !            79: 
        !            80: /**
        !            81:  * Return maximum available real joystick ID
        !            82:  */
        !            83: int Joy_GetMaxId(void)
        !            84: {
        !            85:        int count = SDL_NumJoysticks();
        !            86:        if (count > JOYSTICK_COUNT)
        !            87:                count = JOYSTICK_COUNT;
        !            88:        return count - 1;
        !            89: }
        !            90: 
        !            91: /**
        !            92:  * Make sure real Joystick ID is valid, and if not, disable it & return false
        !            93:  */
        !            94: bool Joy_ValidateJoyId(int i)
        !            95: {
        !            96:        /* Unavailable joystick ID -> disable it if necessary */
        !            97:        if (ConfigureParams.Joysticks.Joy[i].nJoystickMode == JOYSTICK_REALSTICK &&
        !            98:            !bJoystickWorking[ConfigureParams.Joysticks.Joy[i].nJoyId])
        !            99:        {
        !           100:                Log_Printf(LOG_WARN, "Selected real Joystick %d unavailable, disabling ST joystick %d\n", ConfigureParams.Joysticks.Joy[i].nJoyId, i);
        !           101:                ConfigureParams.Joysticks.Joy[i].nJoystickMode = JOYSTICK_DISABLED;
        !           102:                ConfigureParams.Joysticks.Joy[i].nJoyId = 0;
        !           103:                return false;
        !           104:        }
        !           105:        return true;
        !           106: }
        !           107: 
1.1       root      108: /*-----------------------------------------------------------------------*/
1.1.1.8   root      109: /**
                    110:  * This function initialises the (real) joysticks.
                    111:  */
1.1       root      112: void Joy_Init(void)
                    113: {
1.1.1.13  root      114:        /* Joystick axis mapping table                          */
                    115:        /* Matthias Arndt <[email protected]>               */
                    116:        /* Somehow, not all SDL joysticks are created equal.    */
                    117:        /* Not all pads or sticks use axis 0 for x and axis 1   */
                    118:        /* for y information.                                   */
                    119:        /* This table allows to remap the axis to used.         */
                    120:        /* A joystick is identified by its SDL name and         */
                    121:        /* followed by the X axis to use and the Y axis.        */
                    122:        /* Find out the axis number with the tool jstest.       */
                    123: 
                    124:        /* FIXME: Read those settings from a configuration file and make them tunable from the GUI. */
1.1.1.14  root      125:        static const JOYAXISMAPPING AxisMappingTable [] =
1.1.1.13  root      126:        {
1.1.1.15  root      127:                /* Example entry for mapping joystick axis for a certain device: */
                    128:                /* USB game pad with ID ID 0079:0011, sold by Speedlink with axis 3 and 4 used */
                    129:                /*{"USB Gamepad" , 3, 4}, */
1.1.1.14  root      130:                /* Default entry used if no other SDL joystick name does match (should be last of this list) */
1.1.1.13  root      131:                {"*DEFAULT*" , 0, 1},
                    132:        };
                    133: 
1.1.1.14  root      134:        int i, j, nPadsConnected;
1.1.1.13  root      135: 
1.1.1.6   root      136:        /* Initialise SDL's joystick subsystem: */
                    137:        if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
                    138:        {
                    139:                Log_Printf(LOG_ERROR, "Could not init joysticks: %s\n", SDL_GetError());
                    140:                return;
                    141:        }
                    142: 
                    143:        /* Scan joystick connection array for working joysticks */
                    144:        nPadsConnected = SDL_NumJoysticks();
1.1.1.13  root      145:        for (i = 0; i < nPadsConnected && i < JOYSTICK_COUNT ; i++)
1.1.1.6   root      146:        {
                    147:                /* Open the joystick for use */
                    148:                sdlJoystick[i] = SDL_JoystickOpen(i);
                    149:                /* Is joystick ok? */
                    150:                if (sdlJoystick[i] != NULL)
                    151:                {
                    152:                        /* Set as working */
1.1.1.11  root      153:                        bJoystickWorking[i] = true;
1.1.1.16! root      154:                        Log_Printf(LOG_DEBUG, "Joystick %i: %s\n", i, Joy_GetName(i));
1.1.1.14  root      155:                        /* determine joystick axis mapping for given SDL joystick name, last is default: */
                    156:                        for (j = 0; j < ARRAYSIZE(AxisMappingTable)-1; j++) {
1.1.1.13  root      157:                                /* check if ID string matches the one reported by SDL: */
1.1.1.16! root      158:                                if(strncmp(AxisMappingTable[j].SDLJoystickName, Joy_GetName(i), strlen(AxisMappingTable[j].SDLJoystickName)) == 0)
1.1.1.13  root      159:                                        break;
                    160:                        }
                    161: 
1.1.1.14  root      162:                        sdlJoystickMapping[i] = &(AxisMappingTable[j]);
                    163:                        Log_Printf(LOG_DEBUG, "Joystick %i maps axis %d and %d (%s)\n", i, sdlJoystickMapping[i]->XAxisID, sdlJoystickMapping[i]->YAxisID,
                    164:                                        sdlJoystickMapping[i]->SDLJoystickName );
1.1.1.6   root      165:                }
                    166:        }
                    167: 
1.1.1.16! root      168:        for (i = 0; i < JOYSTICK_COUNT ; i++)
        !           169:                Joy_ValidateJoyId(i);
        !           170: 
1.1.1.11  root      171:        JoystickSpaceBar = false;
1.1       root      172: }
                    173: 
                    174: 
1.1.1.2   root      175: /*-----------------------------------------------------------------------*/
1.1.1.8   root      176: /**
                    177:  * Close the (real) joysticks.
                    178:  */
1.1.1.7   root      179: void Joy_UnInit(void)
                    180: {
                    181:        int i, nPadsConnected;
                    182: 
                    183:        nPadsConnected = SDL_NumJoysticks();
                    184: 
1.1.1.13  root      185:        for (i = 0; i < nPadsConnected && i < JOYSTICK_COUNT ; i++)
1.1.1.7   root      186:        {
1.1.1.11  root      187:                if (bJoystickWorking[i] == true)
1.1.1.7   root      188:                {
                    189:                        SDL_JoystickClose(sdlJoystick[i]);
                    190:                }
                    191:        }
                    192: }
                    193: 
                    194: 
                    195: /*-----------------------------------------------------------------------*/
1.1.1.8   root      196: /**
                    197:  * Read details from joystick using SDL calls
                    198:  * NOTE ID is that of SDL
                    199:  */
1.1.1.9   root      200: static bool Joy_ReadJoystick(int nSdlJoyID, JOYREADING *pJoyReading)
1.1.1.6   root      201: {
1.1.1.12  root      202:        /* Joystick is OK, read position from the configured joystick axis */
                    203:        pJoyReading->XPos = SDL_JoystickGetAxis(sdlJoystick[nSdlJoyID], pJoyReading->XAxisID);
                    204:        pJoyReading->YPos = SDL_JoystickGetAxis(sdlJoystick[nSdlJoyID], pJoyReading->YAxisID);
1.1.1.6   root      205:        /* Sets bit #0 if button #1 is pressed: */
                    206:        pJoyReading->Buttons = SDL_JoystickGetButton(sdlJoystick[nSdlJoyID], 0);
                    207:        /* Sets bit #1 if button #2 is pressed: */
                    208:        if (SDL_JoystickGetButton(sdlJoystick[nSdlJoyID], 1))
                    209:                pJoyReading->Buttons |= JOY_BUTTON2;
                    210: 
1.1.1.11  root      211:        return true;
1.1       root      212: }
                    213: 
1.1.1.2   root      214: 
                    215: /*-----------------------------------------------------------------------*/
1.1.1.8   root      216: /**
                    217:  * Read PC joystick and return ST format byte, i.e. lower 4 bits direction
                    218:  * and top bit fire.
                    219:  * NOTE : ID 0 is Joystick 0/Mouse and ID 1 is Joystick 1 (default),
                    220:  *        ID 2 and 3 are STE joypads and ID 4 and 5 are parport joysticks.
                    221:  */
1.1.1.6   root      222: Uint8 Joy_GetStickData(int nStJoyId)
1.1       root      223: {
1.1.1.6   root      224:        Uint8 nData = 0;
                    225:        JOYREADING JoyReading;
                    226:        int nSdlJoyId;
1.1.1.12  root      227:        int nAxes; /* how many joystick axes are on the current selected SDL joystick? */
1.1.1.6   root      228: 
                    229:        nSdlJoyId = ConfigureParams.Joysticks.Joy[nStJoyId].nJoyId;
1.1.1.12  root      230:        nAxes = SDL_JoystickNumAxes(sdlJoystick[nSdlJoyId]);
1.1.1.6   root      231: 
                    232:        /* Are we emulating the joystick via the keyboard? */
                    233:        if (ConfigureParams.Joysticks.Joy[nStJoyId].nJoystickMode == JOYSTICK_KEYBOARD)
                    234:        {
                    235:                /* If holding 'SHIFT' we actually want cursor key movement, so ignore any of this */
                    236:                if ( !(SDL_GetModState()&(KMOD_LSHIFT|KMOD_RSHIFT)) )
                    237:                {
                    238:                        nData = nJoyKeyEmu[nStJoyId];
                    239:                }
                    240:        }
                    241:        else if (ConfigureParams.Joysticks.Joy[nStJoyId].nJoystickMode == JOYSTICK_REALSTICK
                    242:                 && bJoystickWorking[nSdlJoyId])
                    243:        {
1.1.1.12  root      244:                /* get joystick axis from configuration settings and make them plausible */
1.1.1.13  root      245:                JoyReading.XAxisID = sdlJoystickMapping[nSdlJoyId]->XAxisID;
                    246:                JoyReading.YAxisID = sdlJoystickMapping[nSdlJoyId]->YAxisID;
                    247: 
1.1.1.12  root      248:                /* make selected axis IDs plausible */
                    249:                if(  (JoyReading.XAxisID == JoyReading.YAxisID) /* same joystick axis for two directions? */
                    250:                   ||(JoyReading.XAxisID > nAxes)               /* ID for x axis beyond nr of existing axes? */
                    251:                   ||(JoyReading.YAxisID > nAxes)               /* ID for y axis beyond nr of existing axes? */
                    252:                  )
                    253:                {
                    254:                        /* define sane SDL joystick axis defaults and prepare them for saving back to the config file: */
                    255:                        JoyReading.XAxisID = 0;
                    256:                        JoyReading.YAxisID = 1;
                    257:                }
1.1.1.13  root      258: 
1.1.1.12  root      259:                /* Read real joystick and map to emulated ST joystick for emulation */
1.1.1.6   root      260:                if (!Joy_ReadJoystick(nSdlJoyId, &JoyReading))
                    261:                {
1.1.1.12  root      262:                        /* Something is wrong, we cannot read the joystick from SDL */
1.1.1.11  root      263:                        bJoystickWorking[nSdlJoyId] = false;
1.1.1.6   root      264:                        return 0;
                    265:                }
                    266: 
                    267:                /* Directions */
                    268:                if (JoyReading.YPos <= JOYRANGE_UP_VALUE)
1.1.1.11  root      269:                        nData |= ATARIJOY_BITMASK_UP;
1.1.1.6   root      270:                else if (JoyReading.YPos >= JOYRANGE_DOWN_VALUE)
1.1.1.11  root      271:                        nData |= ATARIJOY_BITMASK_DOWN;
1.1.1.6   root      272:                if (JoyReading.XPos <= JOYRANGE_LEFT_VALUE)
1.1.1.11  root      273:                        nData |= ATARIJOY_BITMASK_LEFT;
1.1.1.6   root      274:                else if (JoyReading.XPos >= JOYRANGE_RIGHT_VALUE)
1.1.1.11  root      275:                        nData |= ATARIJOY_BITMASK_RIGHT;
1.1.1.6   root      276: 
                    277:                /* PC Joystick button 1 is set as ST joystick button */
                    278:                if (JoyReading.Buttons & JOY_BUTTON1)
1.1.1.11  root      279:                        nData |= ATARIJOY_BITMASK_FIRE;
1.1.1.6   root      280: 
                    281:                /* Enable PC Joystick button 2 to mimick space bar (For XenonII, Flying Shark etc...) */
                    282:                if (nStJoyId == JOYID_JOYSTICK1 && (JoyReading.Buttons & JOY_BUTTON2))
                    283:                {
1.1.1.11  root      284:                        if (ConfigureParams.Joysticks.Joy[nStJoyId].bEnableJumpOnFire2)
1.1.1.6   root      285:                        {
1.1.1.11  root      286:                                /* If "Jump on Button 2" is enabled, PC Joystick button 2 acts as "ST Joystick up" */
                    287:                                nData |= ATARIJOY_BITMASK_UP;
                    288:                        } else {
                    289:                                /* If "Jump on Button 2" is not enabled, PC Joystick button 2 acts as pressing SPACE on the ST keyboard */
                    290:                                /* Only press 'space bar' if not in NULL state */
                    291:                                if (!JoystickSpaceBar)
                    292:                                {
                    293:                                        /* Press, ikbd will send packets and de-press */
                    294:                                        JoystickSpaceBar = JOYSTICK_SPACE_DOWN;
                    295:                                }
1.1.1.6   root      296:                        }
                    297:                }
                    298:        }
                    299: 
                    300:        /* Ignore fire button every 8 frames if enabled autofire (for both cursor emulation and joystick) */
                    301:        if (ConfigureParams.Joysticks.Joy[nStJoyId].bEnableAutoFire)
                    302:        {
                    303:                if ((nVBLs&0x7)<4)
1.1.1.11  root      304:                        nData &= ~ATARIJOY_BITMASK_FIRE;          /* Remove top bit! */
1.1.1.6   root      305:        }
                    306: 
                    307:        return nData;
1.1       root      308: }
                    309: 
1.1.1.2   root      310: 
                    311: /*-----------------------------------------------------------------------*/
1.1.1.8   root      312: /**
                    313:  * Get the fire button states.
                    314:  * Note: More than one fire buttons are only supported for real joystick,
                    315:  * not for keyboard emulation!
                    316:  */
1.1.1.6   root      317: static int Joy_GetFireButtons(int nStJoyId)
                    318: {
                    319:        int nButtons = 0;
                    320:        int nSdlJoyId;
                    321:        int i, nMaxButtons;
                    322: 
                    323:        nSdlJoyId = ConfigureParams.Joysticks.Joy[nStJoyId].nJoyId;
                    324: 
                    325:        /* Are we emulating the joystick via the keyboard? */
                    326:        if (ConfigureParams.Joysticks.Joy[nStJoyId].nJoystickMode == JOYSTICK_KEYBOARD)
                    327:        {
                    328:                if (nJoyKeyEmu[nStJoyId] & 0x80)
                    329:                {
                    330:                        nButtons |= 1;
                    331:                }
                    332:        }
                    333:        else if (ConfigureParams.Joysticks.Joy[nStJoyId].nJoystickMode == JOYSTICK_REALSTICK
                    334:                 && bJoystickWorking[nSdlJoyId])
                    335:        {
                    336:                nMaxButtons = SDL_JoystickNumButtons(sdlJoystick[nSdlJoyId]);
                    337:                if (nMaxButtons > 17)
                    338:                        nMaxButtons = 17;
                    339:                /* Now read all fire buttons and set a bit for each pressed button: */
                    340:                for (i = 0; i < nMaxButtons; i++)
                    341:                {
                    342:                        if (SDL_JoystickGetButton(sdlJoystick[nSdlJoyId], i))
                    343:                        {
                    344:                                nButtons |= (1 << i);
                    345:                        }
                    346:                }
                    347:        }
1.1.1.2   root      348: 
1.1.1.6   root      349:        return nButtons;
1.1       root      350: }
                    351: 
1.1.1.2   root      352: 
                    353: /*-----------------------------------------------------------------------*/
1.1.1.8   root      354: /**
                    355:  * Set joystick cursor emulation for given port.  This assumes that
                    356:  * if the same keys have been defined for "cursor key emulation" in
                    357:  * other ports, the emulation for them has been switched off. Returns
                    358:  * 1 if the port number was OK, zero for error.
                    359:  */
1.1.1.9   root      360: bool Joy_SetCursorEmulation(int port)
1.1.1.7   root      361: {
                    362:        if (port < 0 || port >= JOYSTICK_COUNT) {
1.1.1.16! root      363:                return false;
1.1.1.7   root      364:        }
                    365:        ConfigureParams.Joysticks.Joy[port].nJoystickMode = JOYSTICK_KEYBOARD;
1.1.1.16! root      366:        return true;
1.1.1.7   root      367: }
                    368: 
                    369: 
                    370: /*-----------------------------------------------------------------------*/
1.1.1.8   root      371: /**
                    372:  * Toggle joystick cursor emulation between port 0, port 1 and being off
                    373:  * from them. When it's turned off from them, the port's previous state
                    374:  * is restored
                    375:  */
1.1       root      376: void Joy_ToggleCursorEmulation(void)
                    377: {
1.1.1.11  root      378:        static JOYSTICKMODE saved[2] = { JOYSTICK_DISABLED, JOYSTICK_DISABLED };
                    379:        JOYSTICKMODE state;
                    380:        int i, port = 2;
1.1.1.7   root      381:        for (i = 0; i < 2; i++) {
                    382:                state = ConfigureParams.Joysticks.Joy[i].nJoystickMode;
                    383:                if (state == JOYSTICK_KEYBOARD) {
                    384:                        port = i;
                    385:                } else {
                    386:                        saved[i] = state;
                    387:                }
                    388:        }
                    389:        switch (port) {
                    390:        case 0:  /* (only) in port 0, disable cursor emu */
                    391:                ConfigureParams.Joysticks.Joy[0].nJoystickMode = saved[0];
                    392:                break;
                    393:        case 1:  /* (at least) in port 1, switch cursor emu to port 0 */
                    394:                ConfigureParams.Joysticks.Joy[1].nJoystickMode = saved[1];
                    395:                ConfigureParams.Joysticks.Joy[0].nJoystickMode = JOYSTICK_KEYBOARD;
                    396:                break;
                    397:        default:  /* neither in port 0 or 1, enable cursor emu to port 1 */
                    398:                ConfigureParams.Joysticks.Joy[1].nJoystickMode = JOYSTICK_KEYBOARD;
1.1.1.6   root      399:        }
1.1.1.15  root      400:        Statusbar_UpdateInfo();
1.1.1.6   root      401: }
                    402: 
                    403: 
                    404: /*-----------------------------------------------------------------------*/
1.1.1.8   root      405: /**
1.1.1.16! root      406:  * Switch between joystick types in given joyport
        !           407:  */
        !           408: bool Joy_SwitchMode(int port)
        !           409: {
        !           410:        int mode;
        !           411:        if (port < 0 || port >= JOYSTICK_COUNT) {
        !           412:                return false;
        !           413:        }
        !           414:        mode = (ConfigureParams.Joysticks.Joy[port].nJoystickMode + 1) % JOYSTICK_MODES;
        !           415:        ConfigureParams.Joysticks.Joy[port].nJoystickMode = mode;
        !           416:        Statusbar_UpdateInfo();
        !           417:        return true;
        !           418: }
        !           419: 
        !           420: 
        !           421: /*-----------------------------------------------------------------------*/
        !           422: /**
1.1.1.8   root      423:  * A key has been pressed down, check if we use it for joystick emulation
                    424:  * via keyboard.
                    425:  */
1.1.1.9   root      426: bool Joy_KeyDown(int symkey, int modkey)
1.1.1.6   root      427: {
                    428:        int i;
                    429: 
1.1.1.7   root      430:        for (i = 0; i < JOYSTICK_COUNT; i++)
1.1.1.6   root      431:        {
                    432:                if (ConfigureParams.Joysticks.Joy[i].nJoystickMode == JOYSTICK_KEYBOARD
                    433:                    && !(modkey & KMOD_SHIFT))
                    434:                {
                    435:                        if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeUp)
                    436:                        {
1.1.1.11  root      437:                                nJoyKeyEmu[i] &= ~ATARIJOY_BITMASK_DOWN;   /* Disable down */
                    438:                                nJoyKeyEmu[i] |= ATARIJOY_BITMASK_UP;    /* Enable up */
                    439:                                return true;
1.1.1.6   root      440:                        }
                    441:                        else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeDown)
                    442:                        {
1.1.1.11  root      443:                                nJoyKeyEmu[i] &= ~ATARIJOY_BITMASK_UP;   /* Disable up */
                    444:                                nJoyKeyEmu[i] |= ATARIJOY_BITMASK_DOWN;    /* Enable down */
                    445:                                return true;
1.1.1.6   root      446:                        }
                    447:                        else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeLeft)
                    448:                        {
1.1.1.11  root      449:                                nJoyKeyEmu[i] &= ~ATARIJOY_BITMASK_RIGHT;   /* Disable right */
                    450:                                nJoyKeyEmu[i] |= ATARIJOY_BITMASK_LEFT;    /* Enable left */
                    451:                                return true;
1.1.1.6   root      452:                        }
                    453:                        else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeRight)
                    454:                        {
1.1.1.11  root      455:                                nJoyKeyEmu[i] &= ~ATARIJOY_BITMASK_LEFT;   /* Disable left */
                    456:                                nJoyKeyEmu[i] |= ATARIJOY_BITMASK_RIGHT;    /* Enable right */
                    457:                                return true;
1.1.1.6   root      458:                        }
                    459:                        else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeFire)
                    460:                        {
1.1.1.11  root      461:                                nJoyKeyEmu[i] |= ATARIJOY_BITMASK_FIRE;
                    462:                                return true;
1.1.1.6   root      463:                        }
                    464:                }
                    465:        }
                    466: 
1.1.1.11  root      467:        return false;
1.1.1.6   root      468: }
                    469: 
                    470: 
                    471: /*-----------------------------------------------------------------------*/
1.1.1.8   root      472: /**
                    473:  * A key has been released, check if we use it for joystick emulation
                    474:  * via keyboard.
                    475:  */
1.1.1.9   root      476: bool Joy_KeyUp(int symkey, int modkey)
1.1.1.6   root      477: {
                    478:        int i;
                    479: 
1.1.1.7   root      480:        for (i = 0; i < JOYSTICK_COUNT; i++)
1.1.1.6   root      481:        {
                    482:                if (ConfigureParams.Joysticks.Joy[i].nJoystickMode == JOYSTICK_KEYBOARD
                    483:                    && !(modkey & KMOD_SHIFT))
                    484:                {
                    485:                        if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeUp)
                    486:                        {
1.1.1.11  root      487:                                nJoyKeyEmu[i] &= ~ATARIJOY_BITMASK_UP;
                    488:                                return true;
1.1.1.6   root      489:                        }
                    490:                        else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeDown)
                    491:                        {
1.1.1.11  root      492:                                nJoyKeyEmu[i] &= ~ATARIJOY_BITMASK_DOWN;
                    493:                                return true;
1.1.1.6   root      494:                        }
                    495:                        else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeLeft)
                    496:                        {
1.1.1.11  root      497:                                nJoyKeyEmu[i] &= ~ATARIJOY_BITMASK_LEFT;
                    498:                                return true;
1.1.1.6   root      499:                        }
                    500:                        else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeRight)
                    501:                        {
1.1.1.11  root      502:                                nJoyKeyEmu[i] &= ~ATARIJOY_BITMASK_RIGHT;
                    503:                                return true;
1.1.1.6   root      504:                        }
                    505:                        else if (symkey == ConfigureParams.Joysticks.Joy[i].nKeyCodeFire)
                    506:                        {
1.1.1.11  root      507:                                nJoyKeyEmu[i] &= ~ATARIJOY_BITMASK_FIRE;
                    508:                                return true;
1.1.1.6   root      509:                        }
                    510:                }
                    511:        }
                    512: 
1.1.1.11  root      513:        return false;
1.1.1.6   root      514: }
                    515: 
                    516: 
                    517: /*-----------------------------------------------------------------------*/
1.1.1.8   root      518: /**
                    519:  * Read from STE joypad buttons register (0xff9200)
                    520:  */
1.1.1.6   root      521: void Joy_StePadButtons_ReadWord(void)
                    522: {
                    523:        Uint16 nData = 0xffff;
                    524: 
                    525:        if (ConfigureParams.Joysticks.Joy[JOYID_STEPADA].nJoystickMode != JOYSTICK_DISABLED
                    526:            && (nSteJoySelect & 0x0f) != 0x0f)
                    527:        {
                    528:                int nButtons = Joy_GetFireButtons(JOYID_STEPADA);
                    529:                if (!(nSteJoySelect & 0x1))
                    530:                {
                    531:                        if (nButtons & 0x01)  /* Fire button A pressed? */
                    532:                                nData &= ~2;
                    533:                        if (nButtons & 0x10)  /* Fire button PAUSE pressed? */
                    534:                                nData &= ~1;
                    535:                }
                    536:                else if (!(nSteJoySelect & 0x2))
                    537:                {
                    538:                        if (nButtons & 0x02)  /* Fire button B pressed? */
                    539:                                nData &= ~2;
                    540:                }
                    541:                else if (!(nSteJoySelect & 0x4))
                    542:                {
                    543:                        if (nButtons & 0x04)  /* Fire button C pressed? */
                    544:                                nData &= ~2;
                    545:                }
                    546:                else if (!(nSteJoySelect & 0x8))
                    547:                {
1.1.1.16! root      548:                        if (nButtons & 0x08)  /* Fire button OPTION pressed? */
1.1.1.6   root      549:                                nData &= ~2;
                    550:                }
                    551:        }
                    552: 
                    553:        if (ConfigureParams.Joysticks.Joy[JOYID_STEPADB].nJoystickMode != JOYSTICK_DISABLED
                    554:            && (nSteJoySelect & 0xf0) != 0xf0)
                    555:        {
                    556:                int nButtons = Joy_GetFireButtons(JOYID_STEPADB);
                    557:                if (!(nSteJoySelect & 0x10))
                    558:                {
                    559:                        if (nButtons & 0x01)  /* Fire button A pressed? */
                    560:                                nData &= ~8;
                    561:                        if (nButtons & 0x10)  /* Fire button PAUSE pressed? */
                    562:                                nData &= ~4;
                    563:                }
                    564:                else if (!(nSteJoySelect & 0x20))
                    565:                {
                    566:                        if (nButtons & 0x02)  /* Fire button B pressed? */
                    567:                                nData &= ~8;
                    568:                }
                    569:                else if (!(nSteJoySelect & 0x40))
                    570:                {
                    571:                        if (nButtons & 0x04)  /* Fire button C pressed? */
                    572:                                nData &= ~8;
                    573:                }
                    574:                else if (!(nSteJoySelect & 0x80))
                    575:                {
                    576:                        if (nButtons & 0x08)  /* Fire button OPTION pressed? */
                    577:                                nData &= ~8;
                    578:                }
                    579:        }
                    580: 
1.1.1.16! root      581:        Dprintf(("0xff9200 -> 0x%04x\n", nData));
1.1.1.6   root      582:        IoMem_WriteWord(0xff9200, nData);
1.1       root      583: }
1.1.1.2   root      584: 
1.1.1.6   root      585: 
                    586: /*-----------------------------------------------------------------------*/
1.1.1.8   root      587: /**
                    588:  * Read from STE joypad direction/buttons register (0xff9202)
1.1.1.16! root      589:  *
        !           590:  * This is used e.g. by Reservoir Gods' Tautology II
1.1.1.8   root      591:  */
1.1.1.6   root      592: void Joy_StePadMulti_ReadWord(void)
                    593: {
1.1.1.16! root      594:        Uint16 nData = 0xff;
1.1.1.6   root      595: 
                    596:        if (ConfigureParams.Joysticks.Joy[JOYID_STEPADA].nJoystickMode != JOYSTICK_DISABLED
                    597:            && (nSteJoySelect & 0x0f) != 0x0f)
                    598:        {
                    599:                nData &= 0xf0;
                    600:                if (!(nSteJoySelect & 0x1))
                    601:                {
                    602:                        nData |= ~Joy_GetStickData(JOYID_STEPADA) & 0x0f;
                    603:                }
                    604:                else if (!(nSteJoySelect & 0x2))
                    605:                {
                    606:                        nData |= ~(Joy_GetFireButtons(JOYID_STEPADA) >> 13) & 0x0f;
                    607:                }
                    608:                else if (!(nSteJoySelect & 0x4))
                    609:                {
                    610:                        nData |= ~(Joy_GetFireButtons(JOYID_STEPADA) >> 9) & 0x0f;
                    611:                }
                    612:                else if (!(nSteJoySelect & 0x8))
                    613:                {
                    614:                        nData |= ~(Joy_GetFireButtons(JOYID_STEPADA) >> 5) & 0x0f;
                    615:                }
                    616:        }
                    617: 
                    618:        if (ConfigureParams.Joysticks.Joy[JOYID_STEPADB].nJoystickMode != JOYSTICK_DISABLED
                    619:            && (nSteJoySelect & 0xf0) != 0xf0)
                    620:        {
                    621:                nData &= 0x0f;
                    622:                if (!(nSteJoySelect & 0x10))
                    623:                {
                    624:                        nData |= ~Joy_GetStickData(JOYID_STEPADB) << 4;
                    625:                }
                    626:                else if (!(nSteJoySelect & 0x20))
                    627:                {
1.1.1.16! root      628:                        nData |= ~(Joy_GetFireButtons(JOYID_STEPADB) >> (13-4)) & 0xf0;
1.1.1.6   root      629:                }
                    630:                else if (!(nSteJoySelect & 0x40))
                    631:                {
1.1.1.16! root      632:                        nData |= ~(Joy_GetFireButtons(JOYID_STEPADB) >> (9-4)) & 0xf0;
1.1.1.6   root      633:                }
                    634:                else if (!(nSteJoySelect & 0x80))
                    635:                {
1.1.1.16! root      636:                        nData |= ~(Joy_GetFireButtons(JOYID_STEPADB) >> (5-4)) & 0xf0;
1.1.1.6   root      637:                }
                    638:        }
                    639: 
1.1.1.16! root      640:        nData = (nData << 8) | 0x0ff;
        !           641:        Dprintf(("0xff9202 -> 0x%04x\n", nData));
        !           642:        IoMem_WriteWord(0xff9202, nData);
1.1.1.6   root      643: }
                    644: 
                    645: 
                    646: /*-----------------------------------------------------------------------*/
1.1.1.8   root      647: /**
                    648:  * Write to STE joypad selection register (0xff9202)
                    649:  */
1.1.1.6   root      650: void Joy_StePadMulti_WriteWord(void)
                    651: {
                    652:        nSteJoySelect = IoMem_ReadWord(0xff9202);
1.1.1.16! root      653:        Dprintf(("0xff9202 <- 0x%04x\n", nSteJoySelect));
1.1.1.6   root      654: }

unix.superglobalmegacorp.com

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