Mercurial > sdl-ios-xcode
diff src/joystick/mint/SDL_sysjoystick.c @ 302:8a86bdf34f0f
Added Atari joystick support (thanks Patrice!)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 07 Mar 2002 20:23:11 +0000 |
parents | |
children | 9c6613983e85 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/joystick/mint/SDL_sysjoystick.c Thu Mar 07 20:23:11 2002 +0000 @@ -0,0 +1,625 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id$"; +#endif + +/* + * Atari Joystick/Joypad drivers + * + * Patrice Mandin + */ + +#include <stdlib.h> +#include <string.h> + +#include <sys/cookie.h> +#include <mint/osbind.h> + +#include "SDL_types.h" +#include "SDL_error.h" +#include "SDL_joystick.h" +#include "SDL_sysjoystick.h" +#include "SDL_joystick_c.h" + +#include "../video/ataricommon/SDL_ikbdinterrupt_s.h" + +/*--- Const ---*/ + +/* We can have: + 1 joystick on IKBD port 1 (port 0 is used by mouse) + 2 joypads on ports A,B + or 4 joysticks on joypads ports A,B + or 1 lightpen on joypad port A + or 2 analog paddles on joypads ports A,B + 2 joysticks on parallel port +*/ + +enum { + IKBD_JOY1=0, + PORTA_PAD, + PORTB_PAD, + PORTA_JOY0, + PORTA_JOY1, + PORTB_JOY0, + PORTB_JOY1, + PORTA_LP, + PORTA_ANPAD, + PORTB_ANPAD, +#if 0 + PARA_JOY0, + PARA_JOY1, +#endif + MAX_JOYSTICKS +}; + +enum { + MCH_ST=0, + MCH_STE, + MCH_TT, + MCH_F30 +}; + +/* Joypad buttons + * Procontroller note: + * L,R are connected to 4,6 + * X,Y,Z are connected to 7,8,9 + */ + +enum { + JP_UP=0, JP_DOWN, JP_LEFT, JP_RIGHT, + JP_KPMULT, JP_KP7, JP_KP4, JP_KP1, + JP_KP0, JP_KP8, JP_KP5, JP_KP2, + JP_KPNUM, JP_KP9, JP_KP6, JP_KP3, + JP_PAUSE, JP_FIRE0, JP_UNDEF0, JP_FIRE1, + JP_UNDEF1, JP_FIRE2, JP_UNDEF2, JP_OPTION +}; + +#define JP_NUM_BUTTONS 17 + +#define PORT_JS_RIGHT (1<<0) +#define PORT_JS_LEFT (1<<1) +#define PORT_JS_DOWN (1<<2) +#define PORT_JS_UP (1<<3) +#define PORT_JS_FIRE (1<<4) + +/*--- Types ---*/ + +typedef struct { + SDL_bool enabled; + unsigned char *name; + Uint32 prevstate; +} atarijoy_t; + +/*--- Variables ---*/ + +static atarijoy_t atarijoysticks[MAX_JOYSTICKS]={ + {SDL_FALSE,"IKBD joystick port 1",0}, + {SDL_FALSE,"Joypad port A",0}, + {SDL_FALSE,"Joypad port B",0}, + {SDL_FALSE,"Joystick 0 port A",0}, + {SDL_FALSE,"Joystick 1 port A",0}, + {SDL_FALSE,"Joystick 0 port B",0}, + {SDL_FALSE,"Joystick 1 port B",0}, + {SDL_FALSE,"Lightpen port A",0}, + {SDL_FALSE,"Analog paddle port A",0}, + {SDL_FALSE,"Analog paddle port B",0} +#if 0 + ,{SDL_FALSE,"Joystick 0 parallel port",0}, + {SDL_FALSE,"Joystick 1 parallel port",0} +#endif +}; + +static const int jp_buttons[JP_NUM_BUTTONS]={ + JP_KPMULT, JP_KP7, JP_KP4, JP_KP1, + JP_KP0, JP_KP8, JP_KP5, JP_KP2, + JP_KPNUM, JP_KP9, JP_KP6, JP_KP3, + JP_PAUSE, JP_FIRE0, JP_FIRE1, JP_FIRE2, + JP_OPTION +}; + +static SDL_bool joypad_ports_enabled=SDL_FALSE; + +/* Updated joypad ports */ +static Uint16 jp_paddles[4]; +static Uint16 jp_lightpens[2]; +static Uint16 jp_directions; +static Uint16 jp_fires; +static Uint32 jp_joypads[2]; + +/*--- Functions prototypes ---*/ + +static int GetEnabledAtariJoystick(int index); +static void UpdateJoypads(void); + +/*--- Functions ---*/ + +int SDL_SYS_JoystickInit(void) +{ + int i; + unsigned long cookie_mch; + const char *envr=getenv("SDL_JOYSTICK_ATARI"); + const char *env_evt=getenv("SDL_ATARI_EVENTSDRIVER"); + SDL_bool ikbd_enabled=SDL_FALSE; + +#define TEST_JOY_ENABLED(env,idstring,num) \ + if (strstr(env,idstring"-off")) { \ + atarijoysticks[num].enabled=SDL_FALSE; \ + } \ + if (strstr(env,idstring"-on")) { \ + atarijoysticks[num].enabled=SDL_TRUE; \ + } + + /* Cookie _MCH present ? if not, assume ST machine */ + if (Getcookie(C__MCH, &cookie_mch) != C_FOUND) { + cookie_mch = MCH_ST << 16; + } + + /* Enable some default joysticks */ + if ((cookie_mch == MCH_ST<<16) || ((cookie_mch>>16) == MCH_STE) || + (cookie_mch == MCH_TT<<16) || (cookie_mch == MCH_F30<<16)) { + ikbd_enabled=SDL_TRUE; + if (env_evt) { + if (!strcmp(env_evt,"ikbd")) { + ikbd_enabled=SDL_FALSE; + } + } + atarijoysticks[IKBD_JOY1].enabled=ikbd_enabled; + } + if ((cookie_mch == MCH_STE<<16) || (cookie_mch == MCH_F30<<16)) { + atarijoysticks[PORTA_PAD].enabled=SDL_TRUE; + atarijoysticks[PORTB_PAD].enabled=SDL_TRUE; + } + + /* Read environment for joysticks to enable */ + if (envr) { + /* IKBD on any Atari, maybe clones */ + if ((cookie_mch == MCH_ST<<16) || ((cookie_mch>>16) == MCH_STE) || + (cookie_mch == MCH_TT<<16) || (cookie_mch == MCH_F30<<16)) { + if (env_evt) { + if (strcmp(env_evt,"ikbd")) { + TEST_JOY_ENABLED(envr, "ikbd-joy1", IKBD_JOY1); + } + } + } + /* Joypads ports only on STE and Falcon */ + if ((cookie_mch == MCH_STE<<16) || (cookie_mch == MCH_F30<<16)) { + TEST_JOY_ENABLED(envr, "porta-pad", PORTA_PAD); + if (!atarijoysticks[PORTA_PAD].enabled) { + TEST_JOY_ENABLED(envr, "porta-joy0", PORTA_JOY0); + TEST_JOY_ENABLED(envr, "porta-joy1", PORTA_JOY1); + if (!(atarijoysticks[PORTA_JOY0].enabled) && !(atarijoysticks[PORTA_JOY1].enabled)) { + TEST_JOY_ENABLED(envr, "porta-lp", PORTA_LP); + if (!atarijoysticks[PORTA_LP].enabled) { + TEST_JOY_ENABLED(envr, "porta-anpad", PORTA_ANPAD); + } + } + } + + TEST_JOY_ENABLED(envr, "portb-pad", PORTB_PAD); + if (!atarijoysticks[PORTB_PAD].enabled) { + TEST_JOY_ENABLED(envr, "portb-joy0", PORTB_JOY0); + TEST_JOY_ENABLED(envr, "portb-joy1", PORTB_JOY1); + if (!(atarijoysticks[PORTB_JOY0].enabled) && !(atarijoysticks[PORTB_JOY1].enabled)) { + TEST_JOY_ENABLED(envr, "portb-anpad", PORTB_ANPAD); + } + } + } +#if 0 + /* Parallel port on any Atari, maybe clones */ + if ((cookie_mch == MCH_ST<<16) || ((cookie_mch>>16) == MCH_STE) || + (cookie_mch == MCH_TT<<16) || (cookie_mch == MCH_F30<<16)) { + TEST_JOY_ENABLED(envr, "para-joy0", PARA_JOY0); + TEST_JOY_ENABLED(envr, "para-joy1", PARA_JOY1); + } +#endif + } + + /* Need to update joypad ports ? */ + joypad_ports_enabled=SDL_FALSE; + for (i=PORTA_PAD;i<=PORTB_ANPAD;i++) { + if (atarijoysticks[i].enabled) { + joypad_ports_enabled=SDL_TRUE; + break; + } + } + + SDL_numjoysticks = 0; + for (i=0;i<MAX_JOYSTICKS;i++) { + if (atarijoysticks[i].enabled) { + ++SDL_numjoysticks; + } + } + + return(SDL_numjoysticks); +} + +static int GetEnabledAtariJoystick(int index) +{ + int i,j; + + /* Return the nth'index' enabled atari joystick */ + j=0; + for (i=0;i<MAX_JOYSTICKS;i++) { + if (atarijoysticks[i].enabled) { + if (j==index) { + break; + } else { + j++; + } + } + } + if (i==MAX_JOYSTICKS) + return -1; + + return i; +} + +const char *SDL_SYS_JoystickName(int index) +{ + int numjoystick; + + numjoystick=GetEnabledAtariJoystick(index); + if (numjoystick==-1) + return NULL; + + return(atarijoysticks[numjoystick].name); +} + +int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) +{ + int numjoystick; + + numjoystick=GetEnabledAtariJoystick(joystick->index); + if (numjoystick==-1) + return -1; + + if ((numjoystick==PORTA_PAD) || (numjoystick==PORTB_PAD)) { + joystick->nbuttons=JP_NUM_BUTTONS; + } else if ((numjoystick==PORTA_LP) || (numjoystick==PORTA_ANPAD) || + (numjoystick==PORTB_ANPAD)) { + joystick->nbuttons=2; + } else { + joystick->nbuttons=1; + } + joystick->naxes=2; + joystick->nballs=0; + joystick->nhats=0; + + return(0); +} + +void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) +{ + int numjoystick; + Uint32 curstate,prevstate; + Sint16 curaxis; + + numjoystick=GetEnabledAtariJoystick(joystick->index); + if (numjoystick==-1) + return; + + prevstate = atarijoysticks[numjoystick].prevstate; + + if (joypad_ports_enabled) { + Supexec(UpdateJoypads); + } + + switch (numjoystick) { + case IKBD_JOY1: + { + curstate = SDL_AtariIkbd_joystick & 0xff; + if (curstate != prevstate) { + /* X axis */ + if ((curstate & (IKBD_JOY_LEFT|IKBD_JOY_RIGHT)) != (prevstate & (IKBD_JOY_LEFT|IKBD_JOY_RIGHT))) { + curaxis=0; + if (curstate & IKBD_JOY_LEFT) { + curaxis=-128; + } else if (curstate & IKBD_JOY_RIGHT) { + curaxis=127; + } + SDL_PrivateJoystickAxis(joystick,0,curaxis); + } + /* Y axis */ + if ((curstate & (IKBD_JOY_UP|IKBD_JOY_DOWN)) != (prevstate & (IKBD_JOY_UP|IKBD_JOY_DOWN))) { + curaxis=0; + if (curstate & IKBD_JOY_UP) { + curaxis=-128; + } else if (curstate & IKBD_JOY_DOWN) { + curaxis=127; + } + SDL_PrivateJoystickAxis(joystick,1,curaxis); + } + /* Button */ + if ((curstate & IKBD_JOY_FIRE) && !(prevstate & IKBD_JOY_FIRE)) { + SDL_PrivateJoystickButton(joystick,0,SDL_PRESSED); + } + if (!(curstate & IKBD_JOY_FIRE) && (prevstate & IKBD_JOY_FIRE)) { + SDL_PrivateJoystickButton(joystick,0,SDL_RELEASED); + } + } + atarijoysticks[IKBD_JOY1].prevstate = curstate; + } + break; + case PORTA_PAD: + case PORTB_PAD: + { + int numjoypad,i; + + numjoypad=0; +/* if (numjoystick==PORTA_PAD) numjoypad=0;*/ + if (numjoystick==PORTB_PAD) numjoypad=1; + + curstate=jp_joypads[numjoypad]; + if (curstate!=prevstate) { + /* X axis */ + if ((curstate & ((1<<JP_LEFT)|(1<<JP_RIGHT))) != (prevstate & ((1<<JP_LEFT)|(1<<JP_RIGHT)))) { + curaxis=0; + if (curstate & (1<<JP_LEFT)) { + curaxis=-128; + } else if (curstate & (1<<JP_RIGHT)) { + curaxis=127; + } + SDL_PrivateJoystickAxis(joystick,0,curaxis); + } + /* Y axis */ + if ((curstate & ((1<<JP_UP)|(1<<JP_DOWN))) != (prevstate & ((1<<JP_UP)|(1<<JP_DOWN)))) { + curaxis=0; + if (curstate & (1<<JP_UP)) { + curaxis=-128; + } else if (curstate & (1<<JP_DOWN)) { + curaxis=127; + } + SDL_PrivateJoystickAxis(joystick,1,curaxis); + } + /* Buttons */ + for (i=0;i<JP_NUM_BUTTONS;i++) { + int button; + + button=1<<jp_buttons[i]; + + if ((curstate & button) && !(prevstate & button)) { + SDL_PrivateJoystickButton(joystick,i,SDL_PRESSED); + } + if (!(curstate & button) && (prevstate & button)) { + SDL_PrivateJoystickButton(joystick,i,SDL_RELEASED); + } + } + } + atarijoysticks[numjoystick].prevstate = curstate; + } + break; + case PORTA_JOY0: + case PORTA_JOY1: + case PORTB_JOY0: + case PORTB_JOY1: + { + int fire_shift=0,dir_shift=0; + + if (numjoystick==PORTA_JOY0) { fire_shift=0; dir_shift=0; } + if (numjoystick==PORTA_JOY1) { fire_shift=1; dir_shift=4; } + if (numjoystick==PORTB_JOY0) { fire_shift=2; dir_shift=8; } + if (numjoystick==PORTB_JOY1) { fire_shift=3; dir_shift=12; } + + curstate = (jp_directions>>dir_shift) & 15; + curstate |= ((jp_fires>>fire_shift) & 1)<<4; + + if (curstate != prevstate) { + /* X axis */ + if ((curstate & (PORT_JS_LEFT|PORT_JS_RIGHT)) != (prevstate & (PORT_JS_LEFT|PORT_JS_RIGHT))) { + curaxis=0; + if (curstate & PORT_JS_LEFT) { + curaxis=-128; + } else if (curstate & PORT_JS_RIGHT) { + curaxis=127; + } + SDL_PrivateJoystickAxis(joystick,0,curaxis); + } + /* Y axis */ + if ((curstate & (PORT_JS_UP|PORT_JS_DOWN)) != (prevstate & (PORT_JS_UP|PORT_JS_DOWN))) { + curaxis=0; + if (curstate & PORT_JS_UP) { + curaxis=-128; + } else if (curstate & PORT_JS_DOWN) { + curaxis=127; + } + SDL_PrivateJoystickAxis(joystick,1,curaxis); + } + /* Button */ + if ((curstate & PORT_JS_FIRE) && !(prevstate & PORT_JS_FIRE)) { + SDL_PrivateJoystickButton(joystick,0,SDL_PRESSED); + } + if (!(curstate & PORT_JS_FIRE) && (prevstate & PORT_JS_FIRE)) { + SDL_PrivateJoystickButton(joystick,0,SDL_RELEASED); + } + } + atarijoysticks[numjoystick].prevstate = curstate; + } + break; + case PORTA_LP: + { + int i; + + curstate = jp_lightpens[0]>>1; + curstate |= (jp_lightpens[1]>>1)<<15; + curstate |= (jp_fires & 3)<<30; + + if (curstate != prevstate) { + /* X axis */ + SDL_PrivateJoystickAxis(joystick,0,(jp_lightpens[0]>>8)-128); + /* Y axis */ + SDL_PrivateJoystickAxis(joystick,1,(jp_lightpens[1]>>8)-128); + /* Buttons */ + for (i=0;i<2;i++) { + int button; + + button=1<<(30+i); + + if ((curstate & button) && !(prevstate & button)) { + SDL_PrivateJoystickButton(joystick,i,SDL_PRESSED); + } + if (!(curstate & button) && (prevstate & button)) { + SDL_PrivateJoystickButton(joystick,i,SDL_RELEASED); + } + } + } + atarijoysticks[numjoystick].prevstate = curstate; + } + break; + case PORTA_ANPAD: + case PORTB_ANPAD: + { + int numpaddle, i; + + numpaddle=0<<1; + if (numjoystick==PORTB_ANPAD) numpaddle=1<<1; + + curstate = jp_paddles[numpaddle]>>1; + curstate |= (jp_paddles[numpaddle+1]>>1)<<15; + curstate |= ((jp_fires>>numpaddle) & 3)<<30; + + if (curstate != prevstate) { + /* X axis */ + SDL_PrivateJoystickAxis(joystick,0,(jp_paddles[numpaddle]>>8)-128); + /* Y axis */ + SDL_PrivateJoystickAxis(joystick,1,(jp_paddles[numpaddle+1]>>8)-128); + /* Buttons */ + for (i=0;i<2;i++) { + int button; + + button=1<<(30+i); + + if ((curstate & button) && !(prevstate & button)) { + SDL_PrivateJoystickButton(joystick,i,SDL_PRESSED); + } + if (!(curstate & button) && (prevstate & button)) { + SDL_PrivateJoystickButton(joystick,i,SDL_RELEASED); + } + } + } + atarijoysticks[numjoystick].prevstate = curstate; + } + break; +#if 0 + case PARA_JOY0: + case PARA_JOY1: + break; +#endif + }; + + return; +} + +void SDL_SYS_JoystickClose(SDL_Joystick *joystick) +{ + return; +} + +void SDL_SYS_JoystickQuit(void) +{ + SDL_numjoysticks=0; + return; +} + +/*--- Joypad I/O read/write interface ---*/ + +#define JOYPAD_IO_BASE (0xffff9200) +struct JOYPAD_IO_S { + Uint16 fires; + Uint16 directions; + Uint16 dummy1[6]; + Uint16 paddles[4]; + Uint16 dummy2[4]; + Uint16 lightpens[2]; +}; +#define JOYPAD_IO ((*(volatile struct JOYPAD_IO_S *)JOYPAD_IO_BASE)) + +static void UpdateJoypads(void) +{ + Uint16 tmp; + + /*--- This function is called in supervisor mode ---*/ + + /* Update joysticks */ + jp_fires = (~(JOYPAD_IO.fires)) & 15; + jp_directions = (~(JOYPAD_IO.directions)); + + /* Update lightpen */ + tmp = JOYPAD_IO.lightpens[0] & 1023; + jp_lightpens[0] = (tmp<<6) | (tmp>>4); + tmp = JOYPAD_IO.lightpens[1] & 1023; + jp_lightpens[1] = (tmp<<6) | (tmp>>4); + + /* Update paddles */ + tmp = (JOYPAD_IO.paddles[0] & 255); + jp_paddles[0] = (tmp<<8) | tmp; + tmp = (JOYPAD_IO.paddles[1] & 255); + jp_paddles[1] = (tmp<<8) | tmp; + tmp = (JOYPAD_IO.paddles[2] & 255); + jp_paddles[2] = (tmp<<8) | tmp; + tmp = (JOYPAD_IO.paddles[3] & 255); + jp_paddles[3] = (tmp<<8) | tmp; + + /* Update joypad 0 */ + JOYPAD_IO.directions=0xfffe; + jp_joypads[0]=((~(JOYPAD_IO.fires)) & 3)<<(16); + JOYPAD_IO.directions=0xfffe; + jp_joypads[0] |= ((~(JOYPAD_IO.directions))>>8) & 15; + + JOYPAD_IO.directions=0xfffd; + jp_joypads[0] |= ((~(JOYPAD_IO.fires)) & 3)<<(16+2); + JOYPAD_IO.directions=0xfffd; + jp_joypads[0] |= (((~(JOYPAD_IO.directions))>>8) & 15)<<4; + + JOYPAD_IO.directions=0xfffb; + jp_joypads[0] |= ((~(JOYPAD_IO.fires)) & 3)<<(16+4); + JOYPAD_IO.directions=0xfffb; + jp_joypads[0] |= (((~(JOYPAD_IO.directions))>>8) & 15)<<8; + + JOYPAD_IO.directions=0xfff7; + jp_joypads[0] |= ((~(JOYPAD_IO.fires)) & 3)<<(16+6); + JOYPAD_IO.directions=0xfff7; + jp_joypads[0] |= (((~(JOYPAD_IO.directions))>>8) & 15)<<12; + + /* Update joypad 1 */ + JOYPAD_IO.directions=0xffef; + jp_joypads[1]=((~(JOYPAD_IO.fires)) & (3<<2))<<(16-2); + JOYPAD_IO.directions=0xffef; + jp_joypads[1] |= ((~(JOYPAD_IO.directions))>>12) & 15; + + JOYPAD_IO.directions=0xffdf; + jp_joypads[1] |= ((~(JOYPAD_IO.fires)) & (3<<2))<<(16); + JOYPAD_IO.directions=0xffdf; + jp_joypads[1] |= (((~(JOYPAD_IO.directions))>>12) & 15)<<4; + + JOYPAD_IO.directions=0xffbf; + jp_joypads[1] |= ((~(JOYPAD_IO.fires)) & (3<<2))<<(16+2); + JOYPAD_IO.directions=0xffbf; + jp_joypads[1] |= (((~(JOYPAD_IO.directions))>>12) & 15)<<8; + + JOYPAD_IO.directions=0xff7f; + jp_joypads[1] |= ((~(JOYPAD_IO.fires)) & (3<<2))<<(16+4); + JOYPAD_IO.directions=0xff7f; + jp_joypads[1] |= (((~(JOYPAD_IO.directions))>>12) & 15)<<12; +}