More work on the CompuMate scheme. The logic for the Controllers is

now complete; I just need to define how to pass actual keyboard keys
through the Event system.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2413 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2012-03-14 22:24:54 +00:00
parent 47f151b87c
commit 82a4bc13b1
5 changed files with 117 additions and 27 deletions

View File

@ -108,6 +108,8 @@ class System;
*/
class CartridgeCM : public Cartridge
{
friend class CompuMate;
public:
/**
Create a new cartridge using the specified image

View File

@ -22,12 +22,15 @@
#include "CompuMate.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CompuMate::CompuMate(const Event& event, const System& system)
: mySystem(system),
CompuMate::CompuMate(CartridgeCM& cart, const Event& event,
const System& system)
: myCart(cart),
myEvent(event),
mySystem(system),
myLeftController(0),
myRightController(0),
myCycleAtLastUpdate(0),
myIOPort(0xff)
myColumn(0)
{
myLeftController = new CMControl(*this, Controller::Left, event, system);
myRightController = new CMControl(*this, Controller::Right, event, system);
@ -46,5 +49,95 @@ void CompuMate::update()
}
myCycleAtLastUpdate = cycle;
// TODO - handle SWCHA changes
// Handle SWCHA changes - the following comes almost directly from z26
Controller& lp = *myLeftController;
Controller& rp = *myRightController;
uInt8 IOPortA = (lp.read() << 4) | rp.read();
lp.myAnalogPinValue[Controller::Nine] = Controller::maximumResistance;
lp.myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
lp.myDigitalPinState[Controller::Six] = true;
rp.myAnalogPinValue[Controller::Nine] = Controller::minimumResistance;
rp.myAnalogPinValue[Controller::Five] = Controller::maximumResistance;
rp.myDigitalPinState[Controller::Six] = true;
uInt8& column = myCart.myColumn;
if(IOPortA & 0x20) column = 0;
if(IOPortA & 0x40) column = (column + 1) % 10;
IOPortA = IOPortA | (0x0c & 0x7f);
#if 0
switch(column)
{
case 0:
if (KeyTable[Key7]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyU]) IOPortA = IOPortA & 0xfb;
if (KeyTable[KeyJ]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyM]) IOPortA = IOPortA & 0xf7;
break;
case 1:
if (KeyTable[Key6]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyY]) IOPortA = IOPortA & 0xfb;
if (KeyTable[KeyH]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyN]) IOPortA = IOPortA & 0xf7;
break;
case 2:
if (KeyTable[Key8]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyI]) IOPortA = IOPortA & 0xfb;
if (KeyTable[KeyK]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyComma]) IOPortA = IOPortA & 0xf7;
break;
case 3:
if (KeyTable[Key2]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyW]) IOPortA = IOPortA & 0xfb;
if (KeyTable[KeyS]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyX]) IOPortA = IOPortA & 0xf7;
break;
case 4:
if (KeyTable[Key3]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyE]) IOPortA = IOPortA & 0xfb;
if (KeyTable[KeyD]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyC]) IOPortA = IOPortA & 0xf7;
break;
case 5:
if (KeyTable[Key0]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyP]) IOPortA = IOPortA & 0xfb;
if (KeyTable[KeyColon]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeySlash]) IOPortA = IOPortA & 0xf7;
break;
case 6:
if (KeyTable[Key9]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyO]) IOPortA = IOPortA & 0xfb;
if (KeyTable[KeyL]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyDot]) IOPortA = IOPortA & 0xf7;
break;
case 7:
if (KeyTable[Key5]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyT]) IOPortA = IOPortA & 0xfb;
if (KeyTable[KeyG]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyB]) IOPortA = IOPortA & 0xf7;
break;
case 8:
if (KeyTable[Key1]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyQ]) IOPortA = IOPortA & 0xfb;
if (KeyTable[KeyA]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyZ]) IOPortA = IOPortA & 0xf7;
break;
case 9:
if (KeyTable[Key4]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyR]) IOPortA = IOPortA & 0xfb;
if (KeyTable[KeyF]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyV]) IOPortA = IOPortA & 0xf7;
break;
default:
break;
}
#endif
// Convert back to digital pins
rp.myDigitalPinState[Controller::One] = IOPortA & 0x01;
rp.myDigitalPinState[Controller::Two] = IOPortA & 0x02;
rp.myDigitalPinState[Controller::Three] = IOPortA & 0x04;
rp.myDigitalPinState[Controller::Four] = IOPortA & 0x08;
}

View File

@ -21,6 +21,7 @@
#define COMPUMATE_HXX
#include "bspf.hxx"
#include "CartCM.hxx"
#include "Control.hxx"
#include "Event.hxx"
@ -32,8 +33,8 @@
unique for the 2600 in that it requires close co-operation between the
cartridge and the left and right controllers.
This class acts as a 'parent' for both the left and right CMControl's,
taking care of their creation and communication between them.
This class acts as a 'parent' for cartridge and both the left and right
CMControl's, taking care of their creation and communication between them.
@author Stephen Anthony
@version $Id$
@ -46,10 +47,11 @@ class CompuMate
Note that this class creates CMControl controllers for both ports,
but does not take responsibility for their deletion.
@param cart The CompuMate cartridge
@param event The event object to use for events
@param system The system using this controller
*/
CompuMate(const Event& event, const System& system);
CompuMate(CartridgeCM& cart, const Event& event, const System& system);
/**
Destructor
@ -57,12 +59,6 @@ class CompuMate
*/
virtual ~CompuMate() { }
public:
/**
Called by the controller(s) when all pins have been written
*/
void update();
/**
Return the left and right CompuMate controllers
*/
@ -70,6 +66,12 @@ class CompuMate
Controller* rightController() { return (Controller*) myRightController; }
private:
/**
Called by the controller(s) when all pins have been written
This method keeps track of consecutive calls, and only updates once
*/
void update();
// The actual CompuMate controller
// More information about these scheme can be found in CartCM.hxx
class CMControl : public Controller
@ -122,7 +124,9 @@ class CompuMate
};
private:
// System object
// Cart, Event and System objects
CartridgeCM& myCart;
const Event& myEvent;
const System& mySystem;
// Left and right controllers
@ -132,8 +136,8 @@ class CompuMate
// Multiple calls at the same cycle should be ignored
uInt32 myCycleAtLastUpdate;
// Internal state of the port pins
uInt8 myIOPort;
// Column currently active
uInt8 myColumn;
};
#endif

View File

@ -617,7 +617,7 @@ void Console::setControllers(const string& rommd5)
if(left == "COMPUMATE" || right == "COMPUMATE")
{
delete myCMHandler;
myCMHandler = new CompuMate(myEvent, *mySystem);
myCMHandler = new CompuMate(*((CartridgeCM*)myCart), myEvent, *mySystem);
myControllers[0] = myCMHandler->leftController();
myControllers[1] = myCMHandler->rightController();
return;

View File

@ -64,16 +64,7 @@ Keyboard::~Keyboard()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Keyboard::write(DigitalPin pin, bool value)
{
switch(pin)
{
case One:
case Two:
case Three:
case Four:
myDigitalPinState[pin] = value;
default:
break;
}
myDigitalPinState[pin] = value;
// Set defaults
myDigitalPinState[Six] = true;