summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2021-10-19 05:35:30 +1100
committer Vas Crabb <vas@vastheman.com>2021-10-19 05:35:30 +1100
commit08ee39da702645560d9924b6d6ab4ee865b9e478 (patch)
treeef39e565cfc60889920238e8bb0e26ee50c122ec
parent5bea4a62929e67e693c8460341e205f3a60ab1a3 (diff)
-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.
-rw-r--r--docs/source/debugger/breakpoint.rst3
-rw-r--r--docs/source/debugger/cheats.rst486
-rw-r--r--docs/source/debugger/general.rst5
-rw-r--r--docs/source/debugger/registerpoints.rst4
-rw-r--r--docs/source/debugger/watchpoint.rst4
-rw-r--r--src/emu/debug/debugcmd.cpp244
-rw-r--r--src/emu/debug/debugcmd.h14
-rw-r--r--src/emu/debug/debughlp.cpp203
-rw-r--r--src/frontend/mame/ui/about.cpp31
-rw-r--r--src/frontend/mame/ui/about.h4
-rw-r--r--src/frontend/mame/ui/ui.cpp17
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 <command>** 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 <filename>
-| :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 <debugger-command-cheatinit>`::
+
+ >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 <debugger-command-cheatnext>` 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 <debugger-command-cheatlist>` 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
+
+ <cheat desc="Possibility 1: 00B85 (01)">
+ <script state="run">
+ <action>:maincpu.ppb@00B85=03</action>
+ </script>
+ </cheat>
+
+
+.. _debugger-command-cheatinit:
cheatinit
---------
-| **cheatinit [<sign><width><swap>,[<address>,<length>[,<cpu>]]]**
-|
-| 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.
-|
-| <sign> can be s(signed) or u(unsigned)
-| <width> can be b(8 bit), w(16 bit), d(32 bit) or q(64 bit)
-| <swap> 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 [[<sign>[<width>[<swap>]]],[<address>,<length>[,<space>]]]**
+
+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
+**<sign>** may be **u** for unsigned or **s** for signed, the
+**<width>** 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);
+**<swap>** 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 **<address>** specifies the address to start searching from, and the
+**<length>** specifies how much memory to search. If specified,
+writable RAM in the range **<address>** through
+**<address>+<length>-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 <address>,<length>**
-|
-| 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 <address>,<length>**
+
+Add writable RAM areas to the cheat search. May be abbreviated to
+``cr``. Before using this command, the
+:ref:`cheatinit command <debugger-command-cheatinit>` must be used to
+initialize the cheat search and set the address space and data format.
+The **<address>** specifies the address to start searching from, and the
+**<length>** specifies how much memory to search. Writable RAM in the
+range **<address>** through **<address>+<length>-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 <condition>[,<comparisonvalue>]**
-|
-| The cheatnext command will make comparisons with the last search matches.
-|
-| Possible <condition>:
-|
-| **all**
-|
-| No <comparisonvalue> needed.
-|
-| Use to update the last value without changing the current matches.
-|
-| **equal [eq]**
-|
-| Without <comparisonvalue> search for all bytes that are equal to the last search.
-| With <comparisonvalue> search for all bytes that are equal to the <comparisonvalue>.
-|
-| **notequal [ne]**
-|
-| Without <comparisonvalue> search for all bytes that are not equal to the last search.
-| With <comparisonvalue> search for all bytes that are not equal to the <comparisonvalue>.
-|
-| **decrease [de, +]**
-|
-| Without <comparisonvalue> search for all bytes that have decreased since the last search.
-| With <comparisonvalue> search for all bytes that have decreased by the <comparisonvalue> since the last search.
-|
-| **increase [in, -]**
-|
-| Without <comparisonvalue> search for all bytes that have increased since the last search.
-| With <comparisonvalue> search for all bytes that have increased by the <comparisonvalue> since the last search.
-|
-| **decreaseorequal [deeq]**
-|
-| No <comparisonvalue> needed.
-|
-| Search for all bytes that have decreased or have same value since the last search.
-|
-| **increaseorequal [ineq]**
-|
-| No <comparisonvalue> needed.
-|
-| Search for all bytes that have decreased or have same value since the last search.
-|
-| **smallerof [lt]**
-|
-| Without <comparisonvalue> this condition is invalid
-| With <comparisonvalue> search for all bytes that are smaller than the <comparisonvalue>.
-|
-| **greaterof [gt]**
-|
-| Without <comparisonvalue> this condition is invalid
-| With <comparisonvalue> search for all bytes that are larger than the <comparisonvalue>.
-|
-| **changedby [ch, ~]**
-|
-| Without <comparisonvalue> this condition is invalid
-| With <comparisonvalue> search for all bytes that have changed by the <comparisonvalue> 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 <condition>[,<comparisonvalue>]**
+
+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 **<condition>** arguments:
+
+``all``
+ Use to update the last value without changing the current matches
+ (the **<comparisonvalue>** is not used).
+``equal`` (``eq``)
+ Without **<comparisonvalue>**, search for values that are equal to
+ the previous search; with **<comparisonvalue>**, search for values
+ that are equal to the **<comparisonvalue>**.
+``notequal`` (``ne``)
+ Without **<comparisonvalue>**, search for values that are not equal
+ to the previous search; with **<comparisonvalue>**, search for
+ values that are not equal to the **<comparisonvalue>**.
+``decrease`` (``de``, ``-``)
+ Without **<comparisonvalue>**, search for values that have decreased
+ since the previous search; with **<comparisonvalue>**, search for
+ values that have decreased by the **<comparisonvalue>** since the
+ previous search.
+``increase`` (``in``, ``+``)
+ Without **<comparisonvalue>**, search for values that have increased
+ since the previous search; with **<comparisonvalue>**, search for
+ values that have increased by the **<comparisonvalue>** since the
+ previous search.
+``decreaseorequal`` (``deeq``)
+ Search for values that have decreased or are unchanged since the
+ previous search (the **<comparisonvalue>** is not used).
+``increaseorequal`` (``ineq``)
+ Search for values that have increased or are unchanged since the
+ previous search (the **<comparisonvalue>** is not used).
+``smallerof`` (``lt``, ``<``)
+ Search for values that are less than the **<comparisonvalue>** (the
+ **<comparisonvalue>** is required).
+``greaterof`` (``gt``, ``>``)
+ Search for values that are greater than the **<comparisonvalue>**
+ (the **<comparisonvalue>** is required).
+``changedby`` (``ch``, ``~``)
+ Search for values that have changed by the **<comparisonvalue>**
+ since the previous search (the **<comparisonvalue>** 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 <condition>[,<comparisonvalue>]**
-|
-| The cheatnextf command will make comparisons with the initial search.
-|
-| Possible <condition>:
-|
-| **all**
-|
-| No <comparisonvalue> needed.
-|
-| Use to update the last value without changing the current matches.
-|
-| **equal [eq]**
-|
-| Without <comparisonvalue> search for all bytes that are equal to the initial search.
-| With <comparisonvalue> search for all bytes that are equal to the <comparisonvalue>.
-|
-| **notequal [ne]**
-|
-| Without <comparisonvalue> search for all bytes that are not equal to the initial search.
-| With <comparisonvalue> search for all bytes that are not equal to the <comparisonvalue>.
-|
-| **decrease [de, +]**
-|
-| Without <comparisonvalue> search for all bytes that have decreased since the initial search.
-| With <comparisonvalue> search for all bytes that have decreased by the <comparisonvalue> since the initial search.
-|
-| **increase [in, -]**
-|
-| Without <comparisonvalue> search for all bytes that have increased since the initial search.
-|
-| With <comparisonvalue> search for all bytes that have increased by the <comparisonvalue> since the initial search.
-|
-| **decreaseorequal [deeq]**
-|
-| No <comparisonvalue> needed.
-|
-| Search for all bytes that have decreased or have same value since the initial search.
-|
-| **increaseorequal [ineq]**
-|
-| No <comparisonvalue> needed.
-|
-| Search for all bytes that have decreased or have same value since the initial search.
-|
-| **smallerof [lt]**
-|
-| Without <comparisonvalue> this condition is invalid.
-| With <comparisonvalue> search for all bytes that are smaller than the <comparisonvalue>.
-|
-| **greaterof [gt]**
-|
-| Without <comparisonvalue> this condition is invalid.
-| With <comparisonvalue> search for all bytes that are larger than the <comparisonvalue>.
-|
-| **changedby [ch, ~]**
-|
-| Without <comparisonvalue> this condition is invalid
-| With <comparisonvalue> search for all bytes that have changed by the <comparisonvalue> 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 <condition>[,<comparisonvalue>]**
+
+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 **<condition>** arguments:
+
+``all``
+ Use to update the last value without changing the current matches
+ (the **<comparisonvalue>** is not used).
+``equal`` (``eq``)
+ Without **<comparisonvalue>**, search for values that are equal to
+ the initial search; with **<comparisonvalue>**, search for values
+ that are equal to the **<comparisonvalue>**.
+``notequal`` (``ne``)
+ Without **<comparisonvalue>**, search for values that are not equal
+ to the initial search; with **<comparisonvalue>**, search for values
+ that are not equal to the **<comparisonvalue>**.
+``decrease`` (``de``, ``-``)
+ Without **<comparisonvalue>**, search for values that have decreased
+ since the initial search; with **<comparisonvalue>**, search for
+ values that have decreased by the **<comparisonvalue>** since the
+ initial search.
+``increase`` (``in``, ``+``)
+ Without **<comparisonvalue>**, search for values that have increased
+ since the initial search; with **<comparisonvalue>**, search for
+ values that have increased by the **<comparisonvalue>** since the
+ initial search.
+``decreaseorequal`` (``deeq``)
+ Search for values that have decreased or are unchanged since the
+ initial search (the **<comparisonvalue>** is not used).
+``increaseorequal`` (``ineq``)
+ Search for values that have increased or are unchanged since the
+ initial search (the **<comparisonvalue>** is not used).
+``smallerof`` (``lt``, ``<``)
+ Search for values that are less than the **<comparisonvalue>** (the
+ **<comparisonvalue>** is required).
+``greaterof`` (``gt``, ``>``)
+ Search for values that are greater than the **<comparisonvalue>**
+ (the **<comparisonvalue>** is required).
+``changedby`` (``ch``, ``~``)
+ Search for values that have changed by the **<comparisonvalue>**
+ since the initial search (the **<comparisonvalue>** 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 [<filename>]**
-|
-| Without <filename> show the list of matches in the debug console.
-| With <filename> save the list of matches in basic XML format to <filename>.
-|
-| 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 [<filename>]**
+
+Without **<filename>**, show the current cheat matches in the debugger
+console; with **<filename>**, 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 <debugger-command-cheatnext>` or
+:ref:`cheatnextf <debugger-command-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 <debugger-command-cheatnext>` or
+ :ref:`cheatnextf <debugger-command-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 <mame-commandline-statedirectory>` 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 <mame-commandline-statedirectory>` 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<std::str
void debugger_commands::execute_cheatrange(bool init, const std::vector<std::string> &params)
{
- 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::vector<std::str
cheat_region[region_count].disabled = false;
region_count++;
}
+ else
+ {
+ // initialize to entire memory by default
+ 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;
+
+ // 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<std::s
CHEAT_CHANGEDBY
};
- if (m_cheat.cpu[0] == 0)
+ address_space *const space = m_cheat.space;
+ if (!space)
{
m_console.printf("Use cheatinit before cheatnext\n");
return;
}
- address_space *space;
- if (!validate_device_space_parameter(m_cheat.cpu, AS_PROGRAM, space))
- return;
-
u64 comp_value = 0;
if (params.size() > 1 && !validate_number_parameter(params[1], comp_value))
return;
@@ -3186,30 +3200,36 @@ void debugger_commands::execute_cheatnext(bool initial, const std::vector<std::s
void debugger_commands::execute_cheatlist(const std::vector<std::string> &params)
{
- 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<std::string> &params
output.rdbuf()->clear();
stream_format(
output,
- " <cheat desc=\"Possibility %d : %0*X (%0*X)\">\n"
+ " <cheat desc=\"Possibility %d: %0*X (%0*X)\">\n"
" <script state=\"run\">\n"
" <action>%s.p%c%c@%0*X=%0*X</action>\n"
" </script>\n"
" </cheat>\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<std::string> &params
{
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<std::string> &params
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<std::string> &params)
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<cheat_map> cheatmap;
- u8 undo;
u8 signed_cheat;
u8 swapped_cheat;
+ std::vector<cheat_map> 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 &param);
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 <command> for further details on each command\n"
"\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"
+ " cheatinit [[<sign>[<width>[<swap>]]],[<address>,<length>[,<space>]]] -- initialize the cheat search to the selected memory area\n"
+ " cheatrange <address>,<length> -- add selected memory area to the cheat search\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"
@@ -1611,157 +1611,184 @@ const help_item f_static_help_list[] =
{
"cheatinit",
"\n"
- " cheatinit [<sign><width>[<swap>],[<address>,<length>[,<CPU>]]]\n"
+ " cheatinit [[<sign>[<width>[<swap>]]],[<address>,<length>[,<space>]]]\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"
- "<sign> can be s(signed) or u(unsigned)\n"
- "<width> can be b(8 bit), w(16 bit), d(32 bit) or q(64 bit)\n"
- "<swap> 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"
+ " <sign>: 's' (signed), 'u' (unsigned)\n"
+ " <width>: 'b' (8-bit), 'w' (16-bit), 'd' (32-bit), 'q' (64-bit)\n"
+ " <swap>: '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 <address> specifies the address to start searching from, and the <length> specifies "
+ "how much memory to search. If specified, writable RAM in the range <address> through "
+ "<address>+<length>-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 <address>,<length>\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 <address> through "
+ "through <address>+<length>-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 <condition>[,<comparisonvalue>]\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 <condition>:\n"
" all\n"
- " no <comparisonvalue> needed.\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 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 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 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 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 previous search.\n"
- " increaseorequal [ineq]\n"
- " no <comparisonvalue> needed.\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"
- " greaterof [gt]\n"
- " without <comparisonvalue> this condition is invalid\n"
- " 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 previous search.\n"
+ " Use to update the last value without changing the current matches.\n"
+ " The <comparisonvalue> is not used.\n"
+ " equal (eq)\n"
+ " Without <comparisonvalue>**, search for values that are equal to the previous "
+ "search.\n"
+ " With <comparisonvalue>, search for values that are equal to the <comparisonvalue>.\n"
+ " notequal (ne)\n"
+ " Without <comparisonvalue>, search for values that are not equal to the previous "
+ "search.\n"
+ " With <comparisonvalue>, search for values that are not equal to the <comparisonvalue>.\n"
+ " decrease (de, -)\n"
+ " Without <comparisonvalue>, search for values that have decreased since the previous "
+ "search.\n"
+ " With <comparisonvalue>, search for values that have decreased by the <comparisonvalue> "
+ "since the previous search.\n"
+ " increase (in, +)\n"
+ " Without <comparisonvalue>, search for values that have increased since the previous "
+ "search.\n"
+ " With <comparisonvalue>, search for values that have increased by the <comparisonvalue> "
+ "since the previous search.\n"
+ " decreaseorequal (deeq)\n"
+ " Search for values that have decreased or are unchanged since the previous search.\n"
+ " The <comparisonvalue> is not used.\n"
+ " increaseorequal (ineq)\n"
+ " Search for values that have increased or are unchanged since the previous search.\n"
+ " The <comparisonvalue> is not used.\n"
+ " smallerof (lt, <)\n"
+ " Search for values that are less than the <comparisonvalue>.\n"
+ " The <comparisonvalue> is required.\n"
+ " greaterof (gt, >)\n"
+ " Search for values that are greater than the <comparisonvalue>.\n"
+ " The <comparisonvalue> is required.\n"
+ " changedby (ch, ~)\n"
+ " Search for values that have changed by the <comparisonvalue> since the previous "
+ "search.\n"
+ " The <comparisonvalue> 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 <condition>[,<comparisonvalue>]\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 <condition>:\n"
" all\n"
- " no <comparisonvalue> needed.\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"
- " notequal [ne]\n"
- " without <comparisonvalue> search for all bytes that are not equal to the initial 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 initial search.\n"
- " with <comparisonvalue> search for all bytes that have decreased by the <comparisonvalue> since the initial search.\n"
- " increase [in, -]\n"
- " without <comparisonvalue> search for all bytes that have increased since the initial search.\n"
- " with <comparisonvalue> search for all bytes that have increased by the <comparisonvalue> since the initial search.\n"
- " decreaseorequal [deeq]\n"
- " no <comparisonvalue> needed.\n"
- " search for all bytes that have decreased or have same value since the initial search.\n"
- " increaseorequal [ineq]\n"
- " no <comparisonvalue> needed.\n"
- " search for all bytes that have decreased or have same value since the initial 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"
- " greaterof [gt]\n"
- " without <comparisonvalue> this condition is invalid.\n"
- " 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 initial search.\n"
+ " Use to update the last value without changing the current matches.\n"
+ " The <comparisonvalue> is not used.\n"
+ " equal (eq)\n"
+ " Without <comparisonvalue>**, search for values that are equal to the initial search.\n"
+ " With <comparisonvalue>, search for values that are equal to the <comparisonvalue>.\n"
+ " notequal (ne)\n"
+ " Without <comparisonvalue>, search for values that are not equal to the initial search.\n"
+ " With <comparisonvalue>, search for values that are not equal to the <comparisonvalue>.\n"
+ " decrease (de, -)\n"
+ " Without <comparisonvalue>, search for values that have decreased since the initial "
+ "search.\n"
+ " With <comparisonvalue>, search for values that have decreased by the <comparisonvalue> "
+ "since the initial search.\n"
+ " increase (in, +)\n"
+ " Without <comparisonvalue>, search for values that have increased since the initial "
+ "search.\n"
+ " With <comparisonvalue>, search for values that have increased by the <comparisonvalue> "
+ "since the initial search.\n"
+ " decreaseorequal (deeq)\n"
+ " Search for values that have decreased or are unchanged since the initial search.\n"
+ " The <comparisonvalue> is not used.\n"
+ " increaseorequal (ineq)\n"
+ " Search for values that have increased or are unchanged since the initial search.\n"
+ " The <comparisonvalue> is not used.\n"
+ " smallerof (lt, <)\n"
+ " Search for values that are less than the <comparisonvalue>.\n"
+ " The <comparisonvalue> is required.\n"
+ " greaterof (gt, >)\n"
+ " Search for values that are greater than the <comparisonvalue>.\n"
+ " The <comparisonvalue> is required.\n"
+ " changedby (ch, ~)\n"
+ " Search for values that have changed by the <comparisonvalue> since the initial search.\n"
+ " The <comparisonvalue> 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 [<filename>]\n"
"\n"
- "Without <filename> show the list of matches in the debug console.\n"
- "With <filename> save the list of matches in basic xml format to <filename>.\n"
+ "Without <filename>, show the current cheat matches in the debugger console; with "
+ "<filename>, 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 <optional>
#include <string>
+#include <vector>
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<std::string> const m_header;
std::optional<text_layout> 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);
}