The CompuMate emulation now correctly processes normal and

shifted keys from the keyboard.  Most control-keys are
supported too, but still TODO is allow the Control key to
pass to the CompuMate controller and not pre-process it
by the EventHandler (so pressing Ctrl-q) shouldn't quit
emulation in that case).


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2414 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2012-03-15 15:22:57 +00:00
parent 82a4bc13b1
commit 44b5cf66b9
6 changed files with 79 additions and 78 deletions

View File

@ -24,6 +24,9 @@
have only one 2600-daptor and want to use it as a left port have only one 2600-daptor and want to use it as a left port
normally, but as a right port for Star Raiders, etc). normally, but as a right port for Star Raiders, etc).
* Added CompuMate bankswitching/controller support; the CompuMate
NTSC and PAL ROMs now work correctly.
* Fixed bug in BoosterGrip controller emulation; the functionality * Fixed bug in BoosterGrip controller emulation; the functionality
of the booster and trigger buttons was reversed. Related to this, of the booster and trigger buttons was reversed. Related to this,
renamed these actions in the Event Mapping dialog to be more clear. renamed these actions in the Event Mapping dialog to be more clear.

View File

@ -20,6 +20,8 @@
#ifndef STELLA_KEYS_HXX #ifndef STELLA_KEYS_HXX
#define STELLA_KEYS_HXX #define STELLA_KEYS_HXX
#include <SDL.h>
/** /**
This class implements a thin wrapper around the SDL keysym enumerations, This class implements a thin wrapper around the SDL keysym enumerations,
such that SDL-specific code doesn't have to go into the internal parts of such that SDL-specific code doesn't have to go into the internal parts of
@ -310,4 +312,12 @@ typedef enum {
// The underlying code doesn't need to know how it's implemented // The underlying code doesn't need to know how it's implemented
typedef int StellaMod; typedef int StellaMod;
// Wrapper around the SDL_GetKeyState function
// This can be used as-is since KBDK keys and SDL keys are the same
class StellaKeys
{
public:
static uInt8* GetKeyState() { return SDL_GetKeyState(NULL); }
};
#endif /* StellaKeys */ #endif /* StellaKeys */

View File

@ -83,8 +83,7 @@ uInt8 CartridgeCM::peek(uInt16 address)
{ {
// NOTE: This does not handle accessing cart ROM/RAM, however, this function // NOTE: This does not handle accessing cart ROM/RAM, however, this function
// should never be called for ROM/RAM because of the way page accessing // should never be called for ROM/RAM because of the way page accessing
// has been setup // has been setup (it will only ever be called for RIOT reads)
// It will only ever be called for RIOT reads
return mySystem->m6532().peek(address); return mySystem->m6532().peek(address);
} }
@ -118,8 +117,8 @@ bool CartridgeCM::bank(uInt16 bank)
uInt16 offset = myCurrentBank << 12; uInt16 offset = myCurrentBank << 12;
uInt16 shift = mySystem->pageShift(); uInt16 shift = mySystem->pageShift();
// Although this scheme contains four 4K banks and one 2K bank, it's easier // Although this scheme contains four 4K ROM banks and one 2K RAM bank,
// to think of things in terms of 2K slices, as follows: // it's easier to think of things in terms of 2K slices, as follows:
// //
// The lower 2K of cart address space always points to the lower 2K of the // The lower 2K of cart address space always points to the lower 2K of the
// current ROM bank // current ROM bank

View File

@ -108,8 +108,6 @@ class System;
*/ */
class CartridgeCM : public Cartridge class CartridgeCM : public Cartridge
{ {
friend class CompuMate;
public: public:
/** /**
Create a new cartridge using the specified image Create a new cartridge using the specified image
@ -213,6 +211,13 @@ class CartridgeCM : public Cartridge
*/ */
bool poke(uInt16 address, uInt8 value); bool poke(uInt16 address, uInt8 value);
/**
Get the current keybord column
@return The column referenced by SWCHA D6 and D5
*/
uInt8 column() const { return myColumn; }
private: private:
// Indicates which bank is currently active // Indicates which bank is currently active
uInt16 myCurrentBank; uInt16 myCurrentBank;

View File

@ -19,6 +19,7 @@
#include "Control.hxx" #include "Control.hxx"
#include "System.hxx" #include "System.hxx"
#include "StellaKeys.hxx"
#include "CompuMate.hxx" #include "CompuMate.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -29,11 +30,15 @@ CompuMate::CompuMate(CartridgeCM& cart, const Event& event,
mySystem(system), mySystem(system),
myLeftController(0), myLeftController(0),
myRightController(0), myRightController(0),
myCycleAtLastUpdate(0), myCycleAtLastUpdate(0)
myColumn(0)
{ {
myLeftController = new CMControl(*this, Controller::Left, event, system); myLeftController = new CMControl(*this, Controller::Left, event, system);
myRightController = new CMControl(*this, Controller::Right, event, system); myRightController = new CMControl(*this, Controller::Right, event, system);
myLeftController->myAnalogPinValue[Controller::Nine] = Controller::maximumResistance;
myLeftController->myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
myRightController->myAnalogPinValue[Controller::Nine] = Controller::minimumResistance;
myRightController->myAnalogPinValue[Controller::Five] = Controller::maximumResistance;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -52,92 +57,85 @@ void CompuMate::update()
// Handle SWCHA changes - the following comes almost directly from z26 // Handle SWCHA changes - the following comes almost directly from z26
Controller& lp = *myLeftController; Controller& lp = *myLeftController;
Controller& rp = *myRightController; Controller& rp = *myRightController;
uInt8 IOPortA = (lp.read() << 4) | rp.read(); uInt8* KeyTable = StellaKeys::GetKeyState();
lp.myAnalogPinValue[Controller::Nine] = Controller::maximumResistance; lp.myAnalogPinValue[Controller::Nine] = Controller::maximumResistance;
lp.myAnalogPinValue[Controller::Five] = Controller::minimumResistance; lp.myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
lp.myDigitalPinState[Controller::Six] = true; lp.myDigitalPinState[Controller::Six] = true;
rp.myAnalogPinValue[Controller::Nine] = Controller::minimumResistance; rp.myAnalogPinValue[Controller::Nine] = Controller::minimumResistance;
rp.myAnalogPinValue[Controller::Five] = Controller::maximumResistance; rp.myAnalogPinValue[Controller::Five] = Controller::maximumResistance;
rp.myDigitalPinState[Controller::Six] = true; rp.myDigitalPinState[Controller::Six] = true;
rp.myDigitalPinState[Controller::Three] = true;
rp.myDigitalPinState[Controller::Four] = true;
uInt8& column = myCart.myColumn; if (KeyTable[KBDK_LSHIFT])
if(IOPortA & 0x20) column = 0; rp.myAnalogPinValue[Controller::Five] = Controller::minimumResistance;
if(IOPortA & 0x40) column = (column + 1) % 10; if (KeyTable[KBDK_LCTRL])
lp.myAnalogPinValue[Controller::Nine] = Controller::minimumResistance;
IOPortA = IOPortA | (0x0c & 0x7f); switch(myCart.column())
#if 0
switch(column)
{ {
case 0: case 0:
if (KeyTable[Key7]) lp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_7]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyU]) IOPortA = IOPortA & 0xfb; if (KeyTable[KBDK_u]) rp.myDigitalPinState[Controller::Three] = false;
if (KeyTable[KeyJ]) rp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_j]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyM]) IOPortA = IOPortA & 0xf7; if (KeyTable[KBDK_m]) rp.myDigitalPinState[Controller::Four] = false;
break; break;
case 1: case 1:
if (KeyTable[Key6]) lp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_6]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyY]) IOPortA = IOPortA & 0xfb; if (KeyTable[KBDK_y]) rp.myDigitalPinState[Controller::Three] = false;
if (KeyTable[KeyH]) rp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_h]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyN]) IOPortA = IOPortA & 0xf7; if (KeyTable[KBDK_n]) rp.myDigitalPinState[Controller::Four] = false;
break; break;
case 2: case 2:
if (KeyTable[Key8]) lp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_8]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyI]) IOPortA = IOPortA & 0xfb; if (KeyTable[KBDK_i]) rp.myDigitalPinState[Controller::Three] = false;
if (KeyTable[KeyK]) rp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_k]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyComma]) IOPortA = IOPortA & 0xf7; if (KeyTable[KBDK_COMMA]) rp.myDigitalPinState[Controller::Four] = false;
break; break;
case 3: case 3:
if (KeyTable[Key2]) lp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_2]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyW]) IOPortA = IOPortA & 0xfb; if (KeyTable[KBDK_w]) rp.myDigitalPinState[Controller::Three] = false;
if (KeyTable[KeyS]) rp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_s]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyX]) IOPortA = IOPortA & 0xf7; if (KeyTable[KBDK_x]) rp.myDigitalPinState[Controller::Four] = false;
break; break;
case 4: case 4:
if (KeyTable[Key3]) lp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_3]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyE]) IOPortA = IOPortA & 0xfb; if (KeyTable[KBDK_e]) rp.myDigitalPinState[Controller::Three] = false;
if (KeyTable[KeyD]) rp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_d]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyC]) IOPortA = IOPortA & 0xf7; if (KeyTable[KBDK_c]) rp.myDigitalPinState[Controller::Four] = false;
break; break;
case 5: case 5:
if (KeyTable[Key0]) lp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_0]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyP]) IOPortA = IOPortA & 0xfb; if (KeyTable[KBDK_p]) rp.myDigitalPinState[Controller::Three] = false;
if (KeyTable[KeyColon]) rp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_COLON]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeySlash]) IOPortA = IOPortA & 0xf7; if (KeyTable[KBDK_SLASH]) rp.myDigitalPinState[Controller::Four] = false;
break; break;
case 6: case 6:
if (KeyTable[Key9]) lp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_9]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyO]) IOPortA = IOPortA & 0xfb; if (KeyTable[KBDK_o]) rp.myDigitalPinState[Controller::Three] = false;
if (KeyTable[KeyL]) rp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_l]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyDot]) IOPortA = IOPortA & 0xf7; if (KeyTable[KBDK_PERIOD]) rp.myDigitalPinState[Controller::Four] = false;
break; break;
case 7: case 7:
if (KeyTable[Key5]) lp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_5]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyT]) IOPortA = IOPortA & 0xfb; if (KeyTable[KBDK_t]) rp.myDigitalPinState[Controller::Three] = false;
if (KeyTable[KeyG]) rp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_g]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyB]) IOPortA = IOPortA & 0xf7; if (KeyTable[KBDK_b]) rp.myDigitalPinState[Controller::Four] = false;
break; break;
case 8: case 8:
if (KeyTable[Key1]) lp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_1]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyQ]) IOPortA = IOPortA & 0xfb; if (KeyTable[KBDK_q]) rp.myDigitalPinState[Controller::Three] = false;
if (KeyTable[KeyA]) rp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_a]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyZ]) IOPortA = IOPortA & 0xf7; if (KeyTable[KBDK_z]) rp.myDigitalPinState[Controller::Four] = false;
break; break;
case 9: case 9:
if (KeyTable[Key4]) lp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_4]) lp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyR]) IOPortA = IOPortA & 0xfb; if (KeyTable[KBDK_r]) rp.myDigitalPinState[Controller::Three] = false;
if (KeyTable[KeyF]) rp.myDigitalPinState[Controller::Six] = false; if (KeyTable[KBDK_f]) rp.myDigitalPinState[Controller::Six] = false;
if (KeyTable[KeyV]) IOPortA = IOPortA & 0xf7; if (KeyTable[KBDK_v]) rp.myDigitalPinState[Controller::Four] = false;
break; break;
default: default:
break; 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

@ -89,18 +89,7 @@ class CompuMate
const System& system) const System& system)
: Controller(jack, event, system, Controller::CompuMate), : Controller(jack, event, system, Controller::CompuMate),
myHandler(handler) myHandler(handler)
{ { }
if(myJack == Left)
{
myAnalogPinValue[Five] = minimumResistance;
myAnalogPinValue[Nine] = maximumResistance;
}
else
{
myAnalogPinValue[Five] = maximumResistance;
myAnalogPinValue[Nine] = minimumResistance;
}
}
/** /**
Destructor Destructor
@ -135,9 +124,6 @@ class CompuMate
// System cycle at which the update() method is called // System cycle at which the update() method is called
// Multiple calls at the same cycle should be ignored // Multiple calls at the same cycle should be ignored
uInt32 myCycleAtLastUpdate; uInt32 myCycleAtLastUpdate;
// Column currently active
uInt8 myColumn;
}; };
#endif #endif