Reworked joystick handling wrt Stelladaptor support; it should work a

little faster than before, and it makes the code much easier to understand.

Made Stelladaptor devices only send events based on which type of
controller is connected to the emulated port (Joystick, Paddles, Driving).
Since we can't detect which type of controller is attached to a
Stelladaptor, previously the code just sent events for all three types.
This causes problems with some games that don't know how to deal with
events that cannot possibly happen at the same time on a real machine
(ie, paddle 0 *and* joystick 0 being operated).

Added code to 'swallow' garbage events generated when Stella is first
launched, usually caused by jitter in the joystick or mouse.  This fixes
some weird problems with internal Stella events being set before we
even enter the main gaming loop.

Still TODO is add support for joystick hats and trackballs, once I can
locate a device which has these items.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@875 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2005-11-12 22:04:57 +00:00
parent 429cc63d1d
commit 8c2eaadaa1
15 changed files with 220 additions and 128 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: mainSDL.cxx,v 1.53 2005-11-11 21:44:19 stephena Exp $
// $Id: mainSDL.cxx,v 1.54 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#include <fstream>
@ -248,6 +248,11 @@ int main(int argc, char* argv[])
#endif
}
// Swallow any spurious events in the queue
// These are normally caused by joystick/mouse jitter
SDL_Event event;
while(SDL_PollEvent(&event)) /* swallow event */ ;
// Start the main loop, and don't exit until the user issues a QUIT command
theOSystem->mainLoop();

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Booster.cxx,v 1.3 2005-06-16 00:55:57 stephena Exp $
// $Id: Booster.cxx,v 1.4 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#include "Event.hxx"
@ -103,3 +103,8 @@ void BoosterGrip::write(DigitalPin, bool)
// Writing doesn't do anything to the booster grip...
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Controller::Type BoosterGrip::type()
{
return Controller::BoosterGrip;
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Booster.hxx,v 1.3 2005-06-16 00:55:57 stephena Exp $
// $Id: Booster.hxx,v 1.4 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#ifndef BOOSTERGRIP_HXX
@ -28,7 +28,7 @@
on it (a booster and a trigger).
@author Bradford W. Mott
@version $Id: Booster.hxx,v 1.3 2005-06-16 00:55:57 stephena Exp $
@version $Id: Booster.hxx,v 1.4 2005-11-12 22:04:57 stephena Exp $
*/
class BoosterGrip : public Controller
{
@ -73,6 +73,11 @@ class BoosterGrip : public Controller
@param value The value to write to the pin
*/
virtual void write(DigitalPin pin, bool value);
/**
Returns the type of this controller,
*/
virtual Type type();
};
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Control.hxx,v 1.2 2005-06-16 01:11:27 stephena Exp $
// $Id: Control.hxx,v 1.3 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#ifndef CONTROLLER_HXX
@ -55,7 +55,7 @@ class Event;
of the controller from the prespective of the controller's jack.
@author Bradford W. Mott
@version $Id: Control.hxx,v 1.2 2005-06-16 01:11:27 stephena Exp $
@version $Id: Control.hxx,v 1.3 2005-11-12 22:04:57 stephena Exp $
*/
class Controller
{
@ -68,6 +68,14 @@ class Controller
Left, Right
};
/**
Enumeration of the controller types
*/
enum Type
{
BoosterGrip, Driving, Keyboard, Paddles, Joystick
};
public:
/**
Create a new controller plugged into the specified jack
@ -127,6 +135,11 @@ class Controller
*/
virtual void write(DigitalPin pin, bool value) = 0;
/**
Returns the type of this controller.
*/
virtual Type type() = 0;
public:
/// Constant which represents maximum resistance for analog pins
static const Int32 maximumResistance;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Driving.cxx,v 1.4 2005-06-16 01:11:27 stephena Exp $
// $Id: Driving.cxx,v 1.5 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#include <assert.h>
@ -134,3 +134,8 @@ void Driving::write(DigitalPin, bool)
// Writing doesn't do anything to the driving controller...
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Controller::Type Driving::type()
{
return Controller::Driving;
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Driving.hxx,v 1.2 2005-06-16 01:11:27 stephena Exp $
// $Id: Driving.hxx,v 1.3 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#ifndef DRIVING_HXX
@ -29,7 +29,7 @@ class System;
The standard Atari 2600 Indy 500 driving controller.
@author Bradford W. Mott
@version $Id: Driving.hxx,v 1.2 2005-06-16 01:11:27 stephena Exp $
@version $Id: Driving.hxx,v 1.3 2005-11-12 22:04:57 stephena Exp $
*/
class Driving : public Controller
{
@ -76,6 +76,11 @@ class Driving : public Controller
*/
virtual void write(DigitalPin pin, bool value);
/**
Returns the type of this controller.
*/
virtual Type type();
private:
// Counter to iterate through the gray codes
uInt32 myCounter;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EventHandler.cxx,v 1.110 2005-11-11 21:44:19 stephena Exp $
// $Id: EventHandler.cxx,v 1.111 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#include <algorithm>
@ -593,7 +593,7 @@ void EventHandler::poll(uInt32 time)
case SDL_MOUSEMOTION:
handleMouseMotionEvent(event);
break; // SDL_MOUSEMOTION
break; // SDL_MOUSEMOTION
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
@ -616,48 +616,78 @@ void EventHandler::poll(uInt32 time)
case SDL_VIDEOEXPOSE:
refreshDisplay();
break; // SDL_VIDEOEXPOSE
}
#ifdef JOYSTICK_SUPPORT
// Read joystick events and modify event states
int stick;
uInt32 code;
uInt8 state = 0;
Uint8 axis;
Uint8 button;
Int32 resistance;
Sint16 value;
JoyType type;
case SDL_JOYBUTTONUP:
case SDL_JOYBUTTONDOWN:
{
if(event.jbutton.which >= kNumJoysticks)
break;
if(event.jbutton.which >= kNumJoysticks)
return;
// Figure put what type of joystick we're dealing with
// Stelladaptors behave differently, and can't be remapped
stick = ourJoystickMapping[event.jbutton.which].stick;
type = ourJoystickMapping[event.jbutton.which].type;
switch(type)
{
case JT_NONE:
break;
case JT_REGULAR:
switch(event.type)
// Stelladaptors handle buttons differently than regular joysticks
int type = ourJoystickMapping[event.jbutton.which].type;
switch(type)
{
case SDL_JOYBUTTONUP:
case SDL_JOYBUTTONDOWN:
case JT_REGULAR:
{
if(event.jbutton.button >= kNumJoyButtons-4)
return;
code = event.jbutton.button;
state = event.jbutton.state == SDL_PRESSED ? 1 : 0;
int stick = ourJoystickMapping[event.jbutton.which].stick;
int code = event.jbutton.button;
int state = event.jbutton.state == SDL_PRESSED ? 1 : 0;
handleJoyEvent(stick, code, state);
break;
break; // Regular joystick button
}
case SDL_JOYAXISMOTION:
axis = event.jaxis.axis;
value = event.jaxis.value;
case JT_STELLADAPTOR_1:
case JT_STELLADAPTOR_2:
{
int button = event.jbutton.button;
int state = event.jbutton.state == SDL_PRESSED ? 1 : 0;
// Since we can't detect what controller is attached to a
// Stelladaptor, we only send events based on controller
// type in ROM properties
Controller::Type ctype = myController[type-2];
switch((int)ctype)
{
// Send button events for the joysticks
case Controller::Joystick:
handleEvent(SA_Button[type-2][button][0], state);
break;
// Send axis events for the paddles
case Controller::Paddles:
handleEvent(SA_Button[type-2][button][1], state);
break;
// Send events for the driving controllers
case Controller::Driving:
handleEvent(SA_Button[type-2][button][2], state);
break;
}
break; // Stelladaptor button
}
}
break; // SDL_JOYBUTTONUP, SDL_JOYBUTTONDOWN
}
case SDL_JOYAXISMOTION:
{
if(event.jbutton.which >= kNumJoysticks)
break;
// Stelladaptors handle axis differently than regular joysticks
int type = ourJoystickMapping[event.jbutton.which].type;
switch(type)
{
case JT_REGULAR:
{
int stick = ourJoystickMapping[event.jbutton.which].stick;
int axis = event.jaxis.axis;
int value = event.jaxis.value;
// Handle emulation of mouse using the joystick
if(myState == S_EMULATE)
@ -675,76 +705,54 @@ void EventHandler::poll(uInt32 time)
}
else
handleMouseWarp(stick, axis, value);
break;
break; // Regular joystick axis
}
case JT_STELLADAPTOR_1:
case JT_STELLADAPTOR_2:
{
int axis = event.jaxis.axis;
int value = event.jaxis.value;
// Since we can't detect what controller is attached to a
// Stelladaptor, we only send events based on controller
// type in ROM properties
Controller::Type ctype = myController[type-2];
switch((int)ctype)
{
// Send axis events for the joysticks
case Controller::Joystick:
handleEvent(SA_Axis[type-2][axis][0], (value < -16384) ? 1 : 0);
handleEvent(SA_Axis[type-2][axis][1], (value > 16384) ? 1 : 0);
break;
// Send axis events for the paddles
case Controller::Paddles:
int resistance = (Int32) (1000000.0 * (32767 - value) / 65534);
handleEvent(SA_Axis[type-2][axis][2], resistance);
break;
// Send events for the driving controllers
case Controller::Driving:
if(axis == 1)
{
if(value <= -16384-4096)
handleEvent(SA_DrivingValue[type-2],2);
else if(value > 16384+4096)
handleEvent(SA_DrivingValue[type-2],1);
else if(value >= 16384-4096)
handleEvent(SA_DrivingValue[type-2],0);
else
handleEvent(SA_DrivingValue[type-2],3);
}
}
break; // Stelladaptor axis
}
}
break; // Regular joystick
case JT_STELLADAPTOR_1:
case JT_STELLADAPTOR_2:
switch(event.type)
{
case SDL_JOYBUTTONUP:
case SDL_JOYBUTTONDOWN:
button = event.jbutton.button;
state = event.jbutton.state == SDL_PRESSED ? 1 : 0;
// Send button events for the joysticks/paddles/driving controllers
if(button == 0)
{
if(type == JT_STELLADAPTOR_1)
{
handleEvent(Event::JoystickZeroFire, state);
handleEvent(Event::DrivingZeroFire, state);
handleEvent(Event::PaddleZeroFire, state);
}
else
{
handleEvent(Event::JoystickOneFire, state);
handleEvent(Event::DrivingOneFire, state);
handleEvent(Event::PaddleTwoFire, state);
}
}
else if(button == 1)
{
if(type == JT_STELLADAPTOR_1)
handleEvent(Event::PaddleOneFire, state);
else
handleEvent(Event::PaddleThreeFire, state);
}
break;
case SDL_JOYAXISMOTION:
axis = event.jaxis.axis;
value = event.jaxis.value;
// Send axis events for the joysticks
handleEvent(SA_Axis[type-2][axis][0], (value < -16384) ? 1 : 0);
handleEvent(SA_Axis[type-2][axis][1], (value > 16384) ? 1 : 0);
// Send axis events for the paddles
resistance = (Int32) (1000000.0 * (32767 - value) / 65534);
handleEvent(SA_Axis[type-2][axis][2], resistance);
// Send events for the driving controllers
if(axis == 1)
{
if(value <= -16384-4096)
handleEvent(SA_DrivingValue[type-2],2);
else if(value > 16384+4096)
handleEvent(SA_DrivingValue[type-2],1);
else if(value >= 16384-4096)
handleEvent(SA_DrivingValue[type-2],0);
else
handleEvent(SA_DrivingValue[type-2],3);
}
break;
}
break; // Stelladaptor joystick
default:
break;
break; // SDL_JOYAXISMOTION
}
#endif // JOYSTICK_SUPPORT
}
#endif
}
// Update the current dialog container at regular intervals
@ -1059,7 +1067,6 @@ void EventHandler::handleEvent(Event::Type event, Int32 state)
{
myOSystem->settings().saveConfig();
myOSystem->createLauncher();
return;
}
break;
@ -1699,6 +1706,10 @@ void EventHandler::setEventState(State state)
{
case S_EMULATE:
myOverlay = NULL;
// Controller types only make sense in Emulate mode
myController[0] = myOSystem->console().controller(Controller::Left).type();
myController[1] = myOSystem->console().controller(Controller::Right).type();
break;
case S_MENU:
@ -2061,11 +2072,19 @@ const Event::Type EventHandler::Paddle_Button[4] = {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Event::Type EventHandler::SA_Axis[2][2][3] = {
{ {Event::JoystickZeroLeft, Event::JoystickZeroRight, Event::PaddleZeroResistance},
{Event::JoystickZeroUp, Event::JoystickZeroDown, Event::PaddleOneResistance } },
{Event::JoystickZeroUp, Event::JoystickZeroDown, Event::PaddleOneResistance} },
{ {Event::JoystickOneLeft, Event::JoystickOneRight, Event::PaddleTwoResistance},
{Event::JoystickOneUp, Event::JoystickOneDown, Event::PaddleThreeResistance} }
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Event::Type EventHandler::SA_Button[2][2][3] = {
{ {Event::JoystickZeroFire, Event::PaddleZeroFire, Event::DrivingZeroFire },
{Event::NoType, Event::PaddleOneFire, Event::NoType} },
{ {Event::JoystickOneFire, Event::PaddleTwoFire, Event::DrivingOneFire },
{Event::NoType, Event::PaddleThreeFire, Event::NoType} }
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Event::Type EventHandler::SA_DrivingValue[2] = {
Event::DrivingZeroValue, Event::DrivingOneValue

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EventHandler.hxx,v 1.54 2005-10-30 20:29:56 stephena Exp $
// $Id: EventHandler.hxx,v 1.55 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#ifndef EVENTHANDLER_HXX
@ -24,6 +24,7 @@
#include "bspf.hxx"
#include "Event.hxx"
#include "Array.hxx"
#include "Control.hxx"
class Console;
class OSystem;
@ -82,7 +83,7 @@ struct Joystick_Map {
mapping can take place.
@author Stephen Anthony
@version $Id: EventHandler.hxx,v 1.54 2005-10-30 20:29:56 stephena Exp $
@version $Id: EventHandler.hxx,v 1.55 2005-11-12 22:04:57 stephena Exp $
*/
class EventHandler
{
@ -411,14 +412,18 @@ class EventHandler
// How far the joystick will move the mouse on each frame tick
int myMouseMove;
// Type of device on each controller port (based on ROM properties)
Controller::Type myController[2];
// Lookup table for paddle resistance events
static const Event::Type Paddle_Resistance[4];
// Lookup table for paddle button events
static const Event::Type Paddle_Button[4];
// Static lookup tables for Stelladaptor axis support
// Static lookup tables for Stelladaptor axis/button support
static const Event::Type SA_Axis[2][2][3];
static const Event::Type SA_Button[2][2][3];
static const Event::Type SA_DrivingValue[2];
};

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Joystick.cxx,v 1.2 2005-06-16 01:11:27 stephena Exp $
// $Id: Joystick.cxx,v 1.3 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#include <assert.h>
@ -74,3 +74,8 @@ void Joystick::write(DigitalPin, bool)
// Writing doesn't do anything to the joystick...
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Controller::Type Joystick::type()
{
return Controller::Joystick;
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Joystick.hxx,v 1.2 2005-06-16 01:11:27 stephena Exp $
// $Id: Joystick.hxx,v 1.3 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#ifndef JOYSTICK_HXX
@ -26,7 +26,7 @@
The standard Atari 2600 joystick controller.
@author Bradford W. Mott
@version $Id: Joystick.hxx,v 1.2 2005-06-16 01:11:27 stephena Exp $
@version $Id: Joystick.hxx,v 1.3 2005-11-12 22:04:57 stephena Exp $
*/
class Joystick : public Controller
{
@ -71,6 +71,11 @@ class Joystick : public Controller
@param value The value to write to the pin
*/
virtual void write(DigitalPin pin, bool value);
/**
Returns the type of this controller.
*/
virtual Type type();
};
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Keyboard.cxx,v 1.2 2005-06-16 01:11:27 stephena Exp $
// $Id: Keyboard.cxx,v 1.3 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#include "Event.hxx"
@ -205,3 +205,8 @@ void Keyboard::write(DigitalPin pin, bool value)
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Controller::Type Keyboard::type()
{
return Controller::Keyboard;
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Keyboard.hxx,v 1.2 2005-06-16 01:11:27 stephena Exp $
// $Id: Keyboard.hxx,v 1.3 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#ifndef KEYBOARD_HXX
@ -26,7 +26,7 @@
The standard Atari 2600 keyboard controller
@author Bradford W. Mott
@version $Id: Keyboard.hxx,v 1.2 2005-06-16 01:11:27 stephena Exp $
@version $Id: Keyboard.hxx,v 1.3 2005-11-12 22:04:57 stephena Exp $
*/
class Keyboard : public Controller
{
@ -72,6 +72,11 @@ class Keyboard : public Controller
*/
virtual void write(DigitalPin pin, bool value);
/**
Returns the type of this controller.
*/
virtual Type type();
private:
// State of the output pins
uInt8 myPinState;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: OSystem.cxx,v 1.44 2005-11-11 21:44:19 stephena Exp $
// $Id: OSystem.cxx,v 1.45 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#include <cassert>
@ -113,10 +113,10 @@ OSystem::OSystem()
myFeatures += "Snapshot ";
#endif
#ifdef DEVELOPER_SUPPORT
myFeatures += "Debugger";
myFeatures += "Debugger ";
#endif
#ifdef CHEATCODE_SUPPORT
myFeatures += "Cheats";
myFeatures += "Cheats"; // FIXME - string too long in 'About'
#endif
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Paddles.cxx,v 1.2 2005-06-16 01:11:28 stephena Exp $
// $Id: Paddles.cxx,v 1.3 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#include <assert.h>
@ -74,3 +74,8 @@ void Paddles::write(DigitalPin, bool)
// Writing doesn't do anything to the paddles...
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Controller::Type Paddles::type()
{
return Controller::Paddles;
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Paddles.hxx,v 1.2 2005-06-16 01:11:28 stephena Exp $
// $Id: Paddles.hxx,v 1.3 2005-11-12 22:04:57 stephena Exp $
//============================================================================
#ifndef PADDLES_HXX
@ -26,7 +26,7 @@
The standard Atari 2600 pair of paddle controllers.
@author Bradford W. Mott
@version $Id: Paddles.hxx,v 1.2 2005-06-16 01:11:28 stephena Exp $
@version $Id: Paddles.hxx,v 1.3 2005-11-12 22:04:57 stephena Exp $
*/
class Paddles : public Controller
{
@ -71,6 +71,11 @@ class Paddles : public Controller
@param value The value to write to the pin
*/
virtual void write(DigitalPin pin, bool value);
/**
Returns the type of this controller.
*/
virtual Type type();
};
#endif