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.<
  • 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.
  • 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:

    - - - - - + + + + + + + + + + + + + + + + + + +
    CODEAddresses which have appeared in the program counter, or -which tentatively can appear in the program counter. These can be edited in hex.
    GFXAddresses 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.
    PGFXAddresses 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.
    DATAAddresses used as an operand for some opcode. These can be edited -in hex.
    ROWAddresses 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

    Distella Configuration Files

    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:

    1. 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.
    2. 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();