Large number of changes related to controller input and handling.

Moved a lot of the code into the respective Controller classes, in the
process cleaning up the EventHandler (which was starting to get a little
unwieldy).

I've borrowed some code and ideas from z26, but also improved on it as
well:

1)  Stelladaptor devices now send their events directly to a
controller class, allowing for any Stelladaptor device to emulate
a controller (to the limits of the input device, of course).

2)  Hopefully fixed Stelladaptor driving controller support.  Eckhard,
could you test this, since I don't have any of those myself?

3)  Improved interaction with different input devices.  For example,
a Stelladaptor, mouse, joystick (digital and/or analog axis), and
the keyboard can now simulate paddle events at the same time.  So it
shouldn't matter what input devices you have plugged in; things should
'just work'.  In the case of Stelladaptor paddles, you may have to
'zero' them by turning completely left, however.

4)  Related to (3), changed mouse events to use relative motion.  This
should fix the issues with paddle emulation/movement behaving
differently based on the window size.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1412 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2008-03-02 19:20:50 +00:00
parent c51a8368da
commit 9dd3582a86
13 changed files with 403 additions and 367 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Booster.cxx,v 1.11 2008-02-06 13:45:20 stephena Exp $ // $Id: Booster.cxx,v 1.12 2008-03-02 19:20:50 stephena Exp $
//============================================================================ //============================================================================
#include "Event.hxx" #include "Event.hxx"
@ -32,6 +32,8 @@ BoosterGrip::BoosterGrip(Jack jack, const Event& event)
myFireEvent = Event::JoystickZeroFire1; myFireEvent = Event::JoystickZeroFire1;
myTriggerEvent = Event::JoystickZeroFire2; myTriggerEvent = Event::JoystickZeroFire2;
myBoosterEvent = Event::JoystickZeroFire3; myBoosterEvent = Event::JoystickZeroFire3;
myXAxisValue = Event::SALeftAxis0Value;
myYAxisValue = Event::SALeftAxis1Value;
} }
else else
{ {
@ -42,6 +44,8 @@ BoosterGrip::BoosterGrip(Jack jack, const Event& event)
myFireEvent = Event::JoystickOneFire1; myFireEvent = Event::JoystickOneFire1;
myTriggerEvent = Event::JoystickOneFire2; myTriggerEvent = Event::JoystickOneFire2;
myBoosterEvent = Event::JoystickOneFire3; myBoosterEvent = Event::JoystickOneFire3;
myXAxisValue = Event::SARightAxis0Value;
myYAxisValue = Event::SARightAxis1Value;
} }
} }
@ -53,6 +57,7 @@ BoosterGrip::~BoosterGrip()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void BoosterGrip::update() void BoosterGrip::update()
{ {
// Digital events (from keyboard or joystick hats & buttons)
myDigitalPinState[One] = (myEvent.get(myUpEvent) == 0); myDigitalPinState[One] = (myEvent.get(myUpEvent) == 0);
myDigitalPinState[Two] = (myEvent.get(myDownEvent) == 0); myDigitalPinState[Two] = (myEvent.get(myDownEvent) == 0);
myDigitalPinState[Three] = (myEvent.get(myLeftEvent) == 0); myDigitalPinState[Three] = (myEvent.get(myLeftEvent) == 0);
@ -65,4 +70,26 @@ void BoosterGrip::update()
minimumResistance : maximumResistance; minimumResistance : maximumResistance;
myAnalogPinValue[Nine] = (myEvent.get(myTriggerEvent) != 0) ? myAnalogPinValue[Nine] = (myEvent.get(myTriggerEvent) != 0) ?
minimumResistance : maximumResistance; minimumResistance : maximumResistance;
// Axis events (usually generated by the Stelladaptor)
int xaxis = myEvent.get(myXAxisValue);
int yaxis = myEvent.get(myYAxisValue);
if(xaxis > 16384-4096)
{
myDigitalPinState[Four] = false;
// Stelladaptor sends "half moved right" for L+R pushed together
if(xaxis < 16384+4096)
myDigitalPinState[Three] = false;
}
if(xaxis < -16384)
myDigitalPinState[Three] = false;
if(yaxis > 16384-4096)
{
myDigitalPinState[Two] = false;
// Stelladaptor sends "half moved down" for U+D pushed together
if(yaxis < 16384+4096)
myDigitalPinState[One] = false;
}
if(yaxis < -16384)
myDigitalPinState[One] = false;
} }

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Booster.hxx,v 1.9 2008-02-06 13:45:20 stephena Exp $ // $Id: Booster.hxx,v 1.10 2008-03-02 19:20:50 stephena Exp $
//============================================================================ //============================================================================
#ifndef BOOSTERGRIP_HXX #ifndef BOOSTERGRIP_HXX
@ -29,7 +29,7 @@
on it (a booster and a trigger). on it (a booster and a trigger).
@author Bradford W. Mott @author Bradford W. Mott
@version $Id: Booster.hxx,v 1.9 2008-02-06 13:45:20 stephena Exp $ @version $Id: Booster.hxx,v 1.10 2008-03-02 19:20:50 stephena Exp $
*/ */
class BoosterGrip : public Controller class BoosterGrip : public Controller
{ {
@ -57,8 +57,9 @@ class BoosterGrip : public Controller
private: private:
// Pre-compute the events we care about based on given port // Pre-compute the events we care about based on given port
// This will eliminate test for left or right port in update() // This will eliminate test for left or right port in update()
Event::Type myUpEvent, myDownEvent, myLeftEvent, myRightEvent, myFireEvent; Event::Type myUpEvent, myDownEvent, myLeftEvent, myRightEvent,
Event::Type myBoosterEvent, myTriggerEvent; myFireEvent, myBoosterEvent, myTriggerEvent,
myXAxisValue, myYAxisValue;
}; };
#endif #endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Driving.cxx,v 1.14 2008-02-06 13:45:21 stephena Exp $ // $Id: Driving.cxx,v 1.15 2008-03-02 19:20:50 stephena Exp $
//============================================================================ //============================================================================
#include "Event.hxx" #include "Event.hxx"
@ -31,14 +31,16 @@ Driving::Driving(Jack jack, const Event& event)
myCCWEvent = Event::JoystickZeroLeft; myCCWEvent = Event::JoystickZeroLeft;
myCWEvent = Event::JoystickZeroRight; myCWEvent = Event::JoystickZeroRight;
myFireEvent = Event::JoystickZeroFire1; myFireEvent = Event::JoystickZeroFire1;
myValueEvent = Event::DrivingZeroValue; myXAxisValue = Event::SALeftAxis0Value;
myYAxisValue = Event::SALeftAxis1Value;
} }
else else
{ {
myCCWEvent = Event::JoystickOneLeft; myCCWEvent = Event::JoystickOneLeft;
myCWEvent = Event::JoystickOneRight; myCWEvent = Event::JoystickOneRight;
myFireEvent = Event::JoystickOneFire1; myFireEvent = Event::JoystickOneFire1;
myValueEvent = Event::DrivingOneValue; myXAxisValue = Event::SARightAxis0Value;
myYAxisValue = Event::SARightAxis1Value;
} }
// Digital pins 3 and 4 are not connected // Digital pins 3 and 4 are not connected
@ -56,100 +58,35 @@ Driving::~Driving()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Driving::update() void Driving::update()
{ {
// TODO - this isn't working with Stelladaptor and real driving controllers int grayIndex = 0;
// Digital events (from keyboard or joystick hats & buttons)
myDigitalPinState[Six] = (myEvent.get(myFireEvent) == 0);
int xaxis = myEvent.get(myXAxisValue);
if(myEvent.get(myCCWEvent) != 0 || xaxis < -16384) myCounter--;
else if(myEvent.get(myCWEvent) != 0 || xaxis > 16384) myCounter++;
// Only consider the lower-most bits (corresponding to pins 1 & 2)
myCounter &= 0x0f;
grayIndex = myCounter >> 2;
// Stelladaptor is the only controller that should set this
int yaxis = myEvent.get(myYAxisValue);
if(yaxis <= -16384-4096)
grayIndex = 2;
else if(yaxis > 16384+4096)
grayIndex = 1;
else if(yaxis >= 16384-4096)
grayIndex = 0;
else if(yaxis < -16384+4096)
grayIndex = 3;
// Gray codes for rotation // Gray codes for rotation
static const uInt8 graytable[] = { 0x03, 0x01, 0x00, 0x02 }; static const uInt8 graytable[] = { 0x03, 0x01, 0x00, 0x02 };
// Determine which gray code we're at
if(myEvent.get(myCCWEvent) != 0)
myCounter--;
else if(myEvent.get(myCWEvent) != 0)
myCounter++;
// Only consider the lower-most bits (corresponding to pins 1 & 2)
myCounter &= 0x0f;
uInt8 gray = graytable[myCounter >> 2];
// Determine which bits are set // Determine which bits are set
uInt8 gray = graytable[grayIndex];
myDigitalPinState[One] = (gray & 0x1) != 0; myDigitalPinState[One] = (gray & 0x1) != 0;
myDigitalPinState[Two] = (gray & 0x2) != 0; myDigitalPinState[Two] = (gray & 0x2) != 0;
myDigitalPinState[Six] = (myEvent.get(myFireEvent) == 0);
} }
/*
bool Driving::read(DigitalPin pin)
{
// Gray codes for clockwise rotation
static const uInt8 clockwise[] = { 0x03, 0x01, 0x00, 0x02 };
// Gray codes for counter-clockwise rotation
static const uInt8 counterclockwise[] = { 0x03, 0x02, 0x00, 0x01 };
// Delay used for moving through the gray code tables
const uInt32 delay = 20;
switch(pin)
{
case One:
++myCounter;
if(myJack == Left)
{
if(myEvent.get(Event::DrivingZeroCounterClockwise) != 0)
{
return (counterclockwise[(myCounter / delay) & 0x03] & 0x01) != 0;
}
else if(myEvent.get(Event::DrivingZeroClockwise) != 0)
{
return (clockwise[(myCounter / delay) & 0x03] & 0x01) != 0;
}
else
return(myEvent.get(Event::DrivingZeroValue) & 0x01);
}
else
{
if(myEvent.get(Event::DrivingOneCounterClockwise) != 0)
{
return (counterclockwise[(myCounter / delay) & 0x03] & 0x01) != 0;
}
else if(myEvent.get(Event::DrivingOneClockwise) != 0)
{
return (clockwise[(myCounter / delay) & 0x03] & 0x01) != 0;
}
else
return(myEvent.get(Event::DrivingOneValue) & 0x01);
}
case Two:
if(myJack == Left)
{
if(myEvent.get(Event::DrivingZeroCounterClockwise) != 0)
{
return (counterclockwise[(myCounter / delay) & 0x03] & 0x02) != 0;
}
else if(myEvent.get(Event::DrivingZeroClockwise) != 0)
{
return (clockwise[(myCounter / delay) & 0x03] & 0x02) != 0;
}
else
return(myEvent.get(Event::DrivingZeroValue) & 0x02);
}
else
{
if(myEvent.get(Event::DrivingOneCounterClockwise) != 0)
{
return (counterclockwise[(myCounter / delay) & 0x03] & 0x02) != 0;
}
else if(myEvent.get(Event::DrivingOneClockwise) != 0)
{
return (clockwise[(myCounter / delay) & 0x03] & 0x02) != 0;
}
else
return(myEvent.get(Event::DrivingOneValue) & 0x02);
}
}
}
*/

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Driving.hxx,v 1.8 2008-02-06 13:45:21 stephena Exp $ // $Id: Driving.hxx,v 1.9 2008-03-02 19:20:50 stephena Exp $
//============================================================================ //============================================================================
#ifndef DRIVING_HXX #ifndef DRIVING_HXX
@ -27,7 +27,7 @@
The standard Atari 2600 Indy 500 driving controller. The standard Atari 2600 Indy 500 driving controller.
@author Bradford W. Mott @author Bradford W. Mott
@version $Id: Driving.hxx,v 1.8 2008-02-06 13:45:21 stephena Exp $ @version $Id: Driving.hxx,v 1.9 2008-03-02 19:20:50 stephena Exp $
*/ */
class Driving : public Controller class Driving : public Controller
{ {
@ -59,7 +59,7 @@ class Driving : public Controller
// Pre-compute the events we care about based on given port // Pre-compute the events we care about based on given port
// This will eliminate test for left or right port in update() // This will eliminate test for left or right port in update()
Event::Type myCWEvent, myCCWEvent, myValueEvent, myFireEvent; Event::Type myCWEvent, myCCWEvent, myFireEvent, myXAxisValue, myYAxisValue;
}; };
#endif #endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Event.cxx,v 1.14 2008-02-06 13:45:21 stephena Exp $ // $Id: Event.cxx,v 1.15 2008-03-02 19:20:50 stephena Exp $
//============================================================================ //============================================================================
#include "OSystem.hxx" #include "OSystem.hxx"
@ -26,15 +26,7 @@
Event::Event() Event::Event()
: myNumberOfTypes(Event::LastType) : myNumberOfTypes(Event::LastType)
{ {
// Set all of the events to 0 / false to start with,
// including analog paddle events. Doing it this way
// is a bit of a hack ...
clear(); clear();
myValues[PaddleZeroResistance] =
myValues[PaddleOneResistance] =
myValues[PaddleTwoResistance] =
myValues[PaddleThreeResistance] = 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -58,9 +50,5 @@ void Event::set(Type type, Int32 value)
void Event::clear() void Event::clear()
{ {
for(int i = 0; i < myNumberOfTypes; ++i) for(int i = 0; i < myNumberOfTypes; ++i)
{ myValues[i] = 0;
if(i != PaddleZeroResistance && i != PaddleOneResistance &&
i != PaddleTwoResistance && i != PaddleThreeResistance)
myValues[i] = 0;
}
} }

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Event.hxx,v 1.32 2008-02-06 13:45:21 stephena Exp $ // $Id: Event.hxx,v 1.33 2008-03-02 19:20:50 stephena Exp $
//============================================================================ //============================================================================
#ifndef EVENT_HXX #ifndef EVENT_HXX
@ -25,7 +25,7 @@ class Event;
/** /**
@author Bradford W. Mott @author Bradford W. Mott
@version $Id: Event.hxx,v 1.32 2008-02-06 13:45:21 stephena Exp $ @version $Id: Event.hxx,v 1.33 2008-03-02 19:20:50 stephena Exp $
*/ */
class Event class Event
{ {
@ -44,20 +44,14 @@ class Event
ConsoleSelect, ConsoleReset, ConsoleSelect, ConsoleReset,
JoystickZeroUp, JoystickZeroDown, JoystickZeroLeft, JoystickZeroRight, JoystickZeroUp, JoystickZeroDown, JoystickZeroLeft, JoystickZeroRight,
JoystickZeroFire1, JoystickZeroFire2, JoystickZeroFire3, JoystickZeroFire1, JoystickZeroFire2, JoystickZeroFire3,
JoystickOneUp, JoystickOneDown, JoystickOneLeft, JoystickOneRight, JoystickOneUp, JoystickOneDown, JoystickOneLeft, JoystickOneRight,
JoystickOneFire1, JoystickOneFire2, JoystickOneFire3, JoystickOneFire1, JoystickOneFire2, JoystickOneFire3,
DrivingZeroValue, DrivingOneValue, PaddleZeroDecrease, PaddleZeroIncrease, PaddleZeroAnalog, PaddleZeroFire,
PaddleOneDecrease, PaddleOneIncrease, PaddleOneAnalog, PaddleOneFire,
PaddleZeroResistance, PaddleZeroFire, PaddleTwoDecrease, PaddleTwoIncrease, PaddleTwoAnalog, PaddleTwoFire,
PaddleZeroDecrease, PaddleZeroIncrease, PaddleZeroAnalog, PaddleThreeDecrease, PaddleThreeIncrease, PaddleThreeAnalog, PaddleThreeFire,
PaddleOneResistance, PaddleOneFire,
PaddleOneDecrease, PaddleOneIncrease, PaddleOneAnalog,
PaddleTwoResistance, PaddleTwoFire,
PaddleTwoDecrease, PaddleTwoIncrease, PaddleTwoAnalog,
PaddleThreeResistance, PaddleThreeFire,
PaddleThreeDecrease, PaddleThreeIncrease, PaddleThreeAnalog,
KeyboardZero1, KeyboardZero2, KeyboardZero3, KeyboardZero1, KeyboardZero2, KeyboardZero3,
KeyboardZero4, KeyboardZero5, KeyboardZero6, KeyboardZero4, KeyboardZero5, KeyboardZero6,
@ -69,6 +63,11 @@ class Event
KeyboardOne7, KeyboardOne8, KeyboardOne9, KeyboardOne7, KeyboardOne8, KeyboardOne9,
KeyboardOneStar, KeyboardOne0, KeyboardOnePound, KeyboardOneStar, KeyboardOne0, KeyboardOnePound,
SALeftAxis0Value, SALeftAxis1Value,
SARightAxis0Value, SARightAxis1Value,
MouseAxisXValue, MouseAxisYValue,
ChangeState, LoadState, SaveState, TakeSnapshot, Quit, ChangeState, LoadState, SaveState, TakeSnapshot, Quit,
PauseMode, MenuMode, CmdMenuMode, DebuggerMode, LauncherMode, PauseMode, MenuMode, CmdMenuMode, DebuggerMode, LauncherMode,
Fry, VolumeDecrease, VolumeIncrease, Fry, VolumeDecrease, VolumeIncrease,

View File

@ -14,7 +14,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: EventHandler.cxx,v 1.214 2008-02-06 13:45:21 stephena Exp $ // $Id: EventHandler.cxx,v 1.215 2008-03-02 19:20:50 stephena Exp $
//============================================================================ //============================================================================
#include <sstream> #include <sstream>
@ -164,14 +164,7 @@ void EventHandler::reset(State state)
if(myState == S_LAUNCHER) if(myState == S_LAUNCHER)
myUseLauncherFlag = true; myUseLauncherFlag = true;
// Set all paddles to minimum resistance by default // FIXME - this should go directly into the Paddles class
for(int i = 0; i < 4; ++i)
{
memset(&myPaddle[i], 0, sizeof(JoyMouse));
myPaddle[i].x = myPaddle[i].y = 1000000;
int resistance = (int)(1000000.0 * (1000000.0 - myPaddle[i].x) / 1000000.0);
myEvent->set(Paddle_Resistance[i], resistance);
}
setPaddleSpeed(0, myOSystem->settings().getInt("p0speed")); setPaddleSpeed(0, myOSystem->settings().getInt("p0speed"));
setPaddleSpeed(1, myOSystem->settings().getInt("p1speed")); setPaddleSpeed(1, myOSystem->settings().getInt("p1speed"));
setPaddleSpeed(2, myOSystem->settings().getInt("p2speed")); setPaddleSpeed(2, myOSystem->settings().getInt("p2speed"));
@ -449,7 +442,7 @@ void EventHandler::poll(uInt32 time)
myOSystem->console().togglePhosphor(); myOSystem->console().togglePhosphor();
break; break;
#if 1 #if 0
// FIXME - these will be removed when a UI is added for event recording // FIXME - these will be removed when a UI is added for event recording
case SDLK_e: // Alt-e starts/stops event recording case SDLK_e: // Alt-e starts/stops event recording
if(myOSystem->state().toggleRecordMode()) if(myOSystem->state().toggleRecordMode())
@ -663,25 +656,13 @@ void EventHandler::poll(uInt32 time)
int button = event.jbutton.button; int button = event.jbutton.button;
int state = event.jbutton.state == SDL_PRESSED ? 1 : 0; 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
// The 'type-2' here refers to the fact that 'JT_STELLADAPTOR_LEFT' // The 'type-2' here refers to the fact that 'JT_STELLADAPTOR_LEFT'
// and 'JT_STELLADAPTOR_RIGHT' are at index 2 and 3 in the JoyType // and 'JT_STELLADAPTOR_RIGHT' are at index 2 and 3 in the JoyType
// enum; subtracting two gives us Controller 0 and 1 // enum; subtracting two gives us Controller 0 and 1
switch((int)myController[type-2])
{
// Send button events for the joysticks and driving controllers
case Controller::Joystick:
case Controller::Driving:
myEvent->set(SA_Button[type-2][button][0], state);
break;
// Send axis events for the paddles // These events don't have to pass through handleEvent, since
case Controller::Paddles: // they can never be remapped
myEvent->set(SA_Button[type-2][button][1], state); myEvent->set(SA_Button[type-2][button], state);
break;
}
break; // Stelladaptor button break; // Stelladaptor button
} }
} }
@ -716,49 +697,16 @@ void EventHandler::poll(uInt32 time)
int axis = event.jaxis.axis; int axis = event.jaxis.axis;
int value = event.jaxis.value; int value = event.jaxis.value;
// Since we can't detect what controller is attached to a // Since the various controller classes deal with the
// Stelladaptor, we only send events based on controller // Stelladaptor differently, we send the raw X and Y axis
// type in ROM properties // data directly, and let the controller handle it
// The 'type-2' here refers to the fact that 'JT_STELLADAPTOR_LEFT' // The 'type-2' here refers to the fact that 'JT_STELLADAPTOR_LEFT'
// and 'JT_STELLADAPTOR_RIGHT' are at index 2 and 3 in the JoyType // and 'JT_STELLADAPTOR_RIGHT' are at index 2 and 3 in the JoyType
// enum; subtracting two gives us Controller 0 and 1 // enum; subtracting two gives us Controller 0 and 1
switch((int)myController[type-2])
{
// Send axis events for the joysticks
case Controller::Joystick:
// Disallow 4-direction movement by turning off the
// other extreme of the axis
myEvent->set(SA_Axis[type-2][axis][0], (value < -16384) ? 1 : 0);
myEvent->set(SA_Axis[type-2][axis][1], (value > 16384) ? 1 : 0);
break;
// Send axis events for the paddles // These events don't have to pass through handleEvent, since
case Controller::Paddles: // they can never be remapped
{ myEvent->set(SA_Axis[type-2][axis], value);
// Determine which paddle we're emulating and see if
// we're getting rapid movement (aka jittering)
if(isJitter(((type-2) << 1) + axis, value))
break;
int resistance = (Int32) (1000000.0 * (32767 - value) / 65534);
myEvent->set(SA_Axis[type-2][axis][2], resistance);
break;
}
// Send events for the driving controllers
case Controller::Driving:
if(axis == 1)
{
if(value <= -16384-4096)
myEvent->set(SA_DrivingValue[type-2],2);
else if(value > 16384+4096)
myEvent->set(SA_DrivingValue[type-2],1);
else if(value >= 16384-4096)
myEvent->set(SA_DrivingValue[type-2],0);
else
myEvent->set(SA_DrivingValue[type-2],3);
}
}
break; // Stelladaptor axis break; // Stelladaptor axis
} }
} }
@ -796,28 +744,6 @@ void EventHandler::poll(uInt32 time)
} }
} }
// Handle paddle emulation using joystick or key events
for(int i = 0; i < 4; ++i)
{
if(myPaddle[i].active)
{
myPaddle[i].x += myPaddle[i].x_amt;
if(myPaddle[i].x < 0)
{
myPaddle[i].x = 0; continue;
}
else if(myPaddle[i].x > 1000000)
{
myPaddle[i].x = 1000000; continue;
}
else
{
int resistance = (int)(1000000.0 * (1000000 - myPaddle[i].x) / 1000000);
myEvent->set(Paddle_Resistance[i], resistance);
}
}
}
// Update controllers and console switches, and in general all other things // Update controllers and console switches, and in general all other things
// related to emulation // related to emulation
if(myState == S_EMULATE) if(myState == S_EMULATE)
@ -848,27 +774,25 @@ void EventHandler::poll(uInt32 time)
// Used to implement continuous events // Used to implement continuous events
myOverlay->updateTime(time); myOverlay->updateTime(time);
} }
// Turn off relative events
myEvent->set(Event::MouseAxisXValue, 0);
myEvent->set(Event::MouseAxisYValue, 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::handleMouseMotionEvent(SDL_Event& event) void EventHandler::handleMouseMotionEvent(SDL_Event& event)
{ {
// Take window zooming into account
int x = event.motion.x, y = event.motion.y;
// Determine which mode we're in, then send the event to the appropriate place // Determine which mode we're in, then send the event to the appropriate place
if(myState == S_EMULATE) if(myState == S_EMULATE)
{ {
int w = myOSystem->frameBuffer().baseWidth(); int x = event.motion.xrel, y = event.motion.yrel;
if(x < 0 || x > w) return; myEvent->set(Event::MouseAxisXValue, x);
int resistance = (int)(1000000.0 * (w - x) / w); myEvent->set(Event::MouseAxisYValue, y);
myEvent->set(Paddle_Resistance[myPaddleMode], resistance);
// Update the digital paddle emulation so it's consistent
myPaddle[myPaddleMode].x = 1000000 - resistance;
} }
else if(myOverlay) else if(myOverlay)
{ {
int x = event.motion.x, y = event.motion.y;
myOSystem->frameBuffer().translateCoords(x, y); myOSystem->frameBuffer().translateCoords(x, y);
myOverlay->handleMouseMotionEvent(x, y, 0); myOverlay->handleMouseMotionEvent(x, y, 0);
} }
@ -934,23 +858,21 @@ void EventHandler::handleJoyAxisEvent(int stick, int axis, int value)
Event::Type eventAxisPos = myJoyAxisTable[stick][axis][1][kEmulationMode]; Event::Type eventAxisPos = myJoyAxisTable[stick][axis][1][kEmulationMode];
// Check for analog events, which are handled differently // Check for analog events, which are handled differently
// We'll pass them off as Stelladaptor events, and let the controllers
// handle it
switch((int)eventAxisNeg) switch((int)eventAxisNeg)
{ {
case Event::PaddleZeroAnalog: case Event::PaddleZeroAnalog:
myEvent->set(Event::PaddleZeroResistance, myEvent->set(Event::SALeftAxis0Value, value);
(int)(1000000.0 * (32767 - value) / 65534));
break; break;
case Event::PaddleOneAnalog: case Event::PaddleOneAnalog:
myEvent->set(Event::PaddleOneResistance, myEvent->set(Event::SALeftAxis1Value, value);
(int)(1000000.0 * (32767 - value) / 65534));
break; break;
case Event::PaddleTwoAnalog: case Event::PaddleTwoAnalog:
myEvent->set(Event::PaddleTwoResistance, myEvent->set(Event::SARightAxis0Value, value);
(int)(1000000.0 * (32767 - value) / 65534));
break; break;
case Event::PaddleThreeAnalog: case Event::PaddleThreeAnalog:
myEvent->set(Event::PaddleThreeResistance, myEvent->set(Event::SARightAxis1Value, value);
(int)(1000000.0 * (32767 - value) / 65534));
break; break;
default: default:
// Otherwise, we know the event is digital // Otherwise, we know the event is digital
@ -1007,95 +929,48 @@ void EventHandler::handleEvent(Event::Type event, int state)
switch(event) switch(event)
{ {
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Preprocess joystick events into equivalent paddle events. // If enabled, make sure 'impossible' joystick directions aren't allowed
// To speed processing, we won't care which type of controller
// is connected; we just set the events and let the controller
// decide how to interpret it.
case Event::JoystickZeroUp: case Event::JoystickZeroUp:
if(!myAllowAllDirectionsFlag && state) if(!myAllowAllDirectionsFlag && state)
myEvent->set(Event::JoystickZeroDown, 0); myEvent->set(Event::JoystickZeroDown, 0);
handleEvent(Event::PaddleOneDecrease, state);
break; break;
case Event::JoystickZeroDown: case Event::JoystickZeroDown:
if(!myAllowAllDirectionsFlag && state) if(!myAllowAllDirectionsFlag && state)
myEvent->set(Event::JoystickZeroUp, 0); myEvent->set(Event::JoystickZeroUp, 0);
handleEvent(Event::PaddleOneIncrease, state);
break; break;
case Event::JoystickZeroLeft: case Event::JoystickZeroLeft:
if(!myAllowAllDirectionsFlag && state) if(!myAllowAllDirectionsFlag && state)
myEvent->set(Event::JoystickZeroRight, 0); myEvent->set(Event::JoystickZeroRight, 0);
handleEvent(Event::PaddleZeroDecrease, state);
break; break;
case Event::JoystickZeroRight: case Event::JoystickZeroRight:
if(!myAllowAllDirectionsFlag && state) if(!myAllowAllDirectionsFlag && state)
myEvent->set(Event::JoystickZeroLeft, 0); myEvent->set(Event::JoystickZeroLeft, 0);
handleEvent(Event::PaddleZeroIncrease, state);
break; break;
case Event::JoystickOneUp: case Event::JoystickOneUp:
if(!myAllowAllDirectionsFlag && state) if(!myAllowAllDirectionsFlag && state)
myEvent->set(Event::JoystickOneDown, 0); myEvent->set(Event::JoystickOneDown, 0);
handleEvent(Event::PaddleThreeDecrease, state);
break; break;
case Event::JoystickOneDown: case Event::JoystickOneDown:
if(!myAllowAllDirectionsFlag && state) if(!myAllowAllDirectionsFlag && state)
myEvent->set(Event::JoystickOneUp, 0); myEvent->set(Event::JoystickOneUp, 0);
handleEvent(Event::PaddleThreeIncrease, state);
break; break;
case Event::JoystickOneLeft: case Event::JoystickOneLeft:
if(!myAllowAllDirectionsFlag && state) if(!myAllowAllDirectionsFlag && state)
myEvent->set(Event::JoystickOneRight, 0); myEvent->set(Event::JoystickOneRight, 0);
handleEvent(Event::PaddleTwoDecrease, state);
break; break;
case Event::JoystickOneRight: case Event::JoystickOneRight:
if(!myAllowAllDirectionsFlag && state) if(!myAllowAllDirectionsFlag && state)
myEvent->set(Event::JoystickOneLeft, 0); myEvent->set(Event::JoystickOneLeft, 0);
handleEvent(Event::PaddleTwoIncrease, state);
break; break;
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
case Event::PaddleZeroDecrease:
myPaddle[0].active = (bool) state;
myPaddle[0].x_amt = -myPaddle[0].amt;
return;
case Event::PaddleZeroIncrease:
myPaddle[0].active = (bool) state;
myPaddle[0].x_amt = myPaddle[0].amt;
return;
case Event::PaddleOneDecrease:
myPaddle[1].active = (bool) state;
myPaddle[1].x_amt = -myPaddle[1].amt;
return;
case Event::PaddleOneIncrease:
myPaddle[1].active = (bool) state;
myPaddle[1].x_amt = myPaddle[1].amt;
return;
case Event::PaddleTwoDecrease:
myPaddle[2].active = (bool) state;
myPaddle[2].x_amt = -myPaddle[2].amt;
return;
case Event::PaddleTwoIncrease:
myPaddle[2].active = (bool) state;
myPaddle[2].x_amt = myPaddle[2].amt;
return;
case Event::PaddleThreeDecrease:
myPaddle[3].active = (bool) state;
myPaddle[3].x_amt = -myPaddle[3].amt;
return;
case Event::PaddleThreeIncrease:
myPaddle[3].active = (bool) state;
myPaddle[3].x_amt = myPaddle[3].amt;
return;
case Event::NoType: // Ignore unmapped events
return;
case Event::Fry: case Event::Fry:
myFryingFlag = bool(state); myFryingFlag = bool(state);
return; return;
@ -1144,6 +1019,9 @@ void EventHandler::handleEvent(Event::Type event, int state)
} }
return; return;
case Event::NoType: // Ignore unmapped events
return;
default: default:
break; break;
} }
@ -1931,25 +1809,6 @@ string EventHandler::keyAtIndex(int idx, EventMode mode)
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline bool EventHandler::isJitter(int paddle, int value)
{
bool jitter = false;
bool leftMotion = myPaddle[paddle].val - myPaddle[paddle].old_val > 0;
int distance = value - myPaddle[paddle].val;
// Filter out jitter by not allowing rapid direction changes
if(distance > 0 && !leftMotion) // movement switched from left to right
jitter = distance < myPaddleThreshold;
else if(distance < 0 && leftMotion) // movement switched from right to left
jitter = distance > -myPaddleThreshold;
myPaddle[paddle].old_val = myPaddle[paddle].val;
myPaddle[paddle].val = value;
return jitter;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::takeSnapshot() void EventHandler::takeSnapshot()
{ {
@ -1993,6 +1852,7 @@ void EventHandler::takeSnapshot()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::setPaddleMode(int num, bool showmessage) void EventHandler::setPaddleMode(int num, bool showmessage)
{ {
// FIXME - communicate with Paddles class
if(num < 0 || num > 3) if(num < 0 || num > 3)
return; return;
@ -2011,6 +1871,7 @@ void EventHandler::setPaddleMode(int num, bool showmessage)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::setPaddleSpeed(int num, int speed) void EventHandler::setPaddleSpeed(int num, int speed)
{ {
/* FIXME - move functionality to Paddles class
if(num < 0 || num > 3 || speed < 0 || speed > 100) if(num < 0 || num > 3 || speed < 0 || speed > 100)
return; return;
@ -2018,14 +1879,17 @@ void EventHandler::setPaddleSpeed(int num, int speed)
ostringstream buf; ostringstream buf;
buf << "p" << num << "speed"; buf << "p" << num << "speed";
myOSystem->settings().setInt(buf.str(), speed); myOSystem->settings().setInt(buf.str(), speed);
*/
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::setPaddleThreshold(int thresh) void EventHandler::setPaddleThreshold(int thresh)
{ {
/* FIXME - move functionality to Paddles class
myPaddleThreshold = thresh; myPaddleThreshold = thresh;
myOSystem->settings().setInt("pthresh", thresh); myOSystem->settings().setInt("pthresh", thresh);
*/
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -2486,12 +2350,6 @@ EventHandler::ActionList EventHandler::ourMenuActionList[kMenuActionListSize] =
{ Event::UINavNext, "Next object", 0 } { Event::UINavNext, "Next object", 0 }
}; };
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Event::Type EventHandler::Paddle_Resistance[4] = {
Event::PaddleZeroResistance, Event::PaddleOneResistance,
Event::PaddleTwoResistance, Event::PaddleThreeResistance
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Event::Type EventHandler::Paddle_Button[4] = { const Event::Type EventHandler::Paddle_Button[4] = {
Event::PaddleZeroFire, Event::PaddleOneFire, Event::PaddleZeroFire, Event::PaddleOneFire,
@ -2499,27 +2357,16 @@ const Event::Type EventHandler::Paddle_Button[4] = {
}; };
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Used by the Stelladaptor to disallow impossible directions (both up & down // Used by the Stelladaptor to send absolute axis values
// or left & right), or for resistance for paddles const Event::Type EventHandler::SA_Axis[2][2] = {
const Event::Type EventHandler::SA_Axis[2][2][3] = { { Event::SALeftAxis0Value, Event::SALeftAxis1Value },
{ {Event::JoystickZeroLeft, Event::JoystickZeroRight, Event::PaddleZeroResistance }, { Event::SARightAxis0Value, Event::SARightAxis1Value }
{Event::JoystickZeroUp, Event::JoystickZeroDown, Event::PaddleOneResistance } },
{ {Event::JoystickOneLeft, Event::JoystickOneRight, Event::PaddleTwoResistance },
{Event::JoystickOneUp, Event::JoystickOneDown, Event::PaddleThreeResistance} }
}; };
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Used by the Stelladaptor to map button presses to joystick or paddles // Used by the Stelladaptor to map button presses to joystick or paddles
// (driving controllers are considered the same as joysticks) // (driving controllers are considered the same as joysticks)
const Event::Type EventHandler::SA_Button[2][2][2] = { const Event::Type EventHandler::SA_Button[2][2] = {
{ {Event::JoystickZeroFire1, Event::PaddleZeroFire }, { Event::JoystickZeroFire1, Event::JoystickZeroFire3 },
{Event::NoType, Event::PaddleOneFire } }, { Event::JoystickOneFire1, Event::JoystickOneFire3 }
{ {Event::JoystickOneFire1, Event::PaddleTwoFire },
{Event::NoType, Event::PaddleThreeFire } }
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Used by the Stelladaptor to send simulated 'gray codes'
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 // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: EventHandler.hxx,v 1.106 2008-02-06 13:45:21 stephena Exp $ // $Id: EventHandler.hxx,v 1.107 2008-03-02 19:20:50 stephena Exp $
//============================================================================ //============================================================================
#ifndef EVENTHANDLER_HXX #ifndef EVENTHANDLER_HXX
@ -61,7 +61,7 @@ enum EventMode {
mapping can take place. mapping can take place.
@author Stephen Anthony @author Stephen Anthony
@version $Id: EventHandler.hxx,v 1.106 2008-02-06 13:45:21 stephena Exp $ @version $Id: EventHandler.hxx,v 1.107 2008-03-02 19:20:50 stephena Exp $
*/ */
class EventHandler class EventHandler
{ {
@ -433,16 +433,6 @@ class EventHandler
*/ */
inline bool eventIsAnalog(Event::Type event); inline bool eventIsAnalog(Event::Type event);
/**
Tests if the given paddle value is displaying a rapid left/right
motion, which is also known as jitter.
@param paddle The paddle to test
@param value The value assigned to the paddle
@return True if jittering, else false
*/
inline bool isJitter(int paddle, int value);
void setEventState(State state); void setEventState(State state);
private: private:
@ -539,9 +529,6 @@ class EventHandler
// Indicates the amount by which we consider a paddle to be jittering // Indicates the amount by which we consider a paddle to be jittering
int myPaddleThreshold; int myPaddleThreshold;
// Used for paddle emulation by keyboard or joystick
JoyMouse myPaddle[4];
// Type of device on each controller port (based on ROM properties) // Type of device on each controller port (based on ROM properties)
Controller::Type myController[2]; Controller::Type myController[2];
@ -549,16 +536,12 @@ class EventHandler
static ActionList ourEmulActionList[kEmulActionListSize]; static ActionList ourEmulActionList[kEmulActionListSize];
static ActionList ourMenuActionList[kMenuActionListSize]; static ActionList ourMenuActionList[kMenuActionListSize];
// Lookup table for paddle resistance events
static const Event::Type Paddle_Resistance[4];
// Lookup table for paddle button events // Lookup table for paddle button events
static const Event::Type Paddle_Button[4]; static const Event::Type Paddle_Button[4];
// Static lookup tables for Stelladaptor axis/button support // Static lookup tables for Stelladaptor axis/button support
static const Event::Type SA_Axis[2][2][3]; static const Event::Type SA_Axis[2][2];
static const Event::Type SA_Button[2][2][2]; static const Event::Type SA_Button[2][2];
static const Event::Type SA_DrivingValue[2];
}; };
#endif #endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Joystick.cxx,v 1.10 2008-02-06 13:45:21 stephena Exp $ // $Id: Joystick.cxx,v 1.11 2008-03-02 19:20:50 stephena Exp $
//============================================================================ //============================================================================
#include "Event.hxx" #include "Event.hxx"
@ -30,6 +30,8 @@ Joystick::Joystick(Jack jack, const Event& event)
myLeftEvent = Event::JoystickZeroLeft; myLeftEvent = Event::JoystickZeroLeft;
myRightEvent = Event::JoystickZeroRight; myRightEvent = Event::JoystickZeroRight;
myFireEvent = Event::JoystickZeroFire1; myFireEvent = Event::JoystickZeroFire1;
myXAxisValue = Event::SALeftAxis0Value;
myYAxisValue = Event::SALeftAxis1Value;
} }
else else
{ {
@ -38,6 +40,8 @@ Joystick::Joystick(Jack jack, const Event& event)
myLeftEvent = Event::JoystickOneLeft; myLeftEvent = Event::JoystickOneLeft;
myRightEvent = Event::JoystickOneRight; myRightEvent = Event::JoystickOneRight;
myFireEvent = Event::JoystickOneFire1; myFireEvent = Event::JoystickOneFire1;
myXAxisValue = Event::SARightAxis0Value;
myYAxisValue = Event::SARightAxis1Value;
} }
// Analog pins are never used by the joystick // Analog pins are never used by the joystick
@ -52,9 +56,32 @@ Joystick::~Joystick()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Joystick::update() void Joystick::update()
{ {
// Digital events (from keyboard or joystick hats & buttons)
myDigitalPinState[One] = (myEvent.get(myUpEvent) == 0); myDigitalPinState[One] = (myEvent.get(myUpEvent) == 0);
myDigitalPinState[Two] = (myEvent.get(myDownEvent) == 0); myDigitalPinState[Two] = (myEvent.get(myDownEvent) == 0);
myDigitalPinState[Three] = (myEvent.get(myLeftEvent) == 0); myDigitalPinState[Three] = (myEvent.get(myLeftEvent) == 0);
myDigitalPinState[Four] = (myEvent.get(myRightEvent) == 0); myDigitalPinState[Four] = (myEvent.get(myRightEvent) == 0);
myDigitalPinState[Six] = (myEvent.get(myFireEvent) == 0); myDigitalPinState[Six] = (myEvent.get(myFireEvent) == 0);
// Axis events (usually generated by the Stelladaptor)
int xaxis = myEvent.get(myXAxisValue);
int yaxis = myEvent.get(myYAxisValue);
if(xaxis > 16384-4096)
{
myDigitalPinState[Four] = false;
// Stelladaptor sends "half moved right" for L+R pushed together
if(xaxis < 16384+4096)
myDigitalPinState[Three] = false;
}
if(xaxis < -16384)
myDigitalPinState[Three] = false;
if(yaxis > 16384-4096)
{
myDigitalPinState[Two] = false;
// Stelladaptor sends "half moved down" for U+D pushed together
if(yaxis < 16384+4096)
myDigitalPinState[One] = false;
}
if(yaxis < -16384)
myDigitalPinState[One] = false;
} }

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Joystick.hxx,v 1.8 2008-02-06 13:45:21 stephena Exp $ // $Id: Joystick.hxx,v 1.9 2008-03-02 19:20:50 stephena Exp $
//============================================================================ //============================================================================
#ifndef JOYSTICK_HXX #ifndef JOYSTICK_HXX
@ -27,7 +27,7 @@
The standard Atari 2600 joystick controller. The standard Atari 2600 joystick controller.
@author Bradford W. Mott @author Bradford W. Mott
@version $Id: Joystick.hxx,v 1.8 2008-02-06 13:45:21 stephena Exp $ @version $Id: Joystick.hxx,v 1.9 2008-03-02 19:20:50 stephena Exp $
*/ */
class Joystick : public Controller class Joystick : public Controller
{ {
@ -55,7 +55,9 @@ class Joystick : public Controller
private: private:
// Pre-compute the events we care about based on given port // Pre-compute the events we care about based on given port
// This will eliminate test for left or right port in update() // This will eliminate test for left or right port in update()
Event::Type myUpEvent, myDownEvent, myLeftEvent, myRightEvent, myFireEvent; Event::Type myUpEvent, myDownEvent, myLeftEvent, myRightEvent,
myXAxisValue, myYAxisValue, myFireEvent;
}; };
#endif #endif

View File

@ -13,62 +13,108 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Paddles.cxx,v 1.11 2008-02-06 13:45:22 stephena Exp $ // $Id: Paddles.cxx,v 1.12 2008-03-02 19:20:50 stephena Exp $
//============================================================================ //============================================================================
#define PADDLE_SENSITIVITY 6
#define TRIGMAX 240
#define TRIGMIN 1
#include "Event.hxx" #include "Event.hxx"
#include "Paddles.hxx" #include "Paddles.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Paddles::Paddles(Jack jack, const Event& event, bool swap) Paddles::Paddles(Jack jack, const Event& event, bool swap)
: Controller(jack, event, Controller::Paddles) : Controller(jack, event, Controller::Paddles),
myMouseBaseX(-1),
myMouseBaseY(-1)
{ {
// Swap the paddle events, from paddle 0 <=> 1 and paddle 2 <=> 3 // Swap the paddle events, from paddle 0 <=> 1 and paddle 2 <=> 3
// Also consider whether this is the left or right port // Also consider whether this is the left or right port
if(myJack == Left) if(myJack == Left)
{ {
if(swap) if(!swap)
{ {
myP0ResEvent = Event::PaddleZeroResistance; myP0AxisValue = Event::SALeftAxis0Value;
myP0DecEvent1 = Event::PaddleZeroDecrease;
myP0DecEvent2 = Event::JoystickZeroRight;
myP0IncEvent1 = Event::PaddleZeroIncrease;
myP0IncEvent2 = Event::JoystickZeroLeft;
myP0FireEvent1 = Event::PaddleZeroFire; myP0FireEvent1 = Event::PaddleZeroFire;
myP0FireEvent2 = Event::JoystickZeroFire1; myP0FireEvent2 = Event::JoystickZeroFire1;
myP1ResEvent = Event::PaddleOneResistance; myP1AxisValue = Event::SALeftAxis1Value;
myP1DecEvent1 = Event::PaddleOneDecrease;
myP1DecEvent2 = Event::JoystickZeroUp;
myP1IncEvent1 = Event::PaddleOneIncrease;
myP1IncEvent2 = Event::JoystickZeroDown;
myP1FireEvent1 = Event::PaddleOneFire; myP1FireEvent1 = Event::PaddleOneFire;
myP1FireEvent2 = Event::JoystickZeroFire3; myP1FireEvent2 = Event::JoystickZeroFire3;
myMouseBaseX = 0;
} }
else else
{ {
myP0ResEvent = Event::PaddleOneResistance; myP0AxisValue = Event::SALeftAxis1Value;
myP0DecEvent1 = Event::PaddleOneDecrease;
myP0DecEvent2 = Event::JoystickZeroUp;
myP0IncEvent1 = Event::PaddleOneIncrease;
myP0IncEvent2 = Event::JoystickZeroDown;
myP0FireEvent1 = Event::PaddleOneFire; myP0FireEvent1 = Event::PaddleOneFire;
myP0FireEvent2 = Event::JoystickZeroFire3; myP0FireEvent2 = Event::JoystickZeroFire3;
myP1ResEvent = Event::PaddleZeroResistance; myP1AxisValue = Event::SALeftAxis0Value;
myP1DecEvent1 = Event::PaddleZeroDecrease;
myP1DecEvent2 = Event::JoystickZeroRight;
myP1IncEvent1 = Event::PaddleZeroIncrease;
myP1IncEvent2 = Event::JoystickZeroLeft;
myP1FireEvent1 = Event::PaddleZeroFire; myP1FireEvent1 = Event::PaddleZeroFire;
myP1FireEvent2 = Event::JoystickZeroFire1; myP1FireEvent2 = Event::JoystickZeroFire1;
myMouseBaseX = 1;
} }
} }
else else
{ {
if(swap) if(!swap)
{ {
myP0ResEvent = Event::PaddleTwoResistance; myP0AxisValue = Event::SARightAxis0Value;
myP0DecEvent1 = Event::PaddleTwoDecrease;
myP0DecEvent2 = Event::JoystickOneRight;
myP0IncEvent1 = Event::PaddleTwoIncrease;
myP0IncEvent2 = Event::JoystickOneLeft;
myP0FireEvent1 = Event::PaddleTwoFire; myP0FireEvent1 = Event::PaddleTwoFire;
myP0FireEvent2 = Event::JoystickOneFire1; myP0FireEvent2 = Event::JoystickOneFire1;
myP1ResEvent = Event::PaddleThreeResistance; myP1AxisValue = Event::SARightAxis1Value;
myP1DecEvent1 = Event::PaddleThreeDecrease;
myP1DecEvent2 = Event::JoystickOneUp;
myP1IncEvent1 = Event::PaddleThreeIncrease;
myP1IncEvent2 = Event::JoystickOneDown;
myP1FireEvent1 = Event::PaddleThreeFire; myP1FireEvent1 = Event::PaddleThreeFire;
myP1FireEvent2 = Event::JoystickOneFire3; myP1FireEvent2 = Event::JoystickOneFire3;
myMouseBaseX = 2;
} }
else else
{ {
myP0ResEvent = Event::PaddleThreeResistance; myP0AxisValue = Event::SARightAxis1Value;
myP0DecEvent1 = Event::PaddleThreeDecrease;
myP0DecEvent2 = Event::JoystickOneUp;
myP0IncEvent1 = Event::PaddleThreeIncrease;
myP0IncEvent2 = Event::JoystickOneDown;
myP0FireEvent1 = Event::PaddleThreeFire; myP0FireEvent1 = Event::PaddleThreeFire;
myP0FireEvent2 = Event::JoystickOneFire3; myP0FireEvent2 = Event::JoystickOneFire3;
myP1ResEvent = Event::PaddleTwoResistance; myP1AxisValue = Event::SARightAxis0Value;
myP1DecEvent1 = Event::PaddleTwoDecrease;
myP1DecEvent2 = Event::JoystickOneRight;
myP1IncEvent1 = Event::PaddleTwoIncrease;
myP1IncEvent2 = Event::JoystickOneLeft;
myP1FireEvent1 = Event::PaddleTwoFire; myP1FireEvent1 = Event::PaddleTwoFire;
myP1FireEvent2 = Event::JoystickOneFire1; myP1FireEvent2 = Event::JoystickOneFire1;
myMouseBaseX = 3;
} }
} }
@ -76,6 +122,13 @@ Paddles::Paddles(Jack jack, const Event& event, bool swap)
myDigitalPinState[One] = myDigitalPinState[One] =
myDigitalPinState[Two] = myDigitalPinState[Two] =
myDigitalPinState[Six] = true; myDigitalPinState[Six] = true;
// Digital emulation of analog paddle movement
myKeyRepeat0 = myPaddleRepeat0 = myKeyRepeat1 = myPaddleRepeat1 = 0;
myCharge[0] = myCharge[1] =
myLastCharge[0] = myLastCharge[1] = 120; // half of maximum paddle charge
myLeftMotion[0] = myLeftMotion[1] = 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -86,11 +139,168 @@ Paddles::~Paddles()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Paddles::update() void Paddles::update()
{ {
// Digital events (from keyboard or joystick hats & buttons)
myDigitalPinState[Three] = myDigitalPinState[Three] =
(myEvent.get(myP0FireEvent1) == 0 && myEvent.get(myP0FireEvent2) == 0);
myDigitalPinState[Four] =
(myEvent.get(myP1FireEvent1) == 0 && myEvent.get(myP1FireEvent2) == 0); (myEvent.get(myP1FireEvent1) == 0 && myEvent.get(myP1FireEvent2) == 0);
myDigitalPinState[Four] =
(myEvent.get(myP0FireEvent1) == 0 && myEvent.get(myP0FireEvent2) == 0);
myAnalogPinValue[Five] = myEvent.get(myP0ResEvent); if(myKeyRepeat0)
myAnalogPinValue[Nine] = myEvent.get(myP1ResEvent); {
myPaddleRepeat0++;
if(myPaddleRepeat0 > PADDLE_SENSITIVITY) myPaddleRepeat0 = 2;
}
if(myKeyRepeat1)
{
myPaddleRepeat1++;
if(myPaddleRepeat1 > PADDLE_SENSITIVITY) myPaddleRepeat1 = 2;
}
myKeyRepeat0 = 0;
myKeyRepeat1 = 0;
if(myEvent.get(myP0DecEvent1) || myEvent.get(myP0DecEvent2))
{
myKeyRepeat0 = 1;
if(myCharge[0] > (myPaddleRepeat0 >> 1))
myCharge[0] -= (myPaddleRepeat0 >> 1);
}
if(myEvent.get(myP0IncEvent1) || myEvent.get(myP0IncEvent2))
{
myKeyRepeat0 = 1;
if((myCharge[0] + (myPaddleRepeat0 >> 1)) < TRIGMAX)
myCharge[0] += (myPaddleRepeat0 >> 1);
}
if(myEvent.get(myP1DecEvent1) || myEvent.get(myP1DecEvent2))
{
myKeyRepeat1 = 1;
if(myCharge[1] > (myPaddleRepeat1 >> 1))
myCharge[1] -= (myPaddleRepeat1 >> 1);
}
if(myEvent.get(myP1IncEvent1) || myEvent.get(myP1IncEvent2))
{
myKeyRepeat1 = 1;
if((myCharge[1] + (myPaddleRepeat1 >> 1)) < TRIGMAX)
myCharge[1] += (myPaddleRepeat1 >> 1);
}
// Mouse events
if(myMouseBaseX == 0 || myMouseBaseX == 1)
{
/* FIXME
if (MPdirection & 0x01) Charge[MouseBaseX] = Charge[MouseBaseX] + srv_micky_x;
else Charge [MouseBaseX] = Charge[MouseBaseX] - srv_micky_x;
*/
myCharge[myMouseBaseX] =
myCharge[myMouseBaseX] - myEvent.get(Event::MouseAxisXValue);
if(myCharge[myMouseBaseX] < TRIGMIN) myCharge[myMouseBaseX] = TRIGMIN;
if(myCharge[myMouseBaseX] > TRIGMAX) myCharge[myMouseBaseX] = TRIGMAX;
}
// Axis events (possibly use analog values)
int xaxis = myEvent.get(myP0AxisValue);
int yaxis = myEvent.get(myP1AxisValue);
// Filter out jitter by not allowing rapid direction changes
int charge0 = ((32767 - xaxis) >> 8) & 0xff;
if(charge0 - myLastCharge[0] > 0) // we are moving left
{
if(!myLeftMotion[0]) // moving right before?
{
if(charge0 - myLastCharge[0] <= 4)
{
myCharge[0] = myLastCharge[0];
}
else
{
myCharge[0] = (charge0 + myLastCharge[0]) >> 1;
myLastCharge[0] = charge0;
myLeftMotion[0] = 1;
}
}
else
{
myCharge[0] = (charge0 + myLastCharge[0]) >> 1;
myLastCharge[0] = charge0;
}
}
// Filter out jitter by not allowing rapid direction changes
else if(charge0 - myLastCharge[0] < 0) // we are moving right
{
if(myLeftMotion[0]) // moving left before?
{
if(myLastCharge[0] - charge0 <= 4)
{
myCharge[0] = myLastCharge[0];
}
else
{
myCharge[0] = (charge0 + myLastCharge[0]) >> 1;
myLastCharge[0] = charge0;
myLeftMotion[0] = 0;
}
}
else
{
myCharge[0] = (charge0 + myLastCharge[0]) >> 1;
myLastCharge[0] = charge0;
}
}
// Filter out jitter by not allowing rapid direction changes
int charge1 = ((32767 - yaxis) >> 8) & 0xff;
if(charge1 - myLastCharge[1] > 0) // we are moving left
{
if(!myLeftMotion[1]) // moving right before?
{
if(charge1 - myLastCharge[1] <= 4)
{
myCharge[1] = myLastCharge[1];
}
else
{
myCharge[1] = (charge1 + myLastCharge[1]) >> 1;
myLastCharge[1] = charge1;
myLeftMotion[1] = 1;
}
}
else
{
myCharge[1] = (charge1 + myLastCharge[1]) >> 1;
myLastCharge[1] = charge1;
}
}
// Filter out jitter by not allowing rapid direction changes
else if(charge1 - myLastCharge[1] < 0) // we are moving right
{
if(myLeftMotion[1]) // moving left before?
{
if(myLastCharge[1] - charge1 <= 4)
{
myCharge[1] = myLastCharge[1];
}
else
{
myCharge[1] = (charge1 + myLastCharge[1]) >> 1;
myLastCharge[1] = charge1;
myLeftMotion[1] = 0;
}
}
else
{
myCharge[1] = (charge1 + myLastCharge[1]) >> 1;
myLastCharge[1] = charge1;
}
}
/* FIXME
if(PaddleAdjust)
{
myCharge[0] = (myCharge[0] >> 1) + PaddleAdjust;
myCharge[1] = (myCharge[1] >> 1) + PaddleAdjust;
}
*/
myAnalogPinValue[Five] = (Int32)(1000000 * (myCharge[1] / 255.0));
myAnalogPinValue[Nine] = (Int32)(1000000 * (myCharge[0] / 255.0));
} }

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Paddles.hxx,v 1.10 2008-02-06 13:45:22 stephena Exp $ // $Id: Paddles.hxx,v 1.11 2008-03-02 19:20:50 stephena Exp $
//============================================================================ //============================================================================
#ifndef PADDLES_HXX #ifndef PADDLES_HXX
@ -27,7 +27,7 @@
The standard Atari 2600 pair of paddle controllers. The standard Atari 2600 pair of paddle controllers.
@author Bradford W. Mott @author Bradford W. Mott
@version $Id: Paddles.hxx,v 1.10 2008-02-06 13:45:22 stephena Exp $ @version $Id: Paddles.hxx,v 1.11 2008-03-02 19:20:50 stephena Exp $
*/ */
class Paddles : public Controller class Paddles : public Controller
{ {
@ -56,8 +56,21 @@ class Paddles : public Controller
private: private:
// Pre-compute the events we care about based on given port // Pre-compute the events we care about based on given port
// This will eliminate test for left or right port in update() // This will eliminate test for left or right port in update()
Event::Type myP0ResEvent, myP1ResEvent, myP0FireEvent1, myP0FireEvent2, Event::Type myP0AxisValue, myP1AxisValue,
myP1FireEvent1, myP1FireEvent2; myP0DecEvent1, myP0DecEvent2, myP0IncEvent1, myP0IncEvent2,
myP1DecEvent1, myP1DecEvent2, myP1IncEvent1, myP1IncEvent2,
myP0FireEvent1, myP0FireEvent2, myP1FireEvent1, myP1FireEvent2;
int myKeyRepeat0;
int myPaddleRepeat0;
int myKeyRepeat1;
int myPaddleRepeat1;
int myCharge[2];
int myLastCharge[2];
int myLeftMotion[2];
int myMouseBaseX, myMouseBaseY;
}; };
#endif #endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: DialogContainer.cxx,v 1.39 2008-02-06 13:45:23 stephena Exp $ // $Id: DialogContainer.cxx,v 1.40 2008-03-02 19:20:50 stephena Exp $
//============================================================================ //============================================================================
#include "OSystem.hxx" #include "OSystem.hxx"
@ -282,6 +282,8 @@ void DialogContainer::handleJoyEvent(int stick, int button, uInt8 state)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value) void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value)
{ {
// FIXME - analog axis events cause autofire to inadvertently come on and not go off
if(myDialogStack.empty()) if(myDialogStack.empty())
return; return;