diff --git a/Changes.txt b/Changes.txt index 21c354d1e..8b71846e3 100644 --- a/Changes.txt +++ b/Changes.txt @@ -12,7 +12,7 @@ Release History =========================================================================== -4.6.1 to 4.7: (July dd, 2015) +4.6.1 to 4.6.5: (September dd, 2015) * Added mappable events for toggling TV color/BW, left difficulty A/B and right difficulty A/B. This means that one key, joystick button, diff --git a/src/debugger/CartDebug.hxx b/src/debugger/CartDebug.hxx index 2c983bfe9..f30cbd32e 100644 --- a/src/debugger/CartDebug.hxx +++ b/src/debugger/CartDebug.hxx @@ -40,7 +40,7 @@ using CartMethod = int (CartDebug::*)(); class CartState : public DebuggerState { public: - IntArray ram; // The actual data values + ByteArray ram; // The actual data values IntArray rport; // Address for reading from RAM IntArray wport; // Address for writing to RAM string bank; // Current banking layout diff --git a/src/debugger/gui/CartRamWidget.cxx b/src/debugger/gui/CartRamWidget.cxx index e76830d04..5ad55abe8 100644 --- a/src/debugger/gui/CartRamWidget.cxx +++ b/src/debugger/gui/CartRamWidget.cxx @@ -17,8 +17,12 @@ // $Id$ //============================================================================ -#include "PopUpWidget.hxx" -#include "InputTextDialog.hxx" +#include "EditTextWidget.hxx" +#include "GuiObject.hxx" +#include "OSystem.hxx" +#include "CartDebug.hxx" +#include "Widget.hxx" + #include "CartRamWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -31,42 +35,38 @@ CartRamWidget::CartRamWidget( myFontWidth(lfont.getMaxCharWidth()), myFontHeight(lfont.getFontHeight()), myLineHeight(lfont.getLineHeight()), - myButtonHeight(myLineHeight + 4), - myCart(cartDebug), - myCurrentRamBank(0) -{ + myButtonHeight(myLineHeight + 4) +{ int lwidth = lfont.getStringWidth("Description: "), fwidth = w - lwidth - 20; - const int bwidth = lfont.getStringWidth("Compare "), - bheight = myLineHeight + 2; EditTextWidget* etw = nullptr; ostringstream buf; int xpos = 2, ypos = 5; - + // Add RAM size - myRamSize = myCart.internalRamSize(); new StaticTextWidget(_boss, _font, xpos, ypos, lwidth, myFontHeight, "RAM Size: ", kTextAlignLeft); - - buf << myRamSize << " bytes"; - if(myRamSize >= 1024) - buf << " / " << (myRamSize/1024) << "KB"; - + + uInt32 ramsize = cartDebug.internalRamSize(); + buf << ramsize << " bytes"; + if(ramsize >= 1024) + buf << " / " << (ramsize/1024) << "KB"; + etw = new EditTextWidget(boss, nfont, xpos+lwidth, ypos, fwidth, myLineHeight, buf.str()); etw->setEditable(false); ypos += myLineHeight + 4; - + // Add Description - const string& desc = myCart.internalRamDescription(); + const string& desc = cartDebug.internalRamDescription(); const uInt16 maxlines = 6; StringParser bs(desc, (fwidth - kScrollBarWidth) / myFontWidth); const StringList& sl = bs.stringList(); uInt32 lines = (int)sl.size(); if(lines < 3) lines = 3; if(lines > maxlines) lines = maxlines; - + new StaticTextWidget(_boss, _font, xpos, ypos, lwidth, myFontHeight, "Description: ", kTextAlignLeft); myDesc = new StringListWidget(boss, nfont, xpos+lwidth, ypos, @@ -74,440 +74,100 @@ CartRamWidget::CartRamWidget( myDesc->setEditable(false); myDesc->setList(sl); addFocusWidget(myDesc); - - ypos += myDesc->getHeight() + myLineHeight + 4; - - // Add RAM grid - xpos = _font.getStringWidth("xxxx"); - myNumRows = myRamSize / 16; - if (myNumRows > 16) myNumRows = 16; - myPageSize = myNumRows * 16; - myRamGrid = new DataGridWidget(_boss, _nfont, xpos, ypos, - 16, myNumRows, 2, 8, Common::Base::F_16, true); - myRamGrid->setTarget(this); - addFocusWidget(myRamGrid); - - // Create actions buttons to the left of the RAM grid - int bx = xpos + myRamGrid->getWidth() + 4; - int by = ypos; - myUndoButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight, - "Undo", kUndoCmd); - myUndoButton->setTarget(this); - - by += bheight + 4; - myRevertButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight, - "Revert", kRevertCmd); - myRevertButton->setTarget(this); - - by += 2 * bheight + 2; - mySearchButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight, - "Search", kSearchCmd); - mySearchButton->setTarget(this); - - by += bheight + 4; - myCompareButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight, - "Compare", kCmpCmd); - myCompareButton->setTarget(this); - - by += bheight + 4; - myRestartButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight, - "Reset", kRestartCmd); - myRestartButton->setTarget(this); - - // Labels for RAM grid - for(int col = 0; col < 16; ++col) - { - new StaticTextWidget(_boss, _font, xpos + col*myRamGrid->colWidth() + 8, - ypos - myLineHeight, - myFontWidth, myFontHeight, - Common::Base::toString(col, Common::Base::F_16_1), - kTextAlignLeft); - } - myRamStart = - new StaticTextWidget(_boss, _font, xpos - _font.getStringWidth("xxxx"), ypos - myLineHeight, - _font.getStringWidth("xxxx"), myFontHeight, - "F0xx", kTextAlignLeft); + ypos += myDesc->getHeight() + myLineHeight + 4; - uInt32 row; - for(row = 0; row < myNumRows; ++row) - { - myRamLabels[row] = - new StaticTextWidget(_boss, _font, xpos - _font.getStringWidth("x "), - ypos + row*myLineHeight + 2, - myFontWidth, myFontHeight, "", kTextAlignLeft); - } + // Add RAM widget + xpos = x + _font.getStringWidth("xxxx"); + myRam = new InternalRamWidget(boss, lfont, nfont, 2, ypos, w, h-ypos, cartDebug); + addToFocusList(myRam->getFocusList()); +} - // for smaller grids, make sure RAM cell detail fields are below the RESET button - if (myNumRows < 8) - row = 8 + 1; - else - row = myNumRows + 1; - - ypos += myLineHeight * row; - // We need to define these widgets from right to left since the leftmost - // one resizes as much as possible - - // Add Binary display of selected RAM cell - xpos = w - 13*myFontWidth - 20; - new StaticTextWidget(boss, lfont, xpos, ypos, 4*myFontWidth, myFontHeight, - "Bin:", kTextAlignLeft); - myBinValue = new EditTextWidget(boss, nfont, xpos + 4*myFontWidth + 5, - ypos-2, 9*myFontWidth, myLineHeight, ""); - myBinValue->setEditable(false); - - // Add Decimal display of selected RAM cell - xpos -= 8*myFontWidth + 5 + 20; - new StaticTextWidget(boss, lfont, xpos, ypos, 4*myFontWidth, myFontHeight, - "Dec:", kTextAlignLeft); - myDecValue = new EditTextWidget(boss, nfont, xpos + 4*myFontWidth + 5, ypos-2, - 4*myFontWidth, myLineHeight, ""); - myDecValue->setEditable(false); - - // Add Label of selected RAM cell - int xpos_r = xpos - 20; - xpos = x + 10; - new StaticTextWidget(boss, lfont, xpos, ypos, 6*myFontWidth, myFontHeight, - "Label:", kTextAlignLeft); - xpos += 6*myFontWidth + 5; - myLabel = new EditTextWidget(boss, nfont, xpos, ypos-2, xpos_r-xpos, - myLineHeight, ""); - myLabel->setEditable(false); - - // Inputbox which will pop up when searching RAM - StringList labels; - labels.push_back("Search: "); - myInputBox = new InputTextDialog(boss, lfont, nfont, labels); - myInputBox->setTarget(this); - - // Start with these buttons disabled - myCompareButton->clearFlags(WIDGET_ENABLED); - myRestartButton->clearFlags(WIDGET_ENABLED); +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartRamWidget::~CartRamWidget() +{ } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartRamWidget::loadConfig() { - fillGrid(true); + myRam->loadConfig(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartRamWidget::fillGrid(bool updateOld) +void CartRamWidget::setOpsWidget(DataGridOpsWidget* w) { - IntArray alist; - IntArray vlist; - BoolArray changed; - uInt32 start = myCurrentRamBank * myPageSize; - const ByteArray& oldRam = myCart.internalRamOld(start, myPageSize); - const ByteArray& currentRam = myCart.internalRamCurrent(start, myPageSize); + myRam->setOpsWidget(w); +} - for(uInt32 i = 0; i < myPageSize; i++) +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartRamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) +{ + myRam->handleCommand(sender, cmd, data, id); +} + +/////////////////////////////////// +// Internal RAM implementation +/////////////////////////////////// + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartRamWidget::InternalRamWidget::InternalRamWidget(GuiObject* boss, + const GUI::Font& lfont, const GUI::Font& nfont, + int x, int y, int w, int h, + CartDebugWidget& dbg) + : RamWidget(boss, lfont, nfont, x, y, w, h, + dbg.internalRamSize(), BSPF_min(dbg.internalRamSize() / 16, 16u), + BSPF_min(dbg.internalRamSize() / 16, 16u) * 16), + myCart(dbg) +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartRamWidget::InternalRamWidget::~InternalRamWidget() +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 CartRamWidget::InternalRamWidget::getValue(int addr) const +{ + return myCart.internalRamGetValue(addr); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartRamWidget::InternalRamWidget::setValue(int addr, uInt8 value) +{ + myCart.internalRamSetValue(addr, value); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartRamWidget::InternalRamWidget::getLabel(int addr) const +{ + return myCart.internalRamLabel(addr); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartRamWidget::InternalRamWidget::fillList(uInt32 start, uInt32 size, + IntArray& alist, IntArray& vlist, BoolArray& changed) const +{ + const ByteArray& oldRam = myCart.internalRamOld(start, size); + const ByteArray& currRam = myCart.internalRamCurrent(start, size); + + for(uInt32 i = 0; i < size; i++) { alist.push_back(i+start); - vlist.push_back(currentRam[i]); - changed.push_back(currentRam[i] != oldRam[i]); + vlist.push_back(currRam[i]); + changed.push_back(currRam[i] != oldRam[i]); } - - if(updateOld) - { - myOldValueList.clear(); - myOldValueList = myCart.internalRamCurrent(start, myCart.internalRamSize()); - } - - myRamGrid->setNumRows(myRamSize / myPageSize); - myRamGrid->setList(alist, vlist, changed); - if(updateOld) - { - myRevertButton->setEnabled(false); - myUndoButton->setEnabled(false); - } - - // Update RAM labels - uInt32 rport = myCart.internalRamRPort(start); - uInt32 page = rport & 0xf0; - char buf[5]; - BSPF_snprintf(buf, 5, "%04X", rport); - buf[2] = buf[3] = 'x'; - myRamStart->setLabel(buf); - for(uInt32 row = 0; row < myNumRows; ++row, page += 0x10) - myRamLabels[row]->setLabel(Common::Base::toString(page>>4, Common::Base::F_16_1)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartRamWidget::showInputBox(int cmd) +uInt32 CartRamWidget::InternalRamWidget::readPort(uInt32 start) const { - // Add inputbox in the middle of the RAM widget - uInt32 x = getAbsX() + ((getWidth() - myInputBox->getWidth()) >> 1); - uInt32 y = getAbsY() + ((getHeight() - myInputBox->getHeight()) >> 1); - myInputBox->show(x, y); - myInputBox->setText(""); - myInputBox->setTitle(""); - myInputBox->setFocus(0); - myInputBox->setEmitSignal(cmd); + return myCart.internalRamRPort(start); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartRamWidget::doSearch(const string& str) +const ByteArray& CartRamWidget::InternalRamWidget::currentRam(uInt32 start) const { - bool comparisonSearch = true; - - if(str.length() == 0) - { - // An empty field means return all memory locations - comparisonSearch = false; - } - else if(str.find_first_of("+-", 0) != string::npos) - { - // Don't accept these characters here, only in compare - return "Invalid input +|-"; - } - - int searchVal = instance().debugger().stringToValue(str); - - // Clear the search array of previous items - mySearchAddr.clear(); - mySearchValue.clear(); - mySearchState.clear(); - - // Now, search all memory locations for this value, and add it to the - // search array - bool hitfound = false; -// CartDebug& dbg = instance().debugger().cartDebug(); -// const CartState& state = (CartState&) dbg.getState(); - - const ByteArray& currentRam = myCart.internalRamCurrent(0, myCart.internalRamSize()); - for(uInt32 addr = 0; addr < myCart.internalRamSize(); ++addr) - { - int value = currentRam[addr]; - if(comparisonSearch && searchVal != value) - { - mySearchState.push_back(false); - } - else - { - mySearchAddr.push_back(addr); - mySearchValue.push_back(value); - mySearchState.push_back(true); - hitfound = true; - } - } - - // If we have some hits, enable the comparison methods - if(hitfound) - { - mySearchButton->setEnabled(false); - myCompareButton->setEnabled(true); - myRestartButton->setEnabled(true); - } - - // Finally, show the search results in the list - showSearchResults(); - - return EmptyString; + return myCart.internalRamCurrent(start, myCart.internalRamSize()); } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartRamWidget::doCompare(const string& str) -{ - bool comparitiveSearch = false; - int searchVal = 0, offset = 0; - - if(str.length() == 0) - return "Enter an absolute or comparitive value"; - - // Do some pre-processing on the string - string::size_type pos = str.find_first_of("+-", 0); - if(pos > 0 && pos != string::npos) - { - // Only accept '+' or '-' at the start of the string - return "Input must be [+|-]NUM"; - } - - // A comparitive search searches memory for locations that have changed by - // the specified amount, vs. for exact values - if(str[0] == '+' || str[0] == '-') - { - comparitiveSearch = true; - bool negative = false; - if(str[0] == '-') - negative = true; - - string tmp = str; - tmp.erase(0, 1); // remove the operator - offset = instance().debugger().stringToValue(tmp); - if(negative) - offset = -offset; - } - else - searchVal = instance().debugger().stringToValue(str); - - // Now, search all memory locations previously 'found' for this value - bool hitfound = false; - const ByteArray& currentRam = myCart.internalRamCurrent(0, myCart.internalRamSize()); - - IntArray tempAddrList, tempValueList; - mySearchState.clear(); - for(uInt32 i = 0; i < myCart.internalRamSize(); ++i) - mySearchState.push_back(false); - - for(uInt32 i = 0; i < mySearchAddr.size(); ++i) - { - if(comparitiveSearch) - { - searchVal = mySearchValue[i] + offset; - if(searchVal < 0 || searchVal > 255) - continue; - } - - int addr = mySearchAddr[i]; - if(currentRam[addr] == searchVal) - { - tempAddrList.push_back(addr); - tempValueList.push_back(searchVal); - mySearchState[addr] = hitfound = true; - } - } - - // Update the searchArray for the new addresses and data - mySearchAddr = tempAddrList; - mySearchValue = tempValueList; - - // If we have some hits, enable the comparison methods - if(hitfound) - { - myCompareButton->setEnabled(true); - myRestartButton->setEnabled(true); - } - - // Finally, show the search results in the list - showSearchResults(); - - return EmptyString; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartRamWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - // We simply change the values in the DataGridWidget - // It will then send the 'kDGItemDataChangedCmd' signal to change the actual - // memory location - int addr, value; - - switch(cmd) - { - case DataGridWidget::kItemDataChangedCmd: - { - addr = myRamGrid->getSelectedAddr(); - value = myRamGrid->getSelectedValue(); - - uInt8 oldval = myCart.internalRamGetValue(addr); - - myCart.internalRamSetValue(addr, value); - myUndoAddress = addr; - myUndoValue = oldval; - - myDecValue->setText(Common::Base::toString(value, Common::Base::F_10)); - myBinValue->setText(Common::Base::toString(value, Common::Base::F_2)); - myRevertButton->setEnabled(true); - myUndoButton->setEnabled(true); - break; - } - - case DataGridWidget::kSelectionChangedCmd: - { - addr = myRamGrid->getSelectedAddr(); - value = myRamGrid->getSelectedValue(); - - myLabel->setText(myCart.internalRamLabel(addr)); - myDecValue->setText(Common::Base::toString(value, Common::Base::F_10)); - myBinValue->setText(Common::Base::toString(value, Common::Base::F_2)); - break; - } - - case kRevertCmd: - for(uInt32 i = 0; i < myOldValueList.size(); ++i) - myCart.internalRamSetValue(i, myOldValueList[i]); - fillGrid(true); - break; - - case kUndoCmd: - myCart.internalRamSetValue(myUndoAddress, myUndoValue); - myUndoButton->setEnabled(false); - fillGrid(false); - break; - - case kSearchCmd: - showInputBox(kSValEntered); - break; - - case kCmpCmd: - showInputBox(kCValEntered); - break; - - case kRestartCmd: - doRestart(); - break; - - case kSValEntered: - { - const string& result = doSearch(myInputBox->getResult()); - if(result != "") - myInputBox->setTitle(result); - else - myInputBox->close(); - break; - } - - case kCValEntered: - { - const string& result = doCompare(myInputBox->getResult()); - if(result != "") - myInputBox->setTitle(result); - else - myInputBox->close(); - break; - } - - case kSetPositionCmd: - myCurrentRamBank = data; - showSearchResults(); - fillGrid(false); - break; - } -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartRamWidget::doRestart() -{ - // Erase all search buffers, reset to start mode - mySearchAddr.clear(); - mySearchValue.clear(); - mySearchState.clear(); - showSearchResults(); - - mySearchButton->setEnabled(true); - myCompareButton->setEnabled(false); - myRestartButton->setEnabled(false); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartRamWidget::showSearchResults() -{ - // Only update the search results for the bank currently being shown - BoolArray temp; - uInt32 start = myCurrentRamBank * myPageSize; - if(mySearchState.size() == 0 || start > mySearchState.size()) - { - for(uInt32 i = 0; i < myPageSize; ++i) - temp.push_back(false); - } - else - { - for(uInt32 i = start; i < start + myPageSize; ++i) - temp.push_back(mySearchState[i]); - } - myRamGrid->setHiliteList(temp); -} - diff --git a/src/debugger/gui/CartRamWidget.hxx b/src/debugger/gui/CartRamWidget.hxx index 5613dba5e..10eeeea53 100644 --- a/src/debugger/gui/CartRamWidget.hxx +++ b/src/debugger/gui/CartRamWidget.hxx @@ -1,8 +1,8 @@ //============================================================================ // -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa +// 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 @@ -21,21 +21,14 @@ #define CART_RAM_WIDGET_HXX class GuiObject; -class InputTextDialog; -class ButtonWidget; -class DataGridWidget; +class DataGridOpsWidget; +class StringListWidget; +class InternalRamWidget; -#include "Base.hxx" -#include "Font.hxx" #include "CartDebugWidget.hxx" -#include "Command.hxx" -#include "DataGridWidget.hxx" -#include "Debugger.hxx" -#include "RomWidget.hxx" +#include "RamWidget.hxx" #include "Widget.hxx" -#include "EditTextWidget.hxx" -#include "StringListWidget.hxx" -#include "StringParser.hxx" +#include "Command.hxx" class CartRamWidget : public Widget, public CommandSender { @@ -43,19 +36,13 @@ class CartRamWidget : public Widget, public CommandSender CartRamWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartDebugWidget& cartDebug); + virtual ~CartRamWidget(); - virtual ~CartRamWidget() { }; + void loadConfig() override; + void setOpsWidget(DataGridOpsWidget* w); private: - void loadConfig() override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - void fillGrid(bool updateOld); - - void showInputBox(int cmd); - string doSearch(const string& str); - string doCompare(const string& str); - void doRestart(); - void showSearchResults(); protected: // Font used for 'normal' text; _font is for 'label' text @@ -65,48 +52,6 @@ class CartRamWidget : public Widget, public CommandSender // we may as well make them protected variables int myFontWidth, myFontHeight, myLineHeight, myButtonHeight; - private: - enum { - kUndoCmd = 'RWud', - kRevertCmd = 'RWrv', - kSearchCmd = 'RWse', - kCmpCmd = 'RWcp', - kRestartCmd = 'RWrs', - kSValEntered = 'RWsv', - kCValEntered = 'RWcv' - }; - - int myUndoAddress; - int myUndoValue; - - CartDebugWidget& myCart; - StringListWidget* myDesc; - - DataGridWidget* myRamGrid; - StaticTextWidget* myRamStart; - StaticTextWidget* myRamLabels[16]; - EditTextWidget* myBinValue; - EditTextWidget* myDecValue; - EditTextWidget* myLabel; - - uInt32 myCurrentRamBank; - uInt32 myRamSize; - uInt32 myPageSize; - uInt32 myNumRows; - - ButtonWidget* myRevertButton; - ButtonWidget* myUndoButton; - ButtonWidget* mySearchButton; - ButtonWidget* myCompareButton; - ButtonWidget* myRestartButton; - - InputTextDialog* myInputBox; - - ByteArray myOldValueList; - IntArray mySearchAddr; - IntArray mySearchValue; - BoolArray mySearchState; - private: // Following constructors and assignment operators not supported CartRamWidget() = delete; @@ -114,6 +59,42 @@ class CartRamWidget : public Widget, public CommandSender CartRamWidget(CartRamWidget&&) = delete; CartRamWidget& operator=(const CartRamWidget&) = delete; CartRamWidget& operator=(CartRamWidget&&) = delete; + + private: + class InternalRamWidget : public RamWidget + { + public: + InternalRamWidget(GuiObject* boss, const GUI::Font& lfont, + const GUI::Font& nfont, + int x, int y, int w, int h, + CartDebugWidget& cartDebug); + virtual ~InternalRamWidget(); + + private: + uInt8 getValue(int addr) const; + void setValue(int addr, uInt8 value); + string getLabel(int addr) const; + + void fillList(uInt32 start, uInt32 size, IntArray& alist, + IntArray& vlist, BoolArray& changed) const; + uInt32 readPort(uInt32 start) const; + const ByteArray& currentRam(uInt32 start) const; + + private: + CartDebugWidget& myCart; + + private: + // Following constructors and assignment operators not supported + InternalRamWidget() = delete; + InternalRamWidget(const InternalRamWidget&) = delete; + InternalRamWidget(InternalRamWidget&&) = delete; + InternalRamWidget& operator=(const InternalRamWidget&) = delete; + InternalRamWidget& operator=(InternalRamWidget&&) = delete; + }; + + private: + StringListWidget* myDesc; + InternalRamWidget* myRam; }; #endif diff --git a/src/debugger/gui/DataGridWidget.cxx b/src/debugger/gui/DataGridWidget.cxx index 0c9f26fad..a389e9a3a 100644 --- a/src/debugger/gui/DataGridWidget.cxx +++ b/src/debugger/gui/DataGridWidget.cxx @@ -215,9 +215,9 @@ void DataGridWidget::setValue(int position, int value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void DataGridWidget::setValueInternal(int position, int value) +void DataGridWidget::setValueInternal(int position, int value, bool changed) { - setValue(position, value, true, false); + setValue(position, value, changed, false); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/gui/DataGridWidget.hxx b/src/debugger/gui/DataGridWidget.hxx index 5a8821037..379302aea 100644 --- a/src/debugger/gui/DataGridWidget.hxx +++ b/src/debugger/gui/DataGridWidget.hxx @@ -64,7 +64,7 @@ class DataGridWidget : public EditableWidget /** Set value at given position */ void setValue(int position, int value); /** Set value at given position, do not emit any signals */ - void setValueInternal(int position, int value); + void setValueInternal(int position, int value, bool changed = true); /** Set value at given position, manually specifying if the value changed */ void setValue(int position, int value, bool changed, bool emitSignal = true); diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index d9a7ad111..80ffa0304 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -26,7 +26,7 @@ #include "AudioWidget.hxx" #include "PromptWidget.hxx" #include "CpuWidget.hxx" -#include "RamWidget.hxx" +#include "RiotRamWidget.hxx" #include "RiotWidget.hxx" #include "RomWidget.hxx" #include "TiaWidget.hxx" @@ -390,7 +390,7 @@ void DebuggerDialog::addRomArea() addToFocusList(myCpu->getFocusList()); xpos = r.left + 10; ypos += myCpu->getHeight() + 10; - myRam = new RamWidget(this, *myLFont, *myNFont, xpos, ypos); + myRam = new RiotRamWidget(this, *myLFont, *myNFont, xpos, ypos, r.width() - 10); addToFocusList(myRam->getFocusList()); // Add the DataGridOpsWidget to any widgets which contain a @@ -434,12 +434,14 @@ void DebuggerDialog::addRomArea() if (myCartDebug->internalRamSize() > 0) { tabID = myRomTab->addTab(" Cartridge RAM "); - myCartRam = new CartRamWidget(myRomTab, *myLFont, *myNFont, 2, 2, tabWidth - 1, - tabHeight - myRomTab->getTabHeight() - 2, *myCartDebug); + myCartRam = + new CartRamWidget(myRomTab, *myLFont, *myNFont, 2, 2, tabWidth - 1, + tabHeight - myRomTab->getTabHeight() - 2, *myCartDebug); if(myCartRam) // TODO - make this always non-null { myRomTab->setParentWidget(tabID, myCartRam); addToFocusList(myCartRam->getFocusList(), myRomTab, tabID); + myCartRam->setOpsWidget(ops); } } } diff --git a/src/debugger/gui/RamWidget.cxx b/src/debugger/gui/RamWidget.cxx index 733457c6d..8f8c14bc1 100644 --- a/src/debugger/gui/RamWidget.cxx +++ b/src/debugger/gui/RamWidget.cxx @@ -17,11 +17,8 @@ // $Id$ //============================================================================ -#include - #include "DataGridWidget.hxx" #include "EditTextWidget.hxx" -#include "FrameBuffer.hxx" #include "GuiObject.hxx" #include "InputTextDialog.hxx" #include "OSystem.hxx" @@ -32,119 +29,135 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - RamWidget::RamWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, - int x, int y) - : Widget(boss, lfont, x, y, 16, 16), + int x, int y, int w, int h, + uInt32 ramsize, uInt32 numrows, uInt32 pagesize) + : Widget(boss, lfont, x, y, w, h), CommandSender(boss), - myUndoAddress(-1), - myUndoValue(-1), - myCurrentRamBank(0) + _nfont(nfont), + myFontWidth(lfont.getMaxCharWidth()), + myFontHeight(lfont.getFontHeight()), + myLineHeight(lfont.getLineHeight()), + myButtonHeight(myLineHeight + 4), + myCurrentRamBank(0), + myRamSize(ramsize), + myNumRows(numrows), + myPageSize(pagesize) { - const int fontWidth = lfont.getMaxCharWidth(), - fontHeight = lfont.getFontHeight(), - lineHeight = lfont.getLineHeight(), - bwidth = lfont.getStringWidth("Compare "), - bheight = lineHeight + 2; int xpos, ypos, lwidth; + const int bwidth = lfont.getStringWidth("Compare "), + bheight = myLineHeight + 2; - // Create a 16x8 grid holding byte values (16 x 8 = 128 RAM bytes) with labels - // Add a scrollbar, since there may be more than 128 bytes of RAM available - xpos = x; ypos = y + lineHeight; lwidth = 4 * fontWidth; - myRamGrid = new DataGridWidget(boss, nfont, xpos + lwidth, ypos, - 16, 8, 2, 8, Common::Base::F_16, true); + ypos = y + myLineHeight; lwidth = 4 * myFontWidth; + + // Add RAM grid (with scrollbar) + xpos = x + _font.getStringWidth("xxxx"); + myRamGrid = new DataGridWidget(_boss, _nfont, xpos, ypos, + 16, myNumRows, 2, 8, Common::Base::F_16, true); myRamGrid->setTarget(this); + myRamGrid->setID(kRamHexID); addFocusWidget(myRamGrid); // Create actions buttons to the left of the RAM grid - xpos += lwidth + myRamGrid->getWidth() + 4; - myUndoButton = new ButtonWidget(boss, lfont, xpos, ypos, bwidth, bheight, + int bx = xpos + myRamGrid->getWidth() + 4; + int by = ypos; + myUndoButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight, "Undo", kUndoCmd); myUndoButton->setTarget(this); - ypos += bheight + 4; - myRevertButton = new ButtonWidget(boss, lfont, xpos, ypos, bwidth, bheight, + by += bheight + 4; + myRevertButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight, "Revert", kRevertCmd); myRevertButton->setTarget(this); - ypos += 2 * bheight + 2; - mySearchButton = new ButtonWidget(boss, lfont, xpos, ypos, bwidth, bheight, + by += 2 * bheight + 2; + mySearchButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight, "Search", kSearchCmd); mySearchButton->setTarget(this); - ypos += bheight + 4; - myCompareButton = new ButtonWidget(boss, lfont, xpos, ypos, bwidth, bheight, + by += bheight + 4; + myCompareButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight, "Compare", kCmpCmd); myCompareButton->setTarget(this); - ypos += bheight + 4; - myRestartButton = new ButtonWidget(boss, lfont, xpos, ypos, bwidth, bheight, + by += bheight + 4; + myRestartButton = new ButtonWidget(boss, lfont, bx, by, bwidth, bheight, "Reset", kRestartCmd); myRestartButton->setTarget(this); - // Remember position of right side of buttons - int xpos_r = xpos + bwidth ; - // Labels for RAM grid - xpos = x; ypos = y + lineHeight; myRamStart = - new StaticTextWidget(boss, lfont, xpos, ypos - lineHeight, - lfont.getStringWidth("xxxx"), fontHeight, - "00xx", kTextAlignLeft); + new StaticTextWidget(_boss, lfont, xpos - _font.getStringWidth("xxxx"), + ypos - myLineHeight, + lfont.getStringWidth("xxxx"), myFontHeight, + "00xx", kTextAlignLeft); for(int col = 0; col < 16; ++col) { - new StaticTextWidget(boss, lfont, xpos + col*myRamGrid->colWidth() + lwidth + 8, - ypos - lineHeight, - fontWidth, fontHeight, + new StaticTextWidget(_boss, lfont, xpos + col*myRamGrid->colWidth() + 8, + ypos - myLineHeight, + myFontWidth, myFontHeight, Common::Base::toString(col, Common::Base::F_16_1), kTextAlignLeft); } - for(int row = 0; row < 8; ++row) + + uInt32 row; + for(row = 0; row < myNumRows; ++row) { myRamLabels[row] = - new StaticTextWidget(boss, lfont, xpos + 8, ypos + row*lineHeight + 2, - 3*fontWidth, fontHeight, "", kTextAlignLeft); + new StaticTextWidget(_boss, _font, xpos - _font.getStringWidth("x "), + ypos + row*myLineHeight + 2, + myFontWidth, myFontHeight, "", kTextAlignLeft); } - ypos += 9 * lineHeight; + // For smaller grids, make sure RAM cell detail fields are below the RESET button + row = myNumRows < 8 ? 9 : myNumRows + 1; + ypos += row * myLineHeight; // We need to define these widgets from right to left since the leftmost // one resizes as much as possible - xpos = xpos_r - 13*fontWidth - 5; - new StaticTextWidget(boss, lfont, xpos, ypos, 4*fontWidth, fontHeight, + + // Add Binary display of selected RAM cell + xpos = x + w - 13*myFontWidth - 20; + new StaticTextWidget(boss, lfont, xpos, ypos, 4*myFontWidth, myFontHeight, "Bin:", kTextAlignLeft); - myBinValue = new EditTextWidget(boss, nfont, xpos + 4*fontWidth + 5, - ypos-2, 9*fontWidth, lineHeight, ""); - myBinValue->setEditable(false); + myBinValue = new DataGridWidget(boss, nfont, xpos + 4*myFontWidth + 5, ypos-2, + 1, 1, 8, 8, Common::Base::F_2); + myBinValue->setTarget(this); + myBinValue->setID(kRamBinID); - xpos -= 8*fontWidth + 5 + 20; - new StaticTextWidget(boss, lfont, xpos, ypos, 4*fontWidth, fontHeight, + // Add Decimal display of selected RAM cell + xpos -= 8*myFontWidth + 5 + 20; + new StaticTextWidget(boss, lfont, xpos, ypos, 4*myFontWidth, myFontHeight, "Dec:", kTextAlignLeft); - myDecValue = new EditTextWidget(boss, nfont, xpos + 4*fontWidth + 5, ypos-2, - 4*fontWidth, lineHeight, ""); - myDecValue->setEditable(false); + myDecValue = new DataGridWidget(boss, nfont, xpos + 4*myFontWidth + 5, ypos-2, + 1, 1, 3, 8, Common::Base::F_10); + myDecValue->setTarget(this); + myDecValue->setID(kRamDecID); - xpos_r = xpos - 20; + addFocusWidget(myDecValue); + addFocusWidget(myBinValue); + + // Add Label of selected RAM cell + int xpos_r = xpos - 20; xpos = x + 10; - new StaticTextWidget(boss, lfont, xpos, ypos, 6*fontWidth, fontHeight, + new StaticTextWidget(boss, lfont, xpos, ypos, 6*myFontWidth, myFontHeight, "Label:", kTextAlignLeft); - xpos += 6*fontWidth + 5; + xpos += 6*myFontWidth + 5; myLabel = new EditTextWidget(boss, nfont, xpos, ypos-2, xpos_r-xpos, - lineHeight, ""); + myLineHeight); myLabel->setEditable(false); - // Calculate real dimensions - _w = lwidth + myRamGrid->getWidth(); - _h = ypos + lineHeight - y; - // Inputbox which will pop up when searching RAM - StringList labels; - labels.push_back("Search: "); + StringList labels = { "Search: " }; myInputBox = make_ptr(boss, lfont, nfont, labels); myInputBox->setTarget(this); // Start with these buttons disabled myCompareButton->clearFlags(WIDGET_ENABLED); myRestartButton->clearFlags(WIDGET_ENABLED); + + // Calculate final height + if(_h == 0) _h = ypos + myLineHeight - y; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -160,30 +173,38 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) // memory location int addr, value; - CartDebug& dbg = instance().debugger().cartDebug(); - const CartState& state = (CartState&) dbg.getState(); switch(cmd) { case DataGridWidget::kItemDataChangedCmd: { - addr = myRamGrid->getSelectedAddr(); - value = myRamGrid->getSelectedValue(); - - // Attempt the write, and revert if it didn't succeed - uInt8 oldval = dbg.peek(state.rport[addr]); - dbg.poke(state.wport[addr], value); - uInt8 newval = dbg.peek(state.rport[addr]); - if(value != newval) + switch(id) { - myRamGrid->setValue(addr - myCurrentRamBank*128, newval, false); - break; + case kRamHexID: + addr = myRamGrid->getSelectedAddr(); + value = myRamGrid->getSelectedValue(); + break; + + case kRamDecID: + addr = myRamGrid->getSelectedAddr(); + value = myDecValue->getSelectedValue(); + break; + + case kRamBinID: + addr = myRamGrid->getSelectedAddr(); + value = myBinValue->getSelectedValue(); + break; } + uInt8 oldval = getValue(addr); + setValue(addr, value); + myUndoAddress = addr; myUndoValue = oldval; - myDecValue->setText(Common::Base::toString(value, Common::Base::F_10)); - myBinValue->setText(Common::Base::toString(value, Common::Base::F_2)); + myRamGrid->setValueInternal(addr - myCurrentRamBank*myPageSize, value, true); + myDecValue->setValueInternal(0, value, true); + myBinValue->setValueInternal(0, value, true); + myRevertButton->setEnabled(true); myUndoButton->setEnabled(true); break; @@ -194,20 +215,20 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) addr = myRamGrid->getSelectedAddr(); value = myRamGrid->getSelectedValue(); - myLabel->setText(dbg.getLabel(state.rport[addr], true)); - myDecValue->setText(Common::Base::toString(value, Common::Base::F_10)); - myBinValue->setText(Common::Base::toString(value, Common::Base::F_2)); + myLabel->setText(getLabel(addr)); + myDecValue->setValueInternal(0, value, false); + myBinValue->setValueInternal(0, value, false); break; } case kRevertCmd: for(uInt32 i = 0; i < myOldValueList.size(); ++i) - dbg.poke(state.wport[i], myOldValueList[i]); + setValue(i, myOldValueList[i]); fillGrid(true); break; case kUndoCmd: - dbg.poke(state.wport[myUndoAddress], myUndoValue); + setValue(myUndoAddress, myUndoValue); myUndoButton->setEnabled(false); fillGrid(false); break; @@ -256,6 +277,8 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) void RamWidget::setOpsWidget(DataGridOpsWidget* w) { myRamGrid->setOpsWidget(w); + myBinValue->setOpsWidget(w); + myDecValue->setOpsWidget(w); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -271,29 +294,13 @@ void RamWidget::fillGrid(bool updateOld) IntArray vlist; BoolArray changed; - if(updateOld) myOldValueList.clear(); + uInt32 start = myCurrentRamBank * myPageSize; + fillList(start, myPageSize, alist, vlist, changed); - CartDebug& dbg = instance().debugger().cartDebug(); + if(updateOld) + myOldValueList = currentRam(start); - const CartState& state = (CartState&) dbg.getState(); - const CartState& oldstate = (CartState&) dbg.getOldState(); - - // Jump to the correct 128 byte 'window' in the RAM area - // This assumes that the RAM areas are aligned on 128 byte boundaries - // TODO - the boundary restriction may not always apply ... - uInt32 start = myCurrentRamBank * 128; - assert(start+128 <= state.ram.size()); - - if(updateOld) myOldValueList = state.ram; - - for(uInt32 i = start; i < start + 16*8; ++i) - { - alist.push_back(i); - vlist.push_back(state.ram[i]); - changed.push_back(state.ram[i] != oldstate.ram[i]); - } - - myRamGrid->setNumRows((int)state.ram.size() / 128); + myRamGrid->setNumRows(myRamSize / myPageSize); myRamGrid->setList(alist, vlist, changed); if(updateOld) { @@ -302,15 +309,13 @@ void RamWidget::fillGrid(bool updateOld) } // Update RAM labels + uInt32 rport = readPort(start), page = rport & 0xf0; char buf[5]; - BSPF_snprintf(buf, 5, "%04X", state.rport[start] & 0xff00); + BSPF_snprintf(buf, 5, "%04X", rport); buf[2] = buf[3] = 'x'; myRamStart->setLabel(buf); - for(uInt32 i = start, row = 0; i < start + 16*8; i += 16, ++row) - { - BSPF_snprintf(buf, 3, "%02X", state.rport[i] & 0x00ff); - myRamLabels[row]->setLabel(buf); - } + for(uInt32 row = 0; row < myNumRows; ++row, page += 0x10) + myRamLabels[row]->setLabel(Common::Base::toString(page>>4, Common::Base::F_16_1)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -351,12 +356,11 @@ string RamWidget::doSearch(const string& str) // Now, search all memory locations for this value, and add it to the // search array + const ByteArray& ram = currentRam(0); bool hitfound = false; - CartDebug& dbg = instance().debugger().cartDebug(); - const CartState& state = (CartState&) dbg.getState(); - for(uInt32 addr = 0; addr < state.ram.size(); ++addr) + for(uInt32 addr = 0; addr < ram.size(); ++addr) { - int value = state.ram[addr]; + int value = ram[addr]; if(comparisonSearch && searchVal != value) { mySearchState.push_back(false); @@ -381,7 +385,7 @@ string RamWidget::doSearch(const string& str) // Finally, show the search results in the list showSearchResults(); - return ""; + return EmptyString; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -420,12 +424,11 @@ string RamWidget::doCompare(const string& str) searchVal = instance().debugger().stringToValue(str); // Now, search all memory locations previously 'found' for this value + const ByteArray& ram = currentRam(0); bool hitfound = false; - CartDebug& dbg = instance().debugger().cartDebug(); - const CartState& state = (CartState&) dbg.getState(); IntArray tempAddrList, tempValueList; mySearchState.clear(); - for(uInt32 i = 0; i < state.rport.size(); ++i) + for(uInt32 i = 0; i < ram.size(); ++i) mySearchState.push_back(false); for(uInt32 i = 0; i < mySearchAddr.size(); ++i) @@ -438,7 +441,7 @@ string RamWidget::doCompare(const string& str) } int addr = mySearchAddr[i]; - if(dbg.peek(state.rport[addr]) == searchVal) + if(ram[addr] == searchVal) { tempAddrList.push_back(addr); tempValueList.push_back(searchVal); @@ -460,7 +463,7 @@ string RamWidget::doCompare(const string& str) // Finally, show the search results in the list showSearchResults(); - return ""; + return EmptyString; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -482,15 +485,15 @@ void RamWidget::showSearchResults() { // Only update the search results for the bank currently being shown BoolArray temp; - uInt32 start = myCurrentRamBank * 128; + uInt32 start = myCurrentRamBank * myPageSize; if(mySearchState.size() == 0 || start > mySearchState.size()) { - for(uInt32 i = 0; i < 128; ++i) + for(uInt32 i = 0; i < myPageSize; ++i) temp.push_back(false); } else { - for(uInt32 i = start; i < start + 128; ++i) + for(uInt32 i = start; i < start + myPageSize; ++i) temp.push_back(mySearchState[i]); } myRamGrid->setHiliteList(temp); diff --git a/src/debugger/gui/RamWidget.hxx b/src/debugger/gui/RamWidget.hxx index 5d5da4641..434e80927 100644 --- a/src/debugger/gui/RamWidget.hxx +++ b/src/debugger/gui/RamWidget.hxx @@ -23,6 +23,7 @@ class GuiObject; class InputTextDialog; class ButtonWidget; +class DataGridWidget; class DataGridOpsWidget; class EditTextWidget; class StaticTextWidget; @@ -34,11 +35,24 @@ class RamWidget : public Widget, public CommandSender { public: RamWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, - int x, int y); + int x, int y, int w, int h, + uInt32 ramsize, uInt32 numrows, uInt32 pagesize); virtual ~RamWidget(); void loadConfig() override; void setOpsWidget(DataGridOpsWidget* w); + void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + + private: + // To be implemented by derived classes + virtual uInt8 getValue(int addr) const = 0; + virtual void setValue(int addr, uInt8 value) = 0; + virtual string getLabel(int addr) const = 0; + + virtual void fillList(uInt32 start, uInt32 size, + IntArray& alist, IntArray& vlist, BoolArray& changed) const = 0; + virtual uInt32 readPort(uInt32 start) const = 0; + virtual const ByteArray& currentRam(uInt32 start) const = 0; private: void fillGrid(bool updateOld); @@ -49,7 +63,13 @@ class RamWidget : public Widget, public CommandSender void doRestart(); void showSearchResults(); - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + protected: + // Font used for 'normal' text; _font is for 'label' text + const GUI::Font& _nfont; + + // These will be needed by most of the child classes; + // we may as well make them protected variables + int myFontWidth, myFontHeight, myLineHeight, myButtonHeight; private: enum { @@ -59,21 +79,26 @@ class RamWidget : public Widget, public CommandSender kCmpCmd = 'RWcp', kRestartCmd = 'RWrs', kSValEntered = 'RWsv', - kCValEntered = 'RWcv' + kCValEntered = 'RWcv', + kRamHexID, + kRamDecID, + kRamBinID }; - int myUndoAddress; - int myUndoValue; - int myCurrentRamBank; + uInt32 myUndoAddress, myUndoValue; + uInt32 myCurrentRamBank; + uInt32 myRamSize; + uInt32 myNumRows; + uInt32 myPageSize; unique_ptr myInputBox; StaticTextWidget* myRamStart; - StaticTextWidget* myRamLabels[8]; - DataGridWidget* myRamGrid; + StaticTextWidget* myRamLabels[16]; - EditTextWidget* myBinValue; - EditTextWidget* myDecValue; + DataGridWidget* myRamGrid; + DataGridWidget* myDecValue; + DataGridWidget* myBinValue; EditTextWidget* myLabel; ButtonWidget* myRevertButton; @@ -82,7 +107,7 @@ class RamWidget : public Widget, public CommandSender ButtonWidget* myCompareButton; ButtonWidget* myRestartButton; - IntArray myOldValueList; + ByteArray myOldValueList; IntArray mySearchAddr; IntArray mySearchValue; BoolArray mySearchState; diff --git a/src/debugger/gui/RiotRamWidget.cxx b/src/debugger/gui/RiotRamWidget.cxx new file mode 100644 index 000000000..894cffac0 --- /dev/null +++ b/src/debugger/gui/RiotRamWidget.cxx @@ -0,0 +1,86 @@ +//============================================================================ +// +// 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-2015 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 "Debugger.hxx" +#include "CartDebug.hxx" + +#include "RiotRamWidget.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +RiotRamWidget::RiotRamWidget(GuiObject* boss, const GUI::Font& lfont, + const GUI::Font& nfont, int x, int y, int w) + : RamWidget(boss, lfont, nfont, x, y, w, 0, 128, 8, 128), + myDbg(instance().debugger().cartDebug()) +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +RiotRamWidget::~RiotRamWidget() +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 RiotRamWidget::getValue(int addr) const +{ + const CartState& state = (CartState&) myDbg.getState(); + return myDbg.peek(state.rport[addr]); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void RiotRamWidget::setValue(int addr, uInt8 value) +{ + const CartState& state = (CartState&) myDbg.getState(); + myDbg.poke(state.wport[addr], value); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string RiotRamWidget::getLabel(int addr) const +{ + const CartState& state = (CartState&) myDbg.getState(); + return myDbg.getLabel(state.rport[addr], true); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void RiotRamWidget::fillList(uInt32 start, uInt32 size, IntArray& alist, + IntArray& vlist, BoolArray& changed) const +{ + const CartState& state = (CartState&) myDbg.getState(); + const CartState& oldstate = (CartState&) myDbg.getOldState(); + + for(uInt32 i = 0; i < size; i++) + { + alist.push_back(i+start); + vlist.push_back(state.ram[i]); + changed.push_back(state.ram[i] != oldstate.ram[i]); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt32 RiotRamWidget::readPort(uInt32 start) const +{ + const CartState& state = (CartState&) myDbg.getState(); + return state.rport[start]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const ByteArray& RiotRamWidget::currentRam(uInt32) const +{ + const CartState& state = (CartState&) myDbg.getState(); + return state.ram; +} diff --git a/src/debugger/gui/RiotRamWidget.hxx b/src/debugger/gui/RiotRamWidget.hxx new file mode 100644 index 000000000..6a2b0e671 --- /dev/null +++ b/src/debugger/gui/RiotRamWidget.hxx @@ -0,0 +1,63 @@ +//============================================================================ +// +// 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-2015 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 RIOT_RAM_WIDGET_HXX +#define RIOT_RAM_WIDGET_HXX + +class GuiObject; +class InputTextDialog; +class ButtonWidget; +class DataGridWidget; +class DataGridOpsWidget; +class EditTextWidget; +class StaticTextWidget; + +#include "CartDebug.hxx" +#include "RamWidget.hxx" + +class RiotRamWidget : public RamWidget +{ + public: + RiotRamWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, + int x, int y, int w); + virtual ~RiotRamWidget(); + + private: + uInt8 getValue(int addr) const; + void setValue(int addr, uInt8 value); + string getLabel(int addr) const; + + void fillList(uInt32 start, uInt32 size, IntArray& alist, + IntArray& vlist, BoolArray& changed) const; + uInt32 readPort(uInt32 start) const; + const ByteArray& currentRam(uInt32 start) const; + + private: + CartDebug& myDbg; + + private: + // Following constructors and assignment operators not supported + RiotRamWidget() = delete; + RiotRamWidget(const RiotRamWidget&) = delete; + RiotRamWidget(RiotRamWidget&&) = delete; + RiotRamWidget& operator=(const RiotRamWidget&) = delete; + RiotRamWidget& operator=(RiotRamWidget&&) = delete; +}; + +#endif diff --git a/src/debugger/gui/module.mk b/src/debugger/gui/module.mk index df959d44f..3f7fd8a69 100644 --- a/src/debugger/gui/module.mk +++ b/src/debugger/gui/module.mk @@ -6,6 +6,7 @@ MODULE_OBJS := \ src/debugger/gui/PromptWidget.o \ src/debugger/gui/RamWidget.o \ src/debugger/gui/RiotWidget.o \ + src/debugger/gui/RiotRamWidget.o \ src/debugger/gui/RomWidget.o \ src/debugger/gui/RomListWidget.o \ src/debugger/gui/RomListSettings.o \ diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx index 932daa7ac..60b5e8f0a 100644 --- a/src/gui/Dialog.hxx +++ b/src/gui/Dialog.hxx @@ -64,7 +64,7 @@ class Dialog : public GuiObject virtual void setDefaults() { } void addFocusWidget(Widget* w) override; - void addToFocusList(WidgetArray& list); + void addToFocusList(WidgetArray& list) override; void addToFocusList(WidgetArray& list, TabWidget* w, int tabId); void addBGroupToFocusList(WidgetArray& list) { _buttonGroup = list; } void addTabWidget(TabWidget* w); diff --git a/src/gui/GuiObject.hxx b/src/gui/GuiObject.hxx index 84fa090c2..e5845168b 100644 --- a/src/gui/GuiObject.hxx +++ b/src/gui/GuiObject.hxx @@ -29,6 +29,7 @@ class Widget; #include "Command.hxx" #include "OSystem.hxx" +#include "Vec.hxx" using WidgetArray = vector; @@ -87,8 +88,9 @@ class GuiObject : public CommandReceiver virtual bool isVisible() const = 0; - /** Add given widget to the focus list */ + /** Add given widget(s) to the focus list */ virtual void addFocusWidget(Widget* w) = 0; + virtual void addToFocusList(WidgetArray& list) = 0; /** Return focus list for this object */ WidgetArray& getFocusList() { return _focusList; } diff --git a/src/gui/Widget.hxx b/src/gui/Widget.hxx index c7b443292..03b5eb9e4 100644 --- a/src/gui/Widget.hxx +++ b/src/gui/Widget.hxx @@ -86,6 +86,9 @@ class Widget : public GuiObject void receivedFocus(); void lostFocus(); void addFocusWidget(Widget* w) override { _focusList.push_back(w); } + void addToFocusList(WidgetArray& list) override { + Vec::append(_focusList, list); + }; /** Set/clear WIDGET_ENABLED flag */ void setEnabled(bool e);