mirror of
https://github.com/holub/mame
synced 2025-04-19 15:11:37 +03:00
-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.
This commit is contained in:
parent
5bea4a6292
commit
08ee39da70
@ -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:
|
||||
|
||||
|
@ -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`
|
||||
**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:
|
||||
.. _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.
|
||||
|
||||
Examples:
|
||||
|
||||
``cheatrange 0x1000,0x10``
|
||||
Add addresses 0x1000-0x100f to the areas to search for cheats.
|
||||
|
||||
Back to :ref:`debugger-cheats-list`
|
||||
|
||||
|
||||
.. _debugger-command-cheatnext:
|
||||
.. _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`
|
||||
**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:
|
||||
.. _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`
|
||||
**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:
|
||||
.. _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`
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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
|
||||
|
@ -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> ¶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();
|
||||
|
||||
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
|
||||
std::string const &srtpnt = params[0];
|
||||
if (!srtpnt.empty())
|
||||
{
|
||||
m_console.printf("Invalid sign: expected s or u\n");
|
||||
return;
|
||||
width = 1;
|
||||
signed_cheat = false;
|
||||
swapped_cheat = false;
|
||||
}
|
||||
|
||||
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() >= 1)
|
||||
{
|
||||
m_console.printf("Invalid width: expected b, w, d or q\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;
|
||||
}
|
||||
}
|
||||
|
||||
if (std::tolower((unsigned char)*(++srtpnt)) == 's')
|
||||
m_cheat.swapped_cheat = true;
|
||||
else
|
||||
m_cheat.swapped_cheat = false;
|
||||
if (srtpnt.length() >= 2)
|
||||
{
|
||||
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 (srtpnt.length() >= 3)
|
||||
{
|
||||
if (std::tolower((unsigned char)srtpnt[2]) == 's')
|
||||
swapped_cheat = true;
|
||||
else
|
||||
{
|
||||
m_console.printf("Invalid swap: expected s\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fourth argument is device/space
|
||||
if (!validate_device_space_parameter((params.size() > 3) ? params[3] : std::string_view(), -1, space))
|
||||
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++;
|
||||
}
|
||||
}
|
||||
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> ¶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<std::string> ¶ms
|
||||
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> ¶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<std::string> ¶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<std::string> ¶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)
|
||||
|
@ -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 ¶m);
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user