diff --git a/Changes.txt b/Changes.txt
index 9daaf6f42..0b2e20aa0 100644
--- a/Changes.txt
+++ b/Changes.txt
@@ -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)
diff --git a/docs/debugger.html b/docs/debugger.html
index 15a80bcb1..46e38d079 100644
--- a/docs/debugger.html
+++ b/docs/debugger.html
@@ -121,13 +121,14 @@ feature that no other 2600 debugger has; it's completely cross-platform.<
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.
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.
+The destination address of the last write is shown besides 'Dest'.
+
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 :)
@@ -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:
-CODE | Addresses which have appeared in the program counter, or
-which tentatively can appear in the program counter. These can be edited in hex. |
-GFX | 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. |
-PGFX | 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. |
-DATA | Addresses used as an operand for some opcode. These can be edited
-in hex. |
-ROW | Addresses not used as any of the above. These are shown up
-to 8 per line, and cannot be edited. |
+
+
+ CODE
+ |
+ Addresses which have appeared in the program counter, or
+ which tentatively can appear in the program counter. These can be edited in hex.
+ |
+
+
+ GFX
+ |
+ 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.
+ |
+
+
+ PGFX
+ |
+ 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.
+ |
+
+
+ COL
+ |
+ 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.
+ |
+
+
+ PCOL
+ |
+ 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.
+ |
+
+
+ BCOL
+ |
+ 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.
+ |
+
+
+ AUD
+ |
+ Addresses which contain data stored in the audio registers
+ (AUDC0/AUDC1/AUDF0/AUDF1/AUDV0/AUDV1). These can be edited
+ in hex.
+ |
+
+
+ DATA
+ |
+ Addresses used as an operand for some opcode. These can be edited
+ in hex.
+ |
+
+
+ ROW
+ |
+ Addresses not used as any of the above. These are shown up
+ to 8 per line and cannot be edited.
+ |
+
-
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
As mentioned in ROM Disassembly, 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:
- Manually set the directives: 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.
- Use configuration files: Configuration files can be used to automatically
diff --git a/docs/graphics/debugger_cpuregs.png b/docs/graphics/debugger_cpuregs.png
index f8cd3cb55..feb238c1b 100644
Binary files a/docs/graphics/debugger_cpuregs.png and b/docs/graphics/debugger_cpuregs.png differ
diff --git a/docs/graphics/debugger_main.png b/docs/graphics/debugger_main.png
index 4a8466e8f..b11c02f96 100644
Binary files a/docs/graphics/debugger_main.png and b/docs/graphics/debugger_main.png differ
diff --git a/docs/graphics/resources/debugger_main.pdn b/docs/graphics/resources/debugger_main.pdn
index e486c0048..de1d1e357 100644
Binary files a/docs/graphics/resources/debugger_main.pdn and b/docs/graphics/resources/debugger_main.pdn differ
diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx
index 176083b1f..c62ea740a 100644
--- a/src/debugger/DebuggerParser.cxx
+++ b/src/debugger/DebuggerParser.cxx
@@ -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::commands = { {
+std::array DebuggerParser::commands = { {
{
"a",
"Set Accumulator to ",
@@ -2311,6 +2302,16 @@ std::array 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 ",
@@ -2321,6 +2322,17 @@ std::array 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 and ",
@@ -2442,6 +2454,16 @@ std::array 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::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",
diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx
index dced64dfb..9de21b3e9 100644
--- a/src/debugger/DebuggerParser.hxx
+++ b/src/debugger/DebuggerParser.hxx
@@ -27,6 +27,7 @@ class FilesystemNode;
struct Command;
#include "bspf.hxx"
+#include "Device.hxx"
class DebuggerParser
{
@@ -97,7 +98,7 @@ class DebuggerParser
std::array parms;
std::function executor;
};
- static std::array commands;
+ static std::array 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();