diff --git a/src/debugger/gui/CartCMWidget.cxx b/src/debugger/gui/CartCMWidget.cxx new file mode 100644 index 000000000..0416a77d8 --- /dev/null +++ b/src/debugger/gui/CartCMWidget.cxx @@ -0,0 +1,198 @@ +//============================================================================ +// +// 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-2013 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. +// +// $Id$ +//============================================================================ + +#include "CartCM.hxx" +#include "RiotDebug.hxx" +#include "DataGridWidget.hxx" +#include "PopUpWidget.hxx" +#include "ToggleBitWidget.hxx" +#include "CartCMWidget.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeCMWidget::CartridgeCMWidget( + GuiObject* boss, const GUI::Font& font, + int x, int y, int w, int h, CartridgeCM& cart) + : CartDebugWidget(boss, font, x, y, w, h), + myCart(cart) +{ + uInt16 size = 4 * 4096; + + string info = + "CM cartridge, four 4K banks + 2K RAM\n" + "2K RAM accessible @ $1800 - $1FFF in read or write-only mode " + "(no separate ports)\n" + "All TIA controller registers (INPT0-INPT5) and RIOT SWCHA are " + "used to control the cart functionality\n" + "Startup bank = 3 (ROM), RAM disabled\n"; + + int xpos = 10, + ypos = addBaseInformation(size, "CompuMate", info) + myLineHeight; + + StringMap items; + items.push_back(" 0 ", "0"); + items.push_back(" 1 ", "1"); + items.push_back(" 2 ", "2"); + items.push_back(" 3 ", "3"); + myBank = + new PopUpWidget(boss, font, xpos, ypos-2, font.getStringWidth(" 0 "), + myLineHeight, items, "Set bank: ", + font.getStringWidth("Set bank: "), kBankChanged); + myBank->setTarget(this); + addFocusWidget(myBank); + + // Raw SWCHA value (this will be broken down further in other UI elements) + int lwidth = font.getStringWidth("Current column: "); + ypos += myLineHeight + 8; + new StaticTextWidget(boss, font, xpos, ypos+2, lwidth, myFontHeight, + "Current SWCHA: ", kTextAlignLeft); + xpos += lwidth; + mySWCHA = new ToggleBitWidget(boss, font, xpos, ypos, 8, 1); + mySWCHA->setTarget(this); + mySWCHA->setEditable(false); + + // Current column number + xpos = 10; ypos += myLineHeight + 5; + new StaticTextWidget(boss, font, xpos, ypos, lwidth, + myFontHeight, "Current column: ", kTextAlignLeft); + xpos += lwidth; + + myColumn = new DataGridWidget(boss, font, xpos, ypos-2, 1, 1, 2, 8, kBASE_16); + myColumn->setTarget(this); + myColumn->setEditable(false); + + // Relevant pins of SWCHA + xpos = 30; + + // D6 (column part) + ypos += myLineHeight + 8; + myIncrease = new CheckboxWidget(boss, font, xpos, ypos, "Increase Column"); + myIncrease->setTarget(this); + myIncrease->setEditable(false); + + int orig_ypos = ypos; // save for when we go to the next column + + // D5 (column part) + ypos += myLineHeight + 4; + myReset = new CheckboxWidget(boss, font, xpos, ypos, "Reset Column"); + myReset->setTarget(this); + myReset->setEditable(false); + + // Row inputs + ypos += myLineHeight + 4; + myRow[0] = new CheckboxWidget(boss, font, xpos, ypos, "Row 0"); + myRow[0]->setTarget(this); + myRow[0]->setEditable(false); + ypos += myLineHeight + 4; + myRow[1] = new CheckboxWidget(boss, font, xpos, ypos, "Row 1"); + myRow[1]->setTarget(this); + myRow[1]->setEditable(false); + ypos += myLineHeight + 4; + myRow[2] = new CheckboxWidget(boss, font, xpos, ypos, "Row 2"); + myRow[2]->setTarget(this); + myRow[2]->setEditable(false); + ypos += myLineHeight + 4; + myRow[3] = new CheckboxWidget(boss, font, xpos, ypos, "Row 3"); + myRow[3]->setTarget(this); + myRow[3]->setEditable(false); + + // Func and Shift keys + ypos += myLineHeight + 4; + myFunc = new CheckboxWidget(boss, font, xpos, ypos, "FUNC key pressed"); + myFunc->setTarget(this); + myFunc->setEditable(false); + ypos += myLineHeight + 4; + myShift = new CheckboxWidget(boss, font, xpos, ypos, "Shift key pressed"); + myShift->setTarget(this); + myShift->setEditable(false); + + // Move to next column + xpos += myShift->getWidth() + 20; ypos = orig_ypos; + + // D7 + myAudIn = new CheckboxWidget(boss, font, xpos, ypos, "Audio Input"); + myAudIn->setTarget(this); + myAudIn->setEditable(false); + + // D6 (audio part) + ypos += myLineHeight + 4; + myAudOut = new CheckboxWidget(boss, font, xpos, ypos, "Audio Output"); + myAudOut->setTarget(this); + myAudOut->setEditable(false); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeCMWidget::saveOldState() +{ + myOldState.swcha = myCart.mySWCHA; + myOldState.column = myCart.myColumn; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeCMWidget::loadConfig() +{ + myBank->setSelected(myCart.myCurrentBank); + + RiotDebug& riot = Debugger::debugger().riotDebug(); + const RiotState& state = (RiotState&) riot.getState(); + + uInt8 swcha = myCart.mySWCHA; + + // SWCHA + BoolArray oldbits, newbits, changed; + Debugger::set_bits(myOldState.swcha, oldbits); + Debugger::set_bits(swcha, newbits); + + for(uInt32 i = 0; i < oldbits.size(); ++i) + changed.push_back(oldbits[i] != newbits[i]); + mySWCHA->setState(newbits, changed); + + // Column + myColumn->setList(0, myCart.myColumn, myCart.myColumn != myOldState.column); + + // Various bits from SWCHA and INPTx + myIncrease->setState(swcha & 0x40); + myReset->setState(swcha & 0x20); + myRow[0]->setState(!(state.INPT4 & 0x80)); + myRow[1]->setState(!(swcha & 0x04)); + myRow[2]->setState(!(state.INPT5 & 0x80)); + myRow[3]->setState(!(swcha & 0x08)); + myFunc->setState(state.INPT0 & 0x80); + myShift->setState(state.INPT3 & 0x80); + + myAudIn->setState(swcha & 0x80); + myAudOut->setState(swcha & 0x40); + + CartDebugWidget::loadConfig(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeCMWidget::handleCommand(CommandSender* sender, + int cmd, int data, int id) +{ + if(cmd == kBankChanged) + { + myCart.unlockBank(); + myCart.mySWCHA &= 0xFC; + myCart.mySWCHA |= myBank->getSelected(); + myCart.bank(myCart.mySWCHA & 0x03); + myCart.lockBank(); + invalidate(); + } +} diff --git a/src/debugger/gui/CartCMWidget.hxx b/src/debugger/gui/CartCMWidget.hxx new file mode 100644 index 000000000..19d2ebd6c --- /dev/null +++ b/src/debugger/gui/CartCMWidget.hxx @@ -0,0 +1,66 @@ +//============================================================================ +// +// 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-2013 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. +// +// $Id$ +//============================================================================ + +#ifndef CARTRIDGECM_WIDGET_HXX +#define CARTRIDGECM_WIDGET_HXX + +class CartridgeCM; +class CheckboxWidget; +class DataGridWidget; +class PopUpWidget; +class ToggleBitWidget; + +#include "CartDebugWidget.hxx" + +class CartridgeCMWidget : public CartDebugWidget +{ + public: + CartridgeCMWidget(GuiObject* boss, const GUI::Font& font, + int x, int y, int w, int h, + CartridgeCM& cart); + virtual ~CartridgeCMWidget() { } + + void saveOldState(); + + void loadConfig(); + void handleCommand(CommandSender* sender, int cmd, int data, int id); + + private: + struct CartState { + uInt8 swcha; + uInt8 column; + }; + + private: + CartridgeCM& myCart; + PopUpWidget* myBank; + + ToggleBitWidget* mySWCHA; + DataGridWidget* myColumn; + CheckboxWidget *myAudIn, *myAudOut, *myIncrease, *myReset; + CheckboxWidget* myRow[4]; + CheckboxWidget *myFunc, *myShift; + PopUpWidget* myRAM; + + CartState myOldState; + + enum { kBankChanged = 'bkCH' }; +}; + +#endif diff --git a/src/debugger/gui/CartDPCWidget.hxx b/src/debugger/gui/CartDPCWidget.hxx index 9a43c4116..e204e51f5 100644 --- a/src/debugger/gui/CartDPCWidget.hxx +++ b/src/debugger/gui/CartDPCWidget.hxx @@ -60,7 +60,7 @@ class CartridgeDPCWidget : public CartDebugWidget DataGridWidget* myMusicMode; DataGridWidget* myRandom; - CartState myState, myOldState; + CartState myOldState; enum { kBankChanged = 'bkCH' }; }; diff --git a/src/debugger/gui/ToggleBitWidget.cxx b/src/debugger/gui/ToggleBitWidget.cxx index 7ee7cd9f9..74e334d3a 100644 --- a/src/debugger/gui/ToggleBitWidget.cxx +++ b/src/debugger/gui/ToggleBitWidget.cxx @@ -38,6 +38,16 @@ ToggleBitWidget::ToggleBitWidget(GuiObject* boss, const GUI::Font& font, _rowHeight = font.getLineHeight(); _colWidth = colchars * font.getMaxCharWidth() + 8; + // Make sure all lists contain some default values + int size = _rows * _cols; + while(size--) + { + _offList.push_back("0"); + _onList.push_back("1"); + _stateList.push_back(false); + _changedList.push_back(false); + } + // Calculate real dimensions _w = _colWidth * cols + 1; _h = _rowHeight * rows + 1; diff --git a/src/debugger/gui/module.mk b/src/debugger/gui/module.mk index 9dee5823b..d2dda1897 100644 --- a/src/debugger/gui/module.mk +++ b/src/debugger/gui/module.mk @@ -25,6 +25,7 @@ MODULE_OBJS := \ src/debugger/gui/Cart3FWidget.o \ src/debugger/gui/Cart4A50Widget.o \ src/debugger/gui/Cart4KWidget.o \ + src/debugger/gui/CartCMWidget.o \ src/debugger/gui/CartCVWidget.o \ src/debugger/gui/CartDPCWidget.o \ src/debugger/gui/CartDPCPlusWidget.o \ diff --git a/src/emucore/CartCM.cxx b/src/emucore/CartCM.cxx index 754264a8e..0a2a027bb 100644 --- a/src/emucore/CartCM.cxx +++ b/src/emucore/CartCM.cxx @@ -38,8 +38,8 @@ CartridgeCM::CartridgeCM(const uInt8* image, uInt32 size, const Settings& settin // On powerup, portA is all 1's, so the last bank of ROM is enabled and // RAM is disabled - myStartBank = 3; - myRamState = 0x10; + mySWCHA = 0xff; + myStartBank = mySWCHA & 0x3; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -97,8 +97,8 @@ bool CartridgeCM::poke(uInt16 address, uInt8 value) // RIOT mirroring, check bankswitch if(address == 0x280) { - myRamState = value; - bank(myRamState & 0x3); + mySWCHA = value; + bank(mySWCHA & 0x3); if(value & 0x20) myColumn = 0; if(value & 0x40) myColumn = (myColumn + 1) % 10; } @@ -140,7 +140,7 @@ bool CartridgeCM::bank(uInt16 bank) { access.type = System::PA_READWRITE; - if(myRamState & 0x10) + if(mySWCHA & 0x10) { access.directPeekBase = &myImage[offset + (address & 0x0FFF)]; access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x0FFF)]; @@ -151,7 +151,7 @@ bool CartridgeCM::bank(uInt16 bank) access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x07FF)]; } - if((myRamState & 0x30) == 0x20) + if((mySWCHA & 0x30) == 0x20) access.directPokeBase = &myRAM[address & 0x7FF]; else access.directPokeBase = 0; @@ -181,7 +181,7 @@ uInt16 CartridgeCM::bankCount() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeCM::patch(uInt16 address, uInt8 value) { - if((myRamState & 0x30) == 0x20) + if((mySWCHA & 0x30) == 0x20) myRAM[address & 0x7FF] = value; else myImage[(myCurrentBank << 12) + address] = value; @@ -203,7 +203,7 @@ bool CartridgeCM::save(Serializer& out) const { out.putString(name()); out.putShort(myCurrentBank); - out.putByte(myRamState); + out.putByte(mySWCHA); out.putByte(myColumn); out.putByteArray(myRAM, 2048); } @@ -225,7 +225,7 @@ bool CartridgeCM::load(Serializer& in) return false; myCurrentBank = in.getShort(); - myRamState = in.getByte(); + mySWCHA = in.getByte(); myColumn = in.getByte(); in.getByteArray(myRAM, 2048); } diff --git a/src/emucore/CartCM.hxx b/src/emucore/CartCM.hxx index 670a76d64..40d2392aa 100644 --- a/src/emucore/CartCM.hxx +++ b/src/emucore/CartCM.hxx @@ -24,6 +24,9 @@ class System; #include "bspf.hxx" #include "Cart.hxx" +#ifdef DEBUGGER_SUPPORT + #include "CartCMWidget.hxx" +#endif /** Cartridge class used for SpectraVideo CompuMate bankswitched games. @@ -105,6 +108,8 @@ class System; */ class CartridgeCM : public Cartridge { + friend class CartridgeCMWidget; + public: /** Create a new cartridge using the specified image @@ -191,6 +196,18 @@ class CartridgeCM : public Cartridge */ string name() const { return "CartridgeCM"; } + #ifdef DEBUGGER_SUPPORT + /** + Get debugger widget responsible for accessing the inner workings + of the cart. + */ + CartDebugWidget* debugWidget(GuiObject* boss, + const GUI::Font& font, int x, int y, int w, int h) + { + return new CartridgeCMWidget(boss, font, x, y, w, h, *this); + } + #endif + public: /** Get the byte at the specified address. @@ -225,8 +242,8 @@ class CartridgeCM : public Cartridge // The 2K of RAM uInt8 myRAM[2048]; - // RAM read/write state - uInt8 myRamState; + // Current copy of SWCHA (controls ROM/RAM accesses) + uInt8 mySWCHA; // Column currently active uInt8 myColumn; diff --git a/src/emucore/CompuMate.hxx b/src/emucore/CompuMate.hxx index 86c9bee66..3a50fad83 100644 --- a/src/emucore/CompuMate.hxx +++ b/src/emucore/CompuMate.hxx @@ -62,8 +62,8 @@ class CompuMate /** Return the left and right CompuMate controllers */ - Controller* leftController() { return (Controller*) myLeftController; } - Controller* rightController() { return (Controller*) myRightController; } + Controller* leftController() { return myLeftController; } + Controller* rightController() { return myRightController; } private: /**