From 08ee39da702645560d9924b6d6ab4ee865b9e478 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Tue, 19 Oct 2021 05:35:30 +1100 Subject: -debugger: Finished updating commands and documentation. * Updated cheat commands to work with arbitrary devices and address spaces. You can still only search RAM areas in a single address space at a time, but any address space of any device can be used now. * Made the cheatinit/cheatrange commands not affect current state if the arguments are invalid. Also fixed some bugs in the cheat commands. * Updated documentation for cheat commands, and added a simple worked example. Also added single-sentence descriptions of what (break|watch|register)points are to the top of the relevant pages. -frontend improvements: * Added a bit more info to the about box, moved the VCS revision to the heading. * Don't show "not" codes in prompts - they're not helpful. --- docs/source/debugger/breakpoint.rst | 3 + docs/source/debugger/cheats.rst | 486 +++++++++++++++++--------------- docs/source/debugger/general.rst | 5 +- docs/source/debugger/registerpoints.rst | 4 + docs/source/debugger/watchpoint.rst | 4 + src/emu/debug/debugcmd.cpp | 244 ++++++++-------- src/emu/debug/debugcmd.h | 14 +- src/emu/debug/debughlp.cpp | 203 +++++++------ src/frontend/mame/ui/about.cpp | 31 +- src/frontend/mame/ui/about.h | 4 +- src/frontend/mame/ui/ui.cpp | 17 +- 11 files changed, 560 insertions(+), 455 deletions(-) diff --git a/docs/source/debugger/breakpoint.rst b/docs/source/debugger/breakpoint.rst index 5dbf6c4effe..f30605b2daa 100644 --- a/docs/source/debugger/breakpoint.rst +++ b/docs/source/debugger/breakpoint.rst @@ -14,6 +14,9 @@ Breakpoint Debugger Commands :ref:`debugger-command-bplist` lists breakpoints +Breakpoints halt execution and activate the debugger before a CPU +executes an instruction at a particular address. + .. _debugger-command-bpset: diff --git a/docs/source/debugger/cheats.rst b/docs/source/debugger/cheats.rst index 1b6764c8e79..24e1e1d0440 100644 --- a/docs/source/debugger/cheats.rst +++ b/docs/source/debugger/cheats.rst @@ -3,144 +3,192 @@ Cheat Debugger Commands ======================= +:ref:`debugger-command-cheatinit` + initialize the cheat search to the selected memory area +:ref:`debugger-command-cheatrange` + add selected memory area to cheat search +:ref:`debugger-command-cheatnext` + filter cheat candidates by comparing to previous values +:ref:`debugger-command-cheatnextf` + filter cheat candidates by comparing to initial value +:ref:`debugger-command-cheatlist` + show the list of cheat search matches or save them to a file +:ref:`debugger-command-cheatundo` + undo the last cheat search (state only) -You can also type **help ** for further details on each command in the MAME Debugger interface. +The debugger includes basic cheat search functionality, which works +by saving the contents of memory, and then filtering locations according +to how the values change. -| :ref:`debugger-command-cheatinit` -- initialize the cheat search to the selected memory area -| :ref:`debugger-command-cheatrange` -- add to the cheat search the selected memory area -| :ref:`debugger-command-cheatnext` -- continue cheat search comparing with the last value -| :ref:`debugger-command-cheatnextf` -- continue cheat search comparing with the first value -| :ref:`debugger-command-cheatlist` -- show the list of cheat search matches or save them to -| :ref:`debugger-command-cheatundo` -- undo the last cheat search (state only) +We’ll demonstrate use of the cheat search functionality to make an +infinite lives cheat for Raiden (``raiden``): - .. _debugger-command-cheatinit: +* Start the game with the debugger active. Allow the game to run, + insert a coin, and start a game, then break into the debugger. +* Ensure the main CPU is visible, and start a search for 8-bit unsigned + values using the + :ref:`cheatinit command `:: + + >cheatinit ub + MAME debugger version 0.236 (mame0236-190-gf7a8ad4fc7d-dirty) + 36928 cheat locations initialized for NEC V30 ':maincpu' program space +* Allow the game to run, lose a life and break into the debugger. +* Use the :ref:`cheatnext command ` to + filter locations that have decreased by 1:: + + >cheatnext -,1 + 12 cheats found +* Allow the game to run, lose another life, break into the + debugger, and filter locations that have decreased by 1 again:: + + >cheatnext -,1 + Address=0B85 Start=03 Current=01 + 1 cheat found +* Use the :ref:`cheatlist command ` to save + the cheat candidate to a file:: + + >cheatlist raiden-p1-lives.xml +* The file now contains an XML fragment with cheat to set the candidate + location to the initial value: + + .. code-block:: XML + + + + + + +.. _debugger-command-cheatinit: cheatinit --------- -| **cheatinit [,[
,[,]]]** -| -| The cheatinit command initializes the cheat search to the selected memory area. -| -| If no parameter is specified the cheat search is initialized to all changeable memory of the main CPU. -| -| can be s(signed) or u(unsigned) -| can be b(8 bit), w(16 bit), d(32 bit) or q(64 bit) -| append s for swapped search -| -| Examples: -| -| cheatinit ub,0x1000,0x10 -| -| Initialize the cheat search from 0x1000 to 0x1010 of the first CPU. -| -| cheatinit sw,0x2000,0x1000,1 -| -| Initialize the cheat search with width of 2 byte in signed mode from 0x2000 to 0x3000 of the second CPU. -| -| cheatinit uds,0x0000,0x1000 -| -| Initialize the cheat search with width of 4 byte swapped from 0x0000 to 0x1000. -| -| Back to :ref:`debugger-cheats-list` - - - .. _debugger-command-cheatrange: +**cheatinit [[[[]]],[
,[,]]]** + +Initialize the cheat search to writable RAM areas in the specified +address space. May be abbreviated to ``ci``. + +The first argument specifies the data format to search for. The +**** may be **u** for unsigned or **s** for signed, the +**** may be **b** for 8-bit (byte), **w** for 16-bit (word), +**d** for 32-bit (double word), or **q** for 64-bit (quadruple word); +**** may be **s** for reversed byte order. If the first argument +is omitted or empty, the data format from the previous cheat search is +used, or unsigned 8-bit format if this is the first cheat search. + +The **
** specifies the address to start searching from, and the +**** specifies how much memory to search. If specified, +writable RAM in the range **
** through +**
+-1**, inclusive, will be searched; otherwise, all +writable RAM in the address space will be searched. + +See :ref:`debugger-devicespec` for details on specifying address spaces. +If the address space is not specified, it defaults to the first address +space exposed by the visible CPU. + +Examples: + +``cheatinit ub,0x1000,0x10`` + Initialize the cheat search for unsigned 8-bit values in addresses + 0x1000-0x100f in the program space of the visible CPU. +``cheatinit sw,0x2000,0x1000,1`` + Initialize the cheat search for signed 16-bit values in addresses + 0x2000-0x2fff in the program space of the second CPU in the system + (zero-based index). +``cheatinit uds,0x0000,0x1000`` + Initialize the cheat search for unsigned 64-bit values with reverse + byte order in addresses 0x0000-0x0fff in the program space of the + visible CPU. + +Back to :ref:`debugger-cheats-list` + + +.. _debugger-command-cheatrange: cheatrange ---------- -| **cheatrange
,** -| -| The cheatrange command adds the selected memory area to the cheat search. -| -| Before using cheatrange it is necessary to initialize the cheat search with cheatinit. -| -| Examples: -| -| cheatrange 0x1000,0x10 -| -| Add the bytes from 0x1000 to 0x1010 to the cheat search. -| -| Back to :ref:`debugger-cheats-list` +**cheatrange
,** + +Add writable RAM areas to the cheat search. May be abbreviated to +``cr``. Before using this command, the +:ref:`cheatinit command ` must be used to +initialize the cheat search and set the address space and data format. +The **
** specifies the address to start searching from, and the +**** specifies how much memory to search. Writable RAM in the +range **
** through **
+-1**, inclusive, will be +added to the areas to search. - .. _debugger-command-cheatnext: +Examples: + +``cheatrange 0x1000,0x10`` + Add addresses 0x1000-0x100f to the areas to search for cheats. + +Back to :ref:`debugger-cheats-list` + + +.. _debugger-command-cheatnext: cheatnext --------- -| **cheatnext [,]** -| -| The cheatnext command will make comparisons with the last search matches. -| -| Possible : -| -| **all** -| -| No needed. -| -| Use to update the last value without changing the current matches. -| -| **equal [eq]** -| -| Without search for all bytes that are equal to the last search. -| With search for all bytes that are equal to the . -| -| **notequal [ne]** -| -| Without search for all bytes that are not equal to the last search. -| With search for all bytes that are not equal to the . -| -| **decrease [de, +]** -| -| Without search for all bytes that have decreased since the last search. -| With search for all bytes that have decreased by the since the last search. -| -| **increase [in, -]** -| -| Without search for all bytes that have increased since the last search. -| With search for all bytes that have increased by the since the last search. -| -| **decreaseorequal [deeq]** -| -| No needed. -| -| Search for all bytes that have decreased or have same value since the last search. -| -| **increaseorequal [ineq]** -| -| No needed. -| -| Search for all bytes that have decreased or have same value since the last search. -| -| **smallerof [lt]** -| -| Without this condition is invalid -| With search for all bytes that are smaller than the . -| -| **greaterof [gt]** -| -| Without this condition is invalid -| With search for all bytes that are larger than the . -| -| **changedby [ch, ~]** -| -| Without this condition is invalid -| With search for all bytes that have changed by the since the last search. -| -| -| Examples: -| -| cheatnext increase -| -| Search for all bytes that have increased since the last search. -| -| cheatnext decrease, 1 -| -| Search for all bytes that have decreased by 1 since the last search. -| -| Back to :ref:`debugger-cheats-list` +**cheatnext [,]** + +Filter candidates by comparing to the previous search values. If five +or fewer candidates remain, they will be shown in the debugger console. +May be abbreviated to ``cn``. + +Possible **** arguments: + +``all`` + Use to update the last value without changing the current matches + (the **** is not used). +``equal`` (``eq``) + Without ****, search for values that are equal to + the previous search; with ****, search for values + that are equal to the ****. +``notequal`` (``ne``) + Without ****, search for values that are not equal + to the previous search; with ****, search for + values that are not equal to the ****. +``decrease`` (``de``, ``-``) + Without ****, search for values that have decreased + since the previous search; with ****, search for + values that have decreased by the **** since the + previous search. +``increase`` (``in``, ``+``) + Without ****, search for values that have increased + since the previous search; with ****, search for + values that have increased by the **** since the + previous search. +``decreaseorequal`` (``deeq``) + Search for values that have decreased or are unchanged since the + previous search (the **** is not used). +``increaseorequal`` (``ineq``) + Search for values that have increased or are unchanged since the + previous search (the **** is not used). +``smallerof`` (``lt``, ``<``) + Search for values that are less than the **** (the + **** is required). +``greaterof`` (``gt``, ``>``) + Search for values that are greater than the **** + (the **** is required). +``changedby`` (``ch``, ``~``) + Search for values that have changed by the **** + since the previous search (the **** is required). + +Examples: + +``cheatnext increase`` + Search for all values that have increased since the previous search. +``cheatnext decrease,1`` + Search for all values that have decreased by 1 since the previous + search. + +Back to :ref:`debugger-cheats-list` .. _debugger-command-cheatnextf: @@ -148,120 +196,100 @@ cheatnext cheatnextf ---------- -| **cheatnextf [,]** -| -| The cheatnextf command will make comparisons with the initial search. -| -| Possible : -| -| **all** -| -| No needed. -| -| Use to update the last value without changing the current matches. -| -| **equal [eq]** -| -| Without search for all bytes that are equal to the initial search. -| With search for all bytes that are equal to the . -| -| **notequal [ne]** -| -| Without search for all bytes that are not equal to the initial search. -| With search for all bytes that are not equal to the . -| -| **decrease [de, +]** -| -| Without search for all bytes that have decreased since the initial search. -| With search for all bytes that have decreased by the since the initial search. -| -| **increase [in, -]** -| -| Without search for all bytes that have increased since the initial search. -| -| With search for all bytes that have increased by the since the initial search. -| -| **decreaseorequal [deeq]** -| -| No needed. -| -| Search for all bytes that have decreased or have same value since the initial search. -| -| **increaseorequal [ineq]** -| -| No needed. -| -| Search for all bytes that have decreased or have same value since the initial search. -| -| **smallerof [lt]** -| -| Without this condition is invalid. -| With search for all bytes that are smaller than the . -| -| **greaterof [gt]** -| -| Without this condition is invalid. -| With search for all bytes that are larger than the . -| -| **changedby [ch, ~]** -| -| Without this condition is invalid -| With search for all bytes that have changed by the since the initial search. -| -| -| Examples: -| -| cheatnextf increase -| -| Search for all bytes that have increased since the initial search. -| -| cheatnextf decrease, 1 -| -| Search for all bytes that have decreased by 1 since the initial search. -| -| Back to :ref:`debugger-cheats-list` - - - .. _debugger-command-cheatlist: +**cheatnextf [,]** + +Filter candidates by comparing to the initial search values. If five or +fewer candidates remain, they will be shown in the debugger console. +May be abbreviated to ``cn``. + +Possible **** arguments: + +``all`` + Use to update the last value without changing the current matches + (the **** is not used). +``equal`` (``eq``) + Without ****, search for values that are equal to + the initial search; with ****, search for values + that are equal to the ****. +``notequal`` (``ne``) + Without ****, search for values that are not equal + to the initial search; with ****, search for values + that are not equal to the ****. +``decrease`` (``de``, ``-``) + Without ****, search for values that have decreased + since the initial search; with ****, search for + values that have decreased by the **** since the + initial search. +``increase`` (``in``, ``+``) + Without ****, search for values that have increased + since the initial search; with ****, search for + values that have increased by the **** since the + initial search. +``decreaseorequal`` (``deeq``) + Search for values that have decreased or are unchanged since the + initial search (the **** is not used). +``increaseorequal`` (``ineq``) + Search for values that have increased or are unchanged since the + initial search (the **** is not used). +``smallerof`` (``lt``, ``<``) + Search for values that are less than the **** (the + **** is required). +``greaterof`` (``gt``, ``>``) + Search for values that are greater than the **** + (the **** is required). +``changedby`` (``ch``, ``~``) + Search for values that have changed by the **** + since the initial search (the **** is required). + +Examples: + +``cheatnextf increase`` + Search for all values that have increased since the initial search. +``cheatnextf decrease,1`` + Search for all values that have decreased by 1 since the initial + search. + +Back to :ref:`debugger-cheats-list` + + +.. _debugger-command-cheatlist: cheatlist --------- -| **cheatlist []** -| -| Without show the list of matches in the debug console. -| With save the list of matches in basic XML format to . -| -| Examples: -| -| cheatlist -| -| Show the current matches in the debug console. -| -| cheatlist cheat.txt -| -| Save the current matches in XML format to cheat.txt. -| -| Back to :ref:`debugger-cheats-list` - - - .. _debugger-command-cheatundo: +**cheatlist []** + +Without ****, show the current cheat matches in the debugger +console; with ****, save the current cheat matches in basic +XML format to the specified file. May be abbreviated to ``cl``. + +Examples: + +``cheatlist`` + Show the current matches in the console. +``cheatlist cheat.xml`` + Save the current matches to the file **cheat.xml** in XML format. + +Back to :ref:`debugger-cheats-list` + + +.. _debugger-command-cheatundo: cheatundo --------- -| **cheatundo** -| -| Undo the results of the last search. -| -| The undo command has no effect on the last value. -| -| -| Examples: -| -| cheatundo -| -| Undo the last search (state only). -| -| Back to :ref:`debugger-cheats-list` +**cheatundo** + +Undo filtering of cheat candidates by the most recent +:ref:`cheatnext ` or +:ref:`cheatnextf ` command. Note that the +previous values *are not* rolled back. May be abbreviated to ``cu``. + +Examples: + +``cheatundo`` + Restore cheat candidates filtered out by the most recent + :ref:`cheatnext ` or + :ref:`cheatnextf ` command. +Back to :ref:`debugger-cheats-list` diff --git a/docs/source/debugger/general.rst b/docs/source/debugger/general.rst index 4edc1b413fb..ffeb1379f3f 100644 --- a/docs/source/debugger/general.rst +++ b/docs/source/debugger/general.rst @@ -415,6 +415,8 @@ Loads the most recent RAM-based saved state. When enabled, rewind states are saved when :ref:`debugger-command-step`, :ref:`debugger-command-over` and :ref:`debugger-command-out` commands are used, storing the machine state as of the moment before stepping. +May be abbreviated to ``rw``. + Consecutively loading rewind states can work like reverse execution. Depending on which steps forward were taken previously, the behavior can be similar to GDB's **reverse-stepi** and **reverse-next** commands. @@ -445,7 +447,7 @@ Creates a save state at the current moment in emulated time. The state file is written to the configured save state directory (see the :ref:`state_directory ` option), and the **.sta** extension is automatically appended to the specified file -name. +name. May be abbreviates to ``ss``. All output from this command is currently echoed into the running machine window. @@ -473,6 +475,7 @@ Restores a saved state file from disk. The specified state file is read from the configured save state directory (see the :ref:`state_directory ` option), and the **.sta** extension is automatically appended to the specified file name. +May be abbreviated to ``sl``. All output for this command is currently echoed into the running machine window. Previous memory and PC tracking statistics are cleared. diff --git a/docs/source/debugger/registerpoints.rst b/docs/source/debugger/registerpoints.rst index e228208e600..aea14edd1ac 100644 --- a/docs/source/debugger/registerpoints.rst +++ b/docs/source/debugger/registerpoints.rst @@ -14,6 +14,10 @@ Registerpoint Debugger Commands :ref:`debugger-command-rplist` lists registerpoints +Registerpoints evaluate an expression each time a CPU executes an +instruction and halt execution and activate the debugger if the result +is true (non-zero). + .. _debugger-command-rpset: diff --git a/docs/source/debugger/watchpoint.rst b/docs/source/debugger/watchpoint.rst index c34006f8a5f..2b25e0631f8 100644 --- a/docs/source/debugger/watchpoint.rst +++ b/docs/source/debugger/watchpoint.rst @@ -14,6 +14,10 @@ Watchpoint Debugger Commands :ref:`debugger-command-wplist` lists watchpoints +Watchpoints halt execution and activate the debugger when a CPU accesses +a location in a particular memory range. + + .. _debugger-command-wpset: wpset diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index bcebb63cf92..04cce880600 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -378,7 +378,7 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu if (name[0] != 0) m_console.source_script(name); - m_cheat.cpu[0] = m_cheat.cpu[1] = 0; + m_cheat.space = nullptr; } @@ -2859,82 +2859,84 @@ void debugger_commands::execute_strdump(int spacenum, const std::vector ¶ms) { - cheat_region_map cheat_region[100]; - memset(cheat_region, 0, sizeof(cheat_region)); - - // validate parameters - address_space *space; - if (!validate_device_space_parameter((params.size() > 3) ? params[3] : std::string_view(), -1, space)) + address_space *space = m_cheat.space; + if (!space && !init) + { + m_console.printf("Use cheatinit before cheatrange\n"); return; + } + u8 width = (space || !init) ? m_cheat.width : 1; + bool signed_cheat = (space || !init) ? m_cheat.signed_cheat : false; + bool swapped_cheat = (space || !init) ? m_cheat.swapped_cheat : false; if (init) { - m_cheat.width = 1; - m_cheat.signed_cheat = false; - m_cheat.swapped_cheat = false; + // first argument is sign/size/swap flags if (!params.empty()) { - char const *srtpnt = params[0].c_str(); + std::string const &srtpnt = params[0]; + if (!srtpnt.empty()) + { + width = 1; + signed_cheat = false; + swapped_cheat = false; + } - char sspec = std::tolower((unsigned char)*srtpnt); - if (sspec == 's') - m_cheat.signed_cheat = true; - else if (sspec == 'u') - m_cheat.signed_cheat = false; - else + if (srtpnt.length() >= 1) { - m_console.printf("Invalid sign: expected s or u\n"); - return; + char const sspec = std::tolower((unsigned char)srtpnt[0]); + if (sspec == 's') + signed_cheat = true; + else if (sspec == 'u') + signed_cheat = false; + else + { + m_console.printf("Invalid sign: expected s or u\n"); + return; + } } - char wspec = std::tolower((unsigned char)*(++srtpnt)); - if (wspec == 'b') - m_cheat.width = 1; - else if (wspec == 'w') - m_cheat.width = 2; - else if (wspec == 'd') - m_cheat.width = 4; - else if (wspec == 'q') - m_cheat.width = 8; - else + if (srtpnt.length() >= 2) { - m_console.printf("Invalid width: expected b, w, d or q\n"); - return; + char const wspec = std::tolower((unsigned char)srtpnt[1]); + if (wspec == 'b') + width = 1; + else if (wspec == 'w') + width = 2; + else if (wspec == 'd') + width = 4; + else if (wspec == 'q') + width = 8; + else + { + m_console.printf("Invalid width: expected b, w, d or q\n"); + return; + } } - if (std::tolower((unsigned char)*(++srtpnt)) == 's') - m_cheat.swapped_cheat = true; - else - m_cheat.swapped_cheat = false; + if (srtpnt.length() >= 3) + { + if (std::tolower((unsigned char)srtpnt[2]) == 's') + swapped_cheat = true; + else + { + m_console.printf("Invalid swap: expected s\n"); + return; + } + } } - } - // initialize entire memory by default - u64 length = 0; - u8 region_count = 0; - if (params.size() <= 1) - { - for (address_map_entry &entry : space->map()->m_entrylist) - { - cheat_region[region_count].offset = entry.m_addrstart & space->addrmask(); - cheat_region[region_count].endoffset = entry.m_addrend & space->addrmask(); - cheat_region[region_count].share = entry.m_share; - cheat_region[region_count].disabled = (entry.m_write.m_type == AMH_RAM) ? false : true; - - // disable double share regions - if (entry.m_share != nullptr) - for (u8 i = 0; i < region_count; i++) - if (cheat_region[i].share != nullptr) - if (strcmp(cheat_region[i].share, entry.m_share) == 0) - cheat_region[region_count].disabled = true; - - region_count++; - } + // fourth argument is device/space + if (!validate_device_space_parameter((params.size() > 3) ? params[3] : std::string_view(), -1, space)) + return; } - else + + cheat_region_map cheat_region[100]; // FIXME: magic number + unsigned region_count = 0; + if (params.size() >= (init ? 3 : 2)) { // validate parameters - u64 offset; + u64 offset, length; if (!validate_number_parameter(params[init ? 1 : 0], offset)) return; if (!validate_number_parameter(params[init ? 2 : 1], length)) @@ -2947,61 +2949,76 @@ void debugger_commands::execute_cheatrange(bool init, const std::vectormap()->m_entrylist) + { + cheat_region[region_count].offset = entry.m_addrstart & space->addrmask(); + cheat_region[region_count].endoffset = entry.m_addrend & space->addrmask(); + cheat_region[region_count].share = entry.m_share; + cheat_region[region_count].disabled = entry.m_write.m_type != AMH_RAM; + + // disable duplicate share regions + if (entry.m_share) + for (unsigned i = 0; i < region_count; i++) + if (cheat_region[i].share && !strcmp(cheat_region[i].share, entry.m_share)) + cheat_region[region_count].disabled = true; + + if (!cheat_region[region_count].disabled) + region_count++; + } + } // determine the writable extent of each region in total u64 real_length = 0; - for (u8 i = 0; i < region_count; i++) - if (!cheat_region[i].disabled) - for (u64 curaddr = cheat_region[i].offset; curaddr <= cheat_region[i].endoffset; curaddr += m_cheat.width) - if (cheat_address_is_valid(*space, curaddr)) - real_length++; + for (unsigned i = 0; i < region_count; i++) + for (u64 curaddr = cheat_region[i].offset; curaddr <= cheat_region[i].endoffset; curaddr += width) + if (cheat_address_is_valid(*space, curaddr)) + real_length++; - if (real_length == 0) + if (!real_length) { m_console.printf("No writable bytes found in this area\n"); return; } - u32 active_cheat = 0; + size_t active_cheat = 0; if (init) { // initialize new cheat system - m_cheat.cheatmap.resize(real_length); + m_cheat.space = space; + m_cheat.width = width; m_cheat.undo = 0; - m_cheat.cpu[0] = params.size() > 3 ? params[3][0] : '0'; + m_cheat.signed_cheat = signed_cheat; + m_cheat.swapped_cheat = swapped_cheat; } else { - // add range to cheat system - if (m_cheat.cpu[0] == 0) - { - m_console.printf("Use cheatinit before cheatrange\n"); - return; - } - - if (!validate_device_space_parameter(m_cheat.cpu, -1, space)) - return; - active_cheat = m_cheat.cheatmap.size(); - m_cheat.cheatmap.resize(m_cheat.cheatmap.size() + real_length); } + m_cheat.cheatmap.resize(active_cheat + real_length); // initialize cheatmap in the selected space - for (u8 i = 0; i < region_count; i++) - if (!cheat_region[i].disabled) - for (u64 curaddr = cheat_region[i].offset; curaddr <= cheat_region[i].endoffset; curaddr += m_cheat.width) - if (cheat_address_is_valid(*space, curaddr)) - { - m_cheat.cheatmap[active_cheat].previous_value = cheat_read_extended(&m_cheat, *space, curaddr); - m_cheat.cheatmap[active_cheat].first_value = m_cheat.cheatmap[active_cheat].previous_value; - m_cheat.cheatmap[active_cheat].offset = curaddr; - m_cheat.cheatmap[active_cheat].state = 1; - m_cheat.cheatmap[active_cheat].undo = 0; - active_cheat++; - } + for (unsigned i = 0; i < region_count; i++) + for (u64 curaddr = cheat_region[i].offset; curaddr <= cheat_region[i].endoffset; curaddr += width) + if (cheat_address_is_valid(*space, curaddr)) + { + m_cheat.cheatmap[active_cheat].previous_value = cheat_read_extended(&m_cheat, *space, curaddr); + m_cheat.cheatmap[active_cheat].first_value = m_cheat.cheatmap[active_cheat].previous_value; + m_cheat.cheatmap[active_cheat].offset = curaddr; + m_cheat.cheatmap[active_cheat].state = 1; + m_cheat.cheatmap[active_cheat].undo = 0; + active_cheat++; + } - // give a detailed init message to avoid searches being mistakingly carried out on the wrong CPU - m_console.printf("%u cheat initialized for CPU index %s ( aka %s )\n", active_cheat, m_cheat.cpu, space->device().tag()); + // give a detailed init message to avoid searches being mistakenly carried out on the wrong CPU + m_console.printf( + "%u cheat locations initialized for %s '%s' %s space\n", + active_cheat, + space->device().type().fullname(), + space->device().tag(), + space->name()); } @@ -3029,16 +3046,13 @@ void debugger_commands::execute_cheatnext(bool initial, const std::vector 1 && !validate_number_parameter(params[1], comp_value)) return; @@ -3186,30 +3200,36 @@ void debugger_commands::execute_cheatnext(bool initial, const std::vector ¶ms) { - if (m_cheat.cpu[0] == 0) + address_space *const space = m_cheat.space; + if (!space) { m_console.printf("Use cheatinit before cheatlist\n"); return; } - address_space *space; - if (!validate_device_space_parameter(m_cheat.cpu, -1, space)) - return; - - device_t &cpu = space->device(); - FILE *f = nullptr; if (params.size() > 0) + { f = fopen(params[0].c_str(), "w"); + if (!f) + { + m_console.printf("Error opening file '%s'\n", params[0]); + return; + } + } + std::string tag(space->device().tag()); char spaceletter; switch (space->spacenum()) { - default: case AS_PROGRAM: spaceletter = 'p'; break; case AS_DATA: spaceletter = 'd'; break; case AS_IO: spaceletter = 'i'; break; - case AS_OPCODES: spaceletter = 'o'; break; + case AS_OPCODES: spaceletter = '3'; break; + default: + tag.append(1, ':'); + tag.append(space->name()); + spaceletter = 'p'; } char sizeletter; @@ -3240,13 +3260,13 @@ void debugger_commands::execute_cheatlist(const std::vector ¶ms output.rdbuf()->clear(); stream_format( output, - " \n" + " \n" " \n" " \n\n", active_cheat, space->logaddrchars(), address, m_cheat.width * 2, value, - cpu.tag(), spaceletter, sizeletter, space->logaddrchars(), address, m_cheat.width * 2, cheat_byte_swap(&m_cheat, m_cheat.cheatmap[cheatindex].first_value) & sizemask); + tag, spaceletter, sizeletter, space->logaddrchars(), address, m_cheat.width * 2, cheat_byte_swap(&m_cheat, m_cheat.cheatmap[cheatindex].first_value) & sizemask); auto const &text(output.vec()); fprintf(f, "%.*s", int(unsigned(text.size())), &text[0]); } @@ -3273,7 +3293,7 @@ void debugger_commands::execute_cheatundo(const std::vector ¶ms { if (m_cheat.undo > 0) { - u32 undo_count = 0; + u64 undo_count = 0; for (u64 cheatindex = 0; cheatindex < m_cheat.cheatmap.size(); cheatindex += 1) { if (m_cheat.cheatmap[cheatindex].undo == m_cheat.undo) @@ -3288,7 +3308,9 @@ void debugger_commands::execute_cheatundo(const std::vector ¶ms m_console.printf("%u cheat reactivated\n", undo_count); } else + { m_console.printf("Maximum undo reached\n"); + } } @@ -4013,7 +4035,7 @@ void debugger_commands::execute_memdump(const std::vector ¶ms) sp.dump_maps(entries[0], entries[1]); for (int mode = 0; mode < 2; mode ++) { - fprintf(file, " device %s space %s %s:\n", memory.device().tag(), sp.name(), mode ? "write" : "read"); + fprintf(file, " %s '%s' space %s %s:\n", memory.device().type().fullname(), memory.device().tag(), sp.name(), mode ? "write" : "read"); for (memory_entry &entry : entries[mode]) { if (octal) diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h index 0f85e80e705..6c82ca143c1 100644 --- a/src/emu/debug/debugcmd.h +++ b/src/emu/debug/debugcmd.h @@ -67,20 +67,20 @@ private: // TODO [RH 31 May 2016]: Move this cheat stuff into its own class struct cheat_system { - char cpu[2]; + address_space *space; u8 width; - std::vector cheatmap; - u8 undo; u8 signed_cheat; u8 swapped_cheat; + std::vector cheatmap; + u8 undo; }; struct cheat_region_map { - u64 offset; - u64 endoffset; - const char *share; - u8 disabled; + u64 offset = 0U; + u64 endoffset = 0U; + const char *share = nullptr; + u8 disabled = 0U; }; device_t &get_device_search_base(std::string_view ¶m); diff --git a/src/emu/debug/debughlp.cpp b/src/emu/debug/debughlp.cpp index c62b7299ea7..87bf8f0f18f 100644 --- a/src/emu/debug/debughlp.cpp +++ b/src/emu/debug/debughlp.cpp @@ -246,8 +246,8 @@ const help_item f_static_help_list[] = "Cheat Commands\n" "Type help for further details on each command\n" "\n" - " cheatinit [[],[
,[,]]] -- initialize the cheat search to the selected memory area\n" - " cheatrange
, -- add to the cheat search the selected memory area\n" + " cheatinit [[[[]]],[
,[,]]] -- initialize the cheat search to the selected memory area\n" + " cheatrange
, -- add selected memory area to the cheat search\n" " cheatnext [,] -- continue cheat search comparing with the previous value\n" " cheatnextf [,] -- continue cheat search comparing with the first value\n" " cheatlist [] -- show the list of cheat search matches or save them to \n" @@ -1611,157 +1611,184 @@ const help_item f_static_help_list[] = { "cheatinit", "\n" - " cheatinit [[],[
,[,]]]\n" + " cheatinit [[[[]]],[
,[,]]]\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" - " can be s(signed) or u(unsigned)\n" - " can be b(8 bit), w(16 bit), d(32 bit) or q(64 bit)\n" - " append s for swapped search\n" + "The cheatinit command initializes the cheat search to writable RAM areas in the specified " + "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 first address space exposed by the device is used.\n" + "\n" + "The first argument specifies the data format to search for:\n" + " : 's' (signed), 'u' (unsigned)\n" + " : 'b' (8-bit), 'w' (16-bit), 'd' (32-bit), 'q' (64-bit)\n" + " : 's' (reverse byte order)\n" + "If the first argument is omitted or empty, the format from the previous cheat search is " + "used, or unsigned 8-bit for the first cheat search.\n" + "\n" + "The
specifies the address to start searching from, and the specifies " + "how much memory to search. If specified, writable RAM in the range
through " + "
+-1, inclusive, will be searched; otherwise, all writable RAM in the " + "address space will be searched.\n" "\n" "Examples:\n" "\n" "cheatinit ub,0x1000,0x10\n" - " Initialize the cheat search from 0x1000 to 0x1010 of the first CPU.\n" + " Initialize the cheat search for unsigned 8-bit values in addresses 0x1000-0x100f in the " + "program space of the visible CPU.\n" "\n" "cheatinit sw,0x2000,0x1000,1\n" - " Initialize the cheat search with width of 2 byte in signed mode from 0x2000 to 0x3000 of the second CPU.\n" + " Initialize the cheat search for signed 16-bit values in addresses 0x2000-0x3000 in the " + "program space of CPU #1.\n" "\n" "cheatinit uds,0x0000,0x1000\n" - " Initialize the cheat search with width of 4 byte swapped from 0x0000 to 0x1000.\n" + " Initialize the cheat search for unsigned 32-bit values with reverse byte order in " + "addresses 0x0000-0x0fff of the program space of the visible CPU.\n" }, { "cheatrange", "\n" " cheatrange
,\n" "\n" - "The cheatrange command adds the selected memory area to the cheat search.\n" - "Before using cheatrange it is necessary to initialize the cheat search with cheatinit.\n" + "The cheatrange command adds writable RAM areas in the range
through " + "through
+-1, inclusive, to the cheat search. Before using cheatrange, " + "the cheatinit command must be used to initialize the cheat search.\n" "\n" "Examples:\n" "\n" "cheatrange 0x1000,0x10\n" - " Add the bytes from 0x1000 to 0x1010 to the cheat search.\n" + " Add addresses 0x1000-0x100f to the cheat search.\n" }, { "cheatnext", "\n" " cheatnext [,]\n" "\n" - "The cheatnext command will make comparisons with the previous search matches.\n" + "The cheatnext command makes comparisons with the previous search matches.\n" "Possible :\n" " all\n" - " no needed.\n" - " use to update the previous value without changing the current matches.\n" - " equal [eq]\n" - " without search for all bytes that are equal to the previous search.\n" - " with search for all bytes that are equal to the .\n" - " notequal [ne]\n" - " without search for all bytes that are not equal to the previous search.\n" - " with search for all bytes that are not equal to the .\n" - " decrease [de, +]\n" - " without search for all bytes that have decreased since the previous search.\n" - " with search for all bytes that have decreased by the since the previous search.\n" - " increase [in, -]\n" - " without search for all bytes that have increased since the previous search.\n" - " with search for all bytes that have increased by the since the previous search.\n" - " decreaseorequal [deeq]\n" - " no needed.\n" - " search for all bytes that have decreased or have same value since the previous search.\n" - " increaseorequal [ineq]\n" - " no needed.\n" - " search for all bytes that have decreased or have same value since the previous search.\n" - " smallerof [lt]\n" - " without this condition is invalid\n" - " with search for all bytes that are smaller than the .\n" - " greaterof [gt]\n" - " without this condition is invalid\n" - " with search for all bytes that are larger than the .\n" - " changedby [ch, ~]\n" - " without this condition is invalid\n" - " with search for all bytes that have changed by the since the previous search.\n" + " Use to update the last value without changing the current matches.\n" + " The is not used.\n" + " equal (eq)\n" + " Without **, search for values that are equal to the previous " + "search.\n" + " With , search for values that are equal to the .\n" + " notequal (ne)\n" + " Without , search for values that are not equal to the previous " + "search.\n" + " With , search for values that are not equal to the .\n" + " decrease (de, -)\n" + " Without , search for values that have decreased since the previous " + "search.\n" + " With , search for values that have decreased by the " + "since the previous search.\n" + " increase (in, +)\n" + " Without , search for values that have increased since the previous " + "search.\n" + " With , search for values that have increased by the " + "since the previous search.\n" + " decreaseorequal (deeq)\n" + " Search for values that have decreased or are unchanged since the previous search.\n" + " The is not used.\n" + " increaseorequal (ineq)\n" + " Search for values that have increased or are unchanged since the previous search.\n" + " The is not used.\n" + " smallerof (lt, <)\n" + " Search for values that are less than the .\n" + " The is required.\n" + " greaterof (gt, >)\n" + " Search for values that are greater than the .\n" + " The is required.\n" + " changedby (ch, ~)\n" + " Search for values that have changed by the since the previous " + "search.\n" + " The is required.\n" "\n" "Examples:\n" "\n" "cheatnext increase\n" - " search for all bytes that have increased since the previous search.\n" + " Search for all values that have increased since the previous search.\n" "\n" - "cheatnext decrease, 1\n" - " search for all bytes that have decreased by 1 since the previous search.\n" + "cheatnext decrease,1\n" + " Search for all values that have decreased by 1 since the previous search.\n" }, { "cheatnextf", "\n" " cheatnextf [,]\n" "\n" - "The cheatnextf command will make comparisons with the initial search.\n" + "The cheatnextf command makes comparisons with the initial search matches.\n" "Possible :\n" " all\n" - " no needed.\n" - " use to update the previous value without changing the current matches.\n" - " equal [eq]\n" - " without search for all bytes that are equal to the initial search.\n" - " with search for all bytes that are equal to the .\n" - " notequal [ne]\n" - " without search for all bytes that are not equal to the initial search.\n" - " with search for all bytes that are not equal to the .\n" - " decrease [de, +]\n" - " without search for all bytes that have decreased since the initial search.\n" - " with search for all bytes that have decreased by the since the initial search.\n" - " increase [in, -]\n" - " without search for all bytes that have increased since the initial search.\n" - " with search for all bytes that have increased by the since the initial search.\n" - " decreaseorequal [deeq]\n" - " no needed.\n" - " search for all bytes that have decreased or have same value since the initial search.\n" - " increaseorequal [ineq]\n" - " no needed.\n" - " search for all bytes that have decreased or have same value since the initial search.\n" - " smallerof [lt]\n" - " without this condition is invalid.\n" - " with search for all bytes that are smaller than the .\n" - " greaterof [gt]\n" - " without this condition is invalid.\n" - " with search for all bytes that are larger than the .\n" - " changedby [ch, ~]\n" - " without this condition is invalid\n" - " with search for all bytes that have changed by the since the initial search.\n" + " Use to update the last value without changing the current matches.\n" + " The is not used.\n" + " equal (eq)\n" + " Without **, search for values that are equal to the initial search.\n" + " With , search for values that are equal to the .\n" + " notequal (ne)\n" + " Without , search for values that are not equal to the initial search.\n" + " With , search for values that are not equal to the .\n" + " decrease (de, -)\n" + " Without , search for values that have decreased since the initial " + "search.\n" + " With , search for values that have decreased by the " + "since the initial search.\n" + " increase (in, +)\n" + " Without , search for values that have increased since the initial " + "search.\n" + " With , search for values that have increased by the " + "since the initial search.\n" + " decreaseorequal (deeq)\n" + " Search for values that have decreased or are unchanged since the initial search.\n" + " The is not used.\n" + " increaseorequal (ineq)\n" + " Search for values that have increased or are unchanged since the initial search.\n" + " The is not used.\n" + " smallerof (lt, <)\n" + " Search for values that are less than the .\n" + " The is required.\n" + " greaterof (gt, >)\n" + " Search for values that are greater than the .\n" + " The is required.\n" + " changedby (ch, ~)\n" + " Search for values that have changed by the since the initial search.\n" + " The is required.\n" "\n" "Examples:\n" "\n" "cheatnextf increase\n" - " search for all bytes that have increased since the initial search.\n" + " Search for all values that have increased since the initial search.\n" "\n" - "cheatnextf decrease, 1\n" - " search for all bytes that have decreased by 1 since the initial search.\n" + "cheatnextf decrease,1\n" + " Search for all values that have decreased by 1 since the initial search.\n" }, { "cheatlist", "\n" " cheatlist []\n" "\n" - "Without show the list of matches in the debug console.\n" - "With save the list of matches in basic xml format to .\n" + "Without , show the current cheat matches in the debugger console; with " + ", save the current cheat matches in basic XML format to the specified file.\n" "\n" "Examples:\n" "\n" "cheatlist\n" - " Show the current matches in the debug console.\n" - "cheatlist cheat.txt\n" - " Save the current matches to cheat.txt.\n" + " Show the current matches in the console.\n" + "cheatlist cheat.xml\n" + " Save the current matches to cheat.xml in XML format.\n" }, { "cheatundo", "\n" " cheatundo\n" "\n" - "Undo the results of the last search.\n" - "The undo command has no effect on the last value.\n" + "Undo filtering of cheat candidates by the most recent cheatnext or cheatnextf command.\n" + "Note that the previous values ARE NOT rolled back.\n" "\n" "Examples:\n" "\n" "cheatundo\n" - " Undo the last search (state only).\n" + " Restore cheat candidates filtered out by the most recent cheatnext or cheatnextf " + "command.\n" }, { "images", diff --git a/src/frontend/mame/ui/about.cpp b/src/frontend/mame/ui/about.cpp index bac2c3b4bdc..ac38d9c08b7 100644 --- a/src/frontend/mame/ui/about.cpp +++ b/src/frontend/mame/ui/about.cpp @@ -39,8 +39,19 @@ namespace { menu_about::menu_about(mame_ui_manager &mui, render_container &container) : menu(mui, container) - , m_title(util::string_format(_("%1$s %2$s"), emulator_info::get_appname(), bare_build_version)) - , m_footer(util::string_format(_("Revision: %1$s"), bare_vcs_revision)) + , m_header{ + util::string_format( +#ifdef MAME_DEBUG + _("%1$s %2$s (%3$s%4$sP%5$s, debug)"), +#else + _("%1$s %2$s (%3$s%4$sP%5$s)"), +#endif + emulator_info::get_appname(), + bare_build_version, + (sizeof(int) == sizeof(void *)) ? "I" : "", + (sizeof(long) == sizeof(void *)) ? "L" : (sizeof(long long) == sizeof(void *)) ? "LL" : "", + sizeof(void *) * 8), + util::string_format(_("Revision: %1$s"), bare_vcs_revision) } { } @@ -60,23 +71,12 @@ menu_about::~menu_about() void menu_about::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { - std::string_view tempbuf[1]; - // draw the title - tempbuf[0] = m_title; draw_text_box( - std::begin(tempbuf), std::end(tempbuf), + std::begin(m_header), std::end(m_header), origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); - - // draw the footer - tempbuf[0] = m_footer; - draw_text_box( - std::begin(tempbuf), std::end(tempbuf), - origx1, origx2, origy2 + ui().box_tb_border(), origy2 + bottom, - text_layout::text_justify::CENTER, text_layout::word_wrapping::NEVER, false, - ui().colors().text_color(), ui().colors().background_color(), 1.0f); } @@ -221,8 +221,7 @@ void menu_about::draw(uint32_t flags) void menu_about::populate(float &customtop, float &custombottom) { // make space for the title and revision - customtop = ui().get_line_height() + 3.0f * ui().box_tb_border(); - custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border(); + customtop = (ui().get_line_height() * m_header.size()) + (ui().box_tb_border() * 3.0f); } diff --git a/src/frontend/mame/ui/about.h b/src/frontend/mame/ui/about.h index b96c7ee2055..8ef133c43c6 100644 --- a/src/frontend/mame/ui/about.h +++ b/src/frontend/mame/ui/about.h @@ -16,6 +16,7 @@ #include #include +#include namespace ui { @@ -34,8 +35,7 @@ private: virtual void populate(float &customtop, float &custombottom) override; virtual void handle() override; - std::string const m_title; - std::string const m_footer; + std::vector const m_header; std::optional m_layout; }; diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index 9046431d1f6..8c8f44224a8 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -2268,7 +2268,22 @@ void mame_ui_manager::menu_reset() std::string mame_ui_manager::get_general_input_setting(ioport_type type, int player, input_seq_type seqtype) { - return machine().input().seq_name(machine().ioport().type_seq(type, player, seqtype)); + input_seq seq(machine().ioport().type_seq(type, player, seqtype)); + input_code codes[16]; // TODO: remove magic number + unsigned len(0U); + for (unsigned i = 0U; std::size(codes) > i; ++i) + { + if (input_seq::not_code == seq[i]) + ++i; + else + codes[len++] = seq[i]; + if (input_seq::end_code == seq[i]) + break; + } + seq.reset(); + for (unsigned i = 0U; len > i; ++i) + seq += codes[i]; + return machine().input().seq_name(seq); } -- cgit v1.2.3