Added extra registers to the DPC scheme in the debugger ROM tab.

The remainder of this commit is basically some cleanup of the
Widget API, and infrastructure fixes to allow CartDebugWidgets to
have change tracking.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2702 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2013-04-20 22:23:42 +00:00
parent de6dbc060c
commit f1530ca86d
23 changed files with 243 additions and 48 deletions

View File

@ -30,11 +30,13 @@
#include "Settings.hxx"
#include "Version.hxx"
#include "CartDebug.hxx"
#include "CartDebugWidget.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem)
: DebuggerSystem(dbg, console),
myOSystem(osystem),
myDebugWidget(0),
myRWPortAddress(0),
myLabelLength(8) // longest pre-defined label
{
@ -147,6 +149,9 @@ void CartDebug::saveOldState()
myOldState.ram.clear();
for(uInt32 i = 0; i < myOldState.rport.size(); ++i)
myOldState.ram.push_back(peek(myOldState.rport[i]));
if(myDebugWidget)
myDebugWidget->saveOldState();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -21,6 +21,7 @@
#define CART_DEBUG_HXX
class Settings;
class CartDebugWidget;
#include <map>
#include <set>
@ -97,6 +98,11 @@ class CartDebug : public DebuggerSystem
void saveOldState();
string toString();
// Used to get/set the debug widget, which contains cart-specific
// functionality
CartDebugWidget* getDebugWidget() const { return myDebugWidget; }
void setDebugWidget(CartDebugWidget* w) { myDebugWidget = w; }
// The following assume that the given addresses are using the
// correct read/write port ranges; no checking will be done to
// confirm this.
@ -321,6 +327,8 @@ class CartDebug : public DebuggerSystem
CartState myState;
CartState myOldState;
CartDebugWidget* myDebugWidget;
// A complete record of relevant diassembly information for each bank
Common::Array<BankInfo> myBankInfo;

View File

@ -40,6 +40,7 @@
#include "TIA.hxx"
#include "CartDebug.hxx"
#include "CartDebugWidget.hxx"
#include "CpuDebug.hxx"
#include "RiotDebug.hxx"
#include "TIADebug.hxx"
@ -181,6 +182,7 @@ void Debugger::initialize()
myBaseDialog = myDialog;
myRewindManager = new RewindManager(*myOSystem, myDialog->rewindButton());
myCartDebug->setDebugWidget(&(myDialog->cartDebug()));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -75,7 +75,6 @@ class Debugger : public DialogContainer
// Make these friend classes, to ease communications with the debugger
// Although it isn't enforced, these classes should use accessor methods
// directly, and not touch the instance variables
friend class CartDebugWidget;
friend class DebuggerDialog;
friend class DebuggerParser;
friend class EventHandler;

View File

@ -18,6 +18,7 @@
//============================================================================
#include "CartDPC.hxx"
#include "DataGridWidget.hxx"
#include "PopUpWidget.hxx"
#include "CartDPCWidget.hxx"
@ -59,6 +60,98 @@ CartridgeDPCWidget::CartridgeDPCWidget(
font.getStringWidth("Set bank: "), kBankChanged);
myBank->setTarget(this);
addFocusWidget(myBank);
ypos += myLineHeight + 12;
// Data fetchers
int lwidth = font.getStringWidth("Data Fetchers: ");
new StaticTextWidget(boss, font, xpos, ypos, lwidth,
myFontHeight, "Data Fetchers: ", kTextAlignLeft);
// Top registers
lwidth = font.getStringWidth("Counter Registers: ");
xpos = 18; ypos += myLineHeight + 8;
new StaticTextWidget(boss, font, xpos, ypos, lwidth,
myFontHeight, "Top Registers: ", kTextAlignLeft);
xpos += lwidth;
myTops = new DataGridWidget(boss, font, xpos, ypos-2, 8, 1, 2, 8, kBASE_16);
myTops->setTarget(this);
myTops->setEditable(false);
// Bottom registers
xpos = 18; ypos += myLineHeight + 8;
new StaticTextWidget(boss, font, xpos, ypos, lwidth,
myFontHeight, "Bottom Registers: ", kTextAlignLeft);
xpos += lwidth;
myBottoms = new DataGridWidget(boss, font, xpos, ypos-2, 8, 1, 2, 8, kBASE_16);
myBottoms->setTarget(this);
myBottoms->setEditable(false);
// Counter registers
xpos = 18; ypos += myLineHeight + 8;
new StaticTextWidget(boss, font, xpos, ypos, lwidth,
myFontHeight, "Counter Registers: ", kTextAlignLeft);
xpos += lwidth;
myCounters = new DataGridWidget(boss, font, xpos, ypos-2, 8, 1, 4, 16, kBASE_16_4);
myCounters->setTarget(this);
myCounters->setEditable(false);
// Flag registers
xpos = 18; ypos += myLineHeight + 8;
new StaticTextWidget(boss, font, xpos, ypos, lwidth,
myFontHeight, "Bottom Registers: ", kTextAlignLeft);
xpos += lwidth;
myFlags = new DataGridWidget(boss, font, xpos, ypos-2, 8, 1, 2, 8, kBASE_16);
myFlags->setTarget(this);
myFlags->setEditable(false);
// Music mode
xpos = 10; ypos += myLineHeight + 12;
lwidth = font.getStringWidth("Music mode (DF5/DF6/DF7): ");
new StaticTextWidget(boss, font, xpos, ypos, lwidth,
myFontHeight, "Music mode (DF5/DF6/DF7): ", kTextAlignLeft);
xpos += lwidth;
myMusicMode = new DataGridWidget(boss, font, xpos, ypos-2, 3, 1, 2, 8, kBASE_16);
myMusicMode->setTarget(this);
myMusicMode->setEditable(false);
// Current random number
xpos = 10; ypos += myLineHeight + 8;
new StaticTextWidget(boss, font, xpos, ypos, lwidth,
myFontHeight, "Current random number: ", kTextAlignLeft);
xpos += lwidth;
myRandom = new DataGridWidget(boss, font, xpos, ypos-2, 1, 1, 2, 8, kBASE_16);
myRandom->setTarget(this);
myRandom->setEditable(false);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeDPCWidget::saveOldState()
{
myOldState.tops.clear();
myOldState.bottoms.clear();
myOldState.counters.clear();
myOldState.flags.clear();
myOldState.music.clear();
for(int i = 0; i < 8; ++i)
{
myOldState.tops.push_back(myCart.myTops[i]);
myOldState.bottoms.push_back(myCart.myBottoms[i]);
myOldState.counters.push_back(myCart.myCounters[i]);
myOldState.flags.push_back(myCart.myFlags[i]);
}
for(int i = 0; i < 3; ++i)
{
myOldState.music.push_back(myCart.myMusicMode[i]);
}
myOldState.random = myCart.myRandomNumber;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -66,6 +159,54 @@ void CartridgeDPCWidget::loadConfig()
{
myBank->setSelected(myCart.myCurrentBank);
// Get registers, using change tracking
IntArray alist;
IntArray vlist;
BoolArray changed;
alist.clear(); vlist.clear(); changed.clear();
for(int i = 0; i < 8; ++i)
{
alist.push_back(0); vlist.push_back(myCart.myTops[i]);
changed.push_back(myCart.myTops[i] != myOldState.tops[i]);
}
myTops->setList(alist, vlist, changed);
alist.clear(); vlist.clear(); changed.clear();
for(int i = 0; i < 8; ++i)
{
alist.push_back(0); vlist.push_back(myCart.myBottoms[i]);
changed.push_back(myCart.myBottoms[i] != myOldState.bottoms[i]);
}
myBottoms->setList(alist, vlist, changed);
alist.clear(); vlist.clear(); changed.clear();
for(int i = 0; i < 8; ++i)
{
alist.push_back(0); vlist.push_back(myCart.myCounters[i]);
changed.push_back(myCart.myCounters[i] != myOldState.counters[i]);
}
myCounters->setList(alist, vlist, changed);
alist.clear(); vlist.clear(); changed.clear();
for(int i = 0; i < 8; ++i)
{
alist.push_back(0); vlist.push_back(myCart.myFlags[i]);
changed.push_back(myCart.myFlags[i] != myOldState.flags[i]);
}
myFlags->setList(alist, vlist, changed);
alist.clear(); vlist.clear(); changed.clear();
for(int i = 0; i < 3; ++i)
{
alist.push_back(0); vlist.push_back(myCart.myMusicMode[i]);
changed.push_back(myCart.myMusicMode[i] != myOldState.music[i]);
}
myMusicMode->setList(alist, vlist, changed);
myRandom->setList(0, myCart.myRandomNumber,
myCart.myRandomNumber != myOldState.random);
CartDebugWidget::loadConfig();
}

View File

@ -22,6 +22,7 @@
class CartridgeDPC;
class PopUpWidget;
class DataGridWidget;
#include "CartDebugWidget.hxx"
@ -33,13 +34,34 @@ class CartridgeDPCWidget : public CartDebugWidget
CartridgeDPC& cart);
virtual ~CartridgeDPCWidget() { }
void saveOldState();
void loadConfig();
void handleCommand(CommandSender* sender, int cmd, int data, int id);
private:
struct CartState {
ByteArray tops;
ByteArray bottoms;
IntArray counters;
ByteArray flags;
BoolArray music;
uInt8 random;
};
private:
CartridgeDPC& myCart;
PopUpWidget* myBank;
DataGridWidget* myTops;
DataGridWidget* myBottoms;
DataGridWidget* myCounters;
DataGridWidget* myFlags;
DataGridWidget* myMusicMode;
DataGridWidget* myRandom;
CartState myState, myOldState;
enum { kBankChanged = 'bkCH' };
};

View File

@ -100,9 +100,13 @@ class CartDebugWidget : public Widget, public CommandSender
// Inform the ROM Widget that the underlying cart has somehow changed
void invalidate()
{
Debugger::debugger().rom().invalidate();
sendCommand(RomWidget::kInvalidateListing, -1, -1);
}
// Some carts need to save old state in the debugger, so that we can
// implement change tracking; most carts probably won't do anything here
virtual void saveOldState() { }
virtual void loadConfig() { myDesc->setSelected(0); }
virtual void handleCommand(CommandSender* sender, int cmd, int data, int id) { };

View File

@ -138,7 +138,7 @@ void CpuWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
switch(cmd)
{
case kDGItemDataChangedCmd:
case DataGridWidget::kItemDataChangedCmd:
switch(id)
{
case kPCRegID:
@ -190,7 +190,7 @@ void CpuWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
}
break;
case kTWItemDataChangedCmd:
case ToggleWidget::kItemDataChangedCmd:
{
bool state = myPSRegister->getSelectedState();

View File

@ -60,11 +60,17 @@ DataGridWidget::DataGridWidget(GuiObject* boss, const GUI::Font& font,
// _textcolorhi to erase it
_caretInverse = true;
// Make sure hilite list contains all false values
// Make sure all lists contain some default values
_hiliteList.clear();
int size = _rows * _cols;
while(size--)
{
_addrList.push_back(0);
_valueList.push_back(0);
_valueStringList.push_back("");
_changedList.push_back(0);
_hiliteList.push_back(false);
}
// Set lower and upper bounds to sane values
setRange(0, 1 << bits);
@ -100,7 +106,6 @@ cerr << "alist.size() = " << alist.size()
assert(size == _rows * _cols);
_addrList.clear();
_addrStringList.clear();
_valueList.clear();
_valueStringList.clear();
_changedList.clear();
@ -127,7 +132,7 @@ cerr << "_addrList.size() = " << _addrList.size()
_editMode = false;
// Send item selected signal for starting with cell 0
sendCommand(kDGSelectionChangedCmd, _selectedItem, _id);
sendCommand(DataGridWidget::kSelectionChangedCmd, _selectedItem, _id);
setDirty(); draw();
}
@ -200,7 +205,7 @@ void DataGridWidget::setValue(int position, int value, bool changed)
_changedList[position] = changed;
_valueList[position] = value;
sendCommand(kDGItemDataChangedCmd, position, _id);
sendCommand(DataGridWidget::kItemDataChangedCmd, position, _id);
setDirty(); draw();
}
@ -234,7 +239,7 @@ void DataGridWidget::handleMouseDown(int x, int y, int button, int clickCount)
_currentRow = _selectedItem / _cols;
_currentCol = _selectedItem - (_currentRow * _cols);
sendCommand(kDGSelectionChangedCmd, _selectedItem, _id);
sendCommand(DataGridWidget::kSelectionChangedCmd, _selectedItem, _id);
setDirty(); draw();
}
}
@ -246,7 +251,7 @@ void DataGridWidget::handleMouseUp(int x, int y, int button, int clickCount)
// send the double click command
if (clickCount == 2 && (_selectedItem == findItem(x, y)))
{
sendCommand(kDGItemDoubleClickedCmd, _selectedItem, _id);
sendCommand(DataGridWidget::kItemDoubleClickedCmd, _selectedItem, _id);
// Start edit mode
if(_editable && !_editMode)
@ -464,7 +469,7 @@ bool DataGridWidget::handleKeyDown(StellaKey key, StellaMod mod, char ascii)
_selectedItem = _currentRow*_cols + _currentCol;
if(_selectedItem != oldItem)
sendCommand(kDGSelectionChangedCmd, _selectedItem, _id);
sendCommand(DataGridWidget::kSelectionChangedCmd, _selectedItem, _id);
setDirty(); draw();
}

View File

@ -33,17 +33,18 @@ class ScrollBarWidget;
#include "Array.hxx"
#include "Rect.hxx"
// Some special commands
enum {
kDGItemDoubleClickedCmd = 'DGdb',
kDGItemActivatedCmd = 'DGac',
kDGItemDataChangedCmd = 'DGch',
kDGSelectionChangedCmd = 'DGsc'
};
/* DataGridWidget */
class DataGridWidget : public EditableWidget
{
public:
// Commands emitted by this commandsender
enum {
kItemDoubleClickedCmd = 'DGdb',
kItemActivatedCmd = 'DGac',
kItemDataChangedCmd = 'DGch',
kSelectionChangedCmd = 'DGsc'
};
public:
DataGridWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int cols, int rows,
@ -120,7 +121,6 @@ class DataGridWidget : public EditableWidget
IntArray _addrList;
IntArray _valueList;
StringList _addrStringList;
StringList _valueStringList;
BoolArray _changedList;
BoolArray _hiliteList;

View File

@ -147,6 +147,10 @@ void DebuggerDialog::handleCommand(CommandSender* sender, int cmd,
doExitRom();
break;
case RomWidget::kInvalidateListing:
myRom->invalidate();
break;
default:
Dialog::handleCommand(sender, cmd, data, id);
}

View File

@ -53,6 +53,7 @@ class DebuggerDialog : public Dialog
TiaOutputWidget& tiaOutput() { return *myTiaOutput; }
TiaZoomWidget& tiaZoom() { return *myTiaZoom; }
RomWidget& rom() { return *myRom; }
CartDebugWidget& cartDebug() { return *myCartDebug; }
EditTextWidget& message() { return *myMessageBox; }
ButtonWidget& rewindButton() { return *myRewindButton; }

View File

@ -164,7 +164,7 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
const CartState& state = (CartState&) dbg.getState();
switch(cmd)
{
case kDGItemDataChangedCmd:
case DataGridWidget::kItemDataChangedCmd:
{
addr = myRamGrid->getSelectedAddr();
value = myRamGrid->getSelectedValue();
@ -189,7 +189,7 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
break;
}
case kDGSelectionChangedCmd:
case DataGridWidget::kSelectionChangedCmd:
{
addr = myRamGrid->getSelectedAddr();
value = myRamGrid->getSelectedValue();

View File

@ -320,7 +320,7 @@ void RiotWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
switch(cmd)
{
case kDGItemDataChangedCmd:
case DataGridWidget::kItemDataChangedCmd:
switch(id)
{
case kTimWriteID:
@ -343,7 +343,7 @@ void RiotWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
}
break;
case kTWItemDataChangedCmd:
case ToggleWidget::kItemDataChangedCmd:
switch(id)
{
case kSWCHABitsID:

View File

@ -202,7 +202,7 @@ void RomWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
break; // kCMenuItemSelectedCmd
}
case kDGItemDataChangedCmd:
case DataGridWidget::kItemDataChangedCmd:
setBank(myBank->getSelectedValue());
break;

View File

@ -38,6 +38,13 @@ class StringList;
class RomWidget : public Widget, public CommandSender
{
public:
enum {
kResolveDataChanged = 'ACrd',
kRomNameEntered = 'RWrn',
kInvalidateListing = 'INli'
};
public:
RomWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h);
virtual ~RomWidget();
@ -58,11 +65,6 @@ class RomWidget : public Widget, public CommandSender
void saveROM(const string& rom);
private:
enum {
kResolveDataChanged = 'ACrd',
kRomNameEntered = 'RWrn'
};
RomListWidget* myRomList;
DataGridWidget* myBank;
PopUpWidget* myResolveData;

View File

@ -585,7 +585,7 @@ void TiaWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
tia.strobeCxclr();
break;
case kDGItemDataChangedCmd:
case DataGridWidget::kItemDataChangedCmd:
switch(id)
{
case kColorRegsID:
@ -660,7 +660,7 @@ void TiaWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
}
break;
case kTWItemDataChangedCmd:
case ToggleWidget::kItemDataChangedCmd:
switch(id)
{
case kGRP0ID:

View File

@ -79,7 +79,7 @@ void ToggleWidget::handleMouseUp(int x, int y, int button, int clickCount)
{
_stateList[_selectedItem] = !_stateList[_selectedItem];
_changedList[_selectedItem] = !_changedList[_selectedItem];
sendCommand(kTWItemDataChangedCmd, _selectedItem, _id);
sendCommand(ToggleWidget::kItemDataChangedCmd, _selectedItem, _id);
setDirty(); draw();
}
}
@ -193,7 +193,7 @@ bool ToggleWidget::handleKeyDown(StellaKey key, StellaMod mod, char ascii)
{
_stateList[_selectedItem] = !_stateList[_selectedItem];
_changedList[_selectedItem] = !_changedList[_selectedItem];
sendCommand(kTWItemDataChangedCmd, _selectedItem, _id);
sendCommand(ToggleWidget::kItemDataChangedCmd, _selectedItem, _id);
}
setDirty(); draw();

View File

@ -27,15 +27,16 @@
#include "Command.hxx"
#include "Array.hxx"
// Some special commands
enum {
kTWItemDataChangedCmd = 'TWch',
kTWSelectionChangedCmd = 'TWsc'
};
/* ToggleWidget */
class ToggleWidget : public Widget, public CommandSender
{
public:
// Commands emitted by this commandsender
enum {
kItemDataChangedCmd = 'TWch',
kSelectionChangedCmd = 'TWsc'
};
public:
ToggleWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int cols, int rows);

View File

@ -42,7 +42,7 @@ CartridgeDPC::CartridgeDPC(const uInt8* image, uInt32 size,
myDisplayImage = myProgramImage + 8192;
// Initialize the DPC data fetcher registers
for(uInt16 i = 0; i < 8; ++i)
for(int i = 0; i < 8; ++i)
myTops[i] = myBottoms[i] = myCounters[i] = myFlags[i] = 0;
// None of the data fetchers are in music mode

View File

@ -30,8 +30,12 @@ class System;
/**
Cartridge class used for Pitfall II. There are two 4K program banks, a
2K display bank, and the DPC chip. For complete details on the DPC chip
see David P. Crane's United States Patent Number 4,644,495.
2K display bank, and the DPC chip. The bankswitching itself is the same
as F8 scheme (hotspots at $1FF8 and $1FF9). DPC chip access is mapped to
$1000 - $1080 ($1000 - $103F is read port, $1040 - $107F is write port).
For complete details on the DPC chip see David P. Crane's United States
Patent Number 4,644,495.
@author Bradford W. Mott
@version $Id$

View File

@ -56,10 +56,7 @@ CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size,
// If the image is larger than 29K, we assume any excess at the
// beginning is ARM code, and skip over it
if(size > 29 * 1024)
{
int offset = size - 29 * 1024;
myProgramImage += offset;
}
myProgramImage += (size - 29 * 1024);
#ifdef THUMB_SUPPORT
// Create Thumbulator ARM emulator

View File

@ -582,7 +582,7 @@ bool Dialog::handleNavEvent(Event::Type e)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::getTabIdForWidget(Widget* w)
{
if(_myTabList.size() == 0)
if(_myTabList.size() == 0 || !w)
return;
for(uInt32 id = 0; id < _myTabList.size(); ++id)