diff --git a/src/emucore/CartCM.hxx b/src/emucore/CartCM.hxx index 5db74be10..b64be7e03 100644 --- a/src/emucore/CartCM.hxx +++ b/src/emucore/CartCM.hxx @@ -108,6 +108,8 @@ class System; */ class CartridgeCM : public Cartridge { + friend class CompuMate; + public: /** Create a new cartridge using the specified image diff --git a/src/emucore/CompuMate.cxx b/src/emucore/CompuMate.cxx index 37527dcb9..f20aa6316 100644 --- a/src/emucore/CompuMate.cxx +++ b/src/emucore/CompuMate.cxx @@ -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; } diff --git a/src/emucore/CompuMate.hxx b/src/emucore/CompuMate.hxx index 57f8a7269..49db2282a 100644 --- a/src/emucore/CompuMate.hxx +++ b/src/emucore/CompuMate.hxx @@ -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 diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index 6dca643ec..fbfa8689b 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -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; diff --git a/src/emucore/Keyboard.cxx b/src/emucore/Keyboard.cxx index ac114872f..7979da41c 100644 --- a/src/emucore/Keyboard.cxx +++ b/src/emucore/Keyboard.cxx @@ -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;