derived Genesis and Booster from Joystick controller class

This commit is contained in:
thrust26 2021-01-30 11:25:51 +01:00
parent b6e0b8fdcd
commit a7bde4603e
6 changed files with 148 additions and 282 deletions

View File

@ -15,36 +15,21 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "Event.hxx"
#include "Booster.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BoosterGrip::BoosterGrip(Jack jack, const Event& event, const System& system)
: Controller(jack, event, system, Controller::Type::BoosterGrip)
: Joystick(jack, event, system, Controller::Type::BoosterGrip)
{
if(myJack == Jack::Left)
{
myUpEvent = Event::JoystickZeroUp;
myDownEvent = Event::JoystickZeroDown;
myLeftEvent = Event::JoystickZeroLeft;
myRightEvent = Event::JoystickZeroRight;
myFireEvent = Event::JoystickZeroFire;
myTriggerEvent = Event::JoystickZeroFire5;
myBoosterEvent = Event::JoystickZeroFire9;
myXAxisValue = Event::PaddleZeroAnalog;
myYAxisValue = Event::PaddleOneAnalog;
}
else
{
myUpEvent = Event::JoystickOneUp;
myDownEvent = Event::JoystickOneDown;
myLeftEvent = Event::JoystickOneLeft;
myRightEvent = Event::JoystickOneRight;
myFireEvent = Event::JoystickOneFire;
myTriggerEvent = Event::JoystickOneFire5;
myBoosterEvent = Event::JoystickOneFire9;
myXAxisValue = Event::PaddleTwoAnalog;
myYAxisValue = Event::PaddleThreeAnalog;
}
setPin(AnalogPin::Five, MAX_RESISTANCE);
@ -52,98 +37,17 @@ BoosterGrip::BoosterGrip(Jack jack, const Event& event, const System& system)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void BoosterGrip::update()
void BoosterGrip::updateButtons()
{
// Digital events (from keyboard or joystick hats & buttons)
setPin(DigitalPin::One, myEvent.get(myUpEvent) == 0);
setPin(DigitalPin::Two, myEvent.get(myDownEvent) == 0);
setPin(DigitalPin::Three, myEvent.get(myLeftEvent) == 0);
setPin(DigitalPin::Four, myEvent.get(myRightEvent) == 0);
bool firePressed = myEvent.get(myFireEvent) != 0;
// The CBS Booster-grip has two more buttons on it. These buttons are
// connected to the inputs usually used by paddles.
setPin(
AnalogPin::Five,
(myEvent.get(myTriggerEvent) != 0) ? MIN_RESISTANCE : MAX_RESISTANCE
);
setPin(
AnalogPin::Nine,
(myEvent.get(myBoosterEvent) != 0) ? MIN_RESISTANCE : MAX_RESISTANCE
);
bool triggerPressed = myEvent.get(myTriggerEvent) != 0;
bool boosterPressed = myEvent.get(myBoosterEvent) != 0;
// Axis events (usually generated by the Stelladaptor)
int xaxis = myEvent.get(myXAxisValue);
int yaxis = myEvent.get(myYAxisValue);
if(xaxis > 16384-4096)
{
setPin(DigitalPin::Four, false);
// Stelladaptor sends "half moved right" for L+R pushed together
if(xaxis < 16384+4096)
setPin(DigitalPin::Three, false);
}
else if(xaxis < -16384)
setPin(DigitalPin::Three, false);
if(yaxis > 16384-4096)
{
setPin(DigitalPin::Two, false);
// Stelladaptor sends "half moved down" for U+D pushed together
if(yaxis < 16384+4096)
setPin(DigitalPin::One, false);
}
else if(yaxis < -16384)
setPin(DigitalPin::One, false);
updateMouseButtons(firePressed, boosterPressed);
// Mouse motion and button events
if(myControlID > -1)
{
// The following code was taken from z26
#define MJ_Threshold 2
int mousex = myEvent.get(Event::MouseAxisXMove),
mousey = myEvent.get(Event::MouseAxisYMove);
if(mousex || mousey)
{
if((!(abs(mousey) > abs(mousex) << 1)) && (abs(mousex) >= MJ_Threshold))
{
if(mousex < 0)
setPin(DigitalPin::Three, false);
else if (mousex > 0)
setPin(DigitalPin::Four, false);
}
if((!(abs(mousex) > abs(mousey) << 1)) && (abs(mousey) >= MJ_Threshold))
{
if(mousey < 0)
setPin(DigitalPin::One, false);
else if(mousey > 0)
setPin(DigitalPin::Two, false);
}
}
// Get mouse button state
firePressed = firePressed
|| myEvent.get(Event::MouseButtonLeftValue);
if(myEvent.get(Event::MouseButtonRightValue))
setPin(AnalogPin::Nine, MIN_RESISTANCE);
}
setPin(DigitalPin::Six, !getAutoFireState(firePressed));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool BoosterGrip::setMouseControl(
Controller::Type xtype, int xid, Controller::Type ytype, int yid)
{
// Currently, the booster-grip takes full control of the mouse, using both
// axes for its two degrees of movement, and the left/right buttons for
// fire and booster, respectively
if(xtype == Controller::Type::BoosterGrip && ytype == Controller::Type::BoosterGrip &&
xid == yid)
{
myControlID = ((myJack == Jack::Left && xid == 0) ||
(myJack == Jack::Right && xid == 1)
) ? xid : -1;
}
else
myControlID = -1;
return true;
setPin(AnalogPin::Five, triggerPressed ? MIN_RESISTANCE : MAX_RESISTANCE);
setPin(AnalogPin::Nine, boosterPressed ? MIN_RESISTANCE : MAX_RESISTANCE);
}

View File

@ -18,8 +18,7 @@
#ifndef BOOSTERGRIP_HXX
#define BOOSTERGRIP_HXX
#include "Control.hxx"
#include "Event.hxx"
#include "Joystick.hxx"
/**
The standard Atari 2600 joystick controller fitted with the
@ -28,7 +27,7 @@
@author Bradford W. Mott
*/
class BoosterGrip : public Controller
class BoosterGrip : public Joystick
{
public:
/**
@ -42,45 +41,21 @@ class BoosterGrip : public Controller
~BoosterGrip() override = default;
public:
/**
Update the entire digital and analog pin state according to the
events currently set.
*/
void update() override;
/**
Returns the name of this controller.
*/
string name() const override { return "BoosterGrip"; }
private:
/**
Determines how this controller will treat values received from the
X/Y axis and left/right buttons of the mouse. Since not all controllers
use the mouse the same way (or at all), it's up to the specific class to
decide how to use this data.
In the current implementation, the left button is tied to the X axis,
and the right one tied to the Y axis.
@param xtype The controller to use for x-axis data
@param xid The controller ID to use for x-axis data (-1 for no id)
@param ytype The controller to use for y-axis data
@param yid The controller ID to use for y-axis data (-1 for no id)
@return Whether the controller supports using the mouse
Update the button pin states.
*/
bool setMouseControl(
Controller::Type xtype, int xid, Controller::Type ytype, int yid) override;
void updateButtons() override;
private:
// Pre-compute the events we care about based on given port
// This will eliminate test for left or right port in update()
Event::Type myUpEvent, myDownEvent, myLeftEvent, myRightEvent,
myFireEvent, myBoosterEvent, myTriggerEvent,
myXAxisValue, myYAxisValue;
// Controller to emulate in normal mouse axis mode
int myControlID{-1};
Event::Type myBoosterEvent, myTriggerEvent;
private:
// Following constructors and assignment operators not supported

View File

@ -15,102 +15,31 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "Event.hxx"
#include "Genesis.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Genesis::Genesis(Jack jack, const Event& event, const System& system)
: Controller(jack, event, system, Controller::Type::Genesis)
: Joystick(jack, event, system, Controller::Type::Genesis)
{
if(myJack == Jack::Left)
{
myUpEvent = Event::JoystickZeroUp;
myDownEvent = Event::JoystickZeroDown;
myLeftEvent = Event::JoystickZeroLeft;
myRightEvent = Event::JoystickZeroRight;
myFire1Event = Event::JoystickZeroFire;
myFire2Event = Event::JoystickZeroFire5;
}
myButtonCEvent = Event::JoystickZeroFire5;
else
{
myUpEvent = Event::JoystickOneUp;
myDownEvent = Event::JoystickOneDown;
myLeftEvent = Event::JoystickOneLeft;
myRightEvent = Event::JoystickOneRight;
myFire1Event = Event::JoystickOneFire;
myFire2Event = Event::JoystickOneFire5;
}
myButtonCEvent = Event::JoystickOneFire5;
setPin(AnalogPin::Five, MIN_RESISTANCE);
setPin(AnalogPin::Nine, MIN_RESISTANCE);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Genesis::update()
void Genesis::updateButtons()
{
// Digital events (from keyboard or joystick hats & buttons)
setPin(DigitalPin::One, myEvent.get(myUpEvent) == 0);
setPin(DigitalPin::Two, myEvent.get(myDownEvent) == 0);
setPin(DigitalPin::Three, myEvent.get(myLeftEvent) == 0);
setPin(DigitalPin::Four, myEvent.get(myRightEvent) == 0);
bool firePressed = myEvent.get(myFire1Event) != 0;
bool firePressed = myEvent.get(myFireEvent) != 0;
// The Genesis has one more button (C) that can be read by the 2600
// However, it seems to work opposite to the BoosterGrip controller,
// in that the logic is inverted
setPin(AnalogPin::Five,
(myEvent.get(myFire2Event) == 0) ? MIN_RESISTANCE : MAX_RESISTANCE
);
bool buttonCPressed = myEvent.get(myButtonCEvent) != 0;
// Mouse motion and button events
if(myControlID > -1)
{
// The following code was taken from z26
#define MJ_Threshold 2
int mousex = myEvent.get(Event::MouseAxisXMove),
mousey = myEvent.get(Event::MouseAxisYMove);
if(mousex || mousey)
{
if((!(abs(mousey) > abs(mousex) << 1)) && (abs(mousex) >= MJ_Threshold))
{
if(mousex < 0)
setPin(DigitalPin::Three, false);
else if(mousex > 0)
setPin(DigitalPin::Four, false);
}
updateMouseButtons(firePressed, buttonCPressed);
if((!(abs(mousex) > abs(mousey) << 1)) && (abs(mousey) >= MJ_Threshold))
{
if(mousey < 0)
setPin(DigitalPin::One, false);
else if(mousey > 0)
setPin(DigitalPin::Two, false);
}
}
// Get mouse button state
firePressed = firePressed
|| myEvent.get(Event::MouseButtonLeftValue);
if(myEvent.get(Event::MouseButtonRightValue))
setPin(AnalogPin::Five, MAX_RESISTANCE);
}
setPin(DigitalPin::Six, !getAutoFireState(firePressed));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Genesis::setMouseControl(
Controller::Type xtype, int xid, Controller::Type ytype, int yid)
{
// Currently, the Genesis controller takes full control of the mouse, using
// both axes for its two degrees of movement, and the left/right buttons for
// 'B' and 'C', respectively
if(xtype == Controller::Type::Genesis && ytype == Controller::Type::Genesis && xid == yid)
{
myControlID = ((myJack == Jack::Left && xid == 0) ||
(myJack == Jack::Right && xid == 1)
) ? xid : -1;
}
else
myControlID = -1;
return true;
setPin(AnalogPin::Five, buttonCPressed ? MAX_RESISTANCE : MIN_RESISTANCE);
}

View File

@ -18,9 +18,7 @@
#ifndef GENESIS_HXX
#define GENESIS_HXX
#include "bspf.hxx"
#include "Control.hxx"
#include "Event.hxx"
#include "Joystick.hxx"
/**
The standard Sega Genesis controller works with the 2600 console for
@ -30,7 +28,7 @@
@author Stephen Anthony
*/
class Genesis : public Controller
class Genesis : public Joystick
{
public:
/**
@ -44,44 +42,21 @@ class Genesis : public Controller
~Genesis() override = default;
public:
/**
Update the entire digital and analog pin state according to the
events currently set.
*/
void update() override;
/**
Returns the name of this controller.
*/
string name() const override { return "Genesis"; }
private:
/**
Determines how this controller will treat values received from the
X/Y axis and left/right buttons of the mouse. Since not all controllers
use the mouse the same way (or at all), it's up to the specific class to
decide how to use this data.
In the current implementation, the left button is tied to the X axis,
and the right one tied to the Y axis.
@param xtype The controller to use for x-axis data
@param xid The controller ID to use for x-axis data (-1 for no id)
@param ytype The controller to use for y-axis data
@param yid The controller ID to use for y-axis data (-1 for no id)
@return Whether the controller supports using the mouse
Update the button pin states.
*/
bool setMouseControl(
Controller::Type xtype, int xid, Controller::Type ytype, int yid) override;
void updateButtons() override;
private:
// Pre-compute the events we care about based on given port
// This will eliminate test for left or right port in update()
Event::Type myUpEvent, myDownEvent, myLeftEvent, myRightEvent,
myFire1Event, myFire2Event;
// Controller to emulate in normal mouse axis mode
int myControlID{-1};
Event::Type myButtonCEvent;
private:
// Following constructors and assignment operators not supported

View File

@ -15,89 +15,133 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "Event.hxx"
#include "Joystick.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Joystick::Joystick(Jack jack, const Event& event, const System& system, bool altmap)
: Controller(jack, event, system, Controller::Type::Joystick)
: Joystick(jack, event, system, Controller::Type::Joystick, altmap)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Joystick::Joystick(Jack jack, const Event& event, const System& system,
Controller::Type type, bool altmap)
: Controller(jack, event, system, type)
{
if(myJack == Jack::Left)
{
if(!altmap)
{
myUpEvent = Event::JoystickZeroUp;
myDownEvent = Event::JoystickZeroDown;
myLeftEvent = Event::JoystickZeroLeft;
myUpEvent = Event::JoystickZeroUp;
myDownEvent = Event::JoystickZeroDown;
myLeftEvent = Event::JoystickZeroLeft;
myRightEvent = Event::JoystickZeroRight;
myFireEvent = Event::JoystickZeroFire;
myFireEvent = Event::JoystickZeroFire;
}
else
{
myUpEvent = Event::JoystickTwoUp;
myDownEvent = Event::JoystickTwoDown;
myLeftEvent = Event::JoystickTwoLeft;
myUpEvent = Event::JoystickTwoUp;
myDownEvent = Event::JoystickTwoDown;
myLeftEvent = Event::JoystickTwoLeft;
myRightEvent = Event::JoystickTwoRight;
myFireEvent = Event::JoystickTwoFire;
myFireEvent = Event::JoystickTwoFire;
}
myXAxisValue = Event::PaddleZeroAnalog;
myYAxisValue = Event::PaddleOneAnalog;
myXAxisValue = Event::PaddleZeroAnalog; // TODO
myYAxisValue = Event::PaddleOneAnalog; // TODO
}
else
{
if(!altmap)
{
myUpEvent = Event::JoystickOneUp;
myDownEvent = Event::JoystickOneDown;
myLeftEvent = Event::JoystickOneLeft;
myUpEvent = Event::JoystickOneUp;
myDownEvent = Event::JoystickOneDown;
myLeftEvent = Event::JoystickOneLeft;
myRightEvent = Event::JoystickOneRight;
myFireEvent = Event::JoystickOneFire;
myFireEvent = Event::JoystickOneFire;
}
else
{
myUpEvent = Event::JoystickThreeUp;
myDownEvent = Event::JoystickThreeDown;
myLeftEvent = Event::JoystickThreeLeft;
myUpEvent = Event::JoystickThreeUp;
myDownEvent = Event::JoystickThreeDown;
myLeftEvent = Event::JoystickThreeLeft;
myRightEvent = Event::JoystickThreeRight;
myFireEvent = Event::JoystickThreeFire;
myFireEvent = Event::JoystickThreeFire;
}
myXAxisValue = Event::PaddleTwoAnalog;
myYAxisValue = Event::PaddleThreeAnalog;
myXAxisValue = Event::PaddleTwoAnalog; // TODO
myYAxisValue = Event::PaddleThreeAnalog; // TODO
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Joystick::update()
{
updateButtons();
updateDigitalAxes();
updateAnalogAxes();
updateMouseAxes();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Joystick::updateButtons()
{
bool firePressed = myEvent.get(myFireEvent) != 0;
// The joystick uses both mouse buttons for the single joystick button
updateMouseButtons(firePressed, firePressed);
setPin(DigitalPin::Six, !getAutoFireState(firePressed));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Joystick::updateMouseButtons(bool& pressedLeft, bool& pressedRight)
{
if(myControlID > -1)
{
pressedLeft |= (myEvent.get(Event::MouseButtonLeftValue) != 0);
pressedRight |= (pressedRight || myEvent.get(Event::MouseButtonRightValue) != 0);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Joystick::updateDigitalAxes()
{
// Digital events (from keyboard or joystick hats & buttons)
setPin(DigitalPin::One, myEvent.get(myUpEvent) == 0);
setPin(DigitalPin::Two, myEvent.get(myDownEvent) == 0);
setPin(DigitalPin::Three, myEvent.get(myLeftEvent) == 0);
setPin(DigitalPin::Four, myEvent.get(myRightEvent) == 0);
bool firePressed = myEvent.get(myFireEvent) != 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Joystick::updateAnalogAxes()
{
// Axis events (usually generated by the Stelladaptor)
int xaxis = myEvent.get(myXAxisValue);
int yaxis = myEvent.get(myYAxisValue);
if(xaxis > 16384-4096)
if(xaxis > 16384 - 4096)
{
setPin(DigitalPin::Four, false);
// Stelladaptor sends "half moved right" for L+R pushed together
if(xaxis < 16384+4096)
if(xaxis < 16384 + 4096)
setPin(DigitalPin::Three, false);
}
else if(xaxis < -16384)
setPin(DigitalPin::Three, false);
if(yaxis > 16384-4096)
if(yaxis > 16384 - 4096)
{
setPin(DigitalPin::Two, false);
// Stelladaptor sends "half moved down" for U+D pushed together
if(yaxis < 16384+4096)
if(yaxis < 16384 + 4096)
setPin(DigitalPin::One, false);
}
else if(yaxis < -16384)
setPin(DigitalPin::One, false);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Joystick::updateMouseAxes()
{
// Mouse motion and button events
if(myControlID > -1)
{
@ -105,6 +149,7 @@ void Joystick::update()
#define MJ_Threshold 2
int mousex = myEvent.get(Event::MouseAxisXMove),
mousey = myEvent.get(Event::MouseAxisYMove);
if(mousex || mousey)
{
if((!(abs(mousey) > abs(mousex) << 1)) && (abs(mousex) >= MJ_Threshold))
@ -123,12 +168,7 @@ void Joystick::update()
setPin(DigitalPin::Two, false);
}
}
// Get mouse button state
firePressed = firePressed
|| myEvent.get(Event::MouseButtonLeftValue)
|| myEvent.get(Event::MouseButtonRightValue);
}
setPin(DigitalPin::Six, !getAutoFireState(firePressed));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -136,9 +176,8 @@ bool Joystick::setMouseControl(
Controller::Type xtype, int xid, Controller::Type ytype, int yid)
{
// Currently, the joystick takes full control of the mouse, using both
// axes for its two degrees of movement, and both mouse buttons for the
// single joystick button
if(xtype == Controller::Type::Joystick && ytype == Controller::Type::Joystick && xid == yid)
// axes for its two degrees of movement
if(xtype == myType && ytype == myType && xid == yid)
{
myControlID = ((myJack == Jack::Left && xid == 0) ||
(myJack == Jack::Right && xid == 1)

View File

@ -18,7 +18,6 @@
#ifndef JOYSTICK_HXX
#define JOYSTICK_HXX
#include "bspf.hxx"
#include "Event.hxx"
#include "Control.hxx"
@ -41,9 +40,23 @@ class Joystick : public Controller
@param system The system using this controller
@param altmap If true, use alternative mapping
*/
Joystick(Jack jack, const Event& event, const System& system, bool altmap = false);
Joystick(Jack jack, const Event& event, const System& system,
bool altmap = false);
~Joystick() override = default;
protected:
/**
Create a new controller plugged into the specified jack
@param jack The jack the controller is plugged into
@param event The event object to use for events
@param system The system using this controller
@param type The controller type
*/
Joystick(Jack jack, const Event& event, const System& system,
Controller::Type type, bool altmap = false);
public:
/**
Update the entire digital and analog pin state according to the
@ -88,17 +101,48 @@ class Joystick : public Controller
static int deadZoneValue(int deadzone);
inline static int deadzone() { return _DEAD_ZONE; }
protected:
/**
Update the button pin states.
*/
virtual void updateButtons();
/**
Update the button states from the mouse button events currently set.
*/
void updateMouseButtons(bool& pressedLeft, bool& pressedRight);
protected:
Event::Type myFireEvent;
private:
// Pre-compute the events we care about based on given port
// This will eliminate test for left or right port in update()
Event::Type myUpEvent, myDownEvent, myLeftEvent, myRightEvent,
myXAxisValue, myYAxisValue, myFireEvent;
myXAxisValue, myYAxisValue;
// Controller to emulate in normal mouse axis mode
int myControlID{-1};
static int _DEAD_ZONE;
private:
/**
Update the axes pin states according to the keyboard
or joystick hats & buttons events currently set.
*/
void updateDigitalAxes();
/**
Update the axes pin states according to the axes value events currently set.
*/
void updateAnalogAxes();
/**
Update the axes pin states according to mouse events currently set.
*/
void updateMouseAxes();
private:
// Following constructors and assignment operators not supported
Joystick() = delete;