diff options
Diffstat (limited to 'src/emu/debug/debughlp.cpp')
-rw-r--r-- | src/emu/debug/debughlp.cpp | 717 |
1 files changed, 432 insertions, 285 deletions
diff --git a/src/emu/debug/debughlp.cpp b/src/emu/debug/debughlp.cpp index 99fda175735..ead08937c15 100644 --- a/src/emu/debug/debughlp.cpp +++ b/src/emu/debug/debughlp.cpp @@ -10,49 +10,28 @@ #include "emu.h" #include "debughlp.h" -#include "corestr.h" -#include <cctype> - +#include "corestr.h" -/*************************************************************************** - CONSTANTS -***************************************************************************/ +#include <cstdio> +#include <iterator> +#include <map> -#define CONSOLE_HISTORY (10000) -#define CONSOLE_LINE_CHARS (100) +namespace { /*************************************************************************** - TYPE DEFINITIONS + TABLE OF HELP ***************************************************************************/ struct help_item { - const char * tag; - const char * help; + char const *tag; + char const *help; }; - - -/*************************************************************************** - LOCAL VARIABLES -***************************************************************************/ - - - -/*************************************************************************** - FUNCTION PROTOTYPES -***************************************************************************/ - - - -/*************************************************************************** - TABLE OF HELP -***************************************************************************/ - -static const help_item static_help_list[] = +const help_item f_static_help_list[] = { { "", @@ -90,12 +69,13 @@ static const help_item static_help_list[] = " tracelog <format>[,<item>[,...]] -- outputs one or more <item>s to the trace file using <format>\n" " tracesym <item>[,...]] -- outputs one or more <item>s to the trace file\n" " history [<CPU>,<length>] -- outputs a brief history of visited opcodes\n" - " trackpc [<bool>,<CPU>,<bool>] -- visually track visited opcodes [boolean to turn on and off, for the given CPU, clear]\n" - " trackmem [<bool>,<bool>] -- record which PC writes to each memory address [boolean to turn on and off, clear]\n" - " pcatmemp <address>[,<CPU>] -- query which PC wrote to a given program memory address for the current CPU\n" - " pcatmemd <address>[,<CPU>] -- query which PC wrote to a given data memory address for the current CPU\n" - " pcatmemi <address>[,<CPU>] -- query which PC wrote to a given I/O memory address for the current CPU\n" - " (Note: you can also query this info by right clicking in a memory window\n" + " trackpc [<bool>,[<CPU>,[<bool>]]] -- visually track visited opcodes [boolean to turn on and off, for CPU, clear]\n" + " trackmem [<bool>,[<CPU>,[<bool>]]] -- record which PC writes to each memory address [boolean to turn on and off, for CPU, clear]\n" + " pcatmem <address>[:<space>] -- query which PC wrote to a given memory address\n" + " pcatmemd <address>[:<space>] -- query which PC wrote to a given data memory address\n" + " pcatmemi <address>[:<space>] -- query which PC wrote to a given I/O memory address\n" + " pcatmemo <address>[:<space>] -- query which PC wrote to a given opcode memory address\n" + " (Note: you can also query this info by right-clicking in a memory window)\n" " rewind[rw] -- go back in time by loading the most recent rewind state" " statesave[ss] <filename> -- save a state file for the current driver\n" " stateload[sl] <filename> -- load a state file for the current driver\n" @@ -111,32 +91,36 @@ static const help_item static_help_list[] = "Type help <command> for further details on each command\n" "\n" " dasm <filename>,<address>,<length>[,<opcodes>[,<CPU>]] -- disassemble to the given file\n" - " f[ind] <address>,<length>[,<data>[,...]] -- search program memory for data\n" + " f[ind] <address>,<length>[,<data>[,...]] -- search memory for data\n" " f[ind]d <address>,<length>[,<data>[,...]] -- search data memory for data\n" " f[ind]i <address>,<length>[,<data>[,...]] -- search I/O memory for data\n" - " fill <address>,<length>[,<data>[,...]] -- fill program memory with data\n" - " filld <address>,<length>[,<data>[,...]] -- fill data memory with data\n" - " filli <address>,<length>[,<data>[,...][ -- fill I/O memory with data\n" - " dump <filename>,<address>,<length>[,<size>[,<ascii>[,<rowsize>[,<CPU>]]]] -- dump program memory as text\n" - " dumpd <filename>,<address>,<length>[,<size>[,<ascii>[,<rowsize>[,<CPU>]]]] -- dump data memory as text\n" - " dumpi <filename>,<address>,<length>[,<size>[,<ascii>[,<rowsize>[,<CPU>]]]] -- dump I/O memory as text\n" - " dumpo <filename>,<address>,<length>[,<size>[,<ascii>[,<rowsize>[,<CPU>]]]] -- dump opcodes memory as text\n" - " strdump <filename>,<address>,<length>[,<term>[,<CPU>]] -- dump ASCII strings from program memory\n" - " strdumpd <filename>,<address>,<length>[,<term>[,<CPU>]] -- dump ASCII strings from data memory\n" - " strdumpi <filename>,<address>,<length>[,<term>[,<CPU>]] -- dump ASCII strings from I/O memory\n" - " strdumpo <filename>,<address>,<length>[,<term>[,<CPU>]] -- dump ASCII strings from opcodes memory\n" - " save <filename>,<address>,<length>[,<CPU>] -- save binary program memory to the given file\n" - " saved <filename>,<address>,<length>[,<CPU>] -- save binary data memory to the given file\n" - " savei <filename>,<address>,<length>[,<CPU>] -- save binary I/O memory to the given file\n" - " saver <filename>,<address>,<length>,<region> -- save binary memory region to the given file\n" - " load <filename>,<address>[,<length>,<CPU>] -- load binary program memory from the given file\n" - " loadd <filename>,<address>[,<length>,<CPU>] -- load binary data memory from the given file\n" - " loadi <filename>,<address>[,<length>,<CPU>] -- load binary I/O memory from the given file\n" - " loadr <filename>,<address>,<length>,<region> -- load binary memory region from the given file\n" - " map <address> -- map logical program address to physical address and bank\n" - " mapd <address> -- map logical data address to physical address and bank\n" - " mapi <address> -- map logical I/O address to physical address and bank\n" - " memdump [<filename>] -- dump the current memory map to <filename>\n" + " fill <address>,<length>[,<data>[,...]] -- fill memory with data\n" + " filld <address>[:<space>],<length>[,<data>[,...]] -- fill data memory with data\n" + " filli <address>[:<space>],<length>[,<data>[,...][ -- fill I/O memory with data\n" + " fillo <address>[:<space>],<length>[,<data>[,...][ -- fill opcode memory with data\n" + " dump <filename>,<address>[:<space>],<length>[,<group>[,<ascii>[,<rowsize>]]] -- dump memory as text\n" + " dumpd <filename>,<address>[:<space>],<length>[,<group>[,<ascii>[,<rowsize>]]] -- dump data memory as text\n" + " dumpi <filename>,<address>[:<space>],<length>[,<group>[,<ascii>[,<rowsize>]]] -- dump I/O memory as text\n" + " dumpo <filename>,<address>[:<space>],<length>[,<group>[,<ascii>[,<rowsize>]]] -- dump opcodes memory as text\n" + " strdump <filename>,<address>[:<space>],<length>[,<term>] -- dump ASCII strings from memory\n" + " strdumpd <filename>,<address>[:<space>],<length>[,<term>] -- dump ASCII strings from data memory\n" + " strdumpi <filename>,<address>[:<space>],<length>[,<term>] -- dump ASCII strings from I/O memory\n" + " strdumpo <filename>,<address>[:<space>],<length>[,<term>] -- dump ASCII strings from opcodes memory\n" + " save <filename>,<address>[:<space>],<length> -- save binary memory to the given file\n" + " saved <filename>,<address>[:<space>],<length> -- save binary data memory to the given file\n" + " savei <filename>,<address>[:<space>],<length> -- save binary I/O memory to the given file\n" + " saveo <filename>,<address>[:<space>],<length> -- save binary opcode memory to the given file\n" + " saver <filename>,<address>[:<space>],<length>,<region> -- save binary memory region to the given file\n" + " load <filename>,<address>[:<space>][,<length>] -- load binary memory from the given file\n" + " loadd <filename>,<address>[:<space>][,<length>] -- load binary data memory from the given file\n" + " loadi <filename>,<address>[:<space>][,<length>] -- load binary I/O memory from the given file\n" + " loado <filename>,<address>[:<space>][,<length>] -- load binary opcode memory from the given file\n" + " loadr <filename>,<address>[:<space>],<length>,<region> -- load binary memory region from the given file\n" + " map <address>[:<space>] -- map logical address to physical address and bank\n" + " mapd <address>[:<space>] -- map logical data address to physical address and bank\n" + " mapi <address>[:<space>] -- map logical I/O address to physical address and bank\n" + " mapo <address>[:<space>] -- map logical opcode address to physical address and bank\n" + " memdump [<filename>,[<root>]] -- dump current memory maps to <filename>\n" }, { "execution", @@ -169,7 +153,7 @@ static const help_item static_help_list[] = "Breakpoint Commands\n" "Type help <command> for further details on each command\n" "\n" - " bp[set] <address>[,<condition>[,<action>]] -- sets breakpoint at <address>\n" + " bp[set] <address>[:<CPU>][,<condition>[,<action>]] -- sets breakpoint at <address>\n" " bpclear [<bpnum>] -- clears a given breakpoint or all if no <bpnum> specified\n" " bpdisable [<bpnum>] -- disables a given breakpoint or all if no <bpnum> specified\n" " bpenable [<bpnum>] -- enables a given breakpoint or all if no <bpnum> specified\n" @@ -181,9 +165,10 @@ static const help_item static_help_list[] = "Watchpoint Commands\n" "Type help <command> for further details on each command\n" "\n" - " wp[set] <address>,<length>,<type>[,<condition>[,<action>]] -- sets program space watchpoint\n" - " wpd[set] <address>,<length>,<type>[,<condition>[,<action>]] -- sets data space watchpoint\n" - " wpi[set] <address>,<length>,<type>[,<condition>[,<action>]] -- sets I/O space watchpoint\n" + " wp[set] <address>[:<space>],<length>,<type>[,<condition>[,<action>]] -- sets watchpoint\n" + " wpd[set] <address>[:<space>],<length>,<type>[,<condition>[,<action>]] -- sets data space watchpoint\n" + " wpi[set] <address>[:<space>],<length>,<type>[,<condition>[,<action>]] -- sets I/O space watchpoint\n" + " wpo[set] <address>[:<space>],<length>,<type>[,<condition>[,<action>]] -- sets opcode space watchpoint\n" " wpclear [<wpnum>] -- clears a given watchpoint or all if no <wpnum> specified\n" " wpdisable [<wpnum>] -- disables a given watchpoint or all if no <wpnum> specified\n" " wpenable [<wpnum>] -- enables a given watchpoint or all if no <wpnum> specified\n" @@ -261,9 +246,9 @@ static const help_item static_help_list[] = "Cheat Commands\n" "Type help <command> for further details on each command\n" "\n" - " cheatinit [<address>,<length>[,<CPU>]] -- initialize the cheat search to the selected memory area\n" + " cheatinit [<sign><width>[<swap>],[<address>,<length>[,<CPU>]]] -- initialize the cheat search to the selected memory area\n" " cheatrange <address>,<length> -- add to the cheat search the selected memory area\n" - " cheatnext <condition>[,<comparisonvalue>] -- continue cheat search comparing with the last value\n" + " cheatnext <condition>[,<comparisonvalue>] -- continue cheat search comparing with the previous value\n" " cheatnextf <condition>[,<comparisonvalue>] -- continue cheat search comparing with the first value\n" " cheatlist [<filename>] -- show the list of cheat search matches or save them to <filename>\n" " cheatundo -- undo the last cheat search (state only)\n" @@ -425,12 +410,13 @@ static const help_item static_help_list[] = { "trackpc", "\n" - " trackpc [<bool>,<CPU>,<bool>]\n" + " trackpc [<bool>,[<CPU>,[<bool>]]]\n" "\n" - "The trackpc command displays which program counters have already been visited in all disassembler " - "windows. The first boolean argument toggles the process on and off. The second argument is a " - "CPU selector; if no CPU is specified, the current CPU is automatically selected. The third argument " - "is a boolean denoting if the existing data should be cleared or not.\n" + "The trackpc command displays which program counters have already been visited in all " + "disassembler views. The first Boolean argument toggles the process on and off. The " + "second argument is a CPU selector (either a tag or a debugger CPU number); if no CPU is " + "specified, the current CPU is assumed. The third argument is a Boolean indicating " + "whether the existing data should be cleared.\n" "\n" "Examples:\n" "\n" @@ -443,19 +429,20 @@ static const help_item static_help_list[] = { "trackmem", "\n" - " trackmem [<bool>,<CPU>,<bool>]\n" + " trackmem [<bool>,[<CPU>,[<bool>]]]\n" "\n" "The trackmem command logs the PC at each time a memory address is written to. " - "The first boolean argument toggles the process on and off. The second argument is a CPU " - "selector; if no CPU is specified, the current CPU is automatically selected. The third argument " - " is a boolean denoting if the existing data should be cleared or not. Please refer to the " - "pcatmem command for information on how to retrieve this data. Also, right clicking in " - "a memory window will display the logged PC for the given address.\n" + "The first Boolean argument toggles the process on and off. The second argument is a CPU " + "selector (either a tag or a debugger CPU number); if no CPU is specified, the current CPU " + "is assumed. The third argument is a Boolean indicating whether the existing data should " + "be cleared. Please refer to the 'pcatmem' command for information on how to retrieve this " + "data. Also, right-clicking in a memory view will display the logged PC for the given " + "address.\n" "\n" "Examples:\n" "\n" "trackmem\n" - " Begin tracking the current CPU's pc.\n" + " Begin tracking memory writes for the current CPU.\n" "\n" "trackmem 1, 0, 1\n" " Continue tracking memory writes on CPU 0, but clear existing track info.\n" @@ -463,18 +450,31 @@ static const help_item static_help_list[] = { "pcatmem", "\n" - " pcatmem(p/d/i) <address>[,<CPU>]\n" + " pcatmem[{d|i|o}] <address>[:<space>]\n" "\n" - "The pcatmem command returns which PC wrote to a given memory address for the current CPU. " - "The first argument is the requested address. The second argument is a CPU selector; if no " - "CPU is specified, the current CPU is automatically selected. Right clicking in a memory window " - "will also display the logged PC for the given address.\n" + "The pcatmem command returns which PC wrote to a given memory address for the current CPU. " + "The argument is the requested address, optionally followed by a colon and a CPU and/or " + "address space. The CPU may be specified as a tag or debugger CPU number; if no CPU is " + "specified, the CPU currently visible in the debugger is assumed. If an address space is " + "not specified, the command suffix sets the address space: 'pcatmem' defaults to the first " + "space exposed by the device, 'pcatmemd' defaults to the data space, 'pcatmemi' defaults to " + "the I/O space, and 'pcatmemo' defaults to the opcodes space.\n" + "Right-clicking in a memory view will also display the logged PC for the given address.\n" "\n" "Examples:\n" "\n" "pcatmem 400000\n" - " Print which PC wrote this CPU's memory location 0x400000.\n" + " Print which PC wrote to this CPU's program space at location 0x400000.\n" + "\n" + "pcatmem 3bc:io\n" + " Print which PC wrote this CPU's memory io space at location 0x3bc.\n" + "\n" + "pcatmem 1400:audiocpu\n" + " Print which PC wrote the CPU :audiocpu's memory program space at location 0x1400.\n" }, + { "pcatmemd", "#pcatmem" }, + { "pcatmemi", "#pcatmem" }, + { "pcatmemo", "#pcatmem" }, { "rewind[rw]", "\n" @@ -583,67 +583,92 @@ static const help_item static_help_list[] = { "find", "\n" - " f[ind][{d|i}] <address>,<length>[,<data>[,...]]\n" - "\n" - "The find/findd/findi commands search through memory for the specified sequence of data. " - "'find' will search program space memory, while 'findd' will search data space memory " - "and 'findi' will search I/O space memory. <address> indicates the address to begin searching, " - "and <length> indicates how much memory to search. <data> can either be a quoted string " - "or a numeric value or expression or the wildcard character '?'. Strings by default imply a " - "byte-sized search; non-string data is searched by default in the native word size of the CPU. " - "To override the search size for non-strings, you can prefix the value with b. to force byte- " - "sized search, w. for word-sized search, d. for dword-sized, and q. for qword-sized. Overrides " - "are remembered, so if you want to search for a series of words, you need only to prefix the " - "first value with a w. Note also that you can intermix sizes in order to perform more complex " - "searches. The entire range <address> through <address>+<length>-1 inclusive will be searched " - "for the sequence, and all occurrences will be displayed.\n" + " f[ind][{d|i|o}] <address>[:<space>],<length>[,<data>[,...]]\n" + "\n" + "The find commands search through memory for the specified sequence of data. The <address> " + "is the address to begin searching from, optionally followed by a device and/or address " + "space; the <length> specifies how much memory to search. The device may be specified as a " + "tag or a debugger CPU number; if no device is specified, the CPU currently visible in the " + "debugger is assumed. If an address space is not specified, the command suffix sets the " + "address space: 'find' defaults to the first address space exposed by the device, 'findd' " + "defaults to the data space, 'findi' defaults to the I/O space, and 'findo' defaults to the " + "opcodes space.\n" + "\n" + "The <data> can either be a quoted string or a numeric value or expression or the wildcard " + "character '?'. By default, strings by default imply a byte-sized search; by default " + "non-string data is searched using the native word size of the address space. To override " + "the search size for non-string data, you can prefix values with b. to force byte-sized " + "search, w. for word-sized search, d. for dword-sized search, and q. for qword-sized " + "search. Overrides propagate to subsequent values, so if you want to search for a sequence " + "of words, you need only prefix the first value with a w. Also note that you can intermix " + "sizes to perform more complex searches. The entire range <address> through " + "<address>+<length>-1, inclusive, will be searched for the sequence, and all occurrences " + "will be displayed.\n" "\n" "Examples:\n" "\n" "find 0,10000,\"HIGH SCORE\",0\n" - " Searches the address range 0-ffff in the current CPU for the string \"HIGH SCORE\" followed " - "by a 0 byte.\n" + " Searches the address range 0-ffff in the current CPU for the string \"HIGH SCORE\" " + "followed by a 0 byte.\n" "\n" - "findd 3000,1000,w.abcd,4567\n" - " Searches the data memory address range 3000-3fff for the word-sized value abcd followed by " - "the word-sized value 4567.\n" + "find 300:tms9918a,100,w.abcd,4567\n" + " Searches the address range 300-3ff in the first address space exposed by the device " + "':tms9918a' memory for the word-sized value abcd followed by the word-sized value 4567.\n" "\n" "find 0,8000,\"AAR\",d.0,\"BEN\",w.0\n" " Searches the address range 0000-7fff for the string \"AAR\" followed by a dword-sized 0 " "followed by the string \"BEN\", followed by a word-sized 0.\n" }, + { "findd", "#find" }, + { "findi", "#find" }, + { "findo", "#find" }, { "fill", "\n" - " fill[{d|i}] <address>,<length>[,<data>[,...]]\n" - "\n" - "The fill/filld/filli commands overwrite a block of memory with copies of the specified " - "sequence of data. 'fill' will fill program space memory, while 'filld' will fill data space " - "memory and 'filli' will fill I/O space memory. <address> indicates the address to begin " - "writing, and <length> indicates how much memory to fill. <data> can either be a quoted " - "string or a numeric value or expression. Non-string data is written by default in the " - "native word size of the CPU. To override the data size for non-strings, you can prefix " - "the value with b. to force byte-sized fill, w. for word-sized fill, d. for dword-sized, " - "and q. for qword-sized. Overrides are remembered, so if you want to fill with a series of " - "words, you need only to prefix the first value with a w. Note also that you can intermix " - "sizes in order to perform more complex fills. The fill operation may be truncated if a page " - "fault occurs or if part of the sequence or string would fall beyond <address>+<length>-1.\n" - }, + " fill[{d|i|o}] <address>[:<space>],<length>[,<data>[,...]]\n" + "\n" + "The fill commands overwrite a block of memory with copies of the supplied data sequence. " + "The <address> specifies the address to begin writing at, optionally followed by a device " + "and/or address space; the <length> specifies how much memory to fill. The device may be " + "specified as a tag or a debugger CPU number; if no device is specified, the CPU currently " + "visible in the debugger is assumed. If an address space is not specified, the command " + "suffix sets the address space: 'fill' defaults to the first address space exposed by the " + "device, 'filld' defaults to the data space, 'filli' defaults to the I/O space, and 'fillo' " + "defaults to the opcodes space.\n" + "\n" + "The <data> can either be a quoted string or a numeric value or expression. By default, " + "non-string data is written using the native word size of the address space. To override " + "the data size for non-string data, you can prefix values with b. to force byte-sized fill, " + "w. for word-sized fill, d. for dword-sized fill, and q. for qword-sized fill. Overrides " + "propagate to subsequent value, so if you want to fill with a series of words, you need " + "only prefix the first value with a w. Also note that you can intermix sizes to perform " + "more complex fills. The fill operation may be truncated if a page fault occurs or if part " + "of the sequence or string would fall beyond <address>+<length>-1.\n" + }, + { "filld", "#fill" }, + { "filli", "#fill" }, + { "fillo", "#fill" }, { "dump", "\n" - " dump[{d|i}] <filename>,<address>,<length>[,<size>[,<ascii>[,<CPU>]]]\n" - "\n" - "The dump/dumpd/dumpi/dumpo commands dump memory to the text file specified in the <filename> " - "parameter. 'dump' will dump program space memory, while 'dumpd' will dump data space memory, " - "'dumpi' will dump I/O space memory and 'dumpo' will dump opcodes memory. <address> indicates " - "the address of the start of dumping, and <length> indicates how much memory to dump. The range " - "<address> through <address>+<length>-1 inclusive will be output to the file. By default, the data " - "will be output in byte format, unless the underlying address space is word/dword/qword-only. " - "You can override this by specifying the <size> parameter, which can be used to group the data in " - "1, 2, 4 or 8-byte chunks. The optional <ascii> parameter can be used to enable (1) or disable (0) " - "the output of ASCII characters to the right of each line; by default, this is enabled. Finally, " - "you can dump memory from another CPU by specifying the <CPU> parameter.\n" + " dump[{d|i|o}] <filename>,<address>[:<space>],<length>[,<group>[,<ascii>[,<rowsize>]]]\n" + "\n" + "The dump commands dump memory to the text file specified in the <filename> parameter. The " + "<address> specifies the address to start dumping from, optionally followed by a device " + "and/or address space; the <length> specifies how much memory to dump. The device may be " + "specified as a tag or a debugger CPU number; if no device is specified, the CPU currently " + "visible in the debugger is assumed. If an address space is not specified, the command " + "suffix sets the address space: 'dump' defaults to the first address space exposed by the " + "device, 'dumpd' defaults to the data space, 'dumpi' defaults to the I/O space, and 'dumpo' " + "defaults to the opcodes space.\n" + "\n" + "The range <address> through <address>+<length>-1, inclusive, will be output to the file. " + "By default, the data will be output using the native word size of the address space. You " + "can override this by specifying the <group> parameter, which can be used to group the data " + "in 1-, 2-, 4- or 8-byte chunks. The optional <ascii> parameter is a Boolean value used to " + "enable or disable output of ASCII characters on the right of each line (enabled by " + "default). The optional <rowsize> parameter specifies the amount of data on each line in " + "address units (defaults to 16 bytes).\n" "\n" "Examples:\n" "\n" @@ -651,54 +676,79 @@ static const help_item static_help_list[] = " Dumps addresses 0-ffff in the current CPU in 1-byte chunks, including ASCII data, to " "the file 'venture.dmp'.\n" "\n" - "dumpd harddriv.dmp,3000,1000,4,0,3\n" + "dumpd harddriv.dmp,3000:3,1000,4,0\n" " Dumps data memory addresses 3000-3fff from CPU #3 in 4-byte chunks, with no ASCII data, " "to the file 'harddriv.dmp'.\n" + "\n" + "dump vram.dmp,0:sms_vdp:videoram,4000,1,0,8\n" + " Dumps 'videoram' space addresses 0000-3fff from the device ':sms_vdp' in 1-byte chunks, " + "with no ASCII data, and 8 bytes per line, to the file 'vram.dmp'.\n" }, + { "dumpd", "#dump" }, + { "dumpi", "#dump" }, + { "dumpo", "#dump" }, { "strdump", "\n" - " strdump[{d|i}] <filename>,<address>,<length>[,<term>[,<CPU>]]\n" + " strdump[{d|i|o}] <filename>,<address>[:<space>],<length>[,<term>]\n" "\n" - "The strdump/strdumpd/strdumpi/strdumpo commands dump memory to the text file specified in the " - "<filename> parameter. 'strdump' will dump program space memory, while 'strdumpd' will dump data " - "space memory, 'strdumpi' will dump I/O space memory and 'strdumpo' will dump opcodes memory. " - "<address> indicates the address of the start of dumping, and <length> indicates how much memory " - "to dump. The range <address> through <address>+<length>-1 inclusive will be output to the file. " - "By default, the data will be interpreted as a series of null-terminated strings, and the dump " - "will have one string on each line and C-style escapes for non-ASCII characters. The optional " - "<term> parameter can be used to specify a different character as the string terminator. Finally, " - "you can dump memory from another CPU by specifying the <CPU> parameter.\n" + "The strdump commands dump memory to the text file specified in the <filename> parameter. " + "The <address> specifies the address to start dumping from, optionally followed by a device " + "and/or address space; the <length> specifies how much memory to dump. The device may be " + "specified as a tag or a debugger CPU number; if no device is specified, the CPU currently " + "visible in the debugger is assumed. If an address space is not specified, the command " + "suffix sets the address space: 'strdump' defaults to the first address space exposed by " + "the device, 'strdumpd' defaults to the data space, 'strdumpi' defaults to the I/O space, " + "and 'strdumpo' defaults to the opcodes space.\n" + "\n" + "By default, the data will be interpreted as a series of NUL-terminated strings, the dump " + "will have one string per line, and C-style escapes will be used for non-ASCII characters. " + "The optional <term> parameter can be used to specify a different string terminator " + "character.\n" }, + { "strdumpd", "#strdump" }, + { "strdumpi", "#strdump" }, + { "strdumpo", "#strdump" }, { "save", "\n" - " save[{d|i}] <filename>,<address>,<length>[,<CPU>]\n" + " save[{d|i|o}] <filename>,<address>[:<space>],<length>\n" + "\n" + "The save commands save raw memory to the binary file specified in the <filename> " + "parameter. The <address> specifies the address to start saving from, optionally followed " + "by a device and/or address space; the <length> specifies how much memory to save. The " + "device may be specified as a tag or a debugger CPU number; if no device is specified, the " + "CPU currently visible in the debugger is assumed. If an address space is not specified, " + "the command suffix sets the address space: 'save' defaults to the first address space " + "exposed by the device, 'saved' defaults to the data space, 'savei' defaults to the I/O " + "space, and 'saveo' defaults to the opcodes space.\n" "\n" - "The save/saved/savei commands save raw memory to the binary file specified in the <filename> " - "parameter. 'save' will save program space memory, while 'saved' will save data space memory " - "and 'savei' will save I/O space memory. <address> indicates the address of the start of saving, " - "and <length> indicates how much memory to save. The range <address> through <address>+<length>-1 " - "inclusive will be output to the file. You can also save memory from another CPU by specifying the " - "<CPU> parameter.\n" + "The range <address> through <address>+<length>-1, inclusive, will be output to the file.\n" "\n" "Examples:\n" "\n" "save venture.bin,0,10000\n" " Saves addresses 0-ffff in the current CPU to the binary file 'venture.bin'.\n" "\n" - "saved harddriv.bin,3000,1000,3\n" + "saved harddriv.bin,3000:3,1000\n" " Saves data memory addresses 3000-3fff from CPU #3 to the binary file 'harddriv.bin'.\n" + "\n" + "save vram.bin,0:sms_vdp:videoram,4000\n" + " Saves 'videoram' space addresses 0000-3fff from the device ':sms_vdp' to the binary file " + "'vram.bin'.\n" }, + { "saved", "#save" }, + { "savei", "#save" }, + { "saveo", "#save" }, { "saver", "\n" " saver <filename>,<address>,<length>,<region>\n" "\n" - "The saver command saves the raw content of memory region <region> to the binary file specified in the " - "<filename> parameter. <address> indicates the address of the start of saving, and <length> indicates " - "how much memory to save. The range <address> through <address>+<length>-1 inclusive will be output to " - "the file.\n" + "The saver command saves the raw content of memory region <region> to the binary file " + "specified in the <filename> parameter. The <address> specifies the address to start " + "saving from, and the <length> specifies how much memory to save. The range <address> " + "through <address>+<length>-1, inclusive, will be output to the file.\n" "\n" "Example:\n" "\n" @@ -708,16 +758,23 @@ static const help_item static_help_list[] = { "load", "\n" - " load[{d|i}] <filename>,<address>[,<length>,<CPU>]\n" + " load[{d|i|o}] <filename>,<address>[:<space>][,<length>]\n" + "\n" + "The load commands load raw memory from the binary file specified in the <filename> " + "parameter. The <address> specifies the address to start loading to, optionally followed " + "by a device and/or address space; the <length> specifies how much memory to load. The " + "device may be specified as a tag or a debugger CPU number; if no device is specified, the " + "CPU currently visible in the debugger is assumed. If an address space is not specified, " + "the command suffix sets the address space: 'load' defaults to the first address space " + "exposed by the device, 'loadd' defaults to the data space, 'loadi' defaults to the I/O " + "space, and 'loado' defaults to the opcodes space.\n" "\n" - "The load/loadd/loadi commands load raw memory from the binary file specified in the <filename> " - "parameter. 'load' will load program space memory, while 'loadd' will load data space memory " - "and 'loadi' will load I/O space memory. <address> indicates the address of the start of loading, " - "and <length> indicates how much memory to load. The range <address> through <address>+<length>-1 " - "inclusive will be read in from the file. If you specify <length> = 0 or a length greater than the " - "total length of the file it will load the entire contents of the file and no more. You can also load " - "memory from another CPU by specifying the <CPU> parameter.\n" - "NOTE: This will only actually write memory that is possible to overwrite in the Memory Window\n" + "The range <address> through <address>+<length>-1, inclusive, will be read in from the " + "file. If the <length> is omitted, if it is zero, or if it is greater than the total " + "length of the file, the entire contents of the file will be loaded but no more.\n" + "\n" + "NOTE: This will only actually write memory that is possible to overwrite via a memory " + "view.\n" "\n" "Examples:\n" "\n" @@ -726,17 +783,25 @@ static const help_item static_help_list[] = "\n" "loadd harddriv.bin,3000,1000,3\n" " Loads data memory addresses 3000-3fff from CPU #3 from the binary file 'harddriv.bin'.\n" + "\n" + "load vram.bin,0:sms_vdp:videoram\n" + " Loads 'videoram' space starting at address 0000 from the device ':sms_vdp' with the " + "entire content of the binary file 'vram.bin'.\n" }, + { "loadd", "#load" }, + { "loadi", "#load" }, + { "loado", "#load" }, { "loadr", "\n" " loadr <filename>,<address>,<length>,<region>\n" "\n" - "The loadr command loads raw memory in the memory region <region> from the binary file specified " - "in the <filename> parameter. <address> indicates the address of the start of loading, and <length> " - "indicates how much memory to load. The range <address> through <address>+<length>-1 inclusive will " - "be read in from the file. If you specify <length> = 0 or a length greater than the total length of " - "the file it will load the entire contents of the file and no more.\n" + "The loadr command loads raw memory in the memory region <region> from the binary file " + "specified in the <filename> parameter. The <address> indicates the address to start " + "loading to, and the <length> specifies how much memory to load. The range <address> " + "through <address>+<length>-1, inclusive, will be read in from the file. If the <length> " + "is zero, or is greater than the total length of the file, the entire contents of the file " + "will be loaded but no more.\n" "\n" "Example:\n" "\n" @@ -1021,17 +1086,21 @@ static const help_item static_help_list[] = { "bpset", "\n" - " bp[set] <address>[,<condition>[,<action>]]\n" + " bp[set] <address>[:<CPU>][,<condition>[,<action>]]\n" "\n" - "Sets a new execution breakpoint at the specified <address>. The optional <condition> " - "parameter lets you specify an expression that will be evaluated each time the breakpoint is " - "hit. If the result of the expression is true (non-zero), the breakpoint will actually halt " - "execution; otherwise, execution will continue with no notification. The optional <action> " - "parameter provides a command that is executed whenever the breakpoint is hit and the " - "<condition> is true. Note that you may need to embed the action within braces { } in order " - "to prevent commas and semicolons from being interpreted as applying to the bpset command " - "itself. Each breakpoint that is set is assigned an index which can be used in other " - "breakpoint commands to reference this breakpoint.\n" + "Sets a new execution breakpoint at the specified <address>. The <address> may optionally " + "be followed by a colon and the tag or debuggers CPU number to specify a CPU explicitly. " + "If no CPU is specified, the CPU currently visible in the debugger is assumed. The " + "optional <condition> parameter lets you specify an expression that will be evaluated each " + "time the breakpoint is hit. If the result of the expression is true (non-zero), the " + "breakpoint will halt execution; otherwise, execution will continue with no notification. " + "The optional <action> parameter provides a command that is executed whenever the " + "breakpoint is hit and the <condition> is true. Note that you may need to embed the action " + "within braces { } in order to prevent commas and semicolons from being interpreted as " + "applying to the 'bpset' command itself.\n" + "\n" + "Each breakpoint that is set is assigned an index which can be used to refer to it in other " + "breakpoint commands.\n" "\n" "Examples:\n" "\n" @@ -1042,17 +1111,18 @@ static const help_item static_help_list[] = " Set a breakpoint that will halt execution whenever the PC is equal to 23456 AND the " "expression (a0 == 0 && a1 == 0) is true.\n" "\n" - "bp 3456,1,{printf \"A0=%08X\\n\",a0; g}\n" - " Set a breakpoint that will halt execution whenever the PC is equal to 3456. When " - "this happens, print A0=<a0val> and continue executing.\n" + "bp 3456:audiocpu,1,{ printf \"A0=%08X\\n\",a0 ; g }\n" + " Set a breakpoint on the CPU ':audiocpu' that will halt execution whenever the PC is " + "equal to 3456. When this happens, print A0=<a0val> and continue executing.\n" "\n" - "bp 45678,a0==100,{a0 = ff; g}\n" - " Set a breakpoint that will halt execution whenever the PC is equal to 45678 AND the " - "expression (a0 == 100) is true. When that happens, set a0 to ff and resume execution.\n" + "bp 45678:2,a0==100,{ a0 = ff ; g }\n" + " Set a breakpoint on CPU #2 that will halt execution whenever the PC is equal to 45678 " + "and the expression (a0 == 100) is true. When that happens, set a0 to ff and resume " + "execution.\n" "\n" - "temp0 = 0; bp 567890,++temp0 >= 10\n" - " Set a breakpoint that will halt execution whenever the PC is equal to 567890 AND the " - "expression (++temp0 >= 10) is true. This effectively breaks only after the breakpoint " + "temp0 = 0 ; bp 567890,++temp0 >= 10\n" + " Set a breakpoint that will halt execution whenever the PC is equal to 567890 and the " + "expression (++temp0 >= 10) is true. This effectively breaks only after the breakpoint " "has been hit 16 times.\n" }, { @@ -1060,13 +1130,13 @@ static const help_item static_help_list[] = "\n" " bpclear [<bpnum>]\n" "\n" - "The bpclear command clears a breakpoint. If <bpnum> is specified, only the requested " - "breakpoint is cleared, otherwise all breakpoints are cleared.\n" + "The bpclear command clears a breakpoint. If <bpnum> is specified, only the requested " + "breakpoint is cleared; otherwise all breakpoints are cleared.\n" "\n" "Examples:\n" "\n" "bpclear 3\n" - " Clear breakpoint index 3.\n" + " Clear the breakpoint with index 3.\n" "\n" "bpclear\n" " Clear all breakpoints.\n" @@ -1076,14 +1146,14 @@ static const help_item static_help_list[] = "\n" " bpdisable [<bpnum>]\n" "\n" - "The bpdisable command disables a breakpoint. If <bpnum> is specified, only the requested " - "breakpoint is disabled, otherwise all breakpoints are disabled. Note that disabling a " + "The bpdisable command disables a breakpoint. If <bpnum> is specified, only the requested " + "breakpoint is disabled; otherwise all breakpoints are disabled. Note that disabling a " "breakpoint does not delete it, it just temporarily marks the breakpoint as inactive.\n" "\n" "Examples:\n" "\n" "bpdisable 3\n" - " Disable breakpoint index 3.\n" + " Disable the breakpoint with index 3.\n" "\n" "bpdisable\n" " Disable all breakpoints.\n" @@ -1093,13 +1163,13 @@ static const help_item static_help_list[] = "\n" " bpenable [<bpnum>]\n" "\n" - "The bpenable command enables a breakpoint. If <bpnum> is specified, only the requested " - "breakpoint is enabled, otherwise all breakpoints are enabled.\n" + "The bpenable command enables a breakpoint. If <bpnum> is specified, only the requested " + "breakpoint is enabled; otherwise all breakpoints are enabled.\n" "\n" "Examples:\n" "\n" "bpenable 3\n" - " Enable breakpoint index 3.\n" + " Enable the breakpoint with index 3.\n" "\n" "bpenable\n" " Enable all breakpoints.\n" @@ -1109,33 +1179,40 @@ static const help_item static_help_list[] = "\n" " bplist\n" "\n" - "The bplist command lists all the current breakpoints, along with their index and any " + "The bplist command lists all the current breakpoints, along with their indices and any " "conditions or actions attached to them.\n" }, { "wpset", "\n" - " wp[{d|i}][set] <address>,<length>,<type>[,<condition>[,<action>]]\n" - "\n" - "Sets a new watchpoint starting at the specified <address> and extending for <length>. The " - "inclusive range of the watchpoint is <address> through <address> + <length> - 1. The 'wpset' " - "command sets a watchpoint on program memory; the 'wpdset' command sets a watchpoint on data " - "memory; and the 'wpiset' sets a watchpoint on I/O memory. The <type> parameter specifies " - "which sort of accesses to trap on. It can be one of three values: 'r' for a read watchpoint " - "'w' for a write watchpoint, and 'rw' for a read/write watchpoint.\n" - "\n" - "The optional <condition> parameter lets you specify an expression that will be evaluated each " - "time the watchpoint is hit. If the result of the expression is true (non-zero), the watchpoint " - "will actually halt execution; otherwise, execution will continue with no notification. The " - "optional <action> parameter provides a command that is executed whenever the watchpoint is hit " - "and the <condition> is true. Note that you may need to embed the action within braces { } in " - "order to prevent commas and semicolons from being interpreted as applying to the wpset command " - "itself. Each watchpoint that is set is assigned an index which can be used in other " - "watchpoint commands to reference this watchpoint.\n" - "\n" - "In order to help <condition> expressions, two variables are available. For all watchpoints, " - "the variable 'wpaddr' is set to the address that actually triggered the watchpoint. For write " - "watchpoints, the variable 'wpdata' is set to the data that is being written.\n" + " wp[{d|i|o}][set] <address>[:<space>],<length>,<type>[,<condition>[,<action>]]\n" + "\n" + "Sets a new watchpoint starting at the specified <address> and extending for <length>. The " + "inclusive range of the watchpoint is <address> through <address>+<length>-1. The " + "<address> may optionally be followed by a CPU and/or address space. The CPU may be " + "specified as a tag or a debugger CPU number; if no CPU is specified, the CPU currently " + "visible in the debugger is assumed. If an address space is not specified, the command " + "suffix sets the address space: 'wpset' defaults to the first address space exposed by the " + "CPU, 'wpdset' defaults to the data space, 'wpiset' defaults to the I/O space, and 'wposet' " + "defaults to the opcodes space. The <type> parameter specifies the access types to trap " + "on - it can be one of three values: 'r' for read accesses, 'w' for write accesses, and " + "'rw' for both read and write accesses.\n" + "\n" + "The optional <condition> parameter lets you specify an expression that will be evaluated " + "each time the watchpoint is triggered. If the result of the expression is true " + "(non-zero), the watchpoint will halt execution; otherwise, execution will continue with no " + "notification. The optional <action> parameter provides a command that is executed " + "whenever the watchpoint is triggered and the <condition> is true. Note that you may need " + "to embed the action within braces { } in order to prevent commas and semicolons from being " + "interpreted as applying to the wpset command itself.\n" + "\n" + "Each watchpoint that is set is assigned an index which can be used to refer to it in other " + "watchpoint commands\n" + "\n" + "To make <condition> expressions more useful, two variables are available: for all " + "watchpoints, the variable 'wpaddr' is set to the access address that triggered the " + "watchpoint; for write watchpoints, the variable 'wpdata' is set to the data that is being " + "written.\n" "\n" "Examples:\n" "\n" @@ -1143,31 +1220,35 @@ static const help_item static_help_list[] = " Set a watchpoint that will halt execution whenever a read or write occurs in the address " "range 1234-1239 inclusive.\n" "\n" - "wp 23456,a,w,wpdata == 1\n" + "wp 23456:data,a,w,wpdata == 1\n" " Set a watchpoint that will halt execution whenever a write occurs in the address range " - "23456-2345f AND the data written is equal to 1.\n" + "23456-2345f of the data space and the data written is equal to 1.\n" "\n" - "wp 3456,20,r,1,{printf \"Read @ %08X\\n\",wpaddr; g}\n" - " Set a watchpoint that will halt execution whenever a read occurs in the address range " - "3456-3475. When this happens, print Read @ <wpaddr> and continue executing.\n" + "wp 3456:maincpu,20,r,1,{ printf \"Read @ %08X\\n\",wpaddr ; g }\n" + " Set a watchpoint on the CPU ':maincpu' that will halt execution whenever a read occurs " + "in the address range 3456-3475. When this happens, print Read @ <wpaddr> and continue " + "execution.\n" "\n" - "temp0 = 0; wp 45678,1,w,wpdata==f0,{temp0++; g}\n" - " Set a watchpoint that will halt execution whenever a write occurs to the address 45678 AND " - "the value being written is equal to f0. When that happens, increment the variable temp0 and " - "resume execution.\n" + "temp0 = 0 ; wp 45678,1,w,wpdata==f0,{ temp0++ ; g }\n" + " Set a watchpoint that will halt execution whenever a write occurs to the address 45678 " + "and the value being written is equal to f0. When that happens, increment the variable " + "temp0 and continue execution.\n" }, + { "wpdset", "#wpset" }, + { "wpiset", "#wpset" }, + { "wposet", "#wpset" }, { "wpclear", "\n" " wpclear [<wpnum>]\n" "\n" - "The wpclear command clears a watchpoint. If <wpnum> is specified, only the requested " - "watchpoint is cleared, otherwise all watchpoints are cleared.\n" + "The wpclear command clears a watchpoint. If <wpnum> is specified, only the requested " + "watchpoint is cleared; otherwise all watchpoints are cleared.\n" "\n" "Examples:\n" "\n" "wpclear 3\n" - " Clear watchpoint index 3.\n" + " Clear the watchpoint with index 3.\n" "\n" "wpclear\n" " Clear all watchpoints.\n" @@ -1177,14 +1258,14 @@ static const help_item static_help_list[] = "\n" " wpdisable [<wpnum>]\n" "\n" - "The wpdisable command disables a watchpoint. If <wpnum> is specified, only the requested " - "watchpoint is disabled, otherwise all watchpoints are disabled. Note that disabling a " + "The wpdisable command disables a watchpoint. If <wpnum> is specified, only the requested " + "watchpoint is disabled; otherwise all watchpoints are disabled. Note that disabling a " "watchpoint does not delete it, it just temporarily marks the watchpoint as inactive.\n" "\n" "Examples:\n" "\n" "wpdisable 3\n" - " Disable watchpoint index 3.\n" + " Disable the watchpoint with index 3.\n" "\n" "wpdisable\n" " Disable all watchpoints.\n" @@ -1194,13 +1275,13 @@ static const help_item static_help_list[] = "\n" " wpenable [<wpnum>]\n" "\n" - "The wpenable command enables a watchpoint. If <wpnum> is specified, only the requested " - "watchpoint is enabled, otherwise all watchpoints are enabled.\n" + "The wpenable command enables a watchpoint. If <wpnum> is specified, only the requested " + "watchpoint is enabled; otherwise all watchpoints are enabled.\n" "\n" "Examples:\n" "\n" "wpenable 3\n" - " Enable watchpoint index 3.\n" + " Enable the watchpoint with index 3.\n" "\n" "wpenable\n" " Enable all watchpoints.\n" @@ -1210,7 +1291,7 @@ static const help_item static_help_list[] = "\n" " wplist\n" "\n" - "The wplist command lists all the current watchpoints, along with their index and any " + "The wplist command lists all the current watchpoints, along with their indices and any " "conditions or actions attached to them.\n" }, { @@ -1300,31 +1381,49 @@ static const help_item static_help_list[] = { "map", "\n" - " map[{d|i}] <address>\n" + " map[{d|i|o}] <address>[:<space>]\n" "\n" - "The map/mapd/mapi commands map a logical address in memory to the correct physical address, as " - "well as specifying the bank. 'map' will map program space memory, while 'mapd' will map data space " - "memory and 'mapi' will map I/O space memory.\n" + "The map commands map a logical memory address to the corresponding physical address, as " + "well as specifying the bank. The address may optionally be followed by a colon and device " + "and/or address space. The device may be specified as a tag or a debugger CPU number; if " + "no device is specified, the CPU currently visible in the debugger is assumed. If an " + "address space is not specified, the command suffix sets the address space: 'map' defaults " + "to the first address space exposed by the device, 'mapd' defaults to the data space, " + "'mapi' defaults to the I/O space, and 'mapo' defaults to the opcodes space.\n" "\n" "Example:\n" "\n" "map 152d0\n" - " Gives physical address and bank for logical address 152d0 in program memory\n" + " Gives physical address and bank for logical address 152d0 in program memory for the " + "currently visible CPU.\n" + "\n" + "map 107:sms_vdp\n" + " Gives physical address and bank for logical address 107 in the first address space for " + "the device ':sms_vdp'.\n" }, + { "mapd", "#map" }, + { "mapi", "#map" }, + { "mapo", "#map" }, { "memdump", "\n" - " memdump [<filename>]\n" + " memdump [<filename>,[<device>]]\n" "\n" - "Dumps the current memory map to <filename>. If <filename> is omitted, then dumps to memdump.log" + "Dumps the current memory maps to the file specified by <filename>, or memdump.log if " + "omitted. If <device> is specified it must be the tag of a device, and only memory maps " + "for the part of the device tree rooted on this device will be dumped.\n" "\n" "Examples:\n" "\n" "memdump mylog.log\n" - " Dumps memory to mylog.log.\n" + " Dumps all memory maps to the file mylog.log.\n" "\n" "memdump\n" - " Dumps memory to memdump.log.\n" + " Dumps all memory maps to the file memdump.log.\n" + "\n" + "memdump audiomaps.log,audiopcb\n" + " Dumps memory maps for device ':audiopcb' and all its child devices to the file " + "audiomaps.log.\n" }, { "comlist", @@ -1355,6 +1454,7 @@ static const help_item static_help_list[] = " Adds the comment 'undocumented opcode!' to the code at address 0x10\n" "\n" }, + { "//", "#comadd" }, { "commit", "\n" @@ -1402,7 +1502,7 @@ static const help_item static_help_list[] = { "cheatinit", "\n" - " cheatinit [<sign><width><swap>,[<address>,<length>[,<CPU>]]]\n" + " cheatinit [<sign><width>[<swap>],[<address>,<length>[,<CPU>]]]\n" "\n" "The cheatinit command initializes the cheat search to the selected memory area.\n" "If no parameter is specified the cheat search is initialized to all changeable memory of the main CPU.\n" @@ -1439,29 +1539,29 @@ static const help_item static_help_list[] = "\n" " cheatnext <condition>[,<comparisonvalue>]\n" "\n" - "The cheatnext command will make comparisons with the last search matches.\n" + "The cheatnext command will make comparisons with the previous search matches.\n" "Possible <condition>:\n" " all\n" " no <comparisonvalue> needed.\n" - " use to update the last value without changing the current matches.\n" + " use to update the previous value without changing the current matches.\n" " equal [eq]\n" - " without <comparisonvalue> search for all bytes that are equal to the last search.\n" + " without <comparisonvalue> search for all bytes that are equal to the previous search.\n" " with <comparisonvalue> search for all bytes that are equal to the <comparisonvalue>.\n" " notequal [ne]\n" - " without <comparisonvalue> search for all bytes that are not equal to the last search.\n" + " without <comparisonvalue> search for all bytes that are not equal to the previous search.\n" " with <comparisonvalue> search for all bytes that are not equal to the <comparisonvalue>.\n" " decrease [de, +]\n" - " without <comparisonvalue> search for all bytes that have decreased since the last search.\n" - " with <comparisonvalue> search for all bytes that have decreased by the <comparisonvalue> since the last search.\n" + " without <comparisonvalue> search for all bytes that have decreased since the previous search.\n" + " with <comparisonvalue> search for all bytes that have decreased by the <comparisonvalue> since the previous search.\n" " increase [in, -]\n" - " without <comparisonvalue> search for all bytes that have increased since the last search.\n" - " with <comparisonvalue> search for all bytes that have increased by the <comparisonvalue> since the last search.\n" + " without <comparisonvalue> search for all bytes that have increased since the previous search.\n" + " with <comparisonvalue> search for all bytes that have increased by the <comparisonvalue> since the previous search.\n" " decreaseorequal [deeq]\n" " no <comparisonvalue> needed.\n" - " search for all bytes that have decreased or have same value since the last search.\n" + " search for all bytes that have decreased or have same value since the previous search.\n" " increaseorequal [ineq]\n" " no <comparisonvalue> needed.\n" - " search for all bytes that have decreased or have same value since the last search.\n" + " search for all bytes that have decreased or have same value since the previous search.\n" " smallerof [lt]\n" " without <comparisonvalue> this condition is invalid\n" " with <comparisonvalue> search for all bytes that are smaller than the <comparisonvalue>.\n" @@ -1470,15 +1570,15 @@ static const help_item static_help_list[] = " with <comparisonvalue> search for all bytes that are larger than the <comparisonvalue>.\n" " changedby [ch, ~]\n" " without <comparisonvalue> this condition is invalid\n" - " with <comparisonvalue> search for all bytes that have changed by the <comparisonvalue> since the last search.\n" + " with <comparisonvalue> search for all bytes that have changed by the <comparisonvalue> since the previous search.\n" "\n" "Examples:\n" "\n" "cheatnext increase\n" - " search for all bytes that have increased since the last search.\n" + " search for all bytes that have increased since the previous search.\n" "\n" "cheatnext decrease, 1\n" - " search for all bytes that have decreased by 1 since the last search.\n" + " search for all bytes that have decreased by 1 since the previous search.\n" }, { "cheatnextf", @@ -1489,7 +1589,7 @@ static const help_item static_help_list[] = "Possible <condition>:\n" " all\n" " no <comparisonvalue> needed.\n" - " use to update the last value without changing the current matches.\n" + " use to update the previous value without changing the current matches.\n" " equal [eq]\n" " without <comparisonvalue> search for all bytes that are equal to the initial search.\n" " with <comparisonvalue> search for all bytes that are equal to the <comparisonvalue>.\n" @@ -1596,41 +1696,88 @@ static const help_item static_help_list[] = /*************************************************************************** - CODE + HELP_MANAGER ***************************************************************************/ -const char *debug_get_help(const char *tag) +class help_manager { - static char ambig_message[1024]; - const help_item *found = nullptr; - int i, msglen, foundcount = 0; - size_t taglen = strlen(tag); +private: + using help_map = std::map<std::string_view, char const *>; + + help_map m_help_list; + help_item const *m_uncached_help = std::begin(f_static_help_list); + + help_manager() = default; + +public: + char const *find(std::string_view tag) + { + // find a cached exact match if possible + std::string const lower = strmakelower(tag); + auto const found = m_help_list.find(lower); + if (m_help_list.end() != found) + return found->second; + + // cache more entries while searching for an exact match + while (std::end(f_static_help_list) != m_uncached_help) + { + help_map::iterator ins; + if (*m_uncached_help->help == '#') + { + auto const xref = m_help_list.find(&m_uncached_help->help[1]); + assert(m_help_list.end() != xref); + ins = m_help_list.emplace(m_uncached_help->tag, xref->second).first; + } + else + { + ins = m_help_list.emplace(m_uncached_help->tag, m_uncached_help->help).first; + } + ++m_uncached_help; + if (lower == ins->first) + return ins->second; + } - /* find a match */ - for (i = 0; i < std::size(static_help_list); i++) - if (!core_strnicmp(static_help_list[i].tag, tag, taglen)) + // find a partial match + auto candidate = m_help_list.lower_bound(lower); + if ((m_help_list.end() != candidate) && (candidate->first.substr(0, lower.length()) == lower)) { - foundcount++; - found = &static_help_list[i]; - if (strlen(found->tag) == taglen) + // if only one partial match, take it + auto const next = std::next(candidate); + if ((m_help_list.end() == next) || (next->first.substr(0, lower.length()) != lower)) + return candidate->second; + + // TODO: pointers to static strings are bad, mmmkay? + static char ambig_message[1024]; + int msglen = std::sprintf(ambig_message, "Ambiguous help request, did you mean:\n"); + do { - foundcount = 1; - break; + msglen += std::sprintf(&ambig_message[msglen], " help %.*s?\n", int(candidate->first.length()), &candidate->first[0]); + ++candidate; } + while ((m_help_list.end() != candidate) && (candidate->first.substr(0, lower.length()) == lower)); + return ambig_message; } - /* only a single match makes sense */ - if (foundcount == 1) - return found->help; + // take the first help entry if no matches at all + return f_static_help_list[0].help; + } + + static help_manager &instance() + { + static help_manager s_instance; + return s_instance; + } +}; + +} // anonymous namespace + - /* if not found, return the first entry */ - if (foundcount == 0) - return static_help_list[0].help; - /* otherwise, indicate ambiguous help */ - msglen = sprintf(ambig_message, "Ambiguous help request, did you mean:\n"); - for (i = 0; i < std::size(static_help_list); i++) - if (!core_strnicmp(static_help_list[i].tag, tag, taglen)) - msglen += sprintf(&ambig_message[msglen], " help %s?\n", static_help_list[i].tag); - return ambig_message; +/*************************************************************************** + PUBLIC INTERFACE +***************************************************************************/ + +const char *debug_get_help(std::string_view tag) +{ + return help_manager::instance().find(tag); } |