Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
/*
** Oricutron
** Copyright (C) 2009-2014 Peter Gordon
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation, version 2
** of the License.
**
** This program 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 General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**
** Joystick emulation
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "system.h"
#include "6502.h"
#include "via.h"
#include "8912.h"
#include "gui.h"
#include "disk.h"
#include "monitor.h"
#include "6551.h"
#include "machine.h"
#include "joystick.h"
#include "plugins/twilighte_board/oric_twilighte_board_plugin.h"
struct keyjoydef
{
char *id;
SDL_COMPAT_KEY sym;
};
static struct keyjoydef keyjoytab[] = { { "BACKSPACE", SDLK_BACKSPACE },
{ "TAB", SDLK_TAB },
{ "CLEAR", SDLK_CLEAR },
{ "RETURN", SDLK_RETURN },
{ "ENTER", SDLK_RETURN },
{ "PAUSE", SDLK_PAUSE },
{ "ESCAPE", SDLK_ESCAPE },
{ "SPACE", SDLK_SPACE },
{ "HELP", SDLK_HELP },
{ "DELETE", SDLK_DELETE },
{ "DEL", SDLK_DELETE },
{ "LSHIFT", SDLK_LSHIFT },
{ "RSHIFT", SDLK_RSHIFT },
{ "RCTRL", SDLK_RCTRL },
{ "LCTRL", SDLK_LCTRL },
{ "RALT", SDLK_RALT },
{ "LALT", SDLK_LALT },
{ "KP0", SDLK_KP0 },
{ "KP1", SDLK_KP1 },
{ "KP2", SDLK_KP2 },
{ "KP3", SDLK_KP3 },
{ "KP4", SDLK_KP4 },
{ "KP5", SDLK_KP5 },
{ "KP6", SDLK_KP6 },
{ "KP7", SDLK_KP7 },
{ "KP8", SDLK_KP8 },
{ "KP9", SDLK_KP9 },
{ "KP_PERIOD", SDLK_KP_PERIOD },
{ "KP_FULLSTOP", SDLK_KP_PERIOD },
{ "KP_DIVIDE", SDLK_KP_DIVIDE },
{ "KP_MULTIPLY", SDLK_KP_MULTIPLY },
{ "KP_MINUS", SDLK_KP_MINUS },
{ "KP_PLUS", SDLK_KP_PLUS },
{ "KP_ENTER", SDLK_KP_ENTER },
{ "KP_EQUALS", SDLK_KP_EQUALS },
{ "UP", SDLK_UP },
{ "DOWN", SDLK_DOWN },
{ "LEFT", SDLK_LEFT },
{ "RIGHT", SDLK_RIGHT },
{ "INSERT", SDLK_INSERT },
{ "HOME", SDLK_HOME },
{ "END", SDLK_END },
{ "PAGEUP", SDLK_PAGEUP },
{ "PAGEDOWN", SDLK_PAGEDOWN },
{ NULL, 0 } };
static SDL_bool joysubinited = SDL_FALSE;
Uint8 joystate_a[7], joystate_b[7];
static SDL_bool is_real_joystick( Sint16 joymode )
{
if( ( joymode >= JOYMODE_SDL0 ) && ( joymode <= JOYMODE_SDL9 ) )
return SDL_TRUE;
return SDL_FALSE;
}
static void close_joysticks( struct machine *oric )
{
if( joysubinited )
{
if( oric->sdljoy_a )
{
SDL_JoystickClose( oric->sdljoy_a );
if( oric->sdljoy_b == oric->sdljoy_a )
oric->sdljoy_b = NULL;
oric->sdljoy_a = NULL;
}
if( oric->sdljoy_b )
{
SDL_JoystickClose( oric->sdljoy_b );
oric->sdljoy_b = NULL;
}
SDL_JoystickEventState( SDL_FALSE );
}
}
// Return an SDL keysym corresponding to the specified name (or 0)
Sint16 joy_keyname_to_sym( char *name )
{
Sint32 i;
char c;
// Just a single char?
if( name[1] == 0 )
{
c = tolower( name[0] );
if( ( c >= 32 ) && ( c < 127 ) ) return c;
return 0;
}
// Look for a matching named key
for( i=0; keyjoytab[i].id; i++ )
{
if( strcasecmp( keyjoytab[i].id, name ) == 0 )
return keyjoytab[i].sym;
}
return 0;
}
static SDL_bool dojoyevent( SDL_Event *ev, struct machine *oric, Sint16 mode, Uint8 *joystate, SDL_Joystick *sjoy )
{
Sint32 i;
SDL_COMPAT_KEY *kbtab;
SDL_bool swallowit = SDL_FALSE;
kbtab = oric->kbjoy2;
switch( mode )
{
case JOYMODE_NONE:
case JOYMODE_MOUSE: // Telestrat only
return SDL_FALSE;
case JOYMODE_KB1:
kbtab = oric->kbjoy1;
case JOYMODE_KB2:
switch( ev->type )
{
case SDL_KEYDOWN:
for( i=0; i<7; i++ )
{
if( ev->key.keysym.sym == kbtab[i] )
{
joystate[i] = 1;
swallowit = SDL_TRUE;
}
}
break;
case SDL_KEYUP:
for( i=0; i<7; i++ )
{
if( ev->key.keysym.sym == kbtab[i] )
{
joystate[i] = 0;
swallowit = SDL_TRUE;
}
}
break;
}
break;
case JOYMODE_SDL0:
case JOYMODE_SDL1:
case JOYMODE_SDL2:
case JOYMODE_SDL3:
case JOYMODE_SDL4:
case JOYMODE_SDL5:
case JOYMODE_SDL6:
case JOYMODE_SDL7:
case JOYMODE_SDL8:
case JOYMODE_SDL9:
if( !sjoy ) return SDL_FALSE;
switch( ev->type )
{
case SDL_JOYAXISMOTION:
if( ev->jaxis.which != (mode-JOYMODE_SDL0) ) return SDL_FALSE;
swallowit = SDL_TRUE;
switch( ev->jaxis.axis )
{
case 0: // left/right
if( ev->jaxis.value < -3200 )
{
joystate[2] = 1; // left
joystate[3] = 0;
} else if( ev->jaxis.value > 3200 ) {
joystate[2] = 0; // right
joystate[3] = 1;
} else {
joystate[2] = 0;
joystate[3] = 0;
}
break;
case 1: // up/down
if( ev->jaxis.value < -3200 )
{
joystate[0] = 1; // up
joystate[1] = 0;
} else if( ev->jaxis.value > 3200 ) {
joystate[0] = 0; // down
joystate[1] = 1;
} else {
joystate[0] = 0;
joystate[1] = 0;
}
break;
}
break;
case SDL_JOYBUTTONDOWN:
if( ev->jbutton.which != (mode-JOYMODE_SDL0) ) return SDL_FALSE;
joystate[4+(ev->jbutton.button % 3)] = 1;
swallowit = SDL_TRUE;
break;
case SDL_JOYBUTTONUP:
if( ev->jbutton.which != (mode-JOYMODE_SDL0) ) return SDL_FALSE;
joystate[4+(ev->jbutton.button % 3)] = 0;
swallowit = SDL_TRUE;
break;
}
break;
}
return swallowit;
}
void joy_buildmask( struct machine *oric )
{
Uint8 mkmask = 0xff;
Uint8 mkmask_f = 0xff;
Uint8 joysel = oric->via.read_port_a( &oric->via );
Uint8 telestrat_joysel = oric->tele_via.read_port_b( &oric->tele_via );
Uint8 twilighteboard_joysel = 0;
SDL_bool gimme_port_a = SDL_FALSE;
SDL_bool gimme_port_b = SDL_FALSE;
if (oric->twilighteboard_activated)
twilighteboard_joysel= twilighteboard_oric_read(oric->twilighte,0x320);
if (oric->type == MACH_ATMOS && oric->twilighteboard_activated)
{
if ( twilighteboard_joysel & 0x80 )
{
// Right Port
if( joystate_a[0] ) mkmask &= 0xef;
if( joystate_a[1] ) mkmask &= 0xf7;
if( joystate_a[2] ) mkmask &= 0xfd;
if( joystate_a[3] ) mkmask &= 0xfe;
if( joystate_a[4] ) mkmask &= 0xfb;
if( joystate_a[5] ) mkmask_f &= 0x7f; // PA7 - fire 2
if( joystate_a[6] ) mkmask_f &= 0xdf; // PA5 - fire 3
gimme_port_a = SDL_TRUE;
gimme_port_b = SDL_TRUE;
}
if ( twilighteboard_joysel & 0x40 )
{
// Left Port
if( joystate_b[0] ) mkmask &= 0xef; // 0x10 - up
if( joystate_b[1] ) mkmask &= 0xf7; // 0x08 - down
if( joystate_b[2] ) mkmask &= 0xfd; // 0x02 - left
if( joystate_b[3] ) mkmask &= 0xfe; // 0x01 - right
if( joystate_b[4] ) mkmask &= 0xfb; // 0x04 - fire
gimme_port_b = SDL_TRUE;
}
if( gimme_port_a )
{
//twilighteboard_oric_write(oric->twilighte, 0x321, 0xff, mkmask_f);
}
if( gimme_port_b )
{
// port B
//twilighteboard_oric_write(oric->twilighte, 0x320, 0xff, mkmask);
}
}
else
if (oric->type == MACH_TELESTRAT)
{
if ( telestrat_joysel & 0x80 )
{
// Right Port
if( joystate_a[0] ) mkmask &= 0xef;
if( joystate_a[1] ) mkmask &= 0xf7;
if( joystate_a[2] ) mkmask &= 0xfd;
if( joystate_a[3] ) mkmask &= 0xfe;
if( joystate_a[4] ) mkmask &= 0xfb;
if( joystate_a[5] ) mkmask_f &= 0x7f; // PA7 - fire 2
if( joystate_a[6] ) mkmask_f &= 0xdf; // PA5 - fire 3
gimme_port_a = SDL_TRUE;
gimme_port_b = SDL_TRUE;
}
if ( telestrat_joysel & 0x40 )
{
// Left Port
if( joystate_b[0] ) mkmask &= 0xef; // 0x10 - up
if( joystate_b[1] ) mkmask &= 0xf7; // 0x08 - down
if( joystate_b[2] ) mkmask &= 0xfd; // 0x02 - left
if( joystate_b[3] ) mkmask &= 0xfe; // 0x01 - right
if( joystate_b[4] ) mkmask &= 0xfb; // 0x04 - fire
gimme_port_b = SDL_TRUE;
}
if( gimme_port_a )
{
oric->tele_via.write_port_a( &oric->tele_via, 0xff, mkmask_f );
}
if( gimme_port_b )
{
oric->tele_via.write_port_b( &oric->tele_via, 0xff, mkmask );
}
}
else
{
switch( oric->joy_iface )
{
case JOYIFACE_ALTAI:
if( joysel & 0x80 )
{
if( joystate_a[0] ) mkmask &= 0xef;
if( joystate_a[1] ) mkmask &= 0xf7;
if( joystate_a[2] ) mkmask &= 0xfe;
if( joystate_a[3] ) mkmask &= 0xfd;
if( joystate_a[4] ) mkmask &= 0xdf;
gimme_port_a = SDL_TRUE;
}
if( joysel & 0x40 )
{
if( joystate_b[0] ) mkmask &= 0xef; // 0x10 - up
if( joystate_b[1] ) mkmask &= 0xf7; // 0x08 - down
if( joystate_b[2] ) mkmask &= 0xfe; // 0x01 - left
if( joystate_b[3] ) mkmask &= 0xfd; // 0x02 - right
if( joystate_b[4] ) mkmask &= 0xdf; // 0x20 - fire
gimme_port_a = SDL_TRUE;
}
break;
case JOYIFACE_IJK:
mkmask &= 0xdf;
if( ((oric->via.ddrb & 0x10)==0) ||
((oric->via.read_port_b( &oric->via )&0x10)!=0) )
break;
gimme_port_a = SDL_TRUE;
if( ( joysel & 0xc0 ) == 0xc0 ) break;
if( joysel & 0x40 )
{
if( joystate_a[0] ) mkmask &= 0xef;
if( joystate_a[1] ) mkmask &= 0xf7;
if( joystate_a[2] ) mkmask &= 0xfd;
if( joystate_a[3] ) mkmask &= 0xfe;
if( joystate_a[4] ) mkmask &= 0xfb;
}
if( joysel & 0x80 )
{
if( joystate_b[0] ) mkmask &= 0xef; // 0x10 - up
if( joystate_b[1] ) mkmask &= 0xf7; // 0x08 - down
if( joystate_b[2] ) mkmask &= 0xfd; // 0x02 - left
if( joystate_b[3] ) mkmask &= 0xfe; // 0x01 - right
if( joystate_b[4] ) mkmask &= 0xfb; // 0x04 - fire
}
break;
}
oric->porta_joy = mkmask;
if( gimme_port_a )
{
oric->via.write_port_a( &oric->via, 0xff, mkmask );
oric->porta_is_ay = SDL_FALSE;
} else {
if( !oric->porta_is_ay )
{
oric->via.write_port_a( &oric->via, 0xff, oric->porta_ay );
oric->porta_is_ay = SDL_TRUE;
}
}
}
}
SDL_bool joy_filter_event( SDL_Event *ev, struct machine *oric )
{
SDL_bool swallow_event;
swallow_event = dojoyevent( ev, oric, (oric->type==MACH_TELESTRAT || (oric->twilighteboard_activated && oric->type==MACH_ATMOS)) ? oric->telejoymode_a : oric->joymode_a, joystate_a, oric->sdljoy_a );
swallow_event |= dojoyevent( ev, oric, (oric->type==MACH_TELESTRAT || (oric->twilighteboard_activated && oric->type==MACH_ATMOS)) ? oric->telejoymode_b : oric->joymode_b, joystate_b, oric->sdljoy_b );
if( swallow_event )
{
// char testytesttest[64];
joy_buildmask( oric );
/*
sprintf( testytesttest, "A: %d%d%d%d-%d%d B: %d%d%d%d-%d%d",
joystate_a[0], joystate_a[1], joystate_a[2], joystate_a[3],
joystate_a[4], joystate_a[5],
joystate_b[0], joystate_b[1], joystate_b[2], joystate_b[3],
joystate_b[4], joystate_b[5] );
SDL_WM_SetCaption( testytesttest, testytesttest );
*/
}
return swallow_event;
}
static void dojoysetup( struct machine *oric, Sint16 mode_a, Sint16 mode_b )
{
Sint32 i;
close_joysticks( oric );
for( i=0; i<6; i++ )
{
joystate_a[i] = 0;
joystate_b[i] = 0;
}
if( (!is_real_joystick( mode_a )) && (!is_real_joystick( mode_b )) )
return;
if( !joysubinited )
{
//dbg_printf( "Initialising joysubsystem" );
if( SDL_InitSubSystem( SDL_INIT_JOYSTICK ) != 0 )
return;
//dbg_printf( "Success!" );
joysubinited = SDL_TRUE;
}
if( is_real_joystick( mode_a ) )
{
oric->sdljoy_a = SDL_JoystickOpen( mode_a - JOYMODE_SDL0 );
//dbg_printf( "Joy0 = %p", oric->sdljoy_a );
SDL_JoystickEventState( SDL_TRUE );
}
if( is_real_joystick( mode_b ) )
{
if( mode_b == mode_a )
{
oric->sdljoy_b = oric->sdljoy_a;
} else {
oric->sdljoy_b = SDL_JoystickOpen( mode_b - JOYMODE_SDL0 );
SDL_JoystickEventState( SDL_TRUE );
}
}
}
void joy_setup( struct machine *oric )
{
if( oric->type == MACH_TELESTRAT || ( oric->type == MACH_ATMOS && oric->twilighteboard_activated) )
dojoysetup( oric, oric->telejoymode_a, oric->telejoymode_b );
else
dojoysetup( oric, oric->joymode_a, oric->joymode_b );
}
SDL_bool init_joy( struct machine *oric )
{
return SDL_TRUE;
}
void shut_joy( struct machine *oric )
{
close_joysticks( oric );
}