Added support for accessing/modifying extended RAM (aka SuperChip) from

the debugger RAM UI.  A scrollbar is now present, which can scroll
through each 128 byte 'bank'.  Labels indicate the current readport,
so you can distinguish between different areas of RAM.  For now,
F4SC, F6SC, F8SC, and FASC have been converted, but I'm looking into the
other schemes now.

The RAM UI takes care of all read/write port issues.  From the POV of
the UI, the RAM can be treated as zero-page; translation is done
behind the scene.  Searching/comparing and change-tracking are also
supported.

The 'ram' command in the debugger prompt now reflects all RAM, and
readport/writeport addresses are shown, making it easier to use the
command withot having to look up the offsets.

Debugger width has been bumped to 1050 pixels wide to accomodate the
new functionality.  We'll see how much trouble this causes ...


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1747 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2009-06-02 17:25:14 +00:00
parent c29a6b26c2
commit 3280901be9
22 changed files with 385 additions and 106 deletions

View File

@ -19,6 +19,9 @@ Stephen Anthony at stephena@users.sourceforge.net.
* Add new TIA infrastructure with improved HMOVE emulation, including * Add new TIA infrastructure with improved HMOVE emulation, including
fixes for (possibly) incorrect VSYNC handling in Q-Bert. fixes for (possibly) incorrect VSYNC handling in Q-Bert.
* Add better support for 'floating' TIA reads as described here:
http://www.atariage.com/forums/index.php?s=&showtopic=143363&view=findpost&p=1762433
* Finalize CRT simulation OpenGL code for the next release, and look * Finalize CRT simulation OpenGL code for the next release, and look
into adding Blargg NTSC filtering (perhaps as a GLSL program). into adding Blargg NTSC filtering (perhaps as a GLSL program).

View File

@ -106,7 +106,7 @@ Debugger::Debugger(OSystem* osystem)
myBreakPoints(NULL), myBreakPoints(NULL),
myReadTraps(NULL), myReadTraps(NULL),
myWriteTraps(NULL), myWriteTraps(NULL),
myWidth(1030), myWidth(1050),
myHeight(620) myHeight(620)
{ {
// Get the dialog size // Get the dialog size
@ -114,7 +114,7 @@ Debugger::Debugger(OSystem* osystem)
myOSystem->settings().getSize("debuggerres", w, h); myOSystem->settings().getSize("debuggerres", w, h);
myWidth = BSPF_max(w, 0); myWidth = BSPF_max(w, 0);
myHeight = BSPF_max(h, 0); myHeight = BSPF_max(h, 0);
myWidth = BSPF_max(myWidth, 1030u); myWidth = BSPF_max(myWidth, 1050u);
myHeight = BSPF_max(myHeight, 620u); myHeight = BSPF_max(myHeight, 620u);
myOSystem->settings().setSize("debuggerres", myWidth, myHeight); myOSystem->settings().setSize("debuggerres", myWidth, myHeight);
@ -190,6 +190,12 @@ void Debugger::setConsole(Console* console)
delete myRamDebug; delete myRamDebug;
myRamDebug = new RamDebug(*this, *myConsole); myRamDebug = new RamDebug(*this, *myConsole);
// Register any RAM areas in the Cartridge
// Zero-page RAM is automatically recognized by RamDebug
uInt16 start, size, roffset, woffset;
if(myConsole->cartridge().getRamArea(start, size, roffset, woffset))
myRamDebug->addRamArea(start, size, roffset, woffset);
delete myRiotDebug; delete myRiotDebug;
myRiotDebug = new RiotDebug(*this, *myConsole); myRiotDebug = new RiotDebug(*this, *myConsole);
@ -205,6 +211,8 @@ void Debugger::setConsole(Console* console)
autoLoadSymbols(myOSystem->romFile()); autoLoadSymbols(myOSystem->romFile());
loadListFile(); loadListFile();
// Make sure cart RAM is added before this is called,
// otherwise the debugger state won't know about it
saveOldState(); saveOldState();
} }

View File

@ -48,12 +48,6 @@ class Expression;
typedef map<string,Expression*> FunctionMap; typedef map<string,Expression*> FunctionMap;
typedef map<string,string> FunctionDefMap; typedef map<string,string> FunctionDefMap;
// Constants for RAM area
enum {
kRamStart = 0x80,
kRamSize = 128
};
/* /*
// These will probably turn out to be unneeded, left for reference for now // These will probably turn out to be unneeded, left for reference for now
// pointer types for Debugger instance methods // pointer types for Debugger instance methods

View File

@ -16,6 +16,7 @@
// $Id$ // $Id$
//============================================================================ //============================================================================
#include "bspf.hxx"
#include "Array.hxx" #include "Array.hxx"
#include "System.hxx" #include "System.hxx"
#include "RamDebug.hxx" #include "RamDebug.hxx"
@ -24,14 +25,37 @@
RamDebug::RamDebug(Debugger& dbg, Console& console) RamDebug::RamDebug(Debugger& dbg, Console& console)
: DebuggerSystem(dbg, console) : DebuggerSystem(dbg, console)
{ {
// Zero-page RAM is always present
addRamArea(0x80, 128, 0, 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RamDebug::addRamArea(uInt16 start, uInt16 size,
uInt16 roffset, uInt16 woffset)
{
// First make sure this area isn't already present
for(uInt32 i = 0; i < myState.rport.size(); ++i)
if(myState.rport[i] == start + roffset ||
myState.wport[i] == start + woffset)
return;
// Otherwise, add a new area
for(uInt32 i = 0; i < size; ++i)
{
myState.rport.push_back(i + start + roffset);
myState.wport.push_back(i + start + woffset);
myOldState.rport.push_back(i + start + roffset);
myOldState.wport.push_back(i + start + woffset);
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const DebuggerState& RamDebug::getState() const DebuggerState& RamDebug::getState()
{ {
myState.ram.clear(); myState.ram.clear();
for(int i=0; i<0x80; i++) for(uInt32 i = 0; i < myState.rport.size(); ++i)
myState.ram.push_back(read(i)); myState.ram.push_back(read(myState.rport[i]));
return myState; return myState;
} }
@ -40,22 +64,20 @@ const DebuggerState& RamDebug::getState()
void RamDebug::saveOldState() void RamDebug::saveOldState()
{ {
myOldState.ram.clear(); myOldState.ram.clear();
for(int i=0; i<0x80; i++) for(uInt32 i = 0; i < myOldState.rport.size(); ++i)
myOldState.ram.push_back(read(i)); myOldState.ram.push_back(read(myOldState.rport[i]));
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int RamDebug::read(int offset) uInt8 RamDebug::read(uInt16 addr)
{ {
offset &= 0x7f; // there are only 128 bytes return mySystem.peek(addr);
return mySystem.peek(offset + 0x80);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RamDebug::write(int offset, int value) void RamDebug::write(uInt16 addr, uInt8 value)
{ {
offset &= 0x7f; // there are only 128 bytes mySystem.poke(addr, value);
mySystem.poke(offset + 0x80, value);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -63,8 +85,7 @@ string RamDebug::toString()
{ {
string result; string result;
char buf[128]; char buf[128];
int bytesPerLine; uInt32 bytesPerLine;
int start = kRamStart, len = kRamSize;
switch(myDebugger.parser().base()) switch(myDebugger.parser().base())
{ {
@ -84,12 +105,24 @@ string RamDebug::toString()
const RamState& state = (RamState&) getState(); const RamState& state = (RamState&) getState();
const RamState& oldstate = (RamState&) getOldState(); const RamState& oldstate = (RamState&) getOldState();
for (uInt8 i = 0x00; i < len; i += bytesPerLine)
uInt32 curraddr = 0;
for(uInt32 i = 0; i < state.ram.size(); i += bytesPerLine)
{ {
sprintf(buf, "%.2x: ", start+i); // We detect different 'pages' of RAM when the addresses jump by
// more than the number of bytes on the previous line
if(state.rport[i] - curraddr > bytesPerLine)
{
sprintf(buf, "%04x: (rport = %04x, wport = %04x)\n",
state.rport[i], state.rport[i], state.wport[i]);
buf[2] = buf[3] = 'x';
result += buf;
}
curraddr = state.rport[i];
sprintf(buf, "%.2x: ", curraddr & 0x00ff);
result += buf; result += buf;
for (uInt8 j = 0; j < bytesPerLine; j++) for(uInt8 j = 0; j < bytesPerLine; ++j)
{ {
result += myDebugger.invIfChanged(state.ram[i+j], oldstate.ram[i+j]); result += myDebugger.invIfChanged(state.ram[i+j], oldstate.ram[i+j]);
result += " "; result += " ";

View File

@ -21,13 +21,16 @@
class System; class System;
#include "bspf.hxx"
#include "Array.hxx" #include "Array.hxx"
#include "DebuggerSystem.hxx" #include "DebuggerSystem.hxx"
class RamState : public DebuggerState class RamState : public DebuggerState
{ {
public: public:
IntArray ram; IntArray ram; // The actual data values
IntArray rport; // Address for reading from RAM
IntArray wport; // Address for writing to RAM
}; };
class RamDebug : public DebuggerSystem class RamDebug : public DebuggerSystem
@ -35,14 +38,27 @@ class RamDebug : public DebuggerSystem
public: public:
RamDebug(Debugger& dbg, Console& console); RamDebug(Debugger& dbg, Console& console);
/**
Let the RAM debugger subsystem treat this area as addressable memory.
@param start The beginning of the RAM area (0x0000 - 0x2000)
@param size Total number of bytes of area
@param roffset Offset to use when reading from RAM (read port)
@param woffset Offset to use when writing to RAM (write port)
*/
void addRamArea(uInt16 start, uInt16 size, uInt16 roffset, uInt16 woffset);
const DebuggerState& getState(); const DebuggerState& getState();
const DebuggerState& getOldState() { return myOldState; } const DebuggerState& getOldState() { return myOldState; }
void saveOldState(); void saveOldState();
string toString(); string toString();
int read(int offset); // The following assume that the given addresses are using the
void write(int offset, int value); // correct read/write port ranges; no checking will be done to
// confirm this.
uInt8 read(uInt16 addr);
void write(uInt16 addr, uInt8 value);
private: private:
RamState myState; RamState myState;

View File

@ -30,7 +30,8 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DataGridWidget::DataGridWidget(GuiObject* boss, const GUI::Font& font, DataGridWidget::DataGridWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int cols, int rows, int x, int y, int cols, int rows,
int colchars, int bits, BaseFormat base) int colchars, int bits, BaseFormat base,
bool useScrollbar)
: EditableWidget(boss, font, x, y, : EditableWidget(boss, font, x, y,
cols*(colchars * font.getMaxCharWidth() + 8) + 1, cols*(colchars * font.getMaxCharWidth() + 8) + 1,
font.getLineHeight()*rows + 1), font.getLineHeight()*rows + 1),
@ -43,7 +44,8 @@ DataGridWidget::DataGridWidget(GuiObject* boss, const GUI::Font& font,
_bits(bits), _bits(bits),
_base(base), _base(base),
_selectedItem(0), _selectedItem(0),
_opsWidget(NULL) _opsWidget(NULL),
_scrollBar(NULL)
{ {
_flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | _flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS |
WIDGET_WANTS_RAWDATA; WIDGET_WANTS_RAWDATA;
@ -59,11 +61,22 @@ DataGridWidget::DataGridWidget(GuiObject* boss, const GUI::Font& font,
// Make sure hilite list contains all false values // Make sure hilite list contains all false values
_hiliteList.clear(); _hiliteList.clear();
int size = _rows * _cols; int size = _rows * _cols;
while((int)_hiliteList.size() < size) while(size--)
_hiliteList.push_back(false); _hiliteList.push_back(false);
// Set lower and upper bounds to sane values // Set lower and upper bounds to sane values
setRange(0, 1 << bits); setRange(0, 1 << bits);
// Add a scrollbar if necessary
if(useScrollbar)
{
_scrollBar = new ScrollBarWidget(boss, font, _x + _w, _y, kScrollBarWidth, _h);
_scrollBar->setTarget(this);
_scrollBar->_numEntries = 1;
_scrollBar->_currentPos = 0;
_scrollBar->_entriesPerPage = 1;
_scrollBar->_wheel_lines = 1;
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -90,9 +103,9 @@ cerr << "alist.size() = " << alist.size()
_valueStringList.clear(); _valueStringList.clear();
_changedList.clear(); _changedList.clear();
_addrList = alist; _addrList = alist;
_valueList = vlist; _valueList = vlist;
_changedList = changed; _changedList = changed;
// An efficiency thing // An efficiency thing
string temp; string temp;
@ -132,26 +145,22 @@ void DataGridWidget::setList(const int a, const int v, const bool c)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DataGridWidget::setHiliteList(const IntArray& hilitelist) void DataGridWidget::setHiliteList(const BoolArray& hilitelist)
{ {
// We can't assume this given list contains the exact number of assert(hilitelist.size() == uInt32(_rows * _cols));
// items in this DataGrid, so we make sure
_hiliteList.clear(); _hiliteList.clear();
int size = _rows * _cols; _hiliteList = hilitelist;
while((int)_hiliteList.size() < size)
_hiliteList.push_back(false);
// Now fill it with the addresses/positions given in 'hilitelist'
for(unsigned int i = 0; i < hilitelist.size(); ++i)
{
int pos = hilitelist[i];
if(pos >= 0 && pos <= size)
_hiliteList[pos] = true;
}
setDirty(); draw(); setDirty(); draw();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DataGridWidget::setNumRows(int rows)
{
if(_scrollBar)
_scrollBar->_numEntries = rows;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DataGridWidget::setSelectedValue(int value) void DataGridWidget::setSelectedValue(int value)
{ {
@ -215,6 +224,12 @@ void DataGridWidget::handleMouseUp(int x, int y, int button, int clickCount)
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DataGridWidget::handleMouseWheel(int x, int y, int direction)
{
_scrollBar->handleMouseWheel(x, y, direction);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int DataGridWidget::findItem(int x, int y) int DataGridWidget::findItem(int x, int y)
{ {
@ -443,8 +458,8 @@ void DataGridWidget::handleCommand(CommandSender* sender, int cmd,
switch (cmd) switch (cmd)
{ {
case kSetPositionCmd: case kSetPositionCmd:
if (_selectedItem != (int)data) // Chain access; pass to parent
_selectedItem = data; sendCommand(kSetPositionCmd, data, _id);
break; break;
case kDGZeroCmd: case kDGZeroCmd:
@ -542,6 +557,10 @@ void DataGridWidget::drawWidget(bool hilite)
// Only draw the caret while editing, and if it's in the current viewport // Only draw the caret while editing, and if it's in the current viewport
if(_editMode) if(_editMode)
drawCaret(); drawCaret();
// Draw the scrollbar
if(_scrollBar)
_scrollBar->recalc(); // takes care of the draw
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -31,6 +31,7 @@
#include "Array.hxx" #include "Array.hxx"
#include "Rect.hxx" #include "Rect.hxx"
#include "DataGridOpsWidget.hxx" #include "DataGridOpsWidget.hxx"
#include "ScrollBarWidget.hxx"
// Some special commands // Some special commands
enum { enum {
@ -46,13 +47,15 @@ class DataGridWidget : public EditableWidget
public: public:
DataGridWidget(GuiObject* boss, const GUI::Font& font, DataGridWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int cols, int rows, int x, int y, int cols, int rows,
int colchars, int bits, BaseFormat format = kBASE_DEFAULT); int colchars, int bits, BaseFormat format = kBASE_DEFAULT,
bool useScrollbar = false);
virtual ~DataGridWidget(); virtual ~DataGridWidget();
void setList(const IntArray& alist, const IntArray& vlist, void setList(const IntArray& alist, const IntArray& vlist,
const BoolArray& changed); const BoolArray& changed);
void setList(const int a, const int v, const bool changed); void setList(const int a, const int v, const bool changed);
void setHiliteList(const IntArray& hilitelist); void setHiliteList(const BoolArray& hilitelist);
void setNumRows(int rows);
void setSelectedValue(int value); void setSelectedValue(int value);
@ -63,12 +66,16 @@ class DataGridWidget : public EditableWidget
virtual void handleMouseDown(int x, int y, int button, int clickCount); virtual void handleMouseDown(int x, int y, int button, int clickCount);
virtual void handleMouseUp(int x, int y, int button, int clickCount); virtual void handleMouseUp(int x, int y, int button, int clickCount);
virtual void handleMouseWheel(int x, int y, int direction);
virtual bool handleKeyDown(int ascii, int keycode, int modifiers); virtual bool handleKeyDown(int ascii, int keycode, int modifiers);
virtual bool handleKeyUp(int ascii, int keycode, int modifiers); virtual bool handleKeyUp(int ascii, int keycode, int modifiers);
virtual void handleCommand(CommandSender* sender, int cmd, int data, int id); virtual void handleCommand(CommandSender* sender, int cmd, int data, int id);
virtual bool wantsFocus() { return true; } virtual bool wantsFocus() { return true; }
// Account for the extra width of embedded scrollbar
virtual int getWidth() const { return _w + (_scrollBar ? kScrollBarWidth : 0); }
void startEditMode(); void startEditMode();
void endEditMode(); void endEditMode();
@ -116,6 +123,7 @@ class DataGridWidget : public EditableWidget
string _backupString; string _backupString;
DataGridOpsWidget* _opsWidget; DataGridOpsWidget* _opsWidget;
ScrollBarWidget* _scrollBar;
private: private:
/** Common operations on the currently selected cell */ /** Common operations on the currently selected cell */

View File

@ -37,7 +37,8 @@ RamWidget::RamWidget(GuiObject* boss, const GUI::Font& font, int x, int y)
: Widget(boss, font, x, y, 16, 16), : Widget(boss, font, x, y, 16, 16),
CommandSender(boss), CommandSender(boss),
myUndoAddress(-1), myUndoAddress(-1),
myUndoValue(-1) myUndoValue(-1),
myCurrentRamBank(0)
{ {
_type = kRamWidget; _type = kRamWidget;
@ -49,9 +50,10 @@ RamWidget::RamWidget(GuiObject* boss, const GUI::Font& font, int x, int y)
int xpos, ypos, lwidth; int xpos, ypos, lwidth;
// Create a 16x8 grid holding byte values (16 x 8 = 128 RAM bytes) with labels // 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; xpos = x; ypos = y + lineHeight; lwidth = 4 * fontWidth;
myRamGrid = new DataGridWidget(boss, font, xpos + lwidth, ypos, myRamGrid = new DataGridWidget(boss, font, xpos + lwidth, ypos,
16, 8, 2, 8, kBASE_16); 16, 8, 2, 8, kBASE_16, true);
myRamGrid->setTarget(this); myRamGrid->setTarget(this);
addFocusWidget(myRamGrid); addFocusWidget(myRamGrid);
@ -83,13 +85,11 @@ RamWidget::RamWidget(GuiObject* boss, const GUI::Font& font, int x, int y)
// Labels for RAM grid // Labels for RAM grid
xpos = x; ypos = y + lineHeight; xpos = x; ypos = y + lineHeight;
for(int row = 0; row < 8; ++row) myRamStart =
{ new StaticTextWidget(boss, font, xpos, ypos - lineHeight,
new StaticTextWidget(boss, font, xpos-2, ypos + row*lineHeight + 2, font.getStringWidth("xxxx"), fontHeight,
lwidth-2, fontHeight, "00xx", kTextAlignLeft);
Debugger::to_hex_8(row*16 + kRamStart) + string(":"),
kTextAlignLeft);
}
for(int col = 0; col < 16; ++col) for(int col = 0; col < 16; ++col)
{ {
new StaticTextWidget(boss, font, xpos + col*myRamGrid->colWidth() + lwidth + 8, new StaticTextWidget(boss, font, xpos + col*myRamGrid->colWidth() + lwidth + 8,
@ -98,7 +98,13 @@ RamWidget::RamWidget(GuiObject* boss, const GUI::Font& font, int x, int y)
Debugger::to_hex_4(col), Debugger::to_hex_4(col),
kTextAlignLeft); kTextAlignLeft);
} }
for(int row = 0; row < 8; ++row)
{
myRamLabels[row] =
new StaticTextWidget(boss, font, xpos + 5, ypos + row*lineHeight + 2,
3*fontWidth, fontHeight, "", kTextAlignLeft);
}
xpos = x + 10; ypos += 9 * lineHeight; xpos = x + 10; ypos += 9 * lineHeight;
new StaticTextWidget(boss, font, xpos, ypos, new StaticTextWidget(boss, font, xpos, ypos,
6*fontWidth, fontHeight, 6*fontWidth, fontHeight,
@ -154,6 +160,7 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
int addr, value; int addr, value;
RamDebug& dbg = instance().debugger().ramDebug(); RamDebug& dbg = instance().debugger().ramDebug();
const RamState& state = (RamState&) dbg.getState();
switch(cmd) switch(cmd)
{ {
case kDGItemDataChangedCmd: case kDGItemDataChangedCmd:
@ -161,9 +168,9 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
value = myRamGrid->getSelectedValue(); value = myRamGrid->getSelectedValue();
myUndoAddress = addr; myUndoAddress = addr;
myUndoValue = dbg.read(addr); myUndoValue = dbg.read(state.rport[addr]);
dbg.write(addr, value); dbg.write(state.wport[addr], value);
myDecValue->setEditString(instance().debugger().valueToString(value, kBASE_10)); myDecValue->setEditString(instance().debugger().valueToString(value, kBASE_10));
myBinValue->setEditString(instance().debugger().valueToString(value, kBASE_2)); myBinValue->setEditString(instance().debugger().valueToString(value, kBASE_2));
myRevertButton->setEnabled(true); myRevertButton->setEnabled(true);
@ -176,20 +183,20 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
value = myRamGrid->getSelectedValue(); value = myRamGrid->getSelectedValue();
myLabel->setEditString( myLabel->setEditString(
instance().debugger().equates().getLabel(addr+kRamStart, true)); instance().debugger().equates().getLabel(state.rport[addr], true));
myDecValue->setEditString(instance().debugger().valueToString(value, kBASE_10)); myDecValue->setEditString(instance().debugger().valueToString(value, kBASE_10));
myBinValue->setEditString(instance().debugger().valueToString(value, kBASE_2)); myBinValue->setEditString(instance().debugger().valueToString(value, kBASE_2));
break; break;
} }
case kRevertCmd: case kRevertCmd:
for(unsigned int i = 0; i < kRamSize; i++) for(uInt32 i = 0; i < myOldValueList.size(); ++i)
dbg.write(i, myOldValueList[i]); dbg.write(state.wport[i], myOldValueList[i]);
fillGrid(true); fillGrid(true);
break; break;
case kUndoCmd: case kUndoCmd:
dbg.write(myUndoAddress, myUndoValue); dbg.write(state.wport[myUndoAddress], myUndoValue);
myUndoButton->setEnabled(false); myUndoButton->setEnabled(false);
fillGrid(false); fillGrid(false);
break; break;
@ -225,13 +232,18 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
parent().removeDialog(); parent().removeDialog();
break; break;
} }
case kSetPositionCmd:
myCurrentRamBank = data;
showSearchResults();
fillGrid(false);
break;
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RamWidget::loadConfig() void RamWidget::loadConfig()
{ {
//cerr << "RamWidget::loadConfig()\n";
fillGrid(true); fillGrid(true);
} }
@ -246,24 +258,42 @@ void RamWidget::fillGrid(bool updateOld)
RamDebug& dbg = instance().debugger().ramDebug(); RamDebug& dbg = instance().debugger().ramDebug();
RamState state = (RamState&) dbg.getState(); const RamState& state = (RamState&) dbg.getState();
RamState oldstate = (RamState&) dbg.getOldState(); const RamState& oldstate = (RamState&) 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());
vlist = state.ram;
if(updateOld) myOldValueList = state.ram; if(updateOld) myOldValueList = state.ram;
for(unsigned int i = 0; i < 16*8; i++) for(uInt32 i = start; i < start + 16*8; ++i)
{ {
alist.push_back(i); alist.push_back(i);
vlist.push_back(state.ram[i]);
changed.push_back(state.ram[i] != oldstate.ram[i]); changed.push_back(state.ram[i] != oldstate.ram[i]);
} }
myRamGrid->setNumRows(state.ram.size() / 128);
myRamGrid->setList(alist, vlist, changed); myRamGrid->setList(alist, vlist, changed);
if(updateOld) if(updateOld)
{ {
myRevertButton->setEnabled(false); myRevertButton->setEnabled(false);
myUndoButton->setEnabled(false); myUndoButton->setEnabled(false);
} }
// Update RAM labels
char buf[5];
sprintf(buf, "%04x", state.rport[start] & 0xff00);
buf[2] = buf[3] = 'x';
myRamStart->setLabel(buf);
for(uInt32 i = start, row = 0; i < start + 16*8; i += 16, ++row)
{
sprintf(buf, "%02x:", state.rport[i] & 0x00ff);
myRamLabels[row]->setLabel(buf);
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -300,23 +330,31 @@ string RamWidget::doSearch(const string& str)
// Clear the search array of previous items // Clear the search array of previous items
mySearchAddr.clear(); mySearchAddr.clear();
mySearchValue.clear(); mySearchValue.clear();
mySearchState.clear();
// Now, search all memory locations for this value, and add it to the // Now, search all memory locations for this value, and add it to the
// search array // search array
bool hitfound = false;
RamDebug& dbg = instance().debugger().ramDebug(); RamDebug& dbg = instance().debugger().ramDebug();
for(int addr = 0; addr < kRamSize; ++addr) const RamState& state = (RamState&) dbg.getState();
for(uInt32 addr = 0; addr < state.ram.size(); ++addr)
{ {
int value = dbg.read(addr); int value = state.ram[addr];
if(comparisonSearch && searchVal != value) if(comparisonSearch && searchVal != value)
continue; {
mySearchState.push_back(false);
mySearchAddr.push_back(addr); }
mySearchValue.push_back(value); 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 we have some hits, enable the comparison methods
if(mySearchAddr.size() > 0) if(hitfound)
{ {
mySearchButton->setEnabled(false); mySearchButton->setEnabled(false);
myCompareButton->setEnabled(true); myCompareButton->setEnabled(true);
@ -324,7 +362,7 @@ string RamWidget::doSearch(const string& str)
} }
// Finally, show the search results in the list // Finally, show the search results in the list
myRamGrid->setHiliteList(mySearchAddr); showSearchResults();
return ""; return "";
} }
@ -364,9 +402,15 @@ string RamWidget::doCompare(const string& str)
else else
searchVal = instance().debugger().stringToValue(str); searchVal = instance().debugger().stringToValue(str);
// Now, search all memory locations specified in mySearchArray for this value // Now, search all memory locations previously 'found' for this value
bool hitfound = false;
RamDebug& dbg = instance().debugger().ramDebug(); RamDebug& dbg = instance().debugger().ramDebug();
const RamState& state = (RamState&) dbg.getState();
IntArray tempAddrList, tempValueList; IntArray tempAddrList, tempValueList;
mySearchState.clear();
for(uInt32 i = 0; i < state.rport.size(); ++i)
mySearchState.push_back(false);
for(unsigned int i = 0; i < mySearchAddr.size(); ++i) for(unsigned int i = 0; i < mySearchAddr.size(); ++i)
{ {
if(comparitiveSearch) if(comparitiveSearch)
@ -377,10 +421,11 @@ string RamWidget::doCompare(const string& str)
} }
int addr = mySearchAddr[i]; int addr = mySearchAddr[i];
if(dbg.read(addr) == searchVal) if(dbg.read(state.rport[addr]) == searchVal)
{ {
tempAddrList.push_back(addr); tempAddrList.push_back(addr);
tempValueList.push_back(searchVal); tempValueList.push_back(searchVal);
mySearchState[addr] = hitfound = true;
} }
} }
@ -389,14 +434,14 @@ string RamWidget::doCompare(const string& str)
mySearchValue = tempValueList; mySearchValue = tempValueList;
// If we have some hits, enable the comparison methods // If we have some hits, enable the comparison methods
if(mySearchAddr.size() > 0) if(hitfound)
{ {
myCompareButton->setEnabled(true); myCompareButton->setEnabled(true);
myRestartButton->setEnabled(true); myRestartButton->setEnabled(true);
} }
// Finally, show the search results in the list // Finally, show the search results in the list
myRamGrid->setHiliteList(mySearchAddr); showSearchResults();
return ""; return "";
} }
@ -407,9 +452,29 @@ void RamWidget::doRestart()
// Erase all search buffers, reset to start mode // Erase all search buffers, reset to start mode
mySearchAddr.clear(); mySearchAddr.clear();
mySearchValue.clear(); mySearchValue.clear();
myRamGrid->setHiliteList(mySearchAddr); mySearchState.clear();
showSearchResults();
mySearchButton->setEnabled(true); mySearchButton->setEnabled(true);
myCompareButton->setEnabled(false); myCompareButton->setEnabled(false);
myRestartButton->setEnabled(false); myRestartButton->setEnabled(false);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RamWidget::showSearchResults()
{
// Only update the search results for the bank currently being shown
BoolArray temp;
uInt32 start = myCurrentRamBank * 128;
if(mySearchState.size() == 0 || start > mySearchState.size())
{
for(uInt32 i = 0; i < 128; ++i)
temp.push_back(false);
}
else
{
for(uInt32 i = start; i < start + 128; ++i)
temp.push_back(mySearchState[i]);
}
myRamGrid->setHiliteList(temp);
}

View File

@ -52,6 +52,7 @@ class RamWidget : public Widget, public CommandSender
string doSearch(const string& str); string doSearch(const string& str);
string doCompare(const string& str); string doCompare(const string& str);
void doRestart(); void doRestart();
void showSearchResults();
private: private:
enum { enum {
@ -66,8 +67,12 @@ class RamWidget : public Widget, public CommandSender
int myUndoAddress; int myUndoAddress;
int myUndoValue; int myUndoValue;
int myCurrentRamBank;
StaticTextWidget* myRamStart;
StaticTextWidget* myRamLabels[8];
DataGridWidget* myRamGrid;
DataGridWidget* myRamGrid;
EditTextWidget* myBinValue; EditTextWidget* myBinValue;
EditTextWidget* myDecValue; EditTextWidget* myDecValue;
EditTextWidget* myLabel; EditTextWidget* myLabel;
@ -83,6 +88,7 @@ class RamWidget : public Widget, public CommandSender
IntArray myOldValueList; IntArray myOldValueList;
IntArray mySearchAddr; IntArray mySearchAddr;
IntArray mySearchValue; IntArray mySearchValue;
BoolArray mySearchState;
}; };
#endif #endif

View File

@ -80,6 +80,23 @@ class Cartridge : public Device
void lockBank() { myBankLocked = true; } void lockBank() { myBankLocked = true; }
void unlockBank() { myBankLocked = false; } void unlockBank() { myBankLocked = false; }
/**
This informs the caller of the addressable range of any extended RAM
present on the cart. If no RAM is present, the method should return
false. Cart classes should override this method if they contain
any extended RAM.
@param start The beginning of the RAM area (0x0000 - 0x2000)
@param size Total number of bytes of area
@param roffset Offset to use when reading from RAM (read port)
@param woffset Offset to use when writing to RAM (write port)
@return True if RAM exists and parameters are modified, else false
*/
virtual bool getRamArea(uInt16& start, uInt16& size,
uInt16& roffset, uInt16& woffset)
{ return false; }
public: public:
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// The following methods are cart-specific and must be implemented // The following methods are cart-specific and must be implemented

View File

@ -243,3 +243,15 @@ bool CartridgeF4SC::load(Deserializer& in)
return true; return true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeF4SC::getRamArea(uInt16& start, uInt16& size,
uInt16& roffset, uInt16& woffset)
{
start = 0x1000;
size = 128;
roffset = 0x80;
woffset = 0x0;
return true;
}

View File

@ -119,6 +119,22 @@ class CartridgeF4SC : public Cartridge
*/ */
virtual string name() const { return "CartridgeF4SC"; } virtual string name() const { return "CartridgeF4SC"; }
/**
This informs the caller of the addressable range of any extended RAM
present on the cart. If no RAM is present, the method should return
false. Cart classes should override this method if they contain
any extended RAM.
@param start The beginning of the RAM area (0x0000 - 0x2000)
@param size Total number of bytes of area
@param roffset Offset to use when reading from RAM (read port)
@param woffset Offset to use when writing to RAM (write port)
@return True if RAM exists and parameters are modified, else false
*/
virtual bool getRamArea(uInt16& start, uInt16& size,
uInt16& roffset, uInt16& woffset);
public: public:
/** /**
Get the byte at the specified address. Get the byte at the specified address.

View File

@ -285,3 +285,15 @@ bool CartridgeF6SC::load(Deserializer& in)
return true; return true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeF6SC::getRamArea(uInt16& start, uInt16& size,
uInt16& roffset, uInt16& woffset)
{
start = 0x1000;
size = 128;
roffset = 0x80;
woffset = 0x0;
return true;
}

View File

@ -119,6 +119,22 @@ class CartridgeF6SC : public Cartridge
*/ */
virtual string name() const { return "CartridgeF6SC"; } virtual string name() const { return "CartridgeF6SC"; }
/**
This informs the caller of the addressable range of any extended RAM
present on the cart. If no RAM is present, the method should return
false. Cart classes should override this method if they contain
any extended RAM.
@param start The beginning of the RAM area (0x0000 - 0x2000)
@param size Total number of bytes of area
@param roffset Offset to use when reading from RAM (read port)
@param woffset Offset to use when writing to RAM (write port)
@return True if RAM exists and parameters are modified, else false
*/
virtual bool getRamArea(uInt16& start, uInt16& size,
uInt16& roffset, uInt16& woffset);
public: public:
/** /**
Get the byte at the specified address. Get the byte at the specified address.

View File

@ -263,3 +263,15 @@ bool CartridgeF8SC::load(Deserializer& in)
return true; return true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeF8SC::getRamArea(uInt16& start, uInt16& size,
uInt16& roffset, uInt16& woffset)
{
start = 0x1000;
size = 128;
roffset = 0x80;
woffset = 0x0;
return true;
}

View File

@ -119,6 +119,22 @@ class CartridgeF8SC : public Cartridge
*/ */
virtual string name() const { return "CartridgeF8SC"; } virtual string name() const { return "CartridgeF8SC"; }
/**
This informs the caller of the addressable range of any extended RAM
present on the cart. If no RAM is present, the method should return
false. Cart classes should override this method if they contain
any extended RAM.
@param start The beginning of the RAM area (0x0000 - 0x2000)
@param size Total number of bytes of area
@param roffset Offset to use when reading from RAM (read port)
@param woffset Offset to use when writing to RAM (write port)
@return True if RAM exists and parameters are modified, else false
*/
virtual bool getRamArea(uInt16& start, uInt16& size,
uInt16& roffset, uInt16& woffset);
public: public:
/** /**
Get the byte at the specified address. Get the byte at the specified address.

View File

@ -275,3 +275,15 @@ bool CartridgeFASC::load(Deserializer& in)
return true; return true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeFASC::getRamArea(uInt16& start, uInt16& size,
uInt16& roffset, uInt16& woffset)
{
start = 0x1000;
size = 256;
roffset = 0x100;
woffset = 0x0;
return true;
}

View File

@ -119,6 +119,22 @@ class CartridgeFASC : public Cartridge
*/ */
virtual string name() const { return "CartridgeFASC"; } virtual string name() const { return "CartridgeFASC"; }
/**
This informs the caller of the addressable range of any extended RAM
present on the cart. If no RAM is present, the method should return
false. Cart classes should override this method if they contain
any extended RAM.
@param start The beginning of the RAM area (0x0000 - 0x2000)
@param size Total number of bytes of area
@param roffset Offset to use when reading from RAM (read port)
@param woffset Offset to use when writing to RAM (write port)
@return True if RAM exists and parameters are modified, else false
*/
virtual bool getRamArea(uInt16& start, uInt16& size,
uInt16& roffset, uInt16& woffset);
public: public:
/** /**
Get the byte at the specified address. Get the byte at the specified address.

View File

@ -191,7 +191,7 @@ bool OSystem::create()
// This logic should also take into account the size of the // This logic should also take into account the size of the
// framebuffer, and try to be intelligent about font sizes // framebuffer, and try to be intelligent about font sizes
// We can probably add ifdefs to take care of corner cases, // We can probably add ifdefs to take care of corner cases,
// but the means we've failed to abstract it enough ... // but that means we've failed to abstract it enough ...
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool smallScreen = myDesktopWidth < 640 || myDesktopHeight < 480; bool smallScreen = myDesktopWidth < 640 || myDesktopHeight < 480;
@ -972,6 +972,5 @@ OSystem::OSystem(const OSystem& osystem)
OSystem& OSystem::operator = (const OSystem&) OSystem& OSystem::operator = (const OSystem&)
{ {
assert(false); assert(false);
return *this; return *this;
} }

View File

@ -61,23 +61,21 @@ static unsigned int down_arrow[8] = {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ScrollBarWidget::ScrollBarWidget(GuiObject* boss, const GUI::Font& font, ScrollBarWidget::ScrollBarWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int w, int h) int x, int y, int w, int h)
: Widget(boss, font, x, y, w, h), CommandSender(boss) : Widget(boss, font, x, y, w, h), CommandSender(boss),
_numEntries(0),
_entriesPerPage(0),
_currentPos(0),
_wheel_lines(0),
_part(kNoPart),
_draggingPart(kNoPart),
_sliderHeight(0),
_sliderPos(0),
_sliderDeltaMouseDownPos(0)
{ {
_flags = WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG; _flags = WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG;
_type = kScrollBarWidget; _type = kScrollBarWidget;
_bgcolor = kWidColor; _bgcolor = kWidColor;
_bgcolorhi = kWidColor; _bgcolorhi = kWidColor;
_part = kNoPart;
_sliderHeight = 0;
_sliderPos = 0;
_draggingPart = kNoPart;
_sliderDeltaMouseDownPos = 0;
_numEntries = 0;
_entriesPerPage = 0;
_currentPos = 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -136,9 +134,9 @@ void ScrollBarWidget::handleMouseWheel(int x, int y, int direction)
return; return;
if(direction < 0) if(direction < 0)
_currentPos -= _WHEEL_LINES; _currentPos -= _wheel_lines ? _wheel_lines : _WHEEL_LINES;
else else
_currentPos += _WHEEL_LINES; _currentPos += _wheel_lines ? _wheel_lines : _WHEEL_LINES;
// Make sure that _currentPos is still inside the bounds // Make sure that _currentPos is still inside the bounds
checkBounds(old_pos); checkBounds(old_pos);

View File

@ -61,6 +61,7 @@ class ScrollBarWidget : public Widget, public CommandSender
int _numEntries; int _numEntries;
int _entriesPerPage; int _entriesPerPage;
int _currentPos; int _currentPos;
int _wheel_lines;
private: private:
typedef enum { typedef enum {

View File

@ -140,7 +140,7 @@ UIDialog::UIDialog(OSystem* osystem, DialogContainer* parent,
myDebuggerWidthSlider = new SliderWidget(myTab, font, xpos, ypos, pwidth, myDebuggerWidthSlider = new SliderWidget(myTab, font, xpos, ypos, pwidth,
lineHeight, "Debugger Width: ", lineHeight, "Debugger Width: ",
lwidth, kDWidthChanged); lwidth, kDWidthChanged);
myDebuggerWidthSlider->setMinValue(1030); myDebuggerWidthSlider->setMinValue(1050);
myDebuggerWidthSlider->setMaxValue(1920); myDebuggerWidthSlider->setMaxValue(1920);
myDebuggerWidthSlider->setStepValue(10); myDebuggerWidthSlider->setStepValue(10);
wid.push_back(myDebuggerWidthSlider); wid.push_back(myDebuggerWidthSlider);
@ -280,7 +280,7 @@ void UIDialog::loadConfig()
// Debugger size // Debugger size
instance().settings().getSize("debuggerres", w, h); instance().settings().getSize("debuggerres", w, h);
w = BSPF_max(w, 1030); w = BSPF_max(w, 1050);
h = BSPF_max(h, 620); h = BSPF_max(h, 620);
w = BSPF_min(w, 1920); w = BSPF_min(w, 1920);
h = BSPF_min(h, 1200); h = BSPF_min(h, 1200);
@ -362,8 +362,8 @@ void UIDialog::setDefaults()
} }
case 1: // Debugger options case 1: // Debugger options
myDebuggerWidthSlider->setValue(1030); myDebuggerWidthSlider->setValue(1050);
myDebuggerWidthLabel->setValue(1030); myDebuggerWidthLabel->setValue(1050);
myDebuggerHeightSlider->setValue(690); myDebuggerHeightSlider->setValue(690);
myDebuggerHeightLabel->setValue(690); myDebuggerHeightLabel->setValue(690);
break; break;