mirror of https://github.com/stella-emu/stella.git
update debugger docs
add missing debugger commands for enhanced DiStella data detection
This commit is contained in:
parent
09fb69f397
commit
1beaf64edd
|
@ -20,9 +20,9 @@
|
|||
a game. This allows the user to save high scores for these games. For each
|
||||
game and variation, the top 10 scores can be saved. (TOOD: Doc)
|
||||
|
||||
* Added displaying last write address in debugger. (TOOD: Doc)
|
||||
* Added displaying last write address in debugger.
|
||||
|
||||
* Added detection of color and audio data in DiStella. (TOOD: Doc)
|
||||
* Added detection of color and audio data in DiStella.
|
||||
|
||||
|
||||
6.0.2 to 6.1: (March 22, 2020)
|
||||
|
|
|
@ -121,13 +121,14 @@ feature that no other 2600 debugger has; it's <b>completely</b> cross-platform.<
|
|||
|
||||
<li>Supports Distella 'configuration directives', which may be used to
|
||||
override automatic code/data determination in the disassembly. For now,
|
||||
the following directives are supported: CODE, GFX, PGFX, DATA, ROW.
|
||||
These directives can be entered at the debugger prompt, or (automatically)
|
||||
the following directives are supported: CODE, GFX, PGFX, COL, PCOL, BCOL, AUD, DATA, ROW.
|
||||
These directives can be entered at the debugger prompt, or be (automatically)
|
||||
loaded and saved in configuration files.</li>
|
||||
|
||||
<li>Extensive disassembly support, both from the emulation core and with help
|
||||
from Distella. Where possible, the disassembly differentiates between code,
|
||||
player graphics and playfield graphics (ie, addresses stored in GRPx and PFx)
|
||||
player and playfield graphics, colors and audio (ie, addresses stored in
|
||||
GRPx, PFx, COLUxx, AUDxx)
|
||||
and data (addresses used as an operand of a command). Code sections are also
|
||||
differentiated between actual code, and 'tentative' code (ie, areas that may
|
||||
represent code sections, but haven't actually been executed yet). Such
|
||||
|
@ -906,7 +907,9 @@ Type "help 'cmd'" to see extended information about the given command.</p>
|
|||
|
||||
<pre>
|
||||
a - Set Accumulator to <value>
|
||||
aud - Mark 'AUD' range in disassembly
|
||||
base - Set default number base to <base> (bin, dec, hex)
|
||||
bcol - Mark 'BCOL' range in disassembly
|
||||
break - Set/clear breakpoint at <address> and <bank>
|
||||
breakif - Set/clear breakpoint on <condition>
|
||||
breaklabel - Set/clear breakpoint on <address> (no mirrors, all banks)
|
||||
|
@ -919,6 +922,7 @@ clearsavestateifs - Clear all savestate points
|
|||
clearwatches - Clear all watches
|
||||
cls - Clear prompt area of text
|
||||
code - Mark 'CODE' range in disassembly
|
||||
col - Mark 'COL' range in disassembly
|
||||
colortest - Show value xx as TIA color
|
||||
d - Decimal Mode Flag: set (0 or 1), or toggle (no arg)
|
||||
data - Mark 'DATA' range in disassembly
|
||||
|
@ -959,6 +963,7 @@ clearsavestateifs - Clear all savestate points
|
|||
n - Negative Flag: set (0 or 1), or toggle (no arg)
|
||||
palette - Show current TIA palette
|
||||
pc - Set Program Counter to address xx
|
||||
pcol - Mark 'PCOL' range in disassembly
|
||||
pgfx - Mark 'PGFX' range in disassembly
|
||||
print - Evaluate/print expression xx in hex/dec/binary
|
||||
ram - Show ZP RAM, or set address xx to yy1 [yy2 ...]
|
||||
|
@ -1217,6 +1222,8 @@ registers. For example, consider the command 'LDA ($80),Y'. The operand of
|
|||
the command resolves to some address, which isn't always easy to determine at
|
||||
first glance. The 'Src Addr' area shows the actual resulting operand/address
|
||||
being used with the given opcode.</p>
|
||||
<p>The destination address of the last write is shown besides 'Dest'.</p>
|
||||
|
||||
<p>There's not much else to say about the CPU Registers widget: if you know 6502
|
||||
assembly, it's pretty self-explanatory. If you don't, well, you should
|
||||
learn :)</p>
|
||||
|
@ -1371,21 +1378,78 @@ can use. These are known as 'directives', and partly correspond to configuration
|
|||
options from the standalone Distella program. They are listed in order of
|
||||
decreasing hierarchy:</p>
|
||||
<table border="1" cellpadding=4>
|
||||
<tr><td><b>CODE</b></td><td>Addresses which have appeared in the program counter, or
|
||||
which tentatively can appear in the program counter. These can be edited in hex.</td></tr>
|
||||
<tr><td><b>GFX</b></td><td>Addresses which contain data stored in the player graphics registers
|
||||
(GRP0/GRP1). These addresses are shown with a bitmap of the graphics, which
|
||||
can be edited in either hex or binary. The bitmap is shown as large blocks.</td></tr>
|
||||
<tr><td><b>PGFX</b></td><td>Addresses which contain data stored in the playfield graphics registers
|
||||
(PF0/PF1/PF2). These addresses are shown with a bitmap of the graphics, which
|
||||
can be edited in either hex or binary. The bitmap is shown as small dashes.</td></tr>
|
||||
<tr><td><b>DATA</b></td><td>Addresses used as an operand for some opcode. These can be edited
|
||||
in hex.</td></tr>
|
||||
<tr><td><b>ROW</b></td><td>Addresses not used as any of the above. These are shown up
|
||||
to 8 per line, and cannot be edited.</td></tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b>CODE</b>
|
||||
</td><td>
|
||||
Addresses which have appeared in the program counter, or
|
||||
which tentatively can appear in the program counter. These can be edited in hex.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>GFX</b>
|
||||
</td><td>
|
||||
Addresses which contain data stored in the player graphics registers
|
||||
(GRP0/GRP1). These addresses are shown with a bitmap of the graphics, which
|
||||
can be edited in either hex or binary. The bitmap is shown as large blocks.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>PGFX</b>
|
||||
</td><td>
|
||||
Addresses which contain data stored in the playfield graphics registers
|
||||
(PF0/PF1/PF2). These addresses are shown with a bitmap of the graphics, which
|
||||
can be edited in either hex or binary. The bitmap is shown as small dashes.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>COL</b>
|
||||
</td><td>
|
||||
Addresses which contain data stored in the player color registers
|
||||
(COLUP0/COLUP1). These addresses are shown as color constants, which
|
||||
can be edited in hex. The color constant names are depending on the ROM's TV type.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>PCOL</b>
|
||||
</td><td>
|
||||
Addresses which contain data stored in the playfield color register
|
||||
(COLUPF). These addresses are shown as color constants, which
|
||||
can be edited in hex. The color constant names are depending on the ROM's TV type.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>BCOL</b>
|
||||
</td><td>
|
||||
Addresses which contain data stored in the background color register
|
||||
(COLUBK). These addresses are shown as color constants, which
|
||||
can be edited in hex. The color constant names are depending on the ROM's TV type.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>AUD</b>
|
||||
</td><td>
|
||||
Addresses which contain data stored in the audio registers
|
||||
(AUDC0/AUDC1/AUDF0/AUDF1/AUDV0/AUDV1). These can be edited
|
||||
in hex.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>DATA</b>
|
||||
</td><td>
|
||||
Addresses used as an operand for some opcode. These can be edited
|
||||
in hex.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>ROW</b>
|
||||
</td><td>
|
||||
Addresses not used as any of the above. These are shown up
|
||||
to 8 per line and cannot be edited.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<p>For code sections, the 6502 mnemonic will be UPPERCASE for all standard instructions,
|
||||
or lowercase for "illegal" 6502 instructions (like "dcp"). If automatic resolving
|
||||
of code sections has been disabled for any reason, you'll likely see a lot
|
||||
|
@ -1523,12 +1587,12 @@ the RAM in the DPC scheme is not viewable by the 6507, so its addresses start fr
|
|||
<br>
|
||||
<h1><a name="DistellaConfiguration">Distella Configuration Files</a></h1>
|
||||
<p>As mentioned in <a href="#Disassembly"><b>ROM Disassembly</b></a>, Stella supports the following directives:
|
||||
CODE/GFX/PGFX/DATA/ROW. While the debugger will try to automatically mark address
|
||||
CODE, GFX, PGFX, COL, PCOL, BCOL, AUD, DATA, ROW. While the debugger will try to automatically mark address
|
||||
space with the appropriate directive, there are times when it will fail. There are
|
||||
several options in this case:</p>
|
||||
<ol>
|
||||
<li><b>Manually set the directives</b>: Directives can be set in the debugger
|
||||
prompt with the code/gfx/pgfx/data/row commands. These accept an address range
|
||||
prompt with the aud/code/col/bcol/gfx/pcol/pgfx/data/row commands. These accept an address range
|
||||
for the given directive type. Setting a range with the same type a second time
|
||||
will remove that directive from the range.</li>
|
||||
<li><b>Use configuration files</b>: Configuration files can be used to automatically
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
Binary file not shown.
|
@ -678,6 +678,44 @@ string DebuggerParser::saveScriptFile(string file)
|
|||
return "saved " + node.getShortPath() + " OK";
|
||||
}
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerParser::executeDirective(Device::AccessType type)
|
||||
{
|
||||
if(argCount != 2)
|
||||
{
|
||||
outputCommandError("specify start and end of range only", myCommand);
|
||||
return;
|
||||
}
|
||||
else if(args[1] < args[0])
|
||||
{
|
||||
commandResult << red("start address must be <= end address");
|
||||
return;
|
||||
}
|
||||
|
||||
bool result = debugger.cartDebug().addDirective(type, args[0], args[1]);
|
||||
string typeStr;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case Device::CODE: typeStr = "CODE"; break;
|
||||
case Device::GFX: typeStr = "GFX"; break;
|
||||
case Device::PGFX: typeStr = "PGFX"; break;
|
||||
case Device::COL: typeStr = "COL"; break;
|
||||
case Device::PCOL: typeStr = "PCOL"; break;
|
||||
case Device::BCOL: typeStr = "BCOL"; break;
|
||||
case Device::AUD: typeStr = "AUD"; break;
|
||||
case Device::DATA: typeStr = "DATA"; break;
|
||||
case Device::ROW: typeStr = "ROW"; break;
|
||||
default: typeStr = "NONE";
|
||||
}
|
||||
|
||||
commandResult << (result ? "added " : "removed ")
|
||||
<< typeStr << " directive on range $"
|
||||
<< hex << args[0] << " $" << hex << args[1];
|
||||
debugger.rom().invalidate();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// executor methods for commands[] array. All are void, no args.
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -689,6 +727,13 @@ void DebuggerParser::executeA()
|
|||
debugger.cpuDebug().setA(uInt8(args[0]));
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "aud"
|
||||
void DebuggerParser::executeAud()
|
||||
{
|
||||
executeDirective(Device::AUD);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "base"
|
||||
void DebuggerParser::executeBase()
|
||||
|
@ -720,6 +765,13 @@ void DebuggerParser::executeBase()
|
|||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "bcol"
|
||||
void DebuggerParser::executeBCol()
|
||||
{
|
||||
executeDirective(Device::BCOL);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "break"
|
||||
void DebuggerParser::executeBreak()
|
||||
|
@ -912,22 +964,14 @@ void DebuggerParser::executeCls()
|
|||
// "code"
|
||||
void DebuggerParser::executeCode()
|
||||
{
|
||||
if(argCount != 2)
|
||||
{
|
||||
outputCommandError("specify start and end of range only", myCommand);
|
||||
return;
|
||||
}
|
||||
else if(args[1] < args[0])
|
||||
{
|
||||
commandResult << red("start address must be <= end address");
|
||||
return;
|
||||
}
|
||||
executeDirective(Device::CODE);
|
||||
}
|
||||
|
||||
bool result = debugger.cartDebug().addDirective(
|
||||
Device::CODE, args[0], args[1]);
|
||||
commandResult << (result ? "added" : "removed") << " CODE directive on range $"
|
||||
<< hex << args[0] << " $" << hex << args[1];
|
||||
debugger.rom().invalidate();
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "col"
|
||||
void DebuggerParser::executeCol()
|
||||
{
|
||||
executeDirective(Device::COL);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -953,22 +997,7 @@ void DebuggerParser::executeD()
|
|||
// "data"
|
||||
void DebuggerParser::executeData()
|
||||
{
|
||||
if(argCount != 2)
|
||||
{
|
||||
outputCommandError("specify start and end of range only", myCommand);
|
||||
return;
|
||||
}
|
||||
else if(args[1] < args[0])
|
||||
{
|
||||
commandResult << red("start address must be <= end address");
|
||||
return;
|
||||
}
|
||||
|
||||
bool result = debugger.cartDebug().addDirective(
|
||||
Device::DATA, args[0], args[1]);
|
||||
commandResult << (result ? "added" : "removed") << " DATA directive on range $"
|
||||
<< hex << args[0] << " $" << hex << args[1];
|
||||
debugger.rom().invalidate();
|
||||
executeDirective(Device::DATA);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -1270,22 +1299,7 @@ void DebuggerParser::executeFunction()
|
|||
// "gfx"
|
||||
void DebuggerParser::executeGfx()
|
||||
{
|
||||
if(argCount != 2)
|
||||
{
|
||||
outputCommandError("specify start and end of range only", myCommand);
|
||||
return;
|
||||
}
|
||||
else if(args[1] < args[0])
|
||||
{
|
||||
commandResult << red("start address must be <= end address");
|
||||
return;
|
||||
}
|
||||
|
||||
bool result = debugger.cartDebug().addDirective(
|
||||
Device::GFX, args[0], args[1]);
|
||||
commandResult << (result ? "added" : "removed") << " GFX directive on range $"
|
||||
<< hex << args[0] << " $" << hex << args[1];
|
||||
debugger.rom().invalidate();
|
||||
executeDirective(Device::GFX);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -1626,26 +1640,18 @@ void DebuggerParser::executePc()
|
|||
debugger.cpuDebug().setPC(args[0]);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "pcol"
|
||||
void DebuggerParser::executePCol()
|
||||
{
|
||||
executeDirective(Device::PCOL);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "pgfx"
|
||||
void DebuggerParser::executePGfx()
|
||||
{
|
||||
if(argCount != 2)
|
||||
{
|
||||
outputCommandError("specify start and end of range only", myCommand);
|
||||
return;
|
||||
}
|
||||
else if(args[1] < args[0])
|
||||
{
|
||||
commandResult << red("start address must be <= end address");
|
||||
return;
|
||||
}
|
||||
|
||||
bool result = debugger.cartDebug().addDirective(
|
||||
Device::PGFX, args[0], args[1]);
|
||||
commandResult << (result ? "added" : "removed") << " PGFX directive on range $"
|
||||
<< hex << args[0] << " $" << hex << args[1];
|
||||
debugger.rom().invalidate();
|
||||
executeDirective(Device::PGFX);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -1722,22 +1728,7 @@ void DebuggerParser::executeRom()
|
|||
// "row"
|
||||
void DebuggerParser::executeRow()
|
||||
{
|
||||
if(argCount != 2)
|
||||
{
|
||||
outputCommandError("specify start and end of range only", myCommand);
|
||||
return;
|
||||
}
|
||||
else if(args[1] < args[0])
|
||||
{
|
||||
commandResult << red("start address must be <= end address");
|
||||
return;
|
||||
}
|
||||
|
||||
bool result = debugger.cartDebug().addDirective(
|
||||
Device::ROW, args[0], args[1]);
|
||||
commandResult << (result ? "added" : "removed") << " ROW directive on range $"
|
||||
<< hex << args[0] << " $" << hex << args[1];
|
||||
debugger.rom().invalidate();
|
||||
executeDirective(Device::ROW);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -2300,7 +2291,7 @@ void DebuggerParser::executeZ()
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// List of all commands available to the parser
|
||||
std::array<DebuggerParser::Command, 95> DebuggerParser::commands = { {
|
||||
std::array<DebuggerParser::Command, 99> DebuggerParser::commands = { {
|
||||
{
|
||||
"a",
|
||||
"Set Accumulator to <value>",
|
||||
|
@ -2311,6 +2302,16 @@ std::array<DebuggerParser::Command, 95> DebuggerParser::commands = { {
|
|||
std::mem_fn(&DebuggerParser::executeA)
|
||||
},
|
||||
|
||||
{
|
||||
"aud",
|
||||
"Mark 'AUD' range in disassembly",
|
||||
"Start and end of range required\nExample: aud f000 f010",
|
||||
true,
|
||||
false,
|
||||
{ Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE },
|
||||
std::mem_fn(&DebuggerParser::executeAud)
|
||||
},
|
||||
|
||||
{
|
||||
"base",
|
||||
"Set default number base to <base>",
|
||||
|
@ -2321,6 +2322,17 @@ std::array<DebuggerParser::Command, 95> DebuggerParser::commands = { {
|
|||
std::mem_fn(&DebuggerParser::executeBase)
|
||||
},
|
||||
|
||||
{
|
||||
"bcol",
|
||||
"Mark 'BCOL' range in disassembly",
|
||||
"Start and end of range required\nExample: bcol f000 f010",
|
||||
true,
|
||||
false,
|
||||
{ Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE },
|
||||
std::mem_fn(&DebuggerParser::executeBCol)
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"break",
|
||||
"Break at <address> and <bank>",
|
||||
|
@ -2442,6 +2454,16 @@ std::array<DebuggerParser::Command, 95> DebuggerParser::commands = { {
|
|||
std::mem_fn(&DebuggerParser::executeCode)
|
||||
},
|
||||
|
||||
{
|
||||
"col",
|
||||
"Mark 'COL' range in disassembly",
|
||||
"Start and end of range required\nExample: col f000 f010",
|
||||
true,
|
||||
false,
|
||||
{ Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE },
|
||||
std::mem_fn(&DebuggerParser::executeCol)
|
||||
},
|
||||
|
||||
{
|
||||
"colortest",
|
||||
"Show value xx as TIA color",
|
||||
|
@ -2847,6 +2869,16 @@ std::array<DebuggerParser::Command, 95> DebuggerParser::commands = { {
|
|||
std::mem_fn(&DebuggerParser::executePc)
|
||||
},
|
||||
|
||||
{
|
||||
"pcol",
|
||||
"Mark 'PCOL' range in disassembly",
|
||||
"Start and end of range required\nExample: col f000 f010",
|
||||
true,
|
||||
false,
|
||||
{ Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE },
|
||||
std::mem_fn(&DebuggerParser::executePCol)
|
||||
},
|
||||
|
||||
{
|
||||
"pgfx",
|
||||
"Mark 'PGFX' range in disassembly",
|
||||
|
|
|
@ -27,6 +27,7 @@ class FilesystemNode;
|
|||
struct Command;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Device.hxx"
|
||||
|
||||
class DebuggerParser
|
||||
{
|
||||
|
@ -97,7 +98,7 @@ class DebuggerParser
|
|||
std::array<Parameters, 10> parms;
|
||||
std::function<void (DebuggerParser*)> executor;
|
||||
};
|
||||
static std::array<Command, 95> commands;
|
||||
static std::array<Command, 99> commands;
|
||||
|
||||
struct Trap
|
||||
{
|
||||
|
@ -140,9 +141,13 @@ class DebuggerParser
|
|||
// output the error with the example provided for the command
|
||||
void outputCommandError(const string& errorMsg, int command);
|
||||
|
||||
void executeDirective(Device::AccessType type);
|
||||
|
||||
// List of available command methods
|
||||
void executeA();
|
||||
void executeAud();
|
||||
void executeBase();
|
||||
void executeBCol();
|
||||
void executeBreak();
|
||||
void executeBreakif();
|
||||
void executeBreaklabel();
|
||||
|
@ -155,6 +160,7 @@ class DebuggerParser
|
|||
void executeClearwatches();
|
||||
void executeCls();
|
||||
void executeCode();
|
||||
void executeCol();
|
||||
void executeColortest();
|
||||
void executeD();
|
||||
void executeData();
|
||||
|
@ -195,6 +201,7 @@ class DebuggerParser
|
|||
void executeN();
|
||||
void executePalette();
|
||||
void executePc();
|
||||
void executePCol();
|
||||
void executePGfx();
|
||||
void executePrint();
|
||||
void executeRam();
|
||||
|
|
Loading…
Reference in New Issue