From a855d6202536ff28e5aae4f22a0f31d8f5b325d0 Mon Sep 17 00:00:00 2001 From: Franklin Wei Date: Sat, 21 Jan 2017 15:18:31 -0500 Subject: Port of Duke Nukem 3D This ports Fabien Sanglard's Chocolate Duke to run on a version of SDL for Rockbox. Change-Id: I8f2c4c78af19de10c1633ed7bb7a997b43256dd9 --- .../sdl/src/joystick/mint/SDL_sysjoystick.c | 826 +++++++++++++++++++++ 1 file changed, 826 insertions(+) create mode 100644 apps/plugins/sdl/src/joystick/mint/SDL_sysjoystick.c (limited to 'apps/plugins/sdl/src/joystick/mint') diff --git a/apps/plugins/sdl/src/joystick/mint/SDL_sysjoystick.c b/apps/plugins/sdl/src/joystick/mint/SDL_sysjoystick.c new file mode 100644 index 0000000000..9a36152927 --- /dev/null +++ b/apps/plugins/sdl/src/joystick/mint/SDL_sysjoystick.c @@ -0,0 +1,826 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 +#include + +#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) + +enum { + TEAMTAP_MAYBE=0, + TEAMTAP_YES, + TEAMTAP_NO +}; + +/* Teamtap detection values */ +static const Uint32 teamtap_ghosts[20][4]={ + {1<>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) || + (cookie_mch == MCH_ARANYM<<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 on STE, Falcon and maybe others */ + if ((cookie_mch == MCH_STE<<16) || (cookie_mch == MCH_F30<<16) || + (cookie_mch == MCH_ARANYM<<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;iindex); + 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); +} + +/* Detect Teamtap using ghost events */ +static void detect_teamtap(int num_port) +{ + int i,j; + + /* Check if joypad 1,2,3 triggered but not 0 */ + for (i=1; i<4; i++) { + if (jp_joypads[num_port*4+i] && (jp_joypads[num_port*4]==0)) { + has_teamtap[num_port] = TEAMTAP_YES; + return; + } + } + + /* Check if joypad 0 on a given port triggered ghost events for + * other joypads + */ + for (i=0; i<20; i++) { + int with_teamtap=1; + + if (jp_joypads[num_port*4]!=teamtap_ghosts[i][0]) + continue; + + /* If any button on first joypad pressed, check other pads */ + for (j=1; j<4; j++) { + if ((jp_joypads[num_port*4+j] & teamtap_ghosts[i][j]) + ==teamtap_ghosts[i][j]) + { + with_teamtap = 0; + } + } + + has_teamtap[num_port] = (with_teamtap ? TEAMTAP_YES : TEAMTAP_NO); + break; + } +} + +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,numport; + + numjoypad = numport = 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; numport = 1; break; + case PORTB_PAD1: + numjoypad = 5; numport = 1; break; + case PORTB_PAD2: + numjoypad = 6; numport = 1; break; + case PORTB_PAD3: + numjoypad = 7; numport = 1; break; + } + + jp_joypads[numjoypad] &= 0xabffff; + + if (has_teamtap[numport]==TEAMTAP_MAYBE) { + detect_teamtap(numport); + } + /* No events for PORTX_PAD[1,2,3] if no teamtap detected */ + if (has_teamtap[numport] == TEAMTAP_NO) { + if ((numjoypad & 3)!=0) { + return; + } + } + + curstate=jp_joypads[numjoypad]; + if (curstate!=prevstate) { + hatstate = SDL_HAT_CENTERED; + if (curstate & (1<>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 */ -- cgit v1.2.3