Major changes to controller infrastructure.

Basically, separate high-level read/write from low-level set/getPin methods.
This commit is contained in:
Stephen Anthony 2019-03-29 20:47:24 -02:30
parent 39884db86f
commit cfe79ec0b1
56 changed files with 677 additions and 620 deletions

View File

@ -46,7 +46,7 @@ MouseControl::MouseControl(Console& console, const string& mode)
Axis yaxis = Axis(int(m_mode[1]) - '0');
ostringstream msg;
msg << "Mouse X-axis is ";
Controller::Type xtype = Controller::Joystick, ytype = Controller::Joystick;
Controller::Type xtype = Controller::Type::Joystick, ytype = Controller::Type::Joystick;
int xid = -1, yid = -1;
switch(xaxis)
{
@ -54,42 +54,42 @@ MouseControl::MouseControl(Console& console, const string& mode)
msg << "not used";
break;
case Paddle0:
xtype = Controller::Paddles;
xtype = Controller::Type::Paddles;
xid = 0;
msg << "Paddle 0";
break;
case Paddle1:
xtype = Controller::Paddles;
xtype = Controller::Type::Paddles;
xid = 1;
msg << "Paddle 1";
break;
case Paddle2:
xtype = Controller::Paddles;
xtype = Controller::Type::Paddles;
xid = 2;
msg << "Paddle 2";
break;
case Paddle3:
xtype = Controller::Paddles;
xtype = Controller::Type::Paddles;
xid = 3;
msg << "Paddle 3";
break;
case Driving0:
xtype = Controller::Driving;
xtype = Controller::Type::Driving;
xid = 0;
msg << "Driving 0";
break;
case Driving1:
xtype = Controller::Driving;
xtype = Controller::Type::Driving;
xid = 1;
msg << "Driving 1";
break;
case MindLink0:
xtype = Controller::MindLink;
xtype = Controller::Type::MindLink;
xid = 0;
msg << "MindLink 0";
break;
case MindLink1:
xtype = Controller::MindLink;
xtype = Controller::Type::MindLink;
xid = 1;
msg << "MindLink 1";
break;
@ -101,42 +101,42 @@ MouseControl::MouseControl(Console& console, const string& mode)
msg << "not used";
break;
case Paddle0:
ytype = Controller::Paddles;
ytype = Controller::Type::Paddles;
yid = 0;
msg << "Paddle 0";
break;
case Paddle1:
ytype = Controller::Paddles;
ytype = Controller::Type::Paddles;
yid = 1;
msg << "Paddle 1";
break;
case Paddle2:
ytype = Controller::Paddles;
ytype = Controller::Type::Paddles;
yid = 2;
msg << "Paddle 2";
break;
case Paddle3:
ytype = Controller::Paddles;
ytype = Controller::Type::Paddles;
yid = 3;
msg << "Paddle 3";
break;
case Driving0:
ytype = Controller::Driving;
ytype = Controller::Type::Driving;
yid = 0;
msg << "Driving 0";
break;
case Driving1:
ytype = Controller::Driving;
ytype = Controller::Type::Driving;
yid = 1;
msg << "Driving 1";
break;
case MindLink0:
ytype = Controller::MindLink;
ytype = Controller::Type::MindLink;
yid = 0;
msg << "MindLink 0";
break;
case MindLink1:
ytype = Controller::MindLink;
ytype = Controller::Type::MindLink;
yid = 1;
msg << "MindLink 1";
break;
@ -192,7 +192,7 @@ void MouseControl::addLeftControllerModes(bool noswap)
{
if(controllerSupportsMouse(myLeftController))
{
if(myLeftController.type() == Controller::Paddles)
if(myLeftController.type() == Controller::Type::Paddles)
{
if(noswap) addPaddleModes(0, 1, 0, 1);
else addPaddleModes(2, 3, 0, 1);
@ -213,7 +213,7 @@ void MouseControl::addRightControllerModes(bool noswap)
{
if(controllerSupportsMouse(myRightController))
{
if(myRightController.type() == Controller::Paddles)
if(myRightController.type() == Controller::Type::Paddles)
{
if(noswap) addPaddleModes(2, 3, 2, 3);
else addPaddleModes(0, 1, 2, 3);
@ -232,7 +232,7 @@ void MouseControl::addRightControllerModes(bool noswap)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void MouseControl::addPaddleModes(int lport, int rport, int lname, int rname)
{
Controller::Type type = Controller::Paddles;
Controller::Type type = Controller::Type::Paddles;
ostringstream msg;
msg << "Mouse is Paddle " << lname << " controller";
MouseMode mode0(type, lport, type, lport, msg.str());
@ -260,5 +260,5 @@ bool MouseControl::controllerSupportsMouse(Controller& controller)
// We can pass in dummy values here, since the controllers will be
// initialized by a call to next() once the system is up and running
return controller.setMouseControl(
Controller::Joystick, -1, Controller::Joystick, -1);
Controller::Type::Joystick, -1, Controller::Type::Joystick, -1);
}

View File

@ -81,8 +81,8 @@ class MouseControl
string message;
explicit MouseMode(const string& msg = "")
: xtype(Controller::Joystick),
ytype(Controller::Joystick),
: xtype(Controller::Type::Joystick),
ytype(Controller::Type::Joystick),
xid(-1),
yid(-1),
message(msg) { }
@ -97,8 +97,8 @@ class MouseControl
friend ostream& operator<<(ostream& os, const MouseMode& mm)
{
os << "xtype=" << mm.xtype << ", xid=" << mm.xid
<< ", ytype=" << mm.ytype << ", yid=" << mm.yid
os << "xtype=" << int(mm.xtype) << ", xid=" << mm.xid
<< ", ytype=" << int(mm.ytype) << ", yid=" << mm.yid
<< ", msg=" << mm.message;
return os;
}

View File

@ -631,7 +631,7 @@ void PhysicalJoystickHandler::handleBtnEvent(int stick, int button, bool pressed
{
switch(myOSystem.console().leftController().type())
{
case Controller::Keyboard:
case Controller::Type::Keyboard:
if(button < 12) myEvent.set(SA_Key[j->type-4][button], pressed ? 1 : 0);
break;
default:
@ -639,7 +639,7 @@ void PhysicalJoystickHandler::handleBtnEvent(int stick, int button, bool pressed
}
switch(myOSystem.console().rightController().type())
{
case Controller::Keyboard:
case Controller::Type::Keyboard:
if(button < 12) myEvent.set(SA_Key[j->type-4][button], pressed ? 1 : 0);
break;
default:

View File

@ -70,9 +70,9 @@ void StateManager::toggleRecordMode()
// normal, and those states files wouldn't be compatible with normal
// controllers.
myMovieWriter.putString(
myOSystem.console().controller(Controller::Left).name());
myOSystem.console().controller(Controller::Jack::Left).name());
myMovieWriter.putString(
myOSystem.console().controller(Controller::Right).name());
myOSystem.console().controller(Controller::Jack::Right).name());
// If we get this far, we're really in movie record mode
myActiveMode = kMovieRecordMode;
@ -112,8 +112,8 @@ void StateManager::toggleRecordMode()
const string& left = myMovieReader.getString();
const string& right = myMovieReader.getString();
if(left != myOSystem.console().controller(Controller::Left).name() ||
right != myOSystem.console().controller(Controller::Right).name())
if(left != myOSystem.console().controller(Controller::Jack::Left).name() ||
right != myOSystem.console().controller(Controller::Jack::Right).name())
return false;
// If we get this far, we're really in movie record mode
@ -184,14 +184,14 @@ void StateManager::update()
#if 0
case Mode::MovieRecord:
myOSystem.console().controller(Controller::Left).save(myMovieWriter);
myOSystem.console().controller(Controller::Right).save(myMovieWriter);
myOSystem.console().controller(Controller::Jack::Left).save(myMovieWriter);
myOSystem.console().controller(Controller::Jack::Right).save(myMovieWriter);
myOSystem.console().switches().save(myMovieWriter);
break;
case Mode::MoviePlayback:
myOSystem.console().controller(Controller::Left).load(myMovieReader);
myOSystem.console().controller(Controller::Right).load(myMovieReader);
myOSystem.console().controller(Controller::Jack::Left).load(myMovieReader);
myOSystem.console().controller(Controller::Jack::Right).load(myMovieReader);
myOSystem.console().switches().load(myMovieReader);
break;
#endif

View File

@ -22,6 +22,7 @@
#include "CartDebug.hxx"
#include "CpuDebug.hxx"
#include "RiotDebug.hxx"
#include "ControlLowLevel.hxx"
#include "TIADebug.hxx"
#include "TiaOutputWidget.hxx"
#include "DebuggerParser.hxx"
@ -1270,110 +1271,110 @@ void DebuggerParser::executeHelp()
// "joy0up"
void DebuggerParser::executeJoy0Up()
{
Controller& controller = debugger.riotDebug().controller(Controller::Left);
ControllerLowLevel lport(debugger.myOSystem.console().leftController());
if(argCount == 0)
controller.set(Controller::One, !controller.read(Controller::One));
lport.togglePin(Controller::DigitalPin::One);
else if(argCount == 1)
controller.set(Controller::One, args[0] != 0);
lport.setPin(Controller::DigitalPin::One, args[0] != 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "joy0down"
void DebuggerParser::executeJoy0Down()
{
Controller& controller = debugger.riotDebug().controller(Controller::Left);
ControllerLowLevel lport(debugger.myOSystem.console().leftController());
if(argCount == 0)
controller.set(Controller::Two, !controller.read(Controller::Two));
lport.togglePin(Controller::DigitalPin::Two);
else if(argCount == 1)
controller.set(Controller::Two, args[0] != 0);
lport.setPin(Controller::DigitalPin::Two, args[0] != 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "joy0left"
void DebuggerParser::executeJoy0Left()
{
Controller& controller = debugger.riotDebug().controller(Controller::Left);
ControllerLowLevel lport(debugger.myOSystem.console().leftController());
if(argCount == 0)
controller.set(Controller::Three, !controller.read(Controller::Three));
lport.togglePin(Controller::DigitalPin::Three);
else if(argCount == 1)
controller.set(Controller::Three, args[0] != 0);
lport.setPin(Controller::DigitalPin::Three, args[0] != 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "joy0right"
void DebuggerParser::executeJoy0Right()
{
Controller& controller = debugger.riotDebug().controller(Controller::Left);
ControllerLowLevel lport(debugger.myOSystem.console().leftController());
if(argCount == 0)
controller.set(Controller::Four, !controller.read(Controller::Four));
lport.togglePin(Controller::DigitalPin::Four);
else if(argCount == 1)
controller.set(Controller::Four, args[0] != 0);
lport.setPin(Controller::DigitalPin::Four, args[0] != 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "joy0fire"
void DebuggerParser::executeJoy0Fire()
{
Controller& controller = debugger.riotDebug().controller(Controller::Left);
ControllerLowLevel lport(debugger.myOSystem.console().leftController());
if(argCount == 0)
controller.set(Controller::Six, !controller.read(Controller::Six));
lport.togglePin(Controller::DigitalPin::Six);
else if(argCount == 1)
controller.set(Controller::Six, args[0] != 0);
lport.setPin(Controller::DigitalPin::Six, args[0] != 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "joy1up"
void DebuggerParser::executeJoy1Up()
{
Controller& controller = debugger.riotDebug().controller(Controller::Right);
ControllerLowLevel rport(debugger.myOSystem.console().rightController());
if(argCount == 0)
controller.set(Controller::One, !controller.read(Controller::One));
rport.togglePin(Controller::DigitalPin::One);
else if(argCount == 1)
controller.set(Controller::One, args[0] != 0);
rport.setPin(Controller::DigitalPin::One, args[0] != 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "joy1down"
void DebuggerParser::executeJoy1Down()
{
Controller& controller = debugger.riotDebug().controller(Controller::Right);
ControllerLowLevel rport(debugger.myOSystem.console().rightController());
if(argCount == 0)
controller.set(Controller::Two, !controller.read(Controller::Two));
rport.togglePin(Controller::DigitalPin::Two);
else if(argCount == 1)
controller.set(Controller::Two, args[0] != 0);
rport.setPin(Controller::DigitalPin::Two, args[0] != 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "joy1left"
void DebuggerParser::executeJoy1Left()
{
Controller& controller = debugger.riotDebug().controller(Controller::Right);
ControllerLowLevel rport(debugger.myOSystem.console().rightController());
if(argCount == 0)
controller.set(Controller::Three, !controller.read(Controller::Three));
rport.togglePin(Controller::DigitalPin::Three);
else if(argCount == 1)
controller.set(Controller::Three, args[0] != 0);
rport.setPin(Controller::DigitalPin::Three, args[0] != 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "joy1right"
void DebuggerParser::executeJoy1Right()
{
Controller& controller = debugger.riotDebug().controller(Controller::Right);
ControllerLowLevel rport(debugger.myOSystem.console().rightController());
if(argCount == 0)
controller.set(Controller::Four, !controller.read(Controller::Four));
rport.togglePin(Controller::DigitalPin::Four);
else if(argCount == 1)
controller.set(Controller::Four, args[0] != 0);
rport.setPin(Controller::DigitalPin::Four, args[0] != 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// "joy1fire"
void DebuggerParser::executeJoy1Fire()
{
Controller& controller = debugger.riotDebug().controller(Controller::Right);
ControllerLowLevel rport(debugger.myOSystem.console().rightController());
if(argCount == 0)
controller.set(Controller::Six, !controller.read(Controller::Six));
rport.togglePin(Controller::DigitalPin::Six);
else if(argCount == 1)
controller.set(Controller::Six, args[0] != 0);
rport.setPin(Controller::DigitalPin::Six, args[0] != 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1596,16 +1597,12 @@ void DebuggerParser::executeReset()
{
debugger.reset();
debugger.rom().invalidate();
debugger.riotDebug().controller(Controller::Left).set(Controller::One, true);
debugger.riotDebug().controller(Controller::Left).set(Controller::Two, true);
debugger.riotDebug().controller(Controller::Left).set(Controller::Three, true);
debugger.riotDebug().controller(Controller::Left).set(Controller::Four, true);
debugger.riotDebug().controller(Controller::Left).set(Controller::Six, true);
debugger.riotDebug().controller(Controller::Right).set(Controller::One, true);
debugger.riotDebug().controller(Controller::Right).set(Controller::Two, true);
debugger.riotDebug().controller(Controller::Right).set(Controller::Three, true);
debugger.riotDebug().controller(Controller::Right).set(Controller::Four, true);
debugger.riotDebug().controller(Controller::Right).set(Controller::Six, true);
ControllerLowLevel lport(debugger.myOSystem.console().leftController());
ControllerLowLevel rport(debugger.myOSystem.console().rightController());
lport.resetDigitalPins();
rport.resetDigitalPins();
commandResult << "reset system";
}

View File

@ -231,13 +231,6 @@ Int32 RiotDebug::timDivider() const
return mySystem.m6532().myDivider;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Controller& RiotDebug::controller(Controller::Jack jack) const
{
return jack == Controller::Left ? myConsole.leftController() :
myConsole.rightController();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool RiotDebug::diffP0(int newVal)
{

View File

@ -84,9 +84,6 @@ class RiotDebug : public DebuggerSystem
Int32 intimClocks() const;
Int32 timDivider() const;
/* Controller ports */
Controller& controller(Controller::Jack jack) const;
/* Console switches */
bool diffP0(int newVal = -1);
bool diffP1(int newVal = -1);

View File

@ -29,7 +29,7 @@ AtariVoxWidget::AtariVoxWidget(GuiObject* boss, const GUI::Font& font,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AtariVoxWidget::eraseCurrent()
{
AtariVox& avox = static_cast<AtariVox&>(myController);
AtariVox& avox = static_cast<AtariVox&>(myController->base());
avox.eraseCurrent();
}
@ -37,7 +37,7 @@ void AtariVoxWidget::eraseCurrent()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool AtariVoxWidget::isPageUsed(uInt32 page)
{
AtariVox& avox = static_cast<AtariVox&>(myController);
AtariVox& avox = static_cast<AtariVox&>(myController->base());
return avox.isPageUsed(page);
}

View File

@ -78,16 +78,16 @@ BoosterWidget::BoosterWidget(GuiObject* boss, const GUI::Font& font,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void BoosterWidget::loadConfig()
{
myPins[kJUp]->setState(!myController.read(ourPinNo[kJUp]));
myPins[kJDown]->setState(!myController.read(ourPinNo[kJDown]));
myPins[kJLeft]->setState(!myController.read(ourPinNo[kJLeft]));
myPins[kJRight]->setState(!myController.read(ourPinNo[kJRight]));
myPins[kJFire]->setState(!myController.read(ourPinNo[kJFire]));
myPins[kJUp]->setState(!myController->getPin(ourPinNo[kJUp]));
myPins[kJDown]->setState(!myController->getPin(ourPinNo[kJDown]));
myPins[kJLeft]->setState(!myController->getPin(ourPinNo[kJLeft]));
myPins[kJRight]->setState(!myController->getPin(ourPinNo[kJRight]));
myPins[kJFire]->setState(!myController->getPin(ourPinNo[kJFire]));
myPins[kJBooster]->setState(
myController.read(Controller::Five) == Controller::MIN_RESISTANCE);
myController->getPin(Controller::AnalogPin::Five) == Controller::MIN_RESISTANCE);
myPins[kJTrigger]->setState(
myController.read(Controller::Nine) == Controller::MIN_RESISTANCE);
myController->getPin(Controller::AnalogPin::Nine) == Controller::MIN_RESISTANCE);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -103,15 +103,15 @@ void BoosterWidget::handleCommand(
case kJLeft:
case kJRight:
case kJFire:
myController.set(ourPinNo[id], !myPins[id]->getState());
myController->setPin(ourPinNo[id], !myPins[id]->getState());
break;
case kJBooster:
myController.set(Controller::Five,
myController->setPin(Controller::AnalogPin::Five,
myPins[id]->getState() ? Controller::MIN_RESISTANCE :
Controller::MAX_RESISTANCE);
break;
case kJTrigger:
myController.set(Controller::Nine,
myController->setPin(Controller::AnalogPin::Nine,
myPins[id]->getState() ? Controller::MIN_RESISTANCE :
Controller::MAX_RESISTANCE);
break;
@ -121,6 +121,6 @@ void BoosterWidget::handleCommand(
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Controller::DigitalPin BoosterWidget::ourPinNo[5] = {
Controller::One, Controller::Two, Controller::Three, Controller::Four,
Controller::Six
Controller::DigitalPin::One, Controller::DigitalPin::Two, Controller::DigitalPin::Three, Controller::DigitalPin::Four,
Controller::DigitalPin::Six
};

View File

@ -25,6 +25,7 @@ class ButtonWidget;
#include "Widget.hxx"
#include "Console.hxx"
#include "Command.hxx"
#include "ControlLowLevel.hxx"
class ControllerWidget : public Widget, public CommandSender
@ -34,7 +35,7 @@ class ControllerWidget : public Widget, public CommandSender
Controller& controller)
: Widget(boss, font, x, y, 16, 16),
CommandSender(boss),
myController(controller)
myController(make_unique<ControllerLowLevel>(controller))
{
_w = 18 * font.getMaxCharWidth();
_h = 8 * font.getLineHeight();
@ -45,19 +46,19 @@ class ControllerWidget : public Widget, public CommandSender
virtual void loadConfig() override { }
protected:
Controller& myController;
unique_ptr<ControllerLowLevel> myController;
protected:
bool isLeftPort()
{
bool swappedPorts = instance().console().properties().get(Console_SwapPorts) == "YES";
return (myController.jack() == Controller::Left) ^ swappedPorts;
return (myController->base().jack() == Controller::Jack::Left) ^ swappedPorts;
}
string getHeader()
{
return (isLeftPort() ? "Left (" : "Right (") + myController.name() + ")";
return (isLeftPort() ? "Left (" : "Right (") + myController->base().name() + ")";
}
private:

View File

@ -60,8 +60,8 @@ DrivingWidget::DrivingWidget(GuiObject* boss, const GUI::Font& font,
void DrivingWidget::loadConfig()
{
uInt8 gray = 0;
if(myController.read(Controller::One)) gray += 1;
if(myController.read(Controller::Two)) gray += 2;
if(myController->getPin(Controller::DigitalPin::One)) gray += 1;
if(myController->getPin(Controller::DigitalPin::Two)) gray += 2;
for(myGrayIndex = 0; myGrayIndex < 4; ++myGrayIndex)
{
@ -72,7 +72,7 @@ void DrivingWidget::loadConfig()
}
}
myFire->setState(!myController.read(Controller::Six));
myFire->setState(!myController->getPin(Controller::DigitalPin::Six));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -83,18 +83,18 @@ void DrivingWidget::handleCommand(
{
case kGrayUpCmd:
myGrayIndex = (myGrayIndex + 1) % 4;
myController.set(Controller::One, (ourGrayTable[myGrayIndex] & 0x1) != 0);
myController.set(Controller::Two, (ourGrayTable[myGrayIndex] & 0x2) != 0);
myController->setPin(Controller::DigitalPin::One, (ourGrayTable[myGrayIndex] & 0x1) != 0);
myController->setPin(Controller::DigitalPin::Two, (ourGrayTable[myGrayIndex] & 0x2) != 0);
setValue(myGrayIndex);
break;
case kGrayDownCmd:
myGrayIndex = myGrayIndex == 0 ? 3 : myGrayIndex - 1;
myController.set(Controller::One, (ourGrayTable[myGrayIndex] & 0x1) != 0);
myController.set(Controller::Two, (ourGrayTable[myGrayIndex] & 0x2) != 0);
myController->setPin(Controller::DigitalPin::One, (ourGrayTable[myGrayIndex] & 0x1) != 0);
myController->setPin(Controller::DigitalPin::Two, (ourGrayTable[myGrayIndex] & 0x2) != 0);
setValue(myGrayIndex);
break;
case kFireCmd:
myController.set(Controller::Six, !myFire->getState());
myController->setPin(Controller::DigitalPin::Six, !myFire->getState());
break;
}
}

View File

@ -72,14 +72,14 @@ GenesisWidget::GenesisWidget(GuiObject* boss, const GUI::Font& font,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GenesisWidget::loadConfig()
{
myPins[kJUp]->setState(!myController.read(ourPinNo[kJUp]));
myPins[kJDown]->setState(!myController.read(ourPinNo[kJDown]));
myPins[kJLeft]->setState(!myController.read(ourPinNo[kJLeft]));
myPins[kJRight]->setState(!myController.read(ourPinNo[kJRight]));
myPins[kJBbtn]->setState(!myController.read(ourPinNo[kJBbtn]));
myPins[kJUp]->setState(!myController->getPin(ourPinNo[kJUp]));
myPins[kJDown]->setState(!myController->getPin(ourPinNo[kJDown]));
myPins[kJLeft]->setState(!myController->getPin(ourPinNo[kJLeft]));
myPins[kJRight]->setState(!myController->getPin(ourPinNo[kJRight]));
myPins[kJBbtn]->setState(!myController->getPin(ourPinNo[kJBbtn]));
myPins[kJCbtn]->setState(
myController.read(Controller::Five) == Controller::MAX_RESISTANCE);
myController->getPin(Controller::AnalogPin::Five) == Controller::MAX_RESISTANCE);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -95,10 +95,10 @@ void GenesisWidget::handleCommand(
case kJLeft:
case kJRight:
case kJBbtn:
myController.set(ourPinNo[id], !myPins[id]->getState());
myController->setPin(ourPinNo[id], !myPins[id]->getState());
break;
case kJCbtn:
myController.set(Controller::Five,
myController->setPin(Controller::AnalogPin::Five,
myPins[id]->getState() ? Controller::MAX_RESISTANCE :
Controller::MIN_RESISTANCE);
break;
@ -108,6 +108,6 @@ void GenesisWidget::handleCommand(
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Controller::DigitalPin GenesisWidget::ourPinNo[5] = {
Controller::One, Controller::Two, Controller::Three, Controller::Four,
Controller::Six
Controller::DigitalPin::One, Controller::DigitalPin::Two, Controller::DigitalPin::Three, Controller::DigitalPin::Four,
Controller::DigitalPin::Six
};

View File

@ -65,11 +65,11 @@ JoystickWidget::JoystickWidget(GuiObject* boss, const GUI::Font& font,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoystickWidget::loadConfig()
{
myPins[kJUp]->setState(!myController.read(ourPinNo[kJUp]));
myPins[kJDown]->setState(!myController.read(ourPinNo[kJDown]));
myPins[kJLeft]->setState(!myController.read(ourPinNo[kJLeft]));
myPins[kJRight]->setState(!myController.read(ourPinNo[kJRight]));
myPins[kJFire]->setState(!myController.read(ourPinNo[kJFire]));
myPins[kJUp]->setState(!myController->getPin(ourPinNo[kJUp]));
myPins[kJDown]->setState(!myController->getPin(ourPinNo[kJDown]));
myPins[kJLeft]->setState(!myController->getPin(ourPinNo[kJLeft]));
myPins[kJRight]->setState(!myController->getPin(ourPinNo[kJRight]));
myPins[kJFire]->setState(!myController->getPin(ourPinNo[kJFire]));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -77,11 +77,11 @@ void JoystickWidget::handleCommand(
CommandSender* sender, int cmd, int data, int id)
{
if(cmd == CheckboxWidget::kCheckActionCmd)
myController.set(ourPinNo[id], !myPins[id]->getState());
myController->setPin(ourPinNo[id], !myPins[id]->getState());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Controller::DigitalPin JoystickWidget::ourPinNo[5] = {
Controller::One, Controller::Two, Controller::Three, Controller::Four,
Controller::Six
Controller::DigitalPin::One, Controller::DigitalPin::Two, Controller::DigitalPin::Three, Controller::DigitalPin::Four,
Controller::DigitalPin::Six
};

View File

@ -68,11 +68,11 @@ PaddleWidget::PaddleWidget(GuiObject* boss, const GUI::Font& font,
void PaddleWidget::loadConfig()
{
myP0Resistance->setValue(Int32(Paddles::MAX_RESISTANCE -
myController.read(Controller::Nine)));
myController->getPin(Controller::AnalogPin::Nine)));
myP1Resistance->setValue(Int32(Paddles::MAX_RESISTANCE -
myController.read(Controller::Five)));
myP0Fire->setState(!myController.read(Controller::Four));
myP1Fire->setState(!myController.read(Controller::Three));
myController->getPin(Controller::AnalogPin::Five)));
myP0Fire->setState(!myController->getPin(Controller::DigitalPin::Four));
myP1Fire->setState(!myController->getPin(Controller::DigitalPin::Three));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -82,18 +82,18 @@ void PaddleWidget::handleCommand(
switch(cmd)
{
case kP0Changed:
myController.set(Controller::Nine,
Int32(Paddles::MAX_RESISTANCE - myP0Resistance->getValue()));
myController->setPin(Controller::AnalogPin::Nine,
Int32(Paddles::MAX_RESISTANCE - myP0Resistance->getValue()));
break;
case kP1Changed:
myController.set(Controller::Five,
Int32(Paddles::MAX_RESISTANCE - myP1Resistance->getValue()));
myController->setPin(Controller::AnalogPin::Five,
Int32(Paddles::MAX_RESISTANCE - myP1Resistance->getValue()));
break;
case kP0Fire:
myController.set(Controller::Four, !myP0Fire->getState());
myController->setPin(Controller::DigitalPin::Four, !myP0Fire->getState());
break;
case kP1Fire:
myController.set(Controller::Three, !myP1Fire->getState());
myController->setPin(Controller::DigitalPin::Three, !myP1Fire->getState());
break;
}
}

View File

@ -75,7 +75,7 @@ void PointingDeviceWidget::loadConfig()
{
setGrayCodeH();
setGrayCodeV();
myFire->setState(!myController.read(Controller::Six));
myFire->setState(!myController->getPin(Controller::DigitalPin::Six));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -83,7 +83,7 @@ void PointingDeviceWidget::handleCommand(CommandSender* sender, int cmd, int dat
{
// since the PointingDevice uses its own, internal state (not reading the controller),
// we have to communicate directly with it
PointingDevice& pDev = static_cast<PointingDevice&>(myController);
PointingDevice& pDev = static_cast<PointingDevice&>(myController->base());
switch(cmd)
{
@ -108,7 +108,7 @@ void PointingDeviceWidget::handleCommand(CommandSender* sender, int cmd, int dat
setGrayCodeV();
break;
case kTBFire:
myController.set(Controller::Six, !myFire->getState());
myController->setPin(Controller::DigitalPin::Six, !myFire->getState());
break;
}
}
@ -116,7 +116,7 @@ void PointingDeviceWidget::handleCommand(CommandSender* sender, int cmd, int dat
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PointingDeviceWidget::setGrayCodeH()
{
PointingDevice& pDev = static_cast<PointingDevice&>(myController);
PointingDevice& pDev = static_cast<PointingDevice&>(myController->base());
pDev.myCountH &= 0b11;
setValue(myGrayValueH, pDev.myCountH, pDev.myTrackBallLeft);
@ -125,7 +125,7 @@ void PointingDeviceWidget::setGrayCodeH()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PointingDeviceWidget::setGrayCodeV()
{
PointingDevice& pDev = static_cast<PointingDevice&>(myController);
PointingDevice& pDev = static_cast<PointingDevice&>(myController->base());
pDev.myCountV &= 0b11;
setValue(myGrayValueV, pDev.myCountV, !pDev.myTrackBallDown);

View File

@ -133,13 +133,12 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont,
myTimDivider->setEditable(false);
// Controller ports
const RiotDebug& riot = instance().debugger().riotDebug();
xpos = col; ypos = 10;
myLeftControl = addControlWidget(boss, lfont, xpos, ypos,
riot.controller(Controller::Left));
instance().console().leftController());
xpos += myLeftControl->getWidth() + 15;
myRightControl = addControlWidget(boss, lfont, xpos, ypos,
riot.controller(Controller::Right));
instance().console().rightController());
// TIA INPTx registers (R), left port
const char* const contLeftReadNames[] = { "INPT0", "INPT1", "INPT4" };
@ -397,16 +396,18 @@ void RiotWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
break;
case kSWCHARBitsID:
{
#if 0
// TODO: Check if there is a nicer way to do this
value = Debugger::get_bits(mySWCHAReadBits->getState());
riot.controller(Controller::Left).set(Controller::One, value & 0b00010000);
riot.controller(Controller::Left).set(Controller::Two, value & 0b00100000);
riot.controller(Controller::Left).set(Controller::Three, value & 0b01000000);
riot.controller(Controller::Left).set(Controller::Four, value & 0b10000000);
riot.controller(Controller::Right).set(Controller::One, value & 0b00000001);
riot.controller(Controller::Right).set(Controller::Two, value & 0b00000010);
riot.controller(Controller::Right).set(Controller::Three, value & 0b00000100);
riot.controller(Controller::Right).set(Controller::Four, value & 0b00001000);
riot.controller(Controller::Jack::Left).set(Controller::DigitalPin::One, value & 0b00010000);
riot.controller(Controller::Jack::Left).set(Controller::DigitalPin::Two, value & 0b00100000);
riot.controller(Controller::Jack::Left).set(Controller::DigitalPin::Three, value & 0b01000000);
riot.controller(Controller::Jack::Left).set(Controller::DigitalPin::Four, value & 0b10000000);
riot.controller(Controller::Jack::Right).set(Controller::DigitalPin::One, value & 0b00000001);
riot.controller(Controller::Jack::Right).set(Controller::DigitalPin::Two, value & 0b00000010);
riot.controller(Controller::Jack::Right).set(Controller::DigitalPin::Three, value & 0b00000100);
riot.controller(Controller::Jack::Right).set(Controller::DigitalPin::Four, value & 0b00001000);
#endif
break;
}
}
@ -447,29 +448,29 @@ ControllerWidget* RiotWidget::addControlWidget(GuiObject* boss, const GUI::Font&
{
switch(controller.type())
{
case Controller::AmigaMouse:
case Controller::Type::AmigaMouse:
return new AmigaMouseWidget(boss, font, x, y, controller);
case Controller::AtariMouse:
case Controller::Type::AtariMouse:
return new AtariMouseWidget(boss, font, x, y, controller);
case Controller::AtariVox:
case Controller::Type::AtariVox:
return new AtariVoxWidget(boss, font, x, y, controller);
case Controller::BoosterGrip:
case Controller::Type::BoosterGrip:
return new BoosterWidget(boss, font, x, y, controller);
case Controller::Driving:
case Controller::Type::Driving:
return new DrivingWidget(boss, font, x, y, controller);
case Controller::Genesis:
case Controller::Type::Genesis:
return new GenesisWidget(boss, font, x, y, controller);
case Controller::Joystick:
case Controller::Type::Joystick:
return new JoystickWidget(boss, font, x, y, controller);
case Controller::Keyboard:
case Controller::Type::Keyboard:
return new KeyboardWidget(boss, font, x, y, controller);
// case Controller::KidVid: // TODO - implement this
// case Controller::MindLink: // TODO - implement this
case Controller::Paddles:
// case Controller::Type::KidVid: // TODO - implement this
// case Controller::Type::MindLink: // TODO - implement this
case Controller::Type::Paddles:
return new PaddleWidget(boss, font, x, y, controller);
case Controller::SaveKey:
case Controller::Type::SaveKey:
return new SaveKeyWidget(boss, font, x, y, controller);
case Controller::TrakBall:
case Controller::Type::TrakBall:
return new TrakBallWidget(boss, font, x, y, controller);
default:
return new NullControlWidget(boss, font, x, y, controller);

View File

@ -29,7 +29,7 @@ SaveKeyWidget::SaveKeyWidget(GuiObject* boss, const GUI::Font& font,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SaveKeyWidget::eraseCurrent()
{
SaveKey& skey = static_cast<SaveKey&>(myController);
SaveKey& skey = static_cast<SaveKey&>(myController->base());
skey.eraseCurrent();
}
@ -37,7 +37,7 @@ void SaveKeyWidget::eraseCurrent()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool SaveKeyWidget::isPageUsed(uInt32 page)
{
SaveKey& skey = static_cast<SaveKey&>(myController);
SaveKey& skey = static_cast<SaveKey&>(myController->base());
return skey.isPageUsed(page);
}

View File

@ -31,10 +31,15 @@ class AmigaMouse : public PointingDevice
@param system The system using this controller
*/
AmigaMouse(Jack jack, const Event& event, const System& system)
: PointingDevice(jack, event, system, Controller::AmigaMouse,
: PointingDevice(jack, event, system, Controller::Type::AmigaMouse,
trackballSensitivity) { }
virtual ~AmigaMouse() = default;
/**
Returns the name of this controller.
*/
string name() const override { return "AmigaMouse"; }
protected:
uInt8 ioPortA(uInt8 countH, uInt8 countV, uInt8, uInt8) override
{

View File

@ -31,10 +31,15 @@ class AtariMouse : public PointingDevice
@param system The system using this controller
*/
AtariMouse(Jack jack, const Event& event, const System& system)
: PointingDevice(jack, event, system, Controller::AtariMouse,
: PointingDevice(jack, event, system, Controller::Type::AtariMouse,
trackballSensitivity) { }
virtual ~AtariMouse() = default;
/**
Returns the name of this controller.
*/
string name() const override { return "AtariMouse"; }
protected:
uInt8 ioPortA(uInt8 countH, uInt8 countV, uInt8, uInt8) override
{

View File

@ -24,7 +24,7 @@
AtariVox::AtariVox(Jack jack, const Event& event, const System& system,
const string& portname, const string& eepromfile,
onMessageCallback callback)
: SaveKey(jack, event, system, eepromfile, callback, Controller::AtariVox),
: SaveKey(jack, event, system, eepromfile, callback, Controller::Type::AtariVox),
myShiftCount(0),
myShiftRegister(0),
myLastDataWriteCycle(0)
@ -35,7 +35,8 @@ AtariVox::AtariVox(Jack jack, const Event& event, const System& system,
else
myAboutString = " (invalid serial port \'" + portname + "\')";
myDigitalPinState[Three] = myDigitalPinState[Four] = true;
setPin(DigitalPin::Three, true);
setPin(DigitalPin::Four, true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -47,9 +48,9 @@ bool AtariVox::read(DigitalPin pin)
switch(pin)
{
// Pin 2: SpeakJet READY
case Two:
case DigitalPin::Two:
// For now, we just assume the device is always ready
return myDigitalPinState[Two] = true;
return setPin(pin, true);
default:
return SaveKey::read(pin);
@ -64,8 +65,8 @@ void AtariVox::write(DigitalPin pin, bool value)
{
// Pin 1: SpeakJet DATA
// output serial data to the speakjet
case One:
myDigitalPinState[One] = value;
case DigitalPin::One:
setPin(pin, value);
clockDataIn(value);
break;

View File

@ -20,10 +20,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BoosterGrip::BoosterGrip(Jack jack, const Event& event, const System& system)
: Controller(jack, event, system, Controller::BoosterGrip),
: Controller(jack, event, system, Controller::Type::BoosterGrip),
myControlID(-1)
{
if(myJack == Left)
if(myJack == Jack::Left)
{
myUpEvent = Event::JoystickZeroUp;
myDownEvent = Event::JoystickZeroDown;
@ -48,28 +48,28 @@ BoosterGrip::BoosterGrip(Jack jack, const Event& event, const System& system)
myYAxisValue = Event::SARightAxis1Value;
}
updateAnalogPin(Five, MAX_RESISTANCE);
updateAnalogPin(Nine, MAX_RESISTANCE);
setPin(AnalogPin::Five, MAX_RESISTANCE);
setPin(AnalogPin::Nine, MAX_RESISTANCE);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void BoosterGrip::update()
{
// Digital events (from keyboard or joystick hats & buttons)
myDigitalPinState[One] = (myEvent.get(myUpEvent) == 0);
myDigitalPinState[Two] = (myEvent.get(myDownEvent) == 0);
myDigitalPinState[Three] = (myEvent.get(myLeftEvent) == 0);
myDigitalPinState[Four] = (myEvent.get(myRightEvent) == 0);
myDigitalPinState[Six] = (myEvent.get(myFireEvent) == 0);
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);
setPin(DigitalPin::Six, 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.
updateAnalogPin(
Five,
setPin(
AnalogPin::Five,
(myEvent.get(myTriggerEvent) != 0) ? MIN_RESISTANCE : MAX_RESISTANCE
);
updateAnalogPin(
Nine,
setPin(
AnalogPin::Nine,
(myEvent.get(myBoosterEvent) != 0) ? MIN_RESISTANCE : MAX_RESISTANCE
);
@ -78,22 +78,22 @@ void BoosterGrip::update()
int yaxis = myEvent.get(myYAxisValue);
if(xaxis > 16384-4096)
{
myDigitalPinState[Four] = false;
setPin(DigitalPin::Four, false);
// Stelladaptor sends "half moved right" for L+R pushed together
if(xaxis < 16384+4096)
myDigitalPinState[Three] = false;
setPin(DigitalPin::Three, false);
}
else if(xaxis < -16384)
myDigitalPinState[Three] = false;
setPin(DigitalPin::Three, false);
if(yaxis > 16384-4096)
{
myDigitalPinState[Two] = false;
setPin(DigitalPin::Two, false);
// Stelladaptor sends "half moved down" for U+D pushed together
if(yaxis < 16384+4096)
myDigitalPinState[One] = false;
setPin(DigitalPin::One, false);
}
else if(yaxis < -16384)
myDigitalPinState[One] = false;
setPin(DigitalPin::One, false);
// Mouse motion and button events
if(myControlID > -1)
@ -107,24 +107,24 @@ void BoosterGrip::update()
if((!(abs(mousey) > abs(mousex) << 1)) && (abs(mousex) >= MJ_Threshold))
{
if(mousex < 0)
myDigitalPinState[Three] = false;
setPin(DigitalPin::Three, false);
else if (mousex > 0)
myDigitalPinState[Four] = false;
setPin(DigitalPin::Four, false);
}
if((!(abs(mousex) > abs(mousey) << 1)) && (abs(mousey) >= MJ_Threshold))
{
if(mousey < 0)
myDigitalPinState[One] = false;
setPin(DigitalPin::One, false);
else if(mousey > 0)
myDigitalPinState[Two] = false;
setPin(DigitalPin::Two, false);
}
}
// Get mouse button state
if(myEvent.get(Event::MouseButtonLeftValue))
myDigitalPinState[Six] = false;
setPin(DigitalPin::Six, false);
if(myEvent.get(Event::MouseButtonRightValue))
updateAnalogPin(Nine, MIN_RESISTANCE);
setPin(AnalogPin::Nine, MIN_RESISTANCE);
}
}
@ -135,11 +135,11 @@ bool BoosterGrip::setMouseControl(
// 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::BoosterGrip && ytype == Controller::BoosterGrip &&
if(xtype == Controller::Type::BoosterGrip && ytype == Controller::Type::BoosterGrip &&
xid == yid)
{
myControlID = ((myJack == Left && xid == 0) ||
(myJack == Right && xid == 1)
myControlID = ((myJack == Jack::Left && xid == 0) ||
(myJack == Jack::Right && xid == 1)
) ? xid : -1;
}
else

View File

@ -48,6 +48,11 @@ class BoosterGrip : public Controller
*/
void update() override;
/**
Returns the name of this controller.
*/
string name() const override { return "BoosterGrip"; }
/**
Determines how this controller will treat values received from the
X/Y axis and left/right buttons of the mouse. Since not all controllers

View File

@ -28,13 +28,13 @@ CompuMate::CompuMate(const Console& console, const Event& event,
{
// These controller pointers will be retrieved by the Console, which will
// also take ownership of them
myLeftController = make_unique<CMControl>(*this, Controller::Left, event, system);
myRightController = make_unique<CMControl>(*this, Controller::Right, event, system);
myLeftController = make_unique<CMControl>(*this, Controller::Jack::Left, event, system);
myRightController = make_unique<CMControl>(*this, Controller::Jack::Right, event, system);
myLeftController->updateAnalogPin(Controller::Nine, Controller::MAX_RESISTANCE);
myLeftController->updateAnalogPin(Controller::Five, Controller::MIN_RESISTANCE);
myRightController->updateAnalogPin(Controller::Nine, Controller::MIN_RESISTANCE);
myRightController->updateAnalogPin(Controller::Five, Controller::MAX_RESISTANCE);
myLeftController->setPin(Controller::AnalogPin::Nine, Controller::MAX_RESISTANCE);
myLeftController->setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
myRightController->setPin(Controller::AnalogPin::Nine, Controller::MIN_RESISTANCE);
myRightController->setPin(Controller::AnalogPin::Five, Controller::MAX_RESISTANCE);
enableKeyHandling(false);
}
@ -52,149 +52,139 @@ void CompuMate::update()
Controller& lp = myConsole.leftController();
Controller& rp = myConsole.rightController();
lp.myAnalogPinValue[Controller::Nine] = Controller::MAX_RESISTANCE;
lp.myAnalogPinValue[Controller::Five] = Controller::MIN_RESISTANCE;
lp.myDigitalPinState[Controller::Six] = true;
rp.myAnalogPinValue[Controller::Nine] = Controller::MIN_RESISTANCE;
rp.myAnalogPinValue[Controller::Five] = Controller::MAX_RESISTANCE;
rp.myDigitalPinState[Controller::Six] = true;
lp.setPin(Controller::AnalogPin::Nine, Controller::MAX_RESISTANCE);
lp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
lp.setPin(Controller::DigitalPin::Six, true);
rp.setPin(Controller::AnalogPin::Nine, Controller::MIN_RESISTANCE);
rp.setPin(Controller::AnalogPin::Five, Controller::MAX_RESISTANCE);
rp.setPin(Controller::DigitalPin::Six, true);
if (myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT])
rp.myAnalogPinValue[Controller::Five] = Controller::MIN_RESISTANCE;
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
if (myKeyTable[KBDK_LCTRL] || myKeyTable[KBDK_RCTRL])
lp.myAnalogPinValue[Controller::Nine] = Controller::MIN_RESISTANCE;
lp.setPin(Controller::AnalogPin::Nine, Controller::MIN_RESISTANCE);
rp.myDigitalPinState[Controller::Three] = true;
rp.myDigitalPinState[Controller::Four] = true;
rp.setPin(Controller::DigitalPin::Three, true);
rp.setPin(Controller::DigitalPin::Four, true);
switch(myColumn) // This is updated inside CartCM class
{
case 0:
if (myKeyTable[KBDK_7]) lp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_U]) rp.myDigitalPinState[Controller::Three] = false;
if (myKeyTable[KBDK_J]) rp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_M]) rp.myDigitalPinState[Controller::Four] = false;
if (myKeyTable[KBDK_7]) lp.setPin(Controller::DigitalPin::Six, false);
if (myKeyTable[KBDK_U]) rp.setPin(Controller::DigitalPin::Three, false);
if (myKeyTable[KBDK_J]) rp.setPin(Controller::DigitalPin::Six, false);
if (myKeyTable[KBDK_M]) rp.setPin(Controller::DigitalPin::Four, false);
break;
case 1:
if (myKeyTable[KBDK_6]) lp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_6]) lp.setPin(Controller::DigitalPin::Six, false);
// Emulate the '?' character (Shift-6) with the actual question key
if (myKeyTable[KBDK_SLASH] && (myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
{
rp.myAnalogPinValue[Controller::Five] = Controller::MIN_RESISTANCE;
lp.myDigitalPinState[Controller::Six] = false;
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
lp.setPin(Controller::DigitalPin::Six, false);
}
if (myKeyTable[KBDK_Y]) rp.myDigitalPinState[Controller::Three] = false;
if (myKeyTable[KBDK_H]) rp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_N]) rp.myDigitalPinState[Controller::Four] = false;
if (myKeyTable[KBDK_Y]) rp.setPin(Controller::DigitalPin::Three, false);
if (myKeyTable[KBDK_H]) rp.setPin(Controller::DigitalPin::Six, false);
if (myKeyTable[KBDK_N]) rp.setPin(Controller::DigitalPin::Four, false);
break;
case 2:
if (myKeyTable[KBDK_8]) lp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_8]) lp.setPin(Controller::DigitalPin::Six, false);
// Emulate the '[' character (Shift-8) with the actual key
if (myKeyTable[KBDK_LEFTBRACKET] && !(myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
{
rp.myAnalogPinValue[Controller::Five] = Controller::MIN_RESISTANCE;
lp.myDigitalPinState[Controller::Six] = false;
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
lp.setPin(Controller::DigitalPin::Six, false);
}
if (myKeyTable[KBDK_I]) rp.myDigitalPinState[Controller::Three] = false;
if (myKeyTable[KBDK_K]) rp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_COMMA]) rp.myDigitalPinState[Controller::Four] = false;
if (myKeyTable[KBDK_I]) rp.setPin(Controller::DigitalPin::Three, false);
if (myKeyTable[KBDK_K]) rp.setPin(Controller::DigitalPin::Six, false);
if (myKeyTable[KBDK_COMMA]) rp.setPin(Controller::DigitalPin::Four, false);
break;
case 3:
if (myKeyTable[KBDK_2]) lp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_2]) lp.setPin(Controller::DigitalPin::Six, false);
// Emulate the '-' character (Shift-2) with the actual minus key
if (myKeyTable[KBDK_MINUS] && !(myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
{
rp.myAnalogPinValue[Controller::Five] = Controller::MIN_RESISTANCE;
lp.myDigitalPinState[Controller::Six] = false;
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
lp.setPin(Controller::DigitalPin::Six, false);
}
if (myKeyTable[KBDK_W]) rp.myDigitalPinState[Controller::Three] = false;
if (myKeyTable[KBDK_S]) rp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_X]) rp.myDigitalPinState[Controller::Four] = false;
if (myKeyTable[KBDK_W]) rp.setPin(Controller::DigitalPin::Three, false);
if (myKeyTable[KBDK_S]) rp.setPin(Controller::DigitalPin::Six, false);
if (myKeyTable[KBDK_X]) rp.setPin(Controller::DigitalPin::Four, false);
break;
case 4:
if (myKeyTable[KBDK_3]) lp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_E]) rp.myDigitalPinState[Controller::Three] = false;
if (myKeyTable[KBDK_D]) rp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_C]) rp.myDigitalPinState[Controller::Four] = false;
if (myKeyTable[KBDK_3]) lp.setPin(Controller::DigitalPin::Six, false);
if (myKeyTable[KBDK_E]) rp.setPin(Controller::DigitalPin::Three, false);
if (myKeyTable[KBDK_D]) rp.setPin(Controller::DigitalPin::Six, false);
if (myKeyTable[KBDK_C]) rp.setPin(Controller::DigitalPin::Four, false);
break;
case 5:
if (myKeyTable[KBDK_0]) lp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_0]) lp.setPin(Controller::DigitalPin::Six, false);
// Emulate the quote character (Shift-0) with the actual quote key
if (myKeyTable[KBDK_APOSTROPHE] && (myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
{
rp.myAnalogPinValue[Controller::Five] = Controller::MIN_RESISTANCE;
lp.myDigitalPinState[Controller::Six] = false;
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
lp.setPin(Controller::DigitalPin::Six, false);
}
if (myKeyTable[KBDK_P]) rp.myDigitalPinState[Controller::Three] = false;
if (myKeyTable[KBDK_P]) rp.setPin(Controller::DigitalPin::Three, false);
if (myKeyTable[KBDK_RETURN] || myKeyTable[KBDK_KP_ENTER])
rp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_SPACE]) rp.myDigitalPinState[Controller::Four] = false;
rp.setPin(Controller::DigitalPin::Six, false);
if (myKeyTable[KBDK_SPACE]) rp.setPin(Controller::DigitalPin::Four, false);
// Emulate Ctrl-space (aka backspace) with the actual Backspace key
if (myKeyTable[KBDK_BACKSPACE])
{
lp.myAnalogPinValue[Controller::Nine] = Controller::MIN_RESISTANCE;
rp.myDigitalPinState[Controller::Four] = false;
lp.setPin(Controller::AnalogPin::Nine, Controller::MIN_RESISTANCE);
rp.setPin(Controller::DigitalPin::Four, false);
}
break;
case 6:
if (myKeyTable[KBDK_9]) lp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_9]) lp.setPin(Controller::DigitalPin::Six, false);
// Emulate the ']' character (Shift-9) with the actual key
if (myKeyTable[KBDK_RIGHTBRACKET] && !(myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
{
rp.myAnalogPinValue[Controller::Five] = Controller::MIN_RESISTANCE;
lp.myDigitalPinState[Controller::Six] = false;
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
lp.setPin(Controller::DigitalPin::Six, false);
}
if (myKeyTable[KBDK_O]) rp.myDigitalPinState[Controller::Three] = false;
if (myKeyTable[KBDK_L]) rp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_PERIOD]) rp.myDigitalPinState[Controller::Four] = false;
if (myKeyTable[KBDK_O]) rp.setPin(Controller::DigitalPin::Three, false);
if (myKeyTable[KBDK_L]) rp.setPin(Controller::DigitalPin::Six, false);
if (myKeyTable[KBDK_PERIOD]) rp.setPin(Controller::DigitalPin::Four, false);
break;
case 7:
if (myKeyTable[KBDK_5]) lp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_5]) lp.setPin(Controller::DigitalPin::Six, false);
// Emulate the '=' character (Shift-5) with the actual equals key
if (myKeyTable[KBDK_EQUALS] && !(myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
{
rp.myAnalogPinValue[Controller::Five] = Controller::MIN_RESISTANCE;
lp.myDigitalPinState[Controller::Six] = false;
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
lp.setPin(Controller::DigitalPin::Six, false);
}
if (myKeyTable[KBDK_T]) rp.myDigitalPinState[Controller::Three] = false;
if (myKeyTable[KBDK_G]) rp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_B]) rp.myDigitalPinState[Controller::Four] = false;
if (myKeyTable[KBDK_T]) rp.setPin(Controller::DigitalPin::Three, false);
if (myKeyTable[KBDK_G]) rp.setPin(Controller::DigitalPin::Six, false);
if (myKeyTable[KBDK_B]) rp.setPin(Controller::DigitalPin::Four, false);
break;
case 8:
if (myKeyTable[KBDK_1]) lp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_1]) lp.setPin(Controller::DigitalPin::Six, false);
// Emulate the '+' character (Shift-1) with the actual plus key (Shift-=)
if (myKeyTable[KBDK_EQUALS] && (myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
{
rp.myAnalogPinValue[Controller::Five] = Controller::MIN_RESISTANCE;
lp.myDigitalPinState[Controller::Six] = false;
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
lp.setPin(Controller::DigitalPin::Six, false);
}
if (myKeyTable[KBDK_Q]) rp.myDigitalPinState[Controller::Three] = false;
if (myKeyTable[KBDK_A]) rp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_Z]) rp.myDigitalPinState[Controller::Four] = false;
if (myKeyTable[KBDK_Q]) rp.setPin(Controller::DigitalPin::Three, false);
if (myKeyTable[KBDK_A]) rp.setPin(Controller::DigitalPin::Six, false);
if (myKeyTable[KBDK_Z]) rp.setPin(Controller::DigitalPin::Four, false);
break;
case 9:
if (myKeyTable[KBDK_4]) lp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_4]) lp.setPin(Controller::DigitalPin::Six, false);
// Emulate the '/' character (Shift-4) with the actual slash key
if (myKeyTable[KBDK_SLASH] && !(myKeyTable[KBDK_LSHIFT] || myKeyTable[KBDK_RSHIFT]))
{
rp.myAnalogPinValue[Controller::Five] = Controller::MIN_RESISTANCE;
lp.myDigitalPinState[Controller::Six] = false;
rp.setPin(Controller::AnalogPin::Five, Controller::MIN_RESISTANCE);
lp.setPin(Controller::DigitalPin::Six, false);
}
if (myKeyTable[KBDK_R]) rp.myDigitalPinState[Controller::Three] = false;
if (myKeyTable[KBDK_F]) rp.myDigitalPinState[Controller::Six] = false;
if (myKeyTable[KBDK_V]) rp.myDigitalPinState[Controller::Four] = false;
if (myKeyTable[KBDK_R]) rp.setPin(Controller::DigitalPin::Three, false);
if (myKeyTable[KBDK_F]) rp.setPin(Controller::DigitalPin::Six, false);
if (myKeyTable[KBDK_V]) rp.setPin(Controller::DigitalPin::Four, false);
break;
default:
break;
}
if (lp.myOnAnalogPinUpdateCallback) {
lp.myOnAnalogPinUpdateCallback(Controller::Five);
lp.myOnAnalogPinUpdateCallback(Controller::Nine);
}
if (rp.myOnAnalogPinUpdateCallback) {
rp.myOnAnalogPinUpdateCallback(Controller::Five);
rp.myOnAnalogPinUpdateCallback(Controller::Nine);
}
}

View File

@ -100,7 +100,7 @@ class CompuMate
*/
CMControl(class CompuMate& handler, Controller::Jack jack, const Event& event,
const System& system)
: Controller(jack, event, system, Controller::CompuMate),
: Controller(jack, event, system, Controller::Type::CompuMate),
myHandler(handler) { }
virtual ~CMControl() = default;
@ -111,7 +111,7 @@ class CompuMate
happen at the same cycle and is redundant.
*/
void controlWrite(uInt8) override {
if(myJack == Controller::Left) myHandler.update();
if(myJack == Controller::Jack::Left) myHandler.update();
}
/**
@ -120,6 +120,11 @@ class CompuMate
*/
void update() override { }
/**
Returns the name of this controller.
*/
string name() const override { return "CompuMate"; }
private:
class CompuMate& myHandler;

View File

@ -116,8 +116,8 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
// For now, we just add dummy joystick controllers, since autodetection
// runs the emulation for a while, and this may interfere with 'smart'
// controllers such as the AVox and SaveKey
myLeftControl = make_unique<Joystick>(Controller::Left, myEvent, *mySystem);
myRightControl = make_unique<Joystick>(Controller::Right, myEvent, *mySystem);
myLeftControl = make_unique<Joystick>(Controller::Jack::Left, myEvent, *mySystem);
myRightControl = make_unique<Joystick>(Controller::Jack::Right, myEvent, *mySystem);
// Let the cart know how to query for the 'Cartridge.StartBank' property
myCart->setStartBankFromPropsFunc([this]() {
@ -819,13 +819,13 @@ void Console::setControllers(const string& rommd5)
if(image != nullptr || size != 0)
{
left = ControllerDetector::detectType(image, size, left,
!swappedPorts ? Controller::Left : Controller::Right, myOSystem.settings());
!swappedPorts ? Controller::Jack::Left : Controller::Jack::Right, myOSystem.settings());
right = ControllerDetector::detectType(image, size, right,
!swappedPorts ? Controller::Right : Controller::Left, myOSystem.settings());
!swappedPorts ? Controller::Jack::Right : Controller::Jack::Left, myOSystem.settings());
}
unique_ptr<Controller> leftC = getControllerPort(rommd5, left, Controller::Left),
rightC = getControllerPort(rommd5, right, Controller::Right);
unique_ptr<Controller> leftC = getControllerPort(rommd5, left, Controller::Jack::Left),
rightC = getControllerPort(rommd5, right, Controller::Jack::Right);
// Swap the ports if necessary
if(!swappedPorts)

View File

@ -21,22 +21,17 @@
#ifndef CONSOLE_IO_HXX
#define CONSOLE_IO_HXX
class ConsoleIO {
class ConsoleIO
{
public:
/**
Get the controller plugged into the specified jack
@return The specified controller
*/
virtual Controller& leftController() const = 0;
virtual Controller& rightController() const = 0;
Controller& controller(Controller::Jack jack) const {
return jack == Controller::Left ? leftController() : rightController();
}
/**
Get the console switches

View File

@ -29,105 +29,31 @@ Controller::Controller(Jack jack, const Event& event, const System& system,
myType(type),
myOnAnalogPinUpdateCallback(nullptr)
{
myDigitalPinState[One] =
myDigitalPinState[Two] =
myDigitalPinState[Three] =
myDigitalPinState[Four] =
myDigitalPinState[Six] = true;
myAnalogPinValue[Five] =
myAnalogPinValue[Nine] = MAX_RESISTANCE;
switch(myType)
{
case Joystick:
myName = "Joystick";
break;
case Paddles:
myName = "Paddles";
break;
case BoosterGrip:
myName = "BoosterGrip";
break;
case Driving:
myName = "Driving";
break;
case Keyboard:
myName = "Keyboard";
break;
case AmigaMouse:
myName = "AmigaMouse";
break;
case AtariMouse:
myName = "AtariMouse";
break;
case TrakBall:
myName = "TrakBall";
break;
case AtariVox:
myName = "AtariVox";
break;
case SaveKey:
myName = "SaveKey";
break;
case KidVid:
myName = "KidVid";
break;
case Genesis:
myName = "Genesis";
break;
case MindLink:
myName = "MindLink";
break;
case CompuMate:
myName = "CompuMate";
break;
}
resetDigitalPins();
resetAnalogPins();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 Controller::read()
{
uInt8 ioport = 0x00;
if(read(One)) ioport |= 0x01;
if(read(Two)) ioport |= 0x02;
if(read(Three)) ioport |= 0x04;
if(read(Four)) ioport |= 0x08;
uInt8 ioport = 0b0000;
if(read(DigitalPin::One)) ioport |= 0b0001;
if(read(DigitalPin::Two)) ioport |= 0b0010;
if(read(DigitalPin::Three)) ioport |= 0b0100;
if(read(DigitalPin::Four)) ioport |= 0b1000;
return ioport;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Controller::read(DigitalPin pin)
{
return myDigitalPinState[pin];
return getPin(pin);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int32 Controller::read(AnalogPin pin)
{
return myAnalogPinValue[pin];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Controller::set(DigitalPin pin, bool value)
{
myDigitalPinState[pin] = value;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Controller::set(AnalogPin pin, Int32 value)
{
updateAnalogPin(pin, value);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Controller::updateAnalogPin(AnalogPin pin, Int32 value)
{
myAnalogPinValue[pin] = value;
if (myOnAnalogPinUpdateCallback) {
myOnAnalogPinUpdateCallback(pin);
}
return getPin(pin);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -136,15 +62,15 @@ bool Controller::save(Serializer& out) const
try
{
// Output the digital pins
out.putBool(myDigitalPinState[One]);
out.putBool(myDigitalPinState[Two]);
out.putBool(myDigitalPinState[Three]);
out.putBool(myDigitalPinState[Four]);
out.putBool(myDigitalPinState[Six]);
out.putBool(getPin(DigitalPin::One));
out.putBool(getPin(DigitalPin::Two));
out.putBool(getPin(DigitalPin::Three));
out.putBool(getPin(DigitalPin::Four));
out.putBool(getPin(DigitalPin::Six));
// Output the analog pins
out.putInt(myAnalogPinValue[Five]);
out.putInt(myAnalogPinValue[Nine]);
out.putInt(getPin(AnalogPin::Five));
out.putInt(getPin(AnalogPin::Nine));
}
catch(...)
{
@ -160,15 +86,15 @@ bool Controller::load(Serializer& in)
try
{
// Input the digital pins
myDigitalPinState[One] = in.getBool();
myDigitalPinState[Two] = in.getBool();
myDigitalPinState[Three] = in.getBool();
myDigitalPinState[Four] = in.getBool();
myDigitalPinState[Six] = in.getBool();
setPin(DigitalPin::One, in.getBool());
setPin(DigitalPin::Two, in.getBool());
setPin(DigitalPin::Three, in.getBool());
setPin(DigitalPin::Four, in.getBool());
setPin(DigitalPin::Six, in.getBool());
// Input the analog pins
myAnalogPinValue[Five] = in.getInt();
myAnalogPinValue[Nine] = in.getInt();
setPin(AnalogPin::Five, in.getInt());
setPin(AnalogPin::Nine, in.getInt());
}
catch(...)
{

View File

@ -19,6 +19,7 @@
#define CONTROLLER_HXX
class Controller;
class ControllerLowLevel;
class Event;
class System;
@ -64,30 +65,30 @@ class Controller : public Serializable
/**
Various classes that need special access to the underlying controller state
*/
friend class M6532;
friend class RiotDebug;
friend class M6532; // FIXME - only needs two methods from this class
friend class CompuMate;
friend class ControllerLowLevel;
public:
/**
Enumeration of the controller jacks
*/
enum Jack { Left = 0, Right = 1 };
enum class Jack { Left = 0, Right = 1 };
/**
Enumeration of the digital pins of a controller port
*/
enum DigitalPin { One, Two, Three, Four, Six };
enum class DigitalPin { One, Two, Three, Four, Six };
/**
Enumeration of the analog pins of a controller port
*/
enum AnalogPin { Five, Nine };
enum class AnalogPin { Five, Nine };
/**
Enumeration of the controller types
*/
enum Type
enum class Type
{
AmigaMouse, AtariMouse, AtariVox, BoosterGrip, CompuMate,
Driving, Genesis, Joystick, Keyboard, KidVid, MindLink,
@ -176,6 +177,11 @@ class Controller : public Serializable
*/
virtual void update() = 0;
/**
Returns the name of this controller.
*/
virtual string name() const = 0;
/**
Answers whether the controller is intrinsically an analog controller.
Specific controllers should override and implement this method.
@ -221,22 +227,10 @@ class Controller : public Serializable
*/
virtual string about(bool swappedPorts) const
{
return name() + " in " + (((myJack == Left) ^ swappedPorts) ?
return name() + " in " + (((myJack == Jack::Left) ^ swappedPorts) ?
"left port" : "right port");
}
/**
The following two functions are used by the debugger to set
the specified pins to the given value. Note that this isn't the
same as a write; the debugger is allowed special access and is
actually 'below' the controller level.
@param pin The pin of the controller jack to modify
@param value The value to set on the pin
*/
void set(DigitalPin pin, bool value);
void set(AnalogPin pin, Int32 value);
/**
Saves the current state of this controller to the given Serializer.
@ -253,11 +247,6 @@ class Controller : public Serializable
*/
bool load(Serializer& in) override;
/**
Returns the name of this controller.
*/
string name() const { return myName; }
/**
Inject a callback to be notified on analog pin updates.
*/
@ -273,7 +262,35 @@ class Controller : public Serializable
static constexpr Int32 MIN_RESISTANCE = 0x00000000;
protected:
void updateAnalogPin(AnalogPin, Int32 value);
/**
Derived classes *must* use these accessor/mutator methods.
The read/write methods above are meant to be used at a higher level.
*/
inline bool setPin(DigitalPin pin, bool value) {
return myDigitalPinState[static_cast<int>(pin)] = value;
}
inline bool getPin(DigitalPin pin) const {
return myDigitalPinState[static_cast<int>(pin)];
}
inline void setPin(AnalogPin pin, Int32 value) {
myAnalogPinValue[static_cast<int>(pin)] = value;
if(myOnAnalogPinUpdateCallback)
myOnAnalogPinUpdateCallback(pin);
}
inline Int32 getPin(AnalogPin pin) const {
return myAnalogPinValue[static_cast<int>(pin)];
}
inline void resetDigitalPins() {
setPin(DigitalPin::One, true);
setPin(DigitalPin::Two, true);
setPin(DigitalPin::Three, true);
setPin(DigitalPin::Four, true);
setPin(DigitalPin::Six, true);
}
inline void resetAnalogPins() {
setPin(AnalogPin::Five, MAX_RESISTANCE);
setPin(AnalogPin::Nine, MAX_RESISTANCE);
}
protected:
/// Specifies which jack the controller is plugged in
@ -288,16 +305,13 @@ class Controller : public Serializable
/// Specifies which type of controller this is (defined by child classes)
const Type myType;
/// Specifies the name of this controller based on type
string myName;
/// The boolean value on each digital pin
bool myDigitalPinState[5];
/// The callback that is dispatched whenver an analog pin has changed
onAnalogPinUpdateCallback myOnAnalogPinUpdateCallback;
private:
/// The boolean value on each digital pin
bool myDigitalPinState[5];
/// The analog value on each analog pin
Int32 myAnalogPinValue[2];

View File

@ -0,0 +1,73 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#ifndef CONTROLLER_LOW_LEVEL_HXX
#define CONTROLLER_LOW_LEVEL_HXX
#include "Control.hxx"
/**
Some subsystems (ie, the debugger) need low-level access to the controller
ports. In particular, they need to be able to bypass the normal read/write
methods and operate directly on the individual pins. This class provides
an abstraction for that functionality.
Classes that inherit from this class will have low-level access to the
Controller class, since it is a 'friend' of that class.
@author Stephen Anthony
*/
class ControllerLowLevel
{
public:
ControllerLowLevel(Controller& controller) : myController(controller) { }
virtual ~ControllerLowLevel() = default;
inline bool setPin(Controller::DigitalPin pin, bool value) {
return myController.setPin(pin, value);
}
inline bool togglePin(Controller::DigitalPin pin) { return false; }
inline bool getPin(Controller::DigitalPin pin) const {
return myController.getPin(pin);
}
inline void setPin(Controller::AnalogPin pin, Int32 value) {
myController.setPin(pin, value);
}
inline Int32 getPin(Controller::AnalogPin pin) const {
return myController.getPin(pin);
}
inline void resetDigitalPins() {
myController.resetDigitalPins();
}
inline void resetAnalogPins() {
myController.resetAnalogPins();
}
inline Controller& base() const { return myController; }
protected:
Controller& myController;
private:
// Following constructors and assignment operators not supported
ControllerLowLevel() = delete;
ControllerLowLevel(const ControllerLowLevel&) = delete;
ControllerLowLevel(ControllerLowLevel&&) = delete;
ControllerLowLevel& operator=(const ControllerLowLevel&) = delete;
ControllerLowLevel& operator=(ControllerLowLevel&&) = delete;
};
#endif

View File

@ -107,7 +107,7 @@ bool ControllerDetector::searchForBytes(const uInt8* image, uInt32 imagesize,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool ControllerDetector::usesJoystickButton(const uInt8* image, uInt32 size, Controller::Jack port)
{
if(port == Controller::Left)
if(port == Controller::Jack::Left)
{
// check for INPT4 access
const int NUM_SIGS_0 = 17;
@ -164,7 +164,7 @@ bool ControllerDetector::usesJoystickButton(const uInt8* image, uInt32 size, Con
if(searchForBytes(image, size, signature_2[i], SIG_SIZE_2))
return true;
}
else if(port == Controller::Right)
else if(port == Controller::Jack::Right)
{
// check for INPT5 and indexed INPT4 access
const int NUM_SIGS_0 = 13;
@ -217,7 +217,7 @@ bool ControllerDetector::usesJoystickButton(const uInt8* image, uInt32 size, Con
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool ControllerDetector::usesKeyboard(const uInt8* image, uInt32 size, Controller::Jack port)
{
if(port == Controller::Left)
if(port == Controller::Jack::Left)
{
// check for INPT0 *AND* INPT1 access
const int NUM_SIGS_0_0 = 4;
@ -279,7 +279,7 @@ bool ControllerDetector::usesKeyboard(const uInt8* image, uInt32 size, Controlle
}
}
}
else if(port == Controller::Right)
else if(port == Controller::Jack::Right)
{
// check for INPT2 *AND* INPT3 access
const int NUM_SIGS_0_0 = 3;
@ -347,7 +347,7 @@ bool ControllerDetector::usesKeyboard(const uInt8* image, uInt32 size, Controlle
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool ControllerDetector::usesGenesisButton(const uInt8* image, uInt32 size, Controller::Jack port)
{
if(port == Controller::Left)
if(port == Controller::Jack::Left)
{
// check for INPT1 access
const int NUM_SIGS_0 = 13;
@ -371,7 +371,7 @@ bool ControllerDetector::usesGenesisButton(const uInt8* image, uInt32 size, Cont
if(searchForBytes(image, size, signature_0[i], SIG_SIZE_0))
return true;
}
else if(port == Controller::Right)
else if(port == Controller::Jack::Right)
{
// check for INPT3 access
const int NUM_SIGS_0 = 9;
@ -398,7 +398,7 @@ bool ControllerDetector::usesGenesisButton(const uInt8* image, uInt32 size, Cont
bool ControllerDetector::usesPaddle(const uInt8* image, uInt32 size,
Controller::Jack port, const Settings& settings)
{
if(port == Controller::Left)
if(port == Controller::Jack::Left)
{
// check for INPT0 access
const int NUM_SIGS_0 = 12;
@ -448,7 +448,7 @@ bool ControllerDetector::usesPaddle(const uInt8* image, uInt32 size,
if(searchForBytes(image, size, signature_2[i], SIG_SIZE_2))
return true;
}
else if(port == Controller::Right)
else if(port == Controller::Jack::Right)
{
// check for INPT2 and indexed INPT0 access
const int NUM_SIGS_0 = 18;
@ -564,7 +564,7 @@ bool ControllerDetector::isProbablyAmigaMouse(const uInt8* image, uInt32 size)
bool ControllerDetector::isProbablySaveKey(const uInt8* image, uInt32 size, Controller::Jack port)
{
// check for known SaveKey code, only supports right port
if(port == Controller::Right)
if(port == Controller::Jack::Right)
{
const int NUM_SIGS = 4;
const int SIG_SIZE = 9;

View File

@ -22,7 +22,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Driving::Driving(Jack jack, const Event& event, const System& system)
: Controller(jack, event, system, Controller::Driving),
: Controller(jack, event, system, Controller::Type::Driving),
myCounter(0),
myGrayIndex(0),
myLastYaxis(0),
@ -30,7 +30,7 @@ Driving::Driving(Jack jack, const Event& event, const System& system)
myControlIDX(-1),
myControlIDY(-1)
{
if(myJack == Left)
if(myJack == Jack::Left)
{
myCCWEvent = Event::JoystickZeroLeft;
myCWEvent = Event::JoystickZeroRight;
@ -48,7 +48,8 @@ Driving::Driving(Jack jack, const Event& event, const System& system)
}
// Digital pins 3 and 4 are not connected
myDigitalPinState[Three] = myDigitalPinState[Four] = true;
setPin(DigitalPin::Three, true);
setPin(DigitalPin::Four, true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -59,7 +60,7 @@ void Driving::update()
myCounter = (myGrayIndex << 2) | (myCounter & 3);
// Digital events (from keyboard or joystick hats & buttons)
myDigitalPinState[Six] = (myEvent.get(myFireEvent) == 0);
setPin(DigitalPin::Six, myEvent.get(myFireEvent) == 0);
int d_axis = myEvent.get(myXAxisValue);
if(myEvent.get(myCCWEvent) != 0 || d_axis < -16384) --myCounter;
else if(myEvent.get(myCWEvent) != 0 || d_axis > 16384) ++myCounter;
@ -72,7 +73,7 @@ void Driving::update()
else if(m_axis > 2) ++myCounter;
if(myEvent.get(Event::MouseButtonLeftValue) ||
myEvent.get(Event::MouseButtonRightValue))
myDigitalPinState[Six] = false;
setPin(DigitalPin::Six, false);
}
else
{
@ -84,7 +85,7 @@ void Driving::update()
if(m_axis < -2) --myCounter;
else if(m_axis > 2) ++myCounter;
if(myEvent.get(Event::MouseButtonLeftValue))
myDigitalPinState[Six] = false;
setPin(DigitalPin::Six, false);
}
if(myControlIDY > -1)
{
@ -92,7 +93,7 @@ void Driving::update()
if(m_axis < -2) --myCounter;
else if(m_axis > 2) ++myCounter;
if(myEvent.get(Event::MouseButtonRightValue))
myDigitalPinState[Six] = false;
setPin(DigitalPin::Six, false);
}
}
@ -123,8 +124,8 @@ void Driving::update()
// Determine which bits are set
uInt8 gray = graytable[myGrayIndex];
myDigitalPinState[One] = (gray & 0x1) != 0;
myDigitalPinState[Two] = (gray & 0x2) != 0;
setPin(DigitalPin::One, (gray & 0x1) != 0);
setPin(DigitalPin::Two, (gray & 0x2) != 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -133,10 +134,10 @@ bool Driving::setMouseControl(
{
// When the mouse emulates a single driving controller, only the X-axis is
// used, and both mouse buttons map to the same 'fire' event
if(xtype == Controller::Driving && ytype == Controller::Driving && xid == yid)
if(xtype == Controller::Type::Driving && ytype == Controller::Type::Driving && xid == yid)
{
myControlID = ((myJack == Left && xid == 0) ||
(myJack == Right && xid == 1)
myControlID = ((myJack == Jack::Left && xid == 0) ||
(myJack == Jack::Right && xid == 1)
) ? xid : -1;
myControlIDX = myControlIDY = -1;
}
@ -145,15 +146,15 @@ bool Driving::setMouseControl(
// Otherwise, each axis can be mapped to a separate driving controller,
// and the buttons map to separate (corresponding) controllers
myControlID = -1;
if(myJack == Left)
if(myJack == Jack::Left)
{
myControlIDX = (xtype == Controller::Driving && xid == 0) ? 0 : -1;
myControlIDY = (ytype == Controller::Driving && yid == 0) ? 0 : -1;
myControlIDX = (xtype == Controller::Type::Driving && xid == 0) ? 0 : -1;
myControlIDY = (ytype == Controller::Type::Driving && yid == 0) ? 0 : -1;
}
else // myJack == Right
{
myControlIDX = (xtype == Controller::Driving && xid == 1) ? 1 : -1;
myControlIDY = (ytype == Controller::Driving && yid == 1) ? 1 : -1;
myControlIDX = (xtype == Controller::Type::Driving && xid == 1) ? 1 : -1;
myControlIDY = (ytype == Controller::Type::Driving && yid == 1) ? 1 : -1;
}
}

View File

@ -47,6 +47,11 @@ class Driving : public Controller
*/
void update() override;
/**
Returns the name of this controller.
*/
string name() const override { return "Driving"; }
/**
Answers whether the controller is intrinsically an analog controller.
*/

View File

@ -1093,8 +1093,8 @@ void EventHandler::setMouseControllerMode(const string& enable)
usemouse = false;
else // 'analog'
{
usemouse = myOSystem.console().controller(Controller::Left).isAnalog() ||
myOSystem.console().controller(Controller::Right).isAnalog();
usemouse = myOSystem.console().leftController().isAnalog() ||
myOSystem.console().rightController().isAnalog();
}
const string& control = usemouse ?
@ -1202,7 +1202,7 @@ void EventHandler::setState(EventHandlerState state)
case EventHandlerState::EMULATION:
myOSystem.sound().mute(false);
enableTextEvents(false);
if(myOSystem.console().leftController().type() == Controller::CompuMate)
if(myOSystem.console().leftController().type() == Controller::Type::CompuMate)
myPKeyHandler->useCtrlKey() = false;
break;

View File

@ -759,8 +759,8 @@ void FrameBuffer::setCursorState()
bool emulation =
myOSystem.eventHandler().state() == EventHandlerState::EMULATION;
bool analog = myOSystem.hasConsole() ?
(myOSystem.console().controller(Controller::Left).isAnalog() ||
myOSystem.console().controller(Controller::Right).isAnalog()) : false;
(myOSystem.console().leftController().isAnalog() ||
myOSystem.console().rightController().isAnalog()) : false;
bool alwaysUseMouse = BSPF::equalsIgnoreCase("always", myOSystem.settings().getString("usemouse"));
grabMouse(emulation && (analog || alwaysUseMouse) && myGrabMouse);

View File

@ -20,10 +20,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Genesis::Genesis(Jack jack, const Event& event, const System& system)
: Controller(jack, event, system, Controller::Genesis),
: Controller(jack, event, system, Controller::Type::Genesis),
myControlID(-1)
{
if(myJack == Left)
if(myJack == Jack::Left)
{
myUpEvent = Event::JoystickZeroUp;
myDownEvent = Event::JoystickZeroDown;
@ -42,25 +42,24 @@ Genesis::Genesis(Jack jack, const Event& event, const System& system)
myFire2Event = Event::JoystickOneFire5;
}
updateAnalogPin(Five, MIN_RESISTANCE);
updateAnalogPin(Nine, MIN_RESISTANCE);
setPin(AnalogPin::Five, MIN_RESISTANCE);
setPin(AnalogPin::Nine, MIN_RESISTANCE);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Genesis::update()
{
// Digital events (from keyboard or joystick hats & buttons)
myDigitalPinState[One] = (myEvent.get(myUpEvent) == 0);
myDigitalPinState[Two] = (myEvent.get(myDownEvent) == 0);
myDigitalPinState[Three] = (myEvent.get(myLeftEvent) == 0);
myDigitalPinState[Four] = (myEvent.get(myRightEvent) == 0);
myDigitalPinState[Six] = (myEvent.get(myFire1Event) == 0);
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);
setPin(DigitalPin::Six, myEvent.get(myFire1Event) == 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
updateAnalogPin(
Five,
setPin(AnalogPin::Five,
(myEvent.get(myFire2Event) == 0) ? MIN_RESISTANCE : MAX_RESISTANCE
);
@ -76,24 +75,24 @@ void Genesis::update()
if((!(abs(mousey) > abs(mousex) << 1)) && (abs(mousex) >= MJ_Threshold))
{
if(mousex < 0)
myDigitalPinState[Three] = false;
else if (mousex > 0)
myDigitalPinState[Four] = false;
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)
myDigitalPinState[One] = false;
setPin(DigitalPin::One, false);
else if(mousey > 0)
myDigitalPinState[Two] = false;
setPin(DigitalPin::Two, false);
}
}
// Get mouse button state
if(myEvent.get(Event::MouseButtonLeftValue))
myDigitalPinState[Six] = false;
setPin(DigitalPin::Six, false);
if(myEvent.get(Event::MouseButtonRightValue))
updateAnalogPin(Five, MAX_RESISTANCE);
setPin(AnalogPin::Five, MAX_RESISTANCE);
}
}
@ -104,10 +103,10 @@ bool Genesis::setMouseControl(
// 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::Genesis && ytype == Controller::Genesis && xid == yid)
if(xtype == Controller::Type::Genesis && ytype == Controller::Type::Genesis && xid == yid)
{
myControlID = ((myJack == Left && xid == 0) ||
(myJack == Right && xid == 1)
myControlID = ((myJack == Jack::Left && xid == 0) ||
(myJack == Jack::Right && xid == 1)
) ? xid : -1;
}
else

View File

@ -50,6 +50,11 @@ class Genesis : public Controller
*/
void update() override;
/**
Returns the name of this controller.
*/
string name() const override { return "Genesis"; }
/**
Determines how this controller will treat values received from the
X/Y axis and left/right buttons of the mouse. Since not all controllers

View File

@ -20,10 +20,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Joystick::Joystick(Jack jack, const Event& event, const System& system)
: Controller(jack, event, system, Controller::Joystick),
: Controller(jack, event, system, Controller::Type::Joystick),
myControlID(-1)
{
if(myJack == Left)
if(myJack == Jack::Left)
{
myUpEvent = Event::JoystickZeroUp;
myDownEvent = Event::JoystickZeroDown;
@ -49,33 +49,33 @@ Joystick::Joystick(Jack jack, const Event& event, const System& system)
void Joystick::update()
{
// Digital events (from keyboard or joystick hats & buttons)
myDigitalPinState[One] = (myEvent.get(myUpEvent) == 0);
myDigitalPinState[Two] = (myEvent.get(myDownEvent) == 0);
myDigitalPinState[Three] = (myEvent.get(myLeftEvent) == 0);
myDigitalPinState[Four] = (myEvent.get(myRightEvent) == 0);
myDigitalPinState[Six] = (myEvent.get(myFireEvent) == 0);
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);
setPin(DigitalPin::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;
setPin(DigitalPin::Four, false);
// Stelladaptor sends "half moved right" for L+R pushed together
if(xaxis < 16384+4096)
myDigitalPinState[Three] = false;
setPin(DigitalPin::Three, false);
}
else if(xaxis < -16384)
myDigitalPinState[Three] = false;
setPin(DigitalPin::Three, false);
if(yaxis > 16384-4096)
{
myDigitalPinState[Two] = false;
setPin(DigitalPin::Two, false);
// Stelladaptor sends "half moved down" for U+D pushed together
if(yaxis < 16384+4096)
myDigitalPinState[One] = false;
setPin(DigitalPin::One, false);
}
else if(yaxis < -16384)
myDigitalPinState[One] = false;
setPin(DigitalPin::One, false);
// Mouse motion and button events
if(myControlID > -1)
@ -89,23 +89,23 @@ void Joystick::update()
if((!(abs(mousey) > abs(mousex) << 1)) && (abs(mousex) >= MJ_Threshold))
{
if(mousex < 0)
myDigitalPinState[Three] = false;
else if (mousex > 0)
myDigitalPinState[Four] = false;
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)
myDigitalPinState[One] = false;
setPin(DigitalPin::One, false);
else if(mousey > 0)
myDigitalPinState[Two] = false;
setPin(DigitalPin::Two, false);
}
}
// Get mouse button state
if(myEvent.get(Event::MouseButtonLeftValue) ||
myEvent.get(Event::MouseButtonRightValue))
myDigitalPinState[Six] = false;
setPin(DigitalPin::Six, false);
}
}
@ -116,10 +116,10 @@ bool Joystick::setMouseControl(
// 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::Joystick && ytype == Controller::Joystick && xid == yid)
if(xtype == Controller::Type::Joystick && ytype == Controller::Type::Joystick && xid == yid)
{
myControlID = ((myJack == Left && xid == 0) ||
(myJack == Right && xid == 1)
myControlID = ((myJack == Jack::Left && xid == 0) ||
(myJack == Jack::Right && xid == 1)
) ? xid : -1;
}
else

View File

@ -47,6 +47,11 @@ class Joystick : public Controller
*/
void update() override;
/**
Returns the name of this controller.
*/
string name() const override { return "Joystick"; }
/**
Determines how this controller will treat values received from the
X/Y axis and left/right buttons of the mouse. Since not all controllers

View File

@ -20,9 +20,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Keyboard::Keyboard(Jack jack, const Event& event, const System& system)
: Controller(jack, event, system, Controller::Keyboard)
: Controller(jack, event, system, Controller::Type::Keyboard)
{
if(myJack == Left)
if(myJack == Jack::Left)
{
myOneEvent = Event::KeyboardZero1;
myTwoEvent = Event::KeyboardZero2;
@ -57,43 +57,41 @@ Keyboard::Keyboard(Jack jack, const Event& event, const System& system)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Keyboard::write(DigitalPin pin, bool value)
{
myDigitalPinState[pin] = value;
setPin(pin, value);
// Set defaults
myDigitalPinState[Six] = true;
setPin(DigitalPin::Six, true);
Int32 resistanceFive = MIN_RESISTANCE;
Int32 resistanceNine = MIN_RESISTANCE;
// Now scan the rows and columns
if(!myDigitalPinState[Four])
if(!getPin(DigitalPin::Four))
{
myDigitalPinState[Six] = (myEvent.get(myPoundEvent) == 0);
setPin(DigitalPin::Six, myEvent.get(myPoundEvent) == 0);
if(myEvent.get(myZeroEvent) != 0) resistanceFive = MAX_RESISTANCE;
if(myEvent.get(myStarEvent) != 0) resistanceNine = MAX_RESISTANCE;
}
if(!myDigitalPinState[Three])
if(!getPin(DigitalPin::Three))
{
myDigitalPinState[Six] = (myEvent.get(myNineEvent) == 0);
setPin(DigitalPin::Six, myEvent.get(myNineEvent) == 0);
if(myEvent.get(myEightEvent) != 0) resistanceFive = MAX_RESISTANCE;
if(myEvent.get(mySevenEvent) != 0) resistanceNine = MAX_RESISTANCE;
}
if(!myDigitalPinState[Two])
if(!getPin(DigitalPin::Two))
{
myDigitalPinState[Six] = (myEvent.get(mySixEvent) == 0);
setPin(DigitalPin::Six, myEvent.get(mySixEvent) == 0);
if(myEvent.get(myFiveEvent) != 0) resistanceFive = MAX_RESISTANCE;
if(myEvent.get(myFourEvent) != 0) resistanceNine = MAX_RESISTANCE;
}
if(!myDigitalPinState[One])
if(!getPin(DigitalPin::One))
{
myDigitalPinState[Six] = (myEvent.get(myThreeEvent) == 0);
setPin(DigitalPin::Six, myEvent.get(myThreeEvent) == 0);
if(myEvent.get(myTwoEvent) != 0) resistanceFive = MAX_RESISTANCE;
if(myEvent.get(myOneEvent) != 0) resistanceNine = MAX_RESISTANCE;
}
if (resistanceFive != read(Five)) {
updateAnalogPin(Five, resistanceFive);
}
if (resistanceNine != read(Nine))
updateAnalogPin(Nine, resistanceNine);
if(resistanceFive != read(AnalogPin::Five))
setPin(AnalogPin::Five, resistanceFive);
if(resistanceNine != read(AnalogPin::Nine))
setPin(AnalogPin::Nine, resistanceNine);
}

View File

@ -57,6 +57,11 @@ class Keyboard : public Controller
*/
void update() override { }
/**
Returns the name of this controller.
*/
string name() const override { return "Keyboard"; }
private:
// Pre-compute the events we care about based on given port
// This will eliminate test for left or right port in update()

View File

@ -23,8 +23,8 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KidVid::KidVid(Jack jack, const Event& event, const System& system,
const string& rommd5)
: Controller(jack, event, system, Controller::KidVid),
myEnabled(myJack == Right),
: Controller(jack, event, system, Controller::Type::KidVid),
myEnabled(myJack == Jack::Right),
// mySampleFile(nullptr),
// mySharedSampleFile(nullptr),
myFileOpened(false),
@ -104,16 +104,16 @@ cerr << "myTape = " << myTape << endl;
}
// Convert separate pin states into a 'register'
uInt8 IOPortA = 0xf0;
if(myDigitalPinState[One]) IOPortA |= 0x01;
if(myDigitalPinState[Two]) IOPortA |= 0x02;
if(myDigitalPinState[Three]) IOPortA |= 0x04;
if(myDigitalPinState[Four]) IOPortA |= 0x08;
uInt8 IOPortA = 0b11110000;
if(getPin(DigitalPin::One)) IOPortA |= 0b0001;
if(getPin(DigitalPin::Two)) IOPortA |= 0b0010;
if(getPin(DigitalPin::Three)) IOPortA |= 0b0100;
if(getPin(DigitalPin::Four)) IOPortA |= 0b1000;
// Is the tape running?
if((myTape != 0) && ((IOPortA & 0x01) == 0x01) && !myTapeBusy)
if((myTape != 0) && ((IOPortA & 0b0001) == 0b0001) && !myTapeBusy)
{
IOPortA = (IOPortA & 0xf7) | (((ourKVData[myIdx >> 3] << (myIdx & 0x07)) & 0x80) >> 4);
IOPortA = (IOPortA & 0b11110111) | (((ourKVData[myIdx >> 3] << (myIdx & 0x07)) & 0x80) >> 4);
// increase to next bit
++myIdx;
@ -153,10 +153,10 @@ cerr << "myTape = " << myTape << endl;
}
// Now convert the register back into separate boolean values
myDigitalPinState[One] = IOPortA & 0x01;
myDigitalPinState[Two] = IOPortA & 0x02;
myDigitalPinState[Three] = IOPortA & 0x04;
myDigitalPinState[Four] = IOPortA & 0x08;
setPin(DigitalPin::One, IOPortA & 0b0001);
setPin(DigitalPin::Two, IOPortA & 0b0010);
setPin(DigitalPin::Three, IOPortA & 0b0100);
setPin(DigitalPin::Four, IOPortA & 0b1000);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -58,6 +58,11 @@ class KidVid : public Controller
*/
void update() override;
/**
Returns the name of this controller.
*/
string name() const override { return "KidVid"; }
private:
// Open/close a WAV sample file
void openSampleFile();

View File

@ -101,7 +101,7 @@ void M6532::update()
Controller& port1 = myConsole.rightController();
// Get current PA7 state
bool prevPA7 = port0.myDigitalPinState[Controller::Four];
bool prevPA7 = port0.getPin(Controller::DigitalPin::Four);
// Update entire port state
port0.update();
@ -109,7 +109,7 @@ void M6532::update()
myConsole.switches().update();
// Get new PA7 state
bool currPA7 = port0.myDigitalPinState[Controller::Four];
bool currPA7 = port0.getPin(Controller::DigitalPin::Four);
// PA7 Flag is set on active transition in appropriate direction
if((!myEdgeDetectPositive && prevPA7 && !currPA7) ||
@ -347,14 +347,14 @@ void M6532::setPinState(bool swcha)
uInt8 ioport = myOutA | ~myDDRA;
port0.write(Controller::One, ioport & 0x10);
port0.write(Controller::Two, ioport & 0x20);
port0.write(Controller::Three, ioport & 0x40);
port0.write(Controller::Four, ioport & 0x80);
port1.write(Controller::One, ioport & 0x01);
port1.write(Controller::Two, ioport & 0x02);
port1.write(Controller::Three, ioport & 0x04);
port1.write(Controller::Four, ioport & 0x08);
port0.write(Controller::DigitalPin::One, ioport & 0b00010000);
port0.write(Controller::DigitalPin::Two, ioport & 0b00100000);
port0.write(Controller::DigitalPin::Three, ioport & 0b01000000);
port0.write(Controller::DigitalPin::Four, ioport & 0b10000000);
port1.write(Controller::DigitalPin::One, ioport & 0b00000001);
port1.write(Controller::DigitalPin::Two, ioport & 0b00000010);
port1.write(Controller::DigitalPin::Three, ioport & 0b00000100);
port1.write(Controller::DigitalPin::Four, ioport & 0b00001000);
if(swcha)
{

View File

@ -20,24 +20,24 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MindLink::MindLink(Jack jack, const Event& event, const System& system)
: Controller(jack, event, system, Controller::MindLink),
: Controller(jack, event, system, Controller::Type::MindLink),
myMindlinkPos(0x2800),
myMindlinkShift(1),
myMouseEnabled(false)
{
myDigitalPinState[One] = true;
myDigitalPinState[Two] = true;
myDigitalPinState[Three] = true;
myDigitalPinState[Four] = true;
setPin(DigitalPin::One, true);
setPin(DigitalPin::Two, true);
setPin(DigitalPin::Three, true);
setPin(DigitalPin::Four, true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void MindLink::update()
{
myDigitalPinState[One] =
myDigitalPinState[Two] =
myDigitalPinState[Three] =
myDigitalPinState[Four] = true;
setPin(DigitalPin::One, true);
setPin(DigitalPin::Two, true);
setPin(DigitalPin::Three, true);
setPin(DigitalPin::Four, true);
if(!myMouseEnabled)
return;
@ -60,12 +60,12 @@ void MindLink::update()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void MindLink::nextMindlinkBit()
{
if(myDigitalPinState[One])
if(getPin(DigitalPin::One))
{
myDigitalPinState[Three] = false;
myDigitalPinState[Four] = false;
setPin(DigitalPin::Three, false);
setPin(DigitalPin::Four, false);
if(myMindlinkPos & myMindlinkShift)
myDigitalPinState[Four] = true;
setPin(DigitalPin::Four, true);
myMindlinkShift <<= 1;
}
}

View File

@ -59,7 +59,7 @@ class MindLink : public Controller
@param pin The pin of the controller jack to write to
@param value The value to write to the pin
*/
void write(DigitalPin pin, bool value) override { myDigitalPinState[pin] = value; }
void write(DigitalPin pin, bool value) override { setPin(pin, value); }
/**
Called after *all* digital pins have been written on Port A.
@ -72,6 +72,11 @@ class MindLink : public Controller
*/
void update() override;
/**
Returns the name of this controller.
*/
string name() const override { return "MindLink"; }
/**
Answers whether the controller is intrinsically an analog controller.
*/

View File

@ -21,15 +21,15 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Paddles::Paddles(Jack jack, const Event& event, const System& system,
bool swappaddle, bool swapaxis, bool swapdir)
: Controller(jack, event, system, Controller::Paddles),
: Controller(jack, event, system, Controller::Type::Paddles),
myMPaddleID(-1),
myMPaddleIDX(-1),
myMPaddleIDY(-1)
{
// We must start with minimum resistance; see commit
// 38b452e1a047a0dca38c5bcce7c271d40f76736e for more information
updateAnalogPin(Five, MIN_RESISTANCE);
updateAnalogPin(Nine, MIN_RESISTANCE);
setPin(AnalogPin::Five, MIN_RESISTANCE);
setPin(AnalogPin::Nine, MIN_RESISTANCE);
// The following logic reflects that mapping paddles to different
// devices can be extremely complex
@ -46,7 +46,7 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
// a given port; this will speed up processing in update()
// Consider whether this is the left or right port
if(myJack == Left)
if(myJack == Jack::Left)
{
if(!swappaddle) // First paddle is 0, second is 1
{
@ -215,9 +215,9 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
}
// Digital pins 1, 2 and 6 are not connected
myDigitalPinState[One] =
myDigitalPinState[Two] =
myDigitalPinState[Six] = true;
setPin(DigitalPin::One, true);
setPin(DigitalPin::Two, true);
setPin(DigitalPin::Six, true);
// Digital emulation of analog paddle movement
myKeyRepeat0 = myKeyRepeat1 = false;
@ -230,13 +230,14 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Paddles::update()
{
myDigitalPinState[Three] = myDigitalPinState[Four] = true;
setPin(DigitalPin::Three, true);
setPin(DigitalPin::Four, true);
// Digital events (from keyboard or joystick hats & buttons)
myDigitalPinState[Three] =
(myEvent.get(myP1FireEvent1) == 0 && myEvent.get(myP1FireEvent2) == 0);
myDigitalPinState[Four] =
(myEvent.get(myP0FireEvent1) == 0 && myEvent.get(myP0FireEvent2) == 0);
setPin(DigitalPin::Three,
myEvent.get(myP1FireEvent1) == 0 && myEvent.get(myP1FireEvent2) == 0);
setPin(DigitalPin::Four,
myEvent.get(myP0FireEvent1) == 0 && myEvent.get(myP0FireEvent2) == 0);
// Paddle movement is a very difficult thing to accurately emulate,
// since it originally came from an analog device that had very
@ -261,12 +262,12 @@ void Paddles::update()
int sa_yaxis = myEvent.get(myP1AxisValue);
if(abs(myLastAxisX - sa_xaxis) > 10)
{
updateAnalogPin(Nine, Int32(MAX_RESISTANCE * ((32767 - Int16(sa_xaxis)) / 65536.0)));
setPin(AnalogPin::Nine, Int32(MAX_RESISTANCE * ((32767 - Int16(sa_xaxis)) / 65536.0)));
sa_changed = true;
}
if(abs(myLastAxisY - sa_yaxis) > 10)
{
updateAnalogPin(Five, Int32(MAX_RESISTANCE * ((32767 - Int16(sa_yaxis)) / 65536.0)));
setPin(AnalogPin::Five, Int32(MAX_RESISTANCE * ((32767 - Int16(sa_yaxis)) / 65536.0)));
sa_changed = true;
}
myLastAxisX = sa_xaxis;
@ -284,7 +285,7 @@ void Paddles::update()
TRIGMIN, TRIGRANGE);
if(myEvent.get(Event::MouseButtonLeftValue) ||
myEvent.get(Event::MouseButtonRightValue))
myDigitalPinState[ourButtonPin[myMPaddleID]] = false;
setPin(ourButtonPin[myMPaddleID], false);
}
else
{
@ -296,7 +297,7 @@ void Paddles::update()
(myEvent.get(Event::MouseAxisXValue) * MOUSE_SENSITIVITY),
TRIGMIN, TRIGRANGE);
if(myEvent.get(Event::MouseButtonLeftValue))
myDigitalPinState[ourButtonPin[myMPaddleIDX]] = false;
setPin(ourButtonPin[myMPaddleIDX], false);
}
if(myMPaddleIDY > -1)
{
@ -304,7 +305,7 @@ void Paddles::update()
(myEvent.get(Event::MouseAxisYValue) * MOUSE_SENSITIVITY),
TRIGMIN, TRIGRANGE);
if(myEvent.get(Event::MouseButtonRightValue))
myDigitalPinState[ourButtonPin[myMPaddleIDY]] = false;
setPin(ourButtonPin[myMPaddleIDY], false);
}
}
@ -353,9 +354,9 @@ void Paddles::update()
// Only change state if the charge has actually changed
if(myCharge[1] != myLastCharge[1])
updateAnalogPin(Five, Int32(MAX_RESISTANCE * (myCharge[1] / float(TRIGMAX))));
setPin(AnalogPin::Five, Int32(MAX_RESISTANCE * (myCharge[1] / float(TRIGMAX))));
if(myCharge[0] != myLastCharge[0])
updateAnalogPin(Nine, Int32(MAX_RESISTANCE * (myCharge[0] / float(TRIGMAX))));
setPin(AnalogPin::Nine, Int32(MAX_RESISTANCE * (myCharge[0] / float(TRIGMAX))));
myLastCharge[1] = myCharge[1];
myLastCharge[0] = myCharge[0];
@ -368,10 +369,10 @@ bool Paddles::setMouseControl(
// In 'automatic' mode, both axes on the mouse map to a single paddle,
// and the paddle axis and direction settings are taken into account
// This overrides any other mode
if(xtype == Controller::Paddles && ytype == Controller::Paddles && xid == yid)
if(xtype == Controller::Type::Paddles && ytype == Controller::Type::Paddles && xid == yid)
{
myMPaddleID = ((myJack == Left && (xid == 0 || xid == 1)) ||
(myJack == Right && (xid == 2 || xid == 3))
myMPaddleID = ((myJack == Jack::Left && (xid == 0 || xid == 1)) ||
(myJack == Jack::Right && (xid == 2 || xid == 3))
) ? xid & 0x01 : -1;
myMPaddleIDX = myMPaddleIDY = -1;
}
@ -380,12 +381,12 @@ bool Paddles::setMouseControl(
// The following is somewhat complex, but we need to pre-process as much
// as possible, so that ::update() can run quickly
myMPaddleID = -1;
if(myJack == Left && xtype == Controller::Paddles)
if(myJack == Jack::Left && xtype == Controller::Type::Paddles)
{
myMPaddleIDX = (xid == 0 || xid == 1) ? xid & 0x01 : -1;
myMPaddleIDY = (yid == 0 || yid == 1) ? yid & 0x01 : -1;
}
else if(myJack == Right && ytype == Controller::Paddles)
else if(myJack == Jack::Right && ytype == Controller::Type::Paddles)
{
myMPaddleIDX = (xid == 2 || xid == 3) ? xid & 0x01 : -1;
myMPaddleIDY = (yid == 2 || yid == 3) ? yid & 0x01 : -1;
@ -422,4 +423,6 @@ int Paddles::DIGITAL_DISTANCE = -1;
int Paddles::MOUSE_SENSITIVITY = -1;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Controller::DigitalPin Paddles::ourButtonPin[2] = { Four, Three };
const Controller::DigitalPin Paddles::ourButtonPin[2] = {
DigitalPin::Four, DigitalPin::Three
};

View File

@ -54,6 +54,11 @@ class Paddles : public Controller
*/
void update() override;
/**
Returns the name of this controller.
*/
string name() const override { return "Paddles"; }
/**
Answers whether the controller is intrinsically an analog controller.
*/

View File

@ -71,10 +71,10 @@ uInt8 PointingDevice::read()
uInt8 portA = ioPortA(myCountH, myCountV, myTrackBallLeft, myTrackBallDown);
myDigitalPinState[One] = portA & 0b0001;
myDigitalPinState[Two] = portA & 0b0010;
myDigitalPinState[Three] = portA & 0b0100;
myDigitalPinState[Four] = portA & 0b1000;
setPin(DigitalPin::One, portA & 0b0001);
setPin(DigitalPin::Two, portA & 0b0010);
setPin(DigitalPin::Three, portA & 0b0100);
setPin(DigitalPin::Four, portA & 0b1000);
return portA;
}
@ -94,8 +94,8 @@ void PointingDevice::update()
myTrackBallDown, myTrackBallLinesV, myScanCountV, myFirstScanOffsetV);
// Get mouse button state
myDigitalPinState[Six] = (myEvent.get(Event::MouseButtonLeftValue) == 0) &&
(myEvent.get(Event::MouseButtonRightValue) == 0);
setPin(DigitalPin::Six, (myEvent.get(Event::MouseButtonLeftValue) == 0) &&
(myEvent.get(Event::MouseButtonRightValue) == 0));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -95,6 +95,8 @@ class PointingDevice : public Controller
// IOPortA values are calculated
virtual uInt8 ioPortA(uInt8 countH, uInt8 countV, uInt8 left, uInt8 down) = 0;
// virtual string pointingDeviceName() const = 0;
private:
void updateDirection(int counter, float& counterRemainder,
bool& trackBallDir, int& trackBallLines,

View File

@ -127,8 +127,8 @@ bool ProfilingRunner::runOne(const ProfilingRun run)
TIA tia(consoleIO, []() { return ConsoleTiming::ntsc; }, mySettings);
System system(rng, cpu, riot, tia, *cartridge);
consoleIO.myLeftControl = make_unique<Joystick>(Controller::Left, event, system);
consoleIO.myRightControl = make_unique<Joystick>(Controller::Right, event, system);
consoleIO.myLeftControl = make_unique<Joystick>(Controller::Jack::Left, event, system);
consoleIO.myRightControl = make_unique<Joystick>(Controller::Jack::Right, event, system);
consoleIO.mySwitches = make_unique<Switches>(event, myProps, mySettings);
tia.bindToControllers();

View File

@ -27,13 +27,14 @@ SaveKey::SaveKey(Jack jack, const Event& event, const System& system,
{
myEEPROM = make_unique<MT24LC256>(eepromfile, system, callback);
myDigitalPinState[One] = myDigitalPinState[Two] = true;
setPin(DigitalPin::One, true);
setPin(DigitalPin::Two, true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SaveKey::SaveKey(Jack jack, const Event& event, const System& system,
const string& eepromfile, onMessageCallback callback)
: SaveKey(jack, event, system, eepromfile, callback, Controller::SaveKey)
: SaveKey(jack, event, system, eepromfile, callback, Controller::Type::SaveKey)
{
}
@ -52,8 +53,8 @@ bool SaveKey::read(DigitalPin pin)
{
// Pin 3: EEPROM SDA
// input data from the 24LC256 EEPROM using the I2C protocol
case Three:
return myDigitalPinState[Three] = myEEPROM->readSDA();
case DigitalPin::Three:
return setPin(pin, myEEPROM->readSDA());
default:
return Controller::read(pin);
@ -68,15 +69,15 @@ void SaveKey::write(DigitalPin pin, bool value)
{
// Pin 3: EEPROM SDA
// output data to the 24LC256 EEPROM using the I2C protocol
case Three:
myDigitalPinState[Three] = value;
case DigitalPin::Three:
setPin(pin, value);
myEEPROM->writeSDA(value);
break;
// Pin 4: EEPROM SCL
// output clock data to the 24LC256 EEPROM using the I2C protocol
case Four:
myDigitalPinState[Four] = value;
case DigitalPin::Four:
setPin(pin, value);
myEEPROM->writeSCL(value);
break;

View File

@ -83,6 +83,11 @@ class SaveKey : public Controller
*/
void update() override { }
/**
Returns the name of this controller.
*/
string name() const override { return "SaveKey"; }
/**
Notification method invoked by the system after its reset method has
been called. It may be necessary to override this method for

View File

@ -31,10 +31,15 @@ class TrakBall : public PointingDevice
@param system The system using this controller
*/
TrakBall(Jack jack, const Event& event, const System& system)
: PointingDevice(jack, event, system, Controller::TrakBall,
: PointingDevice(jack, event, system, Controller::Type::TrakBall,
trackballSensitivity) { }
virtual ~TrakBall() = default;
/**
Returns the name of this controller.
*/
string name() const override { return "TrakBall"; }
protected:
uInt8 ioPortA(uInt8 countH, uInt8 countV, uInt8 left, uInt8 down) override
{

View File

@ -515,13 +515,13 @@ uInt8 TIA::peek(uInt16 address)
case INPT4:
result =
myInput0.inpt(!myConsole.leftController().read(Controller::Six)) |
myInput0.inpt(!myConsole.leftController().read(Controller::DigitalPin::Six)) |
(lastDataBusValue & 0x40);
break;
case INPT5:
result =
myInput1.inpt(!myConsole.rightController().read(Controller::Six)) |
myInput1.inpt(!myConsole.rightController().read(Controller::DigitalPin::Six)) |
(lastDataBusValue & 0x40);
break;
@ -1673,19 +1673,19 @@ void TIA::updatePaddle(uInt8 idx)
Int32 resistance;
switch (idx) {
case 0:
resistance = myConsole.leftController().read(Controller::Nine);
resistance = myConsole.leftController().read(Controller::AnalogPin::Nine);
break;
case 1:
resistance = myConsole.leftController().read(Controller::Five);
resistance = myConsole.leftController().read(Controller::AnalogPin::Five);
break;
case 2:
resistance = myConsole.rightController().read(Controller::Nine);
resistance = myConsole.rightController().read(Controller::AnalogPin::Nine);
break;
case 3:
resistance = myConsole.rightController().read(Controller::Five);
resistance = myConsole.rightController().read(Controller::AnalogPin::Five);
break;
default:

View File

@ -620,10 +620,10 @@ void GameInfoDialog::updateControllerStates()
const Controller& rport = instance().console().rightController();
// we only enable the button if we have a valid previous and new controller.
enableEEEraseButton = ((lport.type() == Controller::SaveKey && contrLeft == "SAVEKEY") ||
(rport.type() == Controller::SaveKey && contrRight == "SAVEKEY") ||
(lport.type() == Controller::AtariVox && contrLeft == "ATARIVOX") ||
(rport.type() == Controller::AtariVox && contrRight == "ATARIVOX"));
enableEEEraseButton = ((lport.type() == Controller::Type::SaveKey && contrLeft == "SAVEKEY") ||
(rport.type() == Controller::Type::SaveKey && contrRight == "SAVEKEY") ||
(lport.type() == Controller::Type::AtariVox && contrLeft == "ATARIVOX") ||
(rport.type() == Controller::Type::AtariVox && contrRight == "ATARIVOX"));
}
myLeftPortLabel->setEnabled(enableSelectControl);
@ -645,13 +645,13 @@ void GameInfoDialog::eraseEEPROM()
Controller& lport = instance().console().leftController();
Controller& rport = instance().console().rightController();
if(lport.type() == Controller::SaveKey || lport.type() == Controller::AtariVox)
if(lport.type() == Controller::Type::SaveKey || lport.type() == Controller::Type::AtariVox)
{
SaveKey& skey = static_cast<SaveKey&>(lport);
skey.eraseCurrent();
}
if(rport.type() == Controller::SaveKey || rport.type() == Controller::AtariVox)
if(rport.type() == Controller::Type::SaveKey || rport.type() == Controller::Type::AtariVox)
{
SaveKey& skey = static_cast<SaveKey&>(rport);
skey.eraseCurrent();

View File

@ -282,8 +282,8 @@ void InputDialog::loadConfig()
Controller& lport = instance().console().leftController();
Controller& rport = instance().console().rightController();
myEraseEEPROMButton->setEnabled(lport.type() == Controller::SaveKey || lport.type() == Controller::AtariVox ||
rport.type() == Controller::SaveKey || rport.type() == Controller::AtariVox);
myEraseEEPROMButton->setEnabled(lport.type() == Controller::Type::SaveKey || lport.type() == Controller::Type::AtariVox ||
rport.type() == Controller::Type::SaveKey || rport.type() == Controller::Type::AtariVox);
}
else
myEraseEEPROMButton->setEnabled(false);
@ -459,13 +459,13 @@ void InputDialog::eraseEEPROM()
Controller& lport = instance().console().leftController();
Controller& rport = instance().console().rightController();
if(lport.type() == Controller::SaveKey || lport.type() == Controller::AtariVox)
if(lport.type() == Controller::Type::SaveKey || lport.type() == Controller::Type::AtariVox)
{
SaveKey& skey = static_cast<SaveKey&>(lport);
skey.eraseCurrent();
}
if(rport.type() == Controller::SaveKey || rport.type() == Controller::AtariVox)
if(rport.type() == Controller::Type::SaveKey || rport.type() == Controller::Type::AtariVox)
{
SaveKey& skey = static_cast<SaveKey&>(rport);
skey.eraseCurrent();