Mercurial > sdl-ios-xcode
view src/joystick/mint/SDL_sysjoystick.c @ 2978:4c9130d66e2c
Added a few things to the TODO list.
Unit testing is becoming more and more important the more features are added
and the more combinations of factors there are to test.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 03 Jan 2009 07:23:11 +0000 |
parents | 99210400e8b9 |
children |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2009 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org */ #include "SDL_config.h" #ifdef SDL_JOYSTICK_MINT /* * Atari Joystick/Joypad drivers * * Patrice Mandin */ #include <mint/cookie.h> #include <mint/osbind.h> #include "SDL_events.h" #include "../SDL_sysjoystick.h" #include "../SDL_joystick_c.h" #include "../../video/ataricommon/SDL_ikbdinterrupt_s.h" #include "../../video/ataricommon/SDL_xbiosevents_c.h" #include "../../video/ataricommon/SDL_xbiosinterrupt_s.h" /*--- Const ---*/ /* We can have: 1 joystick on IKBD port 1, read via hardware I/O or same joystick on IKBD port 1, read via xbios 1 joypad on port A (up to 4 with teamtap) or 2 joysticks on joypad port A or 1 analog paddle on joypad port A or 1 lightpen on joypad port A 1 joypad on port B (up to 4 with teamtap) or 2 joysticks on joypad port B or 1 analog paddle on joypad port B 2 joysticks on parallel port */ enum { IKBD_JOY1 = 0, XBIOS_JOY1, PORTA_PAD0, PORTA_PAD1, PORTA_PAD2, PORTA_PAD3, PORTB_PAD0, PORTB_PAD1, PORTB_PAD2, PORTB_PAD3, 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, MCH_CLONE, MCH_ARANYM }; /* 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, "Xbios joystick port 1", 0}, {SDL_FALSE, "Joypad 0 port A", 0}, {SDL_FALSE, "Joypad 1 port A", 0}, {SDL_FALSE, "Joypad 2 port A", 0}, {SDL_FALSE, "Joypad 3 port A", 0}, {SDL_FALSE, "Joypad 0 port B", 0}, {SDL_FALSE, "Joypad 1 port B", 0}, {SDL_FALSE, "Joypad 2 port B", 0}, {SDL_FALSE, "Joypad 3 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_FIRE0, JP_FIRE1, JP_FIRE2, JP_PAUSE, JP_OPTION, JP_KPMULT, JP_KPNUM, JP_KP0, JP_KP1, JP_KP2, JP_KP3, JP_KP4, JP_KP5, JP_KP6, JP_KP7, JP_KP8, JP_KP9 }; 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[8]; /*--- 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 = SDL_getenv("SDL_JOYSTICK_ATARI"); #define TEST_JOY_ENABLED(env,idstring,num) \ if (SDL_strstr(env,idstring"-off")) { \ atarijoysticks[num].enabled=SDL_FALSE; \ } \ if (SDL_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) || (cookie_mch == MCH_ARANYM << 16)) { atarijoysticks[IKBD_JOY1].enabled = (SDL_AtariIkbd_enabled != 0); } if ((cookie_mch == MCH_STE << 16) || (cookie_mch == MCH_F30 << 16)) { atarijoysticks[PORTA_PAD0].enabled = atarijoysticks[PORTA_PAD1].enabled = atarijoysticks[PORTA_PAD2].enabled = atarijoysticks[PORTA_PAD3].enabled = atarijoysticks[PORTB_PAD0].enabled = atarijoysticks[PORTB_PAD1].enabled = atarijoysticks[PORTB_PAD2].enabled = atarijoysticks[PORTB_PAD3].enabled = SDL_TRUE; } if (!atarijoysticks[IKBD_JOY1].enabled) { atarijoysticks[XBIOS_JOY1].enabled = (SDL_AtariXbios_enabled != 0); } /* 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) || (cookie_mch == MCH_ARANYM << 16)) { if (SDL_AtariIkbd_enabled != 0) { 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_PAD0); if (!atarijoysticks[PORTA_PAD0].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_PAD0); if (!atarijoysticks[PORTB_PAD0].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 (!atarijoysticks[IKBD_JOY1].enabled) { if (SDL_AtariXbios_enabled != 0) { TEST_JOY_ENABLED(envr, "xbios-joy1", XBIOS_JOY1); } } #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_PAD0; 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) { continue; } if (j == index) { break; } ++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; joystick->naxes = 0; joystick->nhats = 0; joystick->nballs = 0; switch (numjoystick) { case PORTA_PAD0: case PORTA_PAD1: case PORTA_PAD2: case PORTA_PAD3: case PORTB_PAD0: case PORTB_PAD1: case PORTB_PAD2: case PORTB_PAD3: joystick->nhats = 1; joystick->nbuttons = JP_NUM_BUTTONS; break; case PORTA_LP: case PORTA_ANPAD: case PORTB_ANPAD: joystick->naxes = 2; joystick->nbuttons = 2; break; default: joystick->nhats = 1; joystick->nbuttons = 1; break; } return (0); } void SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) { int numjoystick; Uint8 hatstate; Uint32 curstate, prevstate; numjoystick = GetEnabledAtariJoystick(joystick->index); if (numjoystick == -1) return; prevstate = atarijoysticks[numjoystick].prevstate; if (joypad_ports_enabled) { Supexec(UpdateJoypads); } switch (numjoystick) { case IKBD_JOY1: case XBIOS_JOY1: { curstate = 0; if (numjoystick == IKBD_JOY1) { curstate = SDL_AtariIkbd_joystick & 0xff; } if (numjoystick == XBIOS_JOY1) { curstate = SDL_AtariXbios_joystick & 0xff; } if (curstate != prevstate) { hatstate = SDL_HAT_CENTERED; if (curstate & IKBD_JOY_LEFT) { hatstate |= SDL_HAT_LEFT; } if (curstate & IKBD_JOY_RIGHT) { hatstate |= SDL_HAT_RIGHT; } if (curstate & IKBD_JOY_UP) { hatstate |= SDL_HAT_UP; } if (curstate & IKBD_JOY_DOWN) { hatstate |= SDL_HAT_DOWN; } SDL_PrivateJoystickHat(joystick, 0, hatstate); /* 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[numjoystick].prevstate = curstate; } break; case PORTA_PAD0: case PORTA_PAD1: case PORTA_PAD2: case PORTA_PAD3: case PORTB_PAD0: case PORTB_PAD1: case PORTB_PAD2: case PORTB_PAD3: { int numjoypad, i; numjoypad = 0; switch (numjoystick) { case PORTA_PAD0: numjoypad = 0; break; case PORTA_PAD1: numjoypad = 1; break; case PORTA_PAD2: numjoypad = 2; break; case PORTA_PAD3: numjoypad = 3; break; case PORTB_PAD0: numjoypad = 4; break; case PORTB_PAD1: numjoypad = 5; break; case PORTB_PAD2: numjoypad = 6; break; case PORTB_PAD3: numjoypad = 7; break; } curstate = jp_joypads[numjoypad]; if (curstate != prevstate) { hatstate = SDL_HAT_CENTERED; if (curstate & (1 << JP_LEFT)) { hatstate |= SDL_HAT_LEFT; } if (curstate & (1 << JP_RIGHT)) { hatstate |= SDL_HAT_RIGHT; } if (curstate & (1 << JP_UP)) { hatstate |= SDL_HAT_UP; } if (curstate & (1 << JP_DOWN)) { hatstate |= SDL_HAT_DOWN; } SDL_PrivateJoystickHat(joystick, 0, hatstate); /* 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) { hatstate = SDL_HAT_CENTERED; if (curstate & PORT_JS_LEFT) { hatstate |= SDL_HAT_LEFT; } if (curstate & PORT_JS_RIGHT) { hatstate |= SDL_HAT_RIGHT; } if (curstate & PORT_JS_UP) { hatstate |= SDL_HAT_UP; } if (curstate & PORT_JS_DOWN) { hatstate |= SDL_HAT_DOWN; } SDL_PrivateJoystickHat(joystick, 0, hatstate); /* 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] ^ 0x8000); /* Y axis */ SDL_PrivateJoystickAxis(joystick, 1, jp_lightpens[1] ^ 0x8000); /* 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] ^ 0x8000); /* Y axis */ SDL_PrivateJoystickAxis(joystick, 1, jp_paddles[numpaddle + 1] ^ 0x8000); /* 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 const Uint16 joypad_masks[8 * 4] = { 0xfffe, 0xfffd, 0xfffb, 0xfff7, 0xfff0, 0xfff1, 0xfff2, 0xfff3, 0xfff4, 0xfff5, 0xfff6, 0xfff8, 0xfff9, 0xfffa, 0xfffc, 0xffff, 0xffef, 0xffdf, 0xffbf, 0xff7f, 0xff0f, 0xff1f, 0xff2f, 0xff3f, 0xff4f, 0xff5f, 0xff6f, 0xff8f, 0xff9f, 0xffaf, 0xffcf, 0xffff }; static void UpdateJoypads(void) { Uint16 tmp, i, j; Uint32 cur_fire, cur_dir; /*--- 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 joypads on teamtap port A */ for (i = 0; i < 4; i++) { jp_joypads[i] = 0; for (j = 0; j < 4; j++) { JOYPAD_IO.directions = joypad_masks[(i * 4) + j]; cur_fire = (~(JOYPAD_IO.fires) & 3) << 16; cur_dir = (~(JOYPAD_IO.directions) >> 8) & 15; jp_joypads[i] |= cur_fire << (j * 2); jp_joypads[i] |= cur_dir << (j * 4); } } /* Update joypads on teamtap port B */ for (i = 4; i < 8; i++) { jp_joypads[i] = 0; for (j = 0; j < 4; j++) { JOYPAD_IO.directions = joypad_masks[(i * 4) + j]; cur_fire = (~(JOYPAD_IO.fires) & 0xc) << 14; cur_dir = (~(JOYPAD_IO.directions) >> 12) & 15; jp_joypads[i] |= cur_fire << (j * 2); jp_joypads[i] |= cur_dir << (j * 4); } } JOYPAD_IO.directions = 0xffff; } #endif /* SDL_JOYSTICK_MINT */ /* vi: set ts=4 sw=4 expandtab: */