Reworked the extended RAM editing in the debugger, allowing for those
schemes that have multiples areas of RAM. Converted F4SC, F6SC, F8SC, FASC to this new functionality. Added ability to modify extended RAM in 3E, CV, E7 and EFSC ROMs. Note that these ROMs can swap RAM in and out dynamically, so what you see in the RAM area won't always be RAM. Updated debugger CpuWidget; decimal and binary values for SP/A/X/Y are now all shown at the same time (previously the registers had to share a decimal/binary view). Updated debugger documentation for recent additions. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1748 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
24
Changes.txt
|
@ -19,16 +19,26 @@
|
|||
greater with support for GLSL (GL Shading Language). This code
|
||||
will be expanded on and optimized in future releases.
|
||||
|
||||
* All bankswitching schemes which include SC extended RAM will now have
|
||||
memory erased if you attempt to read from the write port. Related to
|
||||
this, entering/exiting the debugger will no longer erase the extended
|
||||
RAM.
|
||||
* Adding editing of extended RAM in the debugger RAM UI. The RAM
|
||||
'spreadsheet' now shows the entire address space of RAM in the
|
||||
system, in 128 byte increments. The first bank shown is zero-page,
|
||||
with the others following in consecutive order. The UI takes care
|
||||
of read vs. write port differences, so you don't have to worry
|
||||
about the offsets. For now, all SuperChip based ROMs (EFSC, F4SC,
|
||||
F6SC, F8SC, FASC) as well as 3E, CV and E7 are supported.
|
||||
|
||||
* Patching of ROM for bankswitch types '0840', 'SB', 'UA' and 'X07' is
|
||||
now implemented, but hasn't been extensively tested.
|
||||
* All ROMs which include SC extended RAM will now have memory erased if
|
||||
you attempt to read from the write port. Related to this,
|
||||
entering/exiting the debugger will no longer erase the extended RAM.
|
||||
|
||||
* Patching of ROM for bankswitch types 0840, SB, UA and X07 is now
|
||||
implemented, but hasn't been extensively tested.
|
||||
|
||||
* Visual improvements to the CPU register UI in the debugger; the
|
||||
SP/A/X/Y registers now have separate decimal and binary views.
|
||||
|
||||
* Tweaked paddle control so that all positions are reachable in game
|
||||
4 of Activision Casino.
|
||||
4 of Activision Casino in both NTSC and PAL versions.
|
||||
|
||||
* Auto-detection for '3F' bankswitching improved; several ROMs
|
||||
previously detected as 'F8' now work correctly.
|
||||
|
|
10
Todo.txt
|
@ -22,15 +22,17 @@ Stephen Anthony at stephena@users.sourceforge.net.
|
|||
* 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
|
||||
into adding Blargg NTSC filtering (perhaps as a GLSL program).
|
||||
* Look into adding Blargg NTSC filtering (perhaps as a GLSL program).
|
||||
|
||||
* Either Support Distella as frontend or integrate a 6507 Disassembler
|
||||
|
||||
* Step-debug through disassembled zero-page code (get clarification on this)
|
||||
|
||||
* Improve debugger support for cartridges with dedicated RAM, and add
|
||||
source-level debugging
|
||||
* Improve debugger support for remaining cartridges with dedicated RAM,
|
||||
and add source-level debugging
|
||||
|
||||
* Fix bank going over 255 (when accessing RAM) for 3E in the debugger
|
||||
RomWidget view.
|
||||
|
||||
* 'Fixed Debug Colours' option as explained in the 'Stella 2.6.1 released'
|
||||
thread, post #40 on AtariAge. Basically emulates no$2k6 behaviour.
|
||||
|
|
|
@ -41,7 +41,7 @@ feature that no other 2600 debugger has; it's <b>completely</b> cross-platform.<
|
|||
<li>Symbolic names in disassembly</li>
|
||||
<li>Symbolic names accepted as input</li>
|
||||
<li>Tab completion for commands and symbol names</li>
|
||||
<li>Graphical editor for RIOT RAM. Acts a lot like a spreadsheet.
|
||||
<li>Graphical editor for RIOT and extended RAM. Acts a lot like a spreadsheet.
|
||||
Input in hex, with displays for label/decimal/binary for
|
||||
currently-selected location.</li>
|
||||
<li>GUI CPU state window</li>
|
||||
|
@ -73,7 +73,7 @@ feature that no other 2600 debugger has; it's <b>completely</b> cross-platform.<
|
|||
<li>Save patched ROM ("saverom filename.bin").</li>
|
||||
</ul>
|
||||
|
||||
<h2>Future planned features (post 2.0):</h2>
|
||||
<h2>Future planned features:</h2>
|
||||
|
||||
<ul>
|
||||
<li>GUI for cheat codes (Cheetah and normal codes).</li>
|
||||
|
@ -88,7 +88,7 @@ feature that no other 2600 debugger has; it's <b>completely</b> cross-platform.<
|
|||
available in a very crude form ("loadlist" and "list" commands).</li>
|
||||
<li>More "special variables" for the expression parser.</li>
|
||||
<li>Possibly a mini-assembler</li>
|
||||
<li>Support for extra RAM in Supercharger and other cart types.</li>
|
||||
<li>Support for extra RAM in all remaining cart types.</li>
|
||||
<li>Possibly support for recording and playing back input files, like
|
||||
MAME. This isn't a debugger feature per se, but it'll make it easier
|
||||
to reliably trigger a bug so you can debug it.</li>
|
||||
|
@ -793,9 +793,11 @@ See the "Breakpoints" section for details.</p>
|
|||
<p>This displays the current CPU state, as shown:</p>
|
||||
<p><img src="graphics/debugger_cpuregs.png"></p>
|
||||
<p>All the registers and flags are displayed, and can be changed by
|
||||
double-clicking on them. Flags are toggled on double-click. Selected registers
|
||||
here can also be changed by using the "Data Operations" buttons, further
|
||||
described in (J).</p>
|
||||
double-clicking on them (to the left). Flags are toggled on double-click.
|
||||
Selected registers here can also be changed by using the "Data Operations" buttons,
|
||||
further described in (J). All items are shown in hex. Any label defined for the
|
||||
current PC value is shown to the right. Decimal and binary equivalents
|
||||
are shown for SP/A/X/Y to the right (first decimal, then binary).</p>
|
||||
<p>There's not much else to say about the CPU widget: if you know 6502
|
||||
assembly, it's pretty self-explanatory. If you don't, well, you should
|
||||
learn :)</p>
|
||||
|
@ -826,16 +828,28 @@ respond to these same keyboard shortcuts. If in doubt, give them a try.</p>
|
|||
|
||||
<!-- ///////////////////////////////////////////////////////////////////////// -->
|
||||
<br>
|
||||
<h2><u>(K)</u> M6532/RIOT RAM</h2>
|
||||
<h2><u>(K)</u> M6532/RIOT and extended RAM</h2>
|
||||
<p>This is a spreadsheet-like GUI for inspecting and changing the contents
|
||||
of the 2600's RAM. All 128 bytes of RAM are visible on the screen at
|
||||
once. You can navigate with either the mouse or the keyboard arrow keys.
|
||||
of the 2600's RAM. You can view 128 bytes of RAM at a time, starting with
|
||||
the RAM built in to the console (zero-page RAM). If a cartridge contains
|
||||
extended RAM, a scrollbar will be activated, allowing to scroll in
|
||||
sequence through each 128 byte 'bank' of RAM. The address in the upper left
|
||||
corner indicates the offset (in terms of the read port) for the bank
|
||||
currently being displayed.</p>
|
||||
<p>You can navigate with either the mouse or the keyboard arrow keys.
|
||||
To change a RAM location, either double-click on it or press Enter while
|
||||
it's highlighted. Enter the new value (hex only for now, sorry), then
|
||||
press Enter to make the change. If you change your mind, press Escape
|
||||
and the original value will be restored. The currently selected RAM cell
|
||||
can also be changed by using the Data operations buttons/associated
|
||||
shortcut keys (J).</p>
|
||||
<p><b>Note:</b> Many extended RAM schemes involve different addresses for
|
||||
reading versus writing RAM (read port vs. write port). The UI takes care
|
||||
of this for you; although the addresses shown are for the read port,
|
||||
modifying a cell will use the write port. Also, some bankswitching
|
||||
schemes can swap RAM and ROM dynamically during program execution. In
|
||||
these cases, the values shown may not always be for RAM, and may point
|
||||
to ROM instead. In the latter case, the data cannot be modified.</p>
|
||||
<p><img src="graphics/debugger_ram.png"></p>
|
||||
<p>The 'Undo' button in the upper right should be self-explanatory; it will
|
||||
undo the most previous operation to one cell only. The 'Rev' button is
|
||||
|
@ -849,8 +863,8 @@ The remaining buttons to the right are further explained in section (L).</p>
|
|||
|
||||
<!-- ///////////////////////////////////////////////////////////////////////// -->
|
||||
<br>
|
||||
<h2><u>(L)</u> M6532/RIOT RAM (search/compare mode)</h2>
|
||||
<p>The RIOT RAM widget also lets you search memory for values such as lives or remaining
|
||||
<h2><u>(L)</u> M6532/RIOT and extended RAM (search/compare mode)</h2>
|
||||
<p>The RAM widget also lets you search memory for values such as lives or remaining
|
||||
energy, but it's also very useful when debugging to determine which
|
||||
memory location holds which quantity.</p>
|
||||
<p><img src="graphics/debugger_ramsearch.png"></p>
|
||||
|
@ -867,7 +881,7 @@ addresses and allows another search.</p>
|
|||
<p>The following is an example of inspecting all addresses that have
|
||||
decreased by 1:</p>
|
||||
<ul>
|
||||
<li>Click 'Srch' with empty input. All 128 address/values are highlighted</li>
|
||||
<li>Click 'Srch' with empty input. All address/values are highlighted</li>
|
||||
<li>Exit debugger mode and lose a life, let your energy decrease, or
|
||||
do whatever it is you're trying to debug</li>
|
||||
<li>Enter debugger mode again, click 'Cmp' and and enter a '-1' for input.
|
||||
|
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.3 KiB |
|
@ -34,6 +34,7 @@
|
|||
#include "Console.hxx"
|
||||
#include "System.hxx"
|
||||
#include "M6502.hxx"
|
||||
#include "Cart.hxx"
|
||||
|
||||
#include "EquateList.hxx"
|
||||
#include "CpuDebug.hxx"
|
||||
|
@ -192,9 +193,9 @@ void Debugger::setConsole(Console* console)
|
|||
|
||||
// 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);
|
||||
const Cartridge::RamAreaList& areas = myConsole->cartridge().ramAreas();
|
||||
for(Cartridge::RamAreaList::const_iterator i = areas.begin(); i != areas.end(); ++i)
|
||||
myRamDebug->addRamArea(i->start, i->size, i->roffset, i->woffset);
|
||||
|
||||
delete myRiotDebug;
|
||||
myRiotDebug = new RiotDebug(*this, *myConsole);
|
||||
|
|
|
@ -106,17 +106,19 @@ string RamDebug::toString()
|
|||
const RamState& state = (RamState&) getState();
|
||||
const RamState& oldstate = (RamState&) getOldState();
|
||||
|
||||
uInt32 curraddr = 0;
|
||||
for(uInt32 i = 0; i < state.ram.size(); i += bytesPerLine)
|
||||
uInt32 curraddr = 0, bytesSoFar = 0;
|
||||
for(uInt32 i = 0; i < state.ram.size(); i += bytesPerLine, bytesSoFar += bytesPerLine)
|
||||
{
|
||||
// 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)
|
||||
// more than the number of bytes on the previous line, or when 256
|
||||
// bytes have been previously output
|
||||
if(state.rport[i] - curraddr > bytesPerLine || bytesSoFar >= 256)
|
||||
{
|
||||
sprintf(buf, "%04x: (rport = %04x, wport = %04x)\n",
|
||||
state.rport[i], state.rport[i], state.wport[i]);
|
||||
buf[2] = buf[3] = 'x';
|
||||
result += buf;
|
||||
result += DebuggerParser::red(buf);
|
||||
bytesSoFar = 0;
|
||||
}
|
||||
curraddr = state.rport[i];
|
||||
sprintf(buf, "%.2x: ", curraddr & 0x00ff);
|
||||
|
|
|
@ -60,29 +60,26 @@ CpuWidget::CpuWidget(GuiObject* boss, const GUI::Font& font, int x, int y)
|
|||
lineHeight, "");
|
||||
myPCLabel->setEditable(false);
|
||||
|
||||
// Create read-only textboxes for decimal and binary of currently selected item
|
||||
ypos += myPCLabel->getHeight() + 5 + 5;
|
||||
new StaticTextWidget(boss, font, xpos, ypos, 4*fontWidth, fontHeight,
|
||||
"Dec:", kTextAlignLeft);
|
||||
myDecValue = new EditTextWidget(boss, font, xpos+4*fontWidth + 5, ypos-2,
|
||||
4*fontWidth, lineHeight, "");
|
||||
myDecValue->setEditable(false);
|
||||
|
||||
ypos += myPCLabel->getHeight() + 5;
|
||||
new StaticTextWidget(boss, font, xpos, ypos, 4*fontWidth, fontHeight,
|
||||
"Bin:", kTextAlignLeft);
|
||||
myBinValue = new EditTextWidget(boss, font, xpos+4*fontWidth + 5, ypos-2,
|
||||
9*fontWidth, lineHeight, "");
|
||||
myBinValue->setEditable(false);
|
||||
|
||||
// Create a 1x4 grid with labels for the other CPU registers
|
||||
xpos = x; ypos += myPCGrid->getHeight() + 1 - 2*(myPCLabel->getHeight() + 5) - 5;
|
||||
xpos = x + lwidth; ypos += myPCGrid->getHeight() + 1;
|
||||
myCpuGrid =
|
||||
new DataGridWidget(boss, font, xpos + lwidth, ypos, 1, 4, 2, 8, kBASE_16);
|
||||
new DataGridWidget(boss, font, xpos, ypos, 1, 4, 2, 8, kBASE_16);
|
||||
myCpuGrid->setTarget(this);
|
||||
myCpuGrid->setID(kCpuRegID);
|
||||
addFocusWidget(myCpuGrid);
|
||||
|
||||
// Create a 1x4 grid with decimal and binary values for the other CPU registers
|
||||
xpos = x + lwidth + myPCGrid->getWidth() + 10;
|
||||
myCpuGridDecValue =
|
||||
new DataGridWidget(boss, font, xpos, ypos, 1, 4, 3, 8, kBASE_10);
|
||||
myCpuGridDecValue->setEditable(false);
|
||||
xpos += myCpuGridDecValue->getWidth() + 5;
|
||||
myCpuGridBinValue =
|
||||
new DataGridWidget(boss, font, xpos, ypos, 1, 4, 8, 8, kBASE_2);
|
||||
myCpuGridBinValue->setEditable(false);
|
||||
|
||||
// Add labels for other CPU registers
|
||||
xpos = x;
|
||||
string labels[4] = { "SP:", "A:", "X:", "Y:" };
|
||||
for(int row = 0; row < 4; ++row)
|
||||
{
|
||||
|
@ -140,8 +137,6 @@ void CpuWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
|
|||
case kCpuRegID:
|
||||
addr = myCpuGrid->getSelectedAddr();
|
||||
value = myCpuGrid->getSelectedValue();
|
||||
myDecValue->setEditString(instance().debugger().valueToString(value, kBASE_10));
|
||||
myBinValue->setEditString(instance().debugger().valueToString(value, kBASE_2));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -159,31 +154,30 @@ void CpuWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
|
|||
|
||||
case kSPRegAddr:
|
||||
dbg.setSP(value);
|
||||
myCpuGridDecValue->setValue(0, value);
|
||||
myCpuGridBinValue->setValue(0, value);
|
||||
break;
|
||||
|
||||
case kARegAddr:
|
||||
dbg.setA(value);
|
||||
myCpuGridDecValue->setValue(1, value);
|
||||
myCpuGridBinValue->setValue(1, value);
|
||||
break;
|
||||
|
||||
case kXRegAddr:
|
||||
dbg.setX(value);
|
||||
myCpuGridDecValue->setValue(2, value);
|
||||
myCpuGridBinValue->setValue(2, value);
|
||||
break;
|
||||
|
||||
case kYRegAddr:
|
||||
dbg.setY(value);
|
||||
myCpuGridDecValue->setValue(3, value);
|
||||
myCpuGridBinValue->setValue(3, value);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case kDGSelectionChangedCmd:
|
||||
if(id == kCpuRegID)
|
||||
{
|
||||
value = myCpuGrid->getSelectedValue();
|
||||
myDecValue->setEditString(instance().debugger().valueToString(value, kBASE_10));
|
||||
myBinValue->setEditString(instance().debugger().valueToString(value, kBASE_2));
|
||||
}
|
||||
break;
|
||||
|
||||
case kTWItemDataChangedCmd:
|
||||
{
|
||||
bool state = myPSRegister->getSelectedState();
|
||||
|
@ -277,6 +271,8 @@ void CpuWidget::fillGrid()
|
|||
|
||||
// Finally, update the register list
|
||||
myCpuGrid->setList(alist, vlist, changed);
|
||||
myCpuGridDecValue->setList(alist, vlist, changed);
|
||||
myCpuGridBinValue->setList(alist, vlist, changed);
|
||||
|
||||
// Update the PS register booleans
|
||||
changed.clear();
|
||||
|
|
|
@ -75,10 +75,10 @@ class CpuWidget : public Widget, public CommandSender
|
|||
|
||||
DataGridWidget* myPCGrid;
|
||||
DataGridWidget* myCpuGrid;
|
||||
DataGridWidget* myCpuGridDecValue;
|
||||
DataGridWidget* myCpuGridBinValue;
|
||||
ToggleBitWidget* myPSRegister;
|
||||
EditTextWidget* myPCLabel;
|
||||
EditTextWidget* myBinValue;
|
||||
EditTextWidget* myDecValue;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -131,9 +131,8 @@ cerr << "_addrList.size() = " << _addrList.size()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DataGridWidget::setList(const int a, const int v, const bool c)
|
||||
void DataGridWidget::setList(int a, int v, bool c)
|
||||
{
|
||||
// Convenience method for when the datagrid contains only one value
|
||||
IntArray alist, vlist;
|
||||
BoolArray changed;
|
||||
|
||||
|
@ -163,18 +162,27 @@ void DataGridWidget::setNumRows(int rows)
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DataGridWidget::setSelectedValue(int value)
|
||||
{
|
||||
setValue(_selectedItem, value);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DataGridWidget::setValue(int position, int value)
|
||||
{
|
||||
if(position >= 0 && uInt32(position) < _valueList.size())
|
||||
{
|
||||
// Correctly format the data for viewing
|
||||
_editString = instance().debugger().valueToString(value, _base);
|
||||
|
||||
_valueStringList[_selectedItem] = _editString;
|
||||
_changedList[_selectedItem] = (_valueList[_selectedItem] != value);
|
||||
_valueList[_selectedItem] = value;
|
||||
_valueStringList[position] = _editString;
|
||||
_changedList[position] = (_valueList[position] != value);
|
||||
_valueList[position] = value;
|
||||
|
||||
sendCommand(kDGItemDataChangedCmd, _selectedItem, _id);
|
||||
sendCommand(kDGItemDataChangedCmd, position, _id);
|
||||
|
||||
setDirty(); draw();
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DataGridWidget::setRange(int lower, int upper)
|
||||
|
|
|
@ -53,11 +53,16 @@ class DataGridWidget : public EditableWidget
|
|||
|
||||
void setList(const IntArray& alist, const IntArray& vlist,
|
||||
const BoolArray& changed);
|
||||
void setList(const int a, const int v, const bool changed);
|
||||
/** Convenience method for when the datagrid contains only one value */
|
||||
void setList(int a, int v, bool changed);
|
||||
|
||||
void setHiliteList(const BoolArray& hilitelist);
|
||||
void setNumRows(int rows);
|
||||
|
||||
/** Set value at current selection point */
|
||||
void setSelectedValue(int value);
|
||||
/** Set value at given position */
|
||||
void setValue(int position, int value);
|
||||
|
||||
int getSelectedAddr() const { return _addrList[_selectedItem]; }
|
||||
int getSelectedValue() const { return _valueList[_selectedItem]; }
|
||||
|
|
|
@ -154,7 +154,7 @@ RamWidget::~RamWidget()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
|
||||
{
|
||||
// We simply change the values in the ByteGridWidget
|
||||
// We simply change the values in the DataGridWidget
|
||||
// It will then send the 'kDGItemDataChangedCmd' signal to change the actual
|
||||
// memory location
|
||||
int addr, value;
|
||||
|
|
|
@ -33,10 +33,6 @@
|
|||
#include "RomListWidget.hxx"
|
||||
#include "RomWidget.hxx"
|
||||
|
||||
enum {
|
||||
kRomNameEntered = 'RWrn'
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
RomWidget::RomWidget(GuiObject* boss, const GUI::Font& font, int x, int y)
|
||||
: Widget(boss, font, x, y, 16, 16),
|
||||
|
@ -59,7 +55,7 @@ RomWidget::RomWidget(GuiObject* boss, const GUI::Font& font, int x, int y)
|
|||
|
||||
xpos += t->getWidth() + 10;
|
||||
myBank = new DataGridWidget(boss, font, xpos, ypos-2,
|
||||
1, 1, 3, 8, kBASE_10);
|
||||
1, 1, 4, 8, kBASE_10);
|
||||
myBank->setTarget(this);
|
||||
myBank->setRange(0, instance().debugger().bankCount());
|
||||
if(instance().debugger().bankCount() <= 1)
|
||||
|
@ -75,7 +71,8 @@ RomWidget::RomWidget(GuiObject* boss, const GUI::Font& font, int x, int y)
|
|||
|
||||
xpos += t->getWidth() + 10;
|
||||
myBankCount = new EditTextWidget(boss, font, xpos, ypos-2,
|
||||
30, font.getLineHeight(), "");
|
||||
font.getStringWidth("XXXX"),
|
||||
font.getLineHeight(), "");
|
||||
myBankCount->setEditable(false);
|
||||
|
||||
// Create rom listing
|
||||
|
|
|
@ -59,6 +59,10 @@ class RomWidget : public Widget, public CommandSender
|
|||
void saveROM(const string& rom);
|
||||
|
||||
private:
|
||||
enum {
|
||||
kRomNameEntered = 'RWrn'
|
||||
};
|
||||
|
||||
RomListWidget* myRomList;
|
||||
|
||||
/** List of addresses indexed by line number */
|
||||
|
|
|
@ -181,6 +181,18 @@ bool Cartridge::save(ofstream& out)
|
|||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Cartridge::registerRamArea(uInt16 start, uInt16 size,
|
||||
uInt16 roffset, uInt16 woffset)
|
||||
{
|
||||
RamArea area;
|
||||
area.start = start;
|
||||
area.size = size;
|
||||
area.roffset = roffset;
|
||||
area.woffset = woffset;
|
||||
myRamAreaList.push_back(area);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string Cartridge::autodetectType(const uInt8* image, uInt32 size)
|
||||
{
|
||||
|
|
|
@ -27,6 +27,7 @@ class Properties;
|
|||
class Settings;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Array.hxx"
|
||||
#include "Device.hxx"
|
||||
|
||||
/**
|
||||
|
@ -80,22 +81,20 @@ class Cartridge : public Device
|
|||
void lockBank() { myBankLocked = true; }
|
||||
void unlockBank() { myBankLocked = false; }
|
||||
|
||||
public:
|
||||
/**
|
||||
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.
|
||||
The following list contains addressable areas of ROM that are mapped
|
||||
to RAM (usually Superchip, but there are other types). Since such
|
||||
RAM is normally mapped in at different addresses for read and write
|
||||
ports, read and write offsets must be considered.
|
||||
|
||||
@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
|
||||
@return List of addressable RAM areas (can be empty)
|
||||
*/
|
||||
virtual bool getRamArea(uInt16& start, uInt16& size,
|
||||
uInt16& roffset, uInt16& woffset)
|
||||
{ return false; }
|
||||
struct RamArea {
|
||||
uInt16 start; uInt16 size; uInt16 roffset; uInt16 woffset;
|
||||
};
|
||||
typedef Common::Array<RamArea> RamAreaList;
|
||||
const RamAreaList& ramAreas() { return myRamAreaList; }
|
||||
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -160,9 +159,15 @@ class Cartridge : public Device
|
|||
virtual string name() const = 0;
|
||||
|
||||
protected:
|
||||
// If myBankLocked is true, ignore attempts at bankswitching. This is used
|
||||
// by the debugger, when disassembling/dumping ROM.
|
||||
bool myBankLocked;
|
||||
/**
|
||||
Add the given area to the RamArea list for this cart.
|
||||
|
||||
@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 registerRamArea(uInt16 start, uInt16 size, uInt16 roffset, uInt16 woffset);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -249,7 +254,15 @@ class Cartridge : public Device
|
|||
*/
|
||||
static bool isProbablyFE(const uInt8* image, uInt32 size);
|
||||
|
||||
protected:
|
||||
// If myBankLocked is true, ignore attempts at bankswitching. This is used
|
||||
// by the debugger, when disassembling/dumping ROM.
|
||||
bool myBankLocked;
|
||||
|
||||
private:
|
||||
// Contains RamArea entries for those carts with accessible RAM.
|
||||
RamAreaList myRamAreaList;
|
||||
|
||||
// Contains info about this cartridge in string format
|
||||
static string myAboutString;
|
||||
|
||||
|
|
|
@ -33,6 +33,11 @@ Cartridge3E::Cartridge3E(const uInt8* image, uInt32 size)
|
|||
|
||||
// Copy the ROM image into my buffer
|
||||
memcpy(myImage, image, mySize);
|
||||
|
||||
// This cart can address a 1024 byte bank of RAM @ 0x1000
|
||||
// However, it may not be addressable all the time (it may be swapped out)
|
||||
// so probably most of the time, the area will point to ROM instead
|
||||
registerRamArea(0x1000, 1024, 0x00, 0x400); // 1024 bytes RAM @ 0x1000
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -32,6 +32,9 @@ CartridgeCV::CartridgeCV(const uInt8* image, uInt32 size)
|
|||
memcpy(myROM, image, mySize);
|
||||
|
||||
reset();
|
||||
|
||||
// This cart contains 1024 bytes extended RAM @ 0x1000
|
||||
registerRamArea(0x1000, 1024, 0x00, 0x400);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -28,6 +28,13 @@ CartridgeE7::CartridgeE7(const uInt8* image)
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
memcpy(myImage, image, 16384);
|
||||
|
||||
// This cart can address a 1024 byte bank of RAM @ 0x1000
|
||||
// and 256 bytes @ 0x1800
|
||||
// However, it may not be addressable all the time (it may be swapped out)
|
||||
// so probably most of the time, the area will point to ROM instead
|
||||
registerRamArea(0x1000, 1024, 0x400, 0x00); // 1024 bytes RAM @ 0x1000
|
||||
registerRamArea(0x1800, 256, 0x100, 0x00); // 256 bytes RAM @ 0x1800
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -28,6 +28,9 @@ CartridgeEFSC::CartridgeEFSC(const uInt8* image)
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
memcpy(myImage, image, 65536);
|
||||
|
||||
// This cart contains 128 bytes extended RAM @ 0x1000
|
||||
registerRamArea(0x1000, 128, 0x80, 0x00);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -28,6 +28,9 @@ CartridgeF4SC::CartridgeF4SC(const uInt8* image)
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
memcpy(myImage, image, 32768);
|
||||
|
||||
// This cart contains 128 bytes extended RAM @ 0x1000
|
||||
registerRamArea(0x1000, 128, 0x80, 0x00);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -243,15 +246,3 @@ bool CartridgeF4SC::load(Deserializer& in)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF4SC::getRamArea(uInt16& start, uInt16& size,
|
||||
uInt16& roffset, uInt16& woffset)
|
||||
{
|
||||
start = 0x1000;
|
||||
size = 128;
|
||||
roffset = 0x80;
|
||||
woffset = 0x0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -119,22 +119,6 @@ class CartridgeF4SC : public Cartridge
|
|||
*/
|
||||
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:
|
||||
/**
|
||||
Get the byte at the specified address.
|
||||
|
|
|
@ -28,6 +28,9 @@ CartridgeF6SC::CartridgeF6SC(const uInt8* image)
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
memcpy(myImage, image, 16384);
|
||||
|
||||
// This cart contains 128 bytes extended RAM @ 0x1000
|
||||
registerRamArea(0x1000, 128, 0x80, 0x00);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -285,15 +288,3 @@ bool CartridgeF6SC::load(Deserializer& in)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF6SC::getRamArea(uInt16& start, uInt16& size,
|
||||
uInt16& roffset, uInt16& woffset)
|
||||
{
|
||||
start = 0x1000;
|
||||
size = 128;
|
||||
roffset = 0x80;
|
||||
woffset = 0x0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -119,22 +119,6 @@ class CartridgeF6SC : public Cartridge
|
|||
*/
|
||||
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:
|
||||
/**
|
||||
Get the byte at the specified address.
|
||||
|
|
|
@ -28,6 +28,9 @@ CartridgeF8SC::CartridgeF8SC(const uInt8* image)
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
memcpy(myImage, image, 8192);
|
||||
|
||||
// This cart contains 128 bytes extended RAM @ 0x1000
|
||||
registerRamArea(0x1000, 128, 0x80, 0x00);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -263,15 +266,3 @@ bool CartridgeF8SC::load(Deserializer& in)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF8SC::getRamArea(uInt16& start, uInt16& size,
|
||||
uInt16& roffset, uInt16& woffset)
|
||||
{
|
||||
start = 0x1000;
|
||||
size = 128;
|
||||
roffset = 0x80;
|
||||
woffset = 0x0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -119,22 +119,6 @@ class CartridgeF8SC : public Cartridge
|
|||
*/
|
||||
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:
|
||||
/**
|
||||
Get the byte at the specified address.
|
||||
|
|
|
@ -28,6 +28,9 @@ CartridgeFASC::CartridgeFASC(const uInt8* image)
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
memcpy(myImage, image, 12288);
|
||||
|
||||
// This cart contains 256 bytes extended RAM @ 0x1000
|
||||
registerRamArea(0x1000, 256, 0x100, 0x00);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -275,15 +278,3 @@ bool CartridgeFASC::load(Deserializer& in)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFASC::getRamArea(uInt16& start, uInt16& size,
|
||||
uInt16& roffset, uInt16& woffset)
|
||||
{
|
||||
start = 0x1000;
|
||||
size = 256;
|
||||
roffset = 0x100;
|
||||
woffset = 0x0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -119,22 +119,6 @@ class CartridgeFASC : public Cartridge
|
|||
*/
|
||||
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:
|
||||
/**
|
||||
Get the byte at the specified address.
|
||||
|
|