-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`
|
:ref:`debugger-command-bplist`
|
||||||
lists breakpoints
|
lists breakpoints
|
||||||
|
|
||||||
|
Breakpoints halt execution and activate the debugger before a CPU
|
||||||
|
executes an instruction at a particular address.
|
||||||
|
|
||||||
|
|
||||||
.. _debugger-command-bpset:
|
.. _debugger-command-bpset:
|
||||||
|
|
||||||
|
@ -3,144 +3,192 @@
|
|||||||
Cheat Debugger Commands
|
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
|
We’ll demonstrate use of the cheat search functionality to make an
|
||||||
| :ref:`debugger-command-cheatrange` -- add to the cheat search the selected memory area
|
infinite lives cheat for Raiden (``raiden``):
|
||||||
| :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)
|
|
||||||
|
|
||||||
.. _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
|
||||||
---------
|
---------
|
||||||
|
|
||||||
| **cheatinit [<sign><width><swap>,[<address>,<length>[,<cpu>]]]**
|
**cheatinit [[<sign>[<width>[<swap>]]],[<address>,<length>[,<space>]]]**
|
||||||
|
|
|
||||||
| The cheatinit command initializes the cheat search to the selected memory area.
|
Initialize the cheat search to writable RAM areas in the specified
|
||||||
|
|
address space. May be abbreviated to ``ci``.
|
||||||
| If no parameter is specified the cheat search is initialized to all changeable memory of the main CPU.
|
|
||||||
|
|
The first argument specifies the data format to search for. The
|
||||||
| <sign> can be s(signed) or u(unsigned)
|
**<sign>** may be **u** for unsigned or **s** for signed, the
|
||||||
| <width> can be b(8 bit), w(16 bit), d(32 bit) or q(64 bit)
|
**<width>** may be **b** for 8-bit (byte), **w** for 16-bit (word),
|
||||||
| <swap> append s for swapped search
|
**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
|
||||||
| Examples:
|
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.
|
||||||
| cheatinit ub,0x1000,0x10
|
|
||||||
|
|
The **<address>** specifies the address to start searching from, and the
|
||||||
| Initialize the cheat search from 0x1000 to 0x1010 of the first CPU.
|
**<length>** specifies how much memory to search. If specified,
|
||||||
|
|
writable RAM in the range **<address>** through
|
||||||
| cheatinit sw,0x2000,0x1000,1
|
**<address>+<length>-1**, inclusive, will be searched; otherwise, all
|
||||||
|
|
writable RAM in the address space will be searched.
|
||||||
| Initialize the cheat search with width of 2 byte in signed mode from 0x2000 to 0x3000 of the second CPU.
|
|
||||||
|
|
See :ref:`debugger-devicespec` for details on specifying address spaces.
|
||||||
| cheatinit uds,0x0000,0x1000
|
If the address space is not specified, it defaults to the first address
|
||||||
|
|
space exposed by the visible CPU.
|
||||||
| Initialize the cheat search with width of 4 byte swapped from 0x0000 to 0x1000.
|
|
||||||
|
|
Examples:
|
||||||
| Back to :ref:`debugger-cheats-list`
|
|
||||||
|
``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
|
||||||
----------
|
----------
|
||||||
|
|
||||||
| **cheatrange <address>,<length>**
|
**cheatrange <address>,<length>**
|
||||||
|
|
|
||||||
| The cheatrange command adds the selected memory area to the cheat search.
|
Add writable RAM areas to the cheat search. May be abbreviated to
|
||||||
|
|
``cr``. Before using this command, the
|
||||||
| Before using cheatrange it is necessary to initialize the cheat search with cheatinit.
|
:ref:`cheatinit command <debugger-command-cheatinit>` must be used to
|
||||||
|
|
initialize the cheat search and set the address space and data format.
|
||||||
| Examples:
|
|
||||||
|
|
The **<address>** specifies the address to start searching from, and the
|
||||||
| cheatrange 0x1000,0x10
|
**<length>** specifies how much memory to search. Writable RAM in the
|
||||||
|
|
range **<address>** through **<address>+<length>-1**, inclusive, will be
|
||||||
| Add the bytes from 0x1000 to 0x1010 to the cheat search.
|
added to the areas to search.
|
||||||
|
|
|
||||||
| Back to :ref:`debugger-cheats-list`
|
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
|
||||||
---------
|
---------
|
||||||
|
|
||||||
| **cheatnext <condition>[,<comparisonvalue>]**
|
**cheatnext <condition>[,<comparisonvalue>]**
|
||||||
|
|
|
||||||
| The cheatnext command will make comparisons with the last search matches.
|
Filter candidates by comparing to the previous search values. If five
|
||||||
|
|
or fewer candidates remain, they will be shown in the debugger console.
|
||||||
| Possible <condition>:
|
May be abbreviated to ``cn``.
|
||||||
|
|
|
||||||
| **all**
|
Possible **<condition>** arguments:
|
||||||
|
|
|
||||||
| No <comparisonvalue> needed.
|
``all``
|
||||||
|
|
Use to update the last value without changing the current matches
|
||||||
| Use to update the last value without changing the current matches.
|
(the **<comparisonvalue>** is not used).
|
||||||
|
|
``equal`` (``eq``)
|
||||||
| **equal [eq]**
|
Without **<comparisonvalue>**, search for values that are equal to
|
||||||
|
|
the previous search; with **<comparisonvalue>**, search for values
|
||||||
| Without <comparisonvalue> search for all bytes that are equal to the last search.
|
that are equal to the **<comparisonvalue>**.
|
||||||
| With <comparisonvalue> search for all bytes that are equal to the <comparisonvalue>.
|
``notequal`` (``ne``)
|
||||||
|
|
Without **<comparisonvalue>**, search for values that are not equal
|
||||||
| **notequal [ne]**
|
to the previous search; with **<comparisonvalue>**, search for
|
||||||
|
|
values that are not equal to the **<comparisonvalue>**.
|
||||||
| Without <comparisonvalue> search for all bytes that are not equal to the last search.
|
``decrease`` (``de``, ``-``)
|
||||||
| With <comparisonvalue> search for all bytes that are not equal to the <comparisonvalue>.
|
Without **<comparisonvalue>**, search for values that have decreased
|
||||||
|
|
since the previous search; with **<comparisonvalue>**, search for
|
||||||
| **decrease [de, +]**
|
values that have decreased by the **<comparisonvalue>** since the
|
||||||
|
|
previous search.
|
||||||
| Without <comparisonvalue> search for all bytes that have decreased since the last search.
|
``increase`` (``in``, ``+``)
|
||||||
| With <comparisonvalue> search for all bytes that have decreased by the <comparisonvalue> since the last search.
|
Without **<comparisonvalue>**, search for values that have increased
|
||||||
|
|
since the previous search; with **<comparisonvalue>**, search for
|
||||||
| **increase [in, -]**
|
values that have increased by the **<comparisonvalue>** since the
|
||||||
|
|
previous search.
|
||||||
| Without <comparisonvalue> search for all bytes that have increased since the last search.
|
``decreaseorequal`` (``deeq``)
|
||||||
| With <comparisonvalue> search for all bytes that have increased by the <comparisonvalue> since the last search.
|
Search for values that have decreased or are unchanged since the
|
||||||
|
|
previous search (the **<comparisonvalue>** is not used).
|
||||||
| **decreaseorequal [deeq]**
|
``increaseorequal`` (``ineq``)
|
||||||
|
|
Search for values that have increased or are unchanged since the
|
||||||
| No <comparisonvalue> needed.
|
previous search (the **<comparisonvalue>** is not used).
|
||||||
|
|
``smallerof`` (``lt``, ``<``)
|
||||||
| Search for all bytes that have decreased or have same value since the last search.
|
Search for values that are less than the **<comparisonvalue>** (the
|
||||||
|
|
**<comparisonvalue>** is required).
|
||||||
| **increaseorequal [ineq]**
|
``greaterof`` (``gt``, ``>``)
|
||||||
|
|
Search for values that are greater than the **<comparisonvalue>**
|
||||||
| No <comparisonvalue> needed.
|
(the **<comparisonvalue>** is required).
|
||||||
|
|
``changedby`` (``ch``, ``~``)
|
||||||
| Search for all bytes that have decreased or have same value since the last search.
|
Search for values that have changed by the **<comparisonvalue>**
|
||||||
|
|
since the previous search (the **<comparisonvalue>** is required).
|
||||||
| **smallerof [lt]**
|
|
||||||
|
|
Examples:
|
||||||
| Without <comparisonvalue> this condition is invalid
|
|
||||||
| With <comparisonvalue> search for all bytes that are smaller than the <comparisonvalue>.
|
``cheatnext increase``
|
||||||
|
|
Search for all values that have increased since the previous search.
|
||||||
| **greaterof [gt]**
|
``cheatnext decrease,1``
|
||||||
|
|
Search for all values that have decreased by 1 since the previous
|
||||||
| Without <comparisonvalue> this condition is invalid
|
search.
|
||||||
| With <comparisonvalue> search for all bytes that are larger than the <comparisonvalue>.
|
|
||||||
|
|
Back to :ref:`debugger-cheats-list`
|
||||||
| **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`
|
|
||||||
|
|
||||||
|
|
||||||
.. _debugger-command-cheatnextf:
|
.. _debugger-command-cheatnextf:
|
||||||
@ -148,120 +196,100 @@ cheatnext
|
|||||||
cheatnextf
|
cheatnextf
|
||||||
----------
|
----------
|
||||||
|
|
||||||
| **cheatnextf <condition>[,<comparisonvalue>]**
|
**cheatnextf <condition>[,<comparisonvalue>]**
|
||||||
|
|
|
||||||
| The cheatnextf command will make comparisons with the initial search.
|
Filter candidates by comparing to the initial search values. If five or
|
||||||
|
|
fewer candidates remain, they will be shown in the debugger console.
|
||||||
| Possible <condition>:
|
May be abbreviated to ``cn``.
|
||||||
|
|
|
||||||
| **all**
|
Possible **<condition>** arguments:
|
||||||
|
|
|
||||||
| No <comparisonvalue> needed.
|
``all``
|
||||||
|
|
Use to update the last value without changing the current matches
|
||||||
| Use to update the last value without changing the current matches.
|
(the **<comparisonvalue>** is not used).
|
||||||
|
|
``equal`` (``eq``)
|
||||||
| **equal [eq]**
|
Without **<comparisonvalue>**, search for values that are equal to
|
||||||
|
|
the initial search; with **<comparisonvalue>**, search for values
|
||||||
| Without <comparisonvalue> search for all bytes that are equal to the initial search.
|
that are equal to the **<comparisonvalue>**.
|
||||||
| With <comparisonvalue> search for all bytes that are equal to the <comparisonvalue>.
|
``notequal`` (``ne``)
|
||||||
|
|
Without **<comparisonvalue>**, search for values that are not equal
|
||||||
| **notequal [ne]**
|
to the initial search; with **<comparisonvalue>**, search for values
|
||||||
|
|
that are not equal to the **<comparisonvalue>**.
|
||||||
| Without <comparisonvalue> search for all bytes that are not equal to the initial search.
|
``decrease`` (``de``, ``-``)
|
||||||
| With <comparisonvalue> search for all bytes that are not equal to the <comparisonvalue>.
|
Without **<comparisonvalue>**, search for values that have decreased
|
||||||
|
|
since the initial search; with **<comparisonvalue>**, search for
|
||||||
| **decrease [de, +]**
|
values that have decreased by the **<comparisonvalue>** since the
|
||||||
|
|
initial search.
|
||||||
| Without <comparisonvalue> search for all bytes that have decreased since the initial search.
|
``increase`` (``in``, ``+``)
|
||||||
| With <comparisonvalue> search for all bytes that have decreased by the <comparisonvalue> since the initial search.
|
Without **<comparisonvalue>**, search for values that have increased
|
||||||
|
|
since the initial search; with **<comparisonvalue>**, search for
|
||||||
| **increase [in, -]**
|
values that have increased by the **<comparisonvalue>** since the
|
||||||
|
|
initial search.
|
||||||
| Without <comparisonvalue> search for all bytes that have increased since the initial search.
|
``decreaseorequal`` (``deeq``)
|
||||||
|
|
Search for values that have decreased or are unchanged since the
|
||||||
| With <comparisonvalue> search for all bytes that have increased by the <comparisonvalue> since the initial search.
|
initial search (the **<comparisonvalue>** is not used).
|
||||||
|
|
``increaseorequal`` (``ineq``)
|
||||||
| **decreaseorequal [deeq]**
|
Search for values that have increased or are unchanged since the
|
||||||
|
|
initial search (the **<comparisonvalue>** is not used).
|
||||||
| No <comparisonvalue> needed.
|
``smallerof`` (``lt``, ``<``)
|
||||||
|
|
Search for values that are less than the **<comparisonvalue>** (the
|
||||||
| Search for all bytes that have decreased or have same value since the initial search.
|
**<comparisonvalue>** is required).
|
||||||
|
|
``greaterof`` (``gt``, ``>``)
|
||||||
| **increaseorequal [ineq]**
|
Search for values that are greater than the **<comparisonvalue>**
|
||||||
|
|
(the **<comparisonvalue>** is required).
|
||||||
| No <comparisonvalue> needed.
|
``changedby`` (``ch``, ``~``)
|
||||||
|
|
Search for values that have changed by the **<comparisonvalue>**
|
||||||
| Search for all bytes that have decreased or have same value since the initial search.
|
since the initial search (the **<comparisonvalue>** is required).
|
||||||
|
|
|
||||||
| **smallerof [lt]**
|
Examples:
|
||||||
|
|
|
||||||
| Without <comparisonvalue> this condition is invalid.
|
``cheatnextf increase``
|
||||||
| With <comparisonvalue> search for all bytes that are smaller than the <comparisonvalue>.
|
Search for all values that have increased since the initial search.
|
||||||
|
|
``cheatnextf decrease,1``
|
||||||
| **greaterof [gt]**
|
Search for all values that have decreased by 1 since the initial
|
||||||
|
|
search.
|
||||||
| Without <comparisonvalue> this condition is invalid.
|
|
||||||
| With <comparisonvalue> search for all bytes that are larger than the <comparisonvalue>.
|
Back to :ref:`debugger-cheats-list`
|
||||||
|
|
|
||||||
| **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:
|
.. _debugger-command-cheatlist:
|
||||||
|
|
||||||
cheatlist
|
cheatlist
|
||||||
---------
|
---------
|
||||||
|
|
||||||
| **cheatlist [<filename>]**
|
**cheatlist [<filename>]**
|
||||||
|
|
|
||||||
| Without <filename> show the list of matches in the debug console.
|
Without **<filename>**, show the current cheat matches in the debugger
|
||||||
| With <filename> save the list of matches in basic XML format to <filename>.
|
console; with **<filename>**, save the current cheat matches in basic
|
||||||
|
|
XML format to the specified file. May be abbreviated to ``cl``.
|
||||||
| Examples:
|
|
||||||
|
|
Examples:
|
||||||
| cheatlist
|
|
||||||
|
|
``cheatlist``
|
||||||
| Show the current matches in the debug console.
|
Show the current matches in the console.
|
||||||
|
|
``cheatlist cheat.xml``
|
||||||
| cheatlist cheat.txt
|
Save the current matches to the file **cheat.xml** in XML format.
|
||||||
|
|
|
||||||
| Save the current matches in XML format to cheat.txt.
|
Back to :ref:`debugger-cheats-list`
|
||||||
|
|
|
||||||
| Back to :ref:`debugger-cheats-list`
|
|
||||||
|
|
||||||
|
|
||||||
.. _debugger-command-cheatundo:
|
.. _debugger-command-cheatundo:
|
||||||
|
|
||||||
cheatundo
|
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`
|
|
||||||
|
|
||||||
|
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`,
|
states are saved when :ref:`debugger-command-step`,
|
||||||
:ref:`debugger-command-over` and :ref:`debugger-command-out` commands
|
:ref:`debugger-command-over` and :ref:`debugger-command-out` commands
|
||||||
are used, storing the machine state as of the moment before stepping.
|
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.
|
Consecutively loading rewind states can work like reverse execution.
|
||||||
Depending on which steps forward were taken previously, the behavior can
|
Depending on which steps forward were taken previously, the behavior can
|
||||||
be similar to GDB's **reverse-stepi** and **reverse-next** commands.
|
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
|
file is written to the configured save state directory (see the
|
||||||
:ref:`state_directory <mame-commandline-statedirectory>` option), and
|
:ref:`state_directory <mame-commandline-statedirectory>` option), and
|
||||||
the **.sta** extension is automatically appended to the specified file
|
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
|
All output from this command is currently echoed into the running machine
|
||||||
window.
|
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
|
from the configured save state directory (see the
|
||||||
:ref:`state_directory <mame-commandline-statedirectory>` option), and the
|
:ref:`state_directory <mame-commandline-statedirectory>` option), and the
|
||||||
**.sta** extension is automatically appended to the specified file name.
|
**.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
|
All output for this command is currently echoed into the running machine
|
||||||
window. Previous memory and PC tracking statistics are cleared.
|
window. Previous memory and PC tracking statistics are cleared.
|
||||||
|
@ -14,6 +14,10 @@ Registerpoint Debugger Commands
|
|||||||
:ref:`debugger-command-rplist`
|
:ref:`debugger-command-rplist`
|
||||||
lists registerpoints
|
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:
|
.. _debugger-command-rpset:
|
||||||
|
|
||||||
|
@ -14,6 +14,10 @@ Watchpoint Debugger Commands
|
|||||||
:ref:`debugger-command-wplist`
|
:ref:`debugger-command-wplist`
|
||||||
lists watchpoints
|
lists watchpoints
|
||||||
|
|
||||||
|
Watchpoints halt execution and activate the debugger when a CPU accesses
|
||||||
|
a location in a particular memory range.
|
||||||
|
|
||||||
|
|
||||||
.. _debugger-command-wpset:
|
.. _debugger-command-wpset:
|
||||||
|
|
||||||
wpset
|
wpset
|
||||||
|
@ -378,7 +378,7 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu
|
|||||||
if (name[0] != 0)
|
if (name[0] != 0)
|
||||||
m_console.source_script(name);
|
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)
|
void debugger_commands::execute_cheatrange(bool init, const std::vector<std::string> ¶ms)
|
||||||
{
|
{
|
||||||
cheat_region_map cheat_region[100];
|
address_space *space = m_cheat.space;
|
||||||
memset(cheat_region, 0, sizeof(cheat_region));
|
if (!space && !init)
|
||||||
|
{
|
||||||
// validate parameters
|
m_console.printf("Use cheatinit before cheatrange\n");
|
||||||
address_space *space;
|
|
||||||
if (!validate_device_space_parameter((params.size() > 3) ? params[3] : std::string_view(), -1, space))
|
|
||||||
return;
|
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)
|
if (init)
|
||||||
{
|
{
|
||||||
m_cheat.width = 1;
|
// first argument is sign/size/swap flags
|
||||||
m_cheat.signed_cheat = false;
|
|
||||||
m_cheat.swapped_cheat = false;
|
|
||||||
if (!params.empty())
|
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 (srtpnt.length() >= 1)
|
||||||
|
{
|
||||||
|
char const sspec = std::tolower((unsigned char)srtpnt[0]);
|
||||||
if (sspec == 's')
|
if (sspec == 's')
|
||||||
m_cheat.signed_cheat = true;
|
signed_cheat = true;
|
||||||
else if (sspec == 'u')
|
else if (sspec == 'u')
|
||||||
m_cheat.signed_cheat = false;
|
signed_cheat = false;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_console.printf("Invalid sign: expected s or u\n");
|
m_console.printf("Invalid sign: expected s or u\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char wspec = std::tolower((unsigned char)*(++srtpnt));
|
if (srtpnt.length() >= 2)
|
||||||
|
{
|
||||||
|
char const wspec = std::tolower((unsigned char)srtpnt[1]);
|
||||||
if (wspec == 'b')
|
if (wspec == 'b')
|
||||||
m_cheat.width = 1;
|
width = 1;
|
||||||
else if (wspec == 'w')
|
else if (wspec == 'w')
|
||||||
m_cheat.width = 2;
|
width = 2;
|
||||||
else if (wspec == 'd')
|
else if (wspec == 'd')
|
||||||
m_cheat.width = 4;
|
width = 4;
|
||||||
else if (wspec == 'q')
|
else if (wspec == 'q')
|
||||||
m_cheat.width = 8;
|
width = 8;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_console.printf("Invalid width: expected b, w, d or q\n");
|
m_console.printf("Invalid width: expected b, w, d or q\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::tolower((unsigned char)*(++srtpnt)) == 's')
|
|
||||||
m_cheat.swapped_cheat = true;
|
|
||||||
else
|
|
||||||
m_cheat.swapped_cheat = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize entire memory by default
|
if (srtpnt.length() >= 3)
|
||||||
u64 length = 0;
|
|
||||||
u8 region_count = 0;
|
|
||||||
if (params.size() <= 1)
|
|
||||||
{
|
{
|
||||||
for (address_map_entry &entry : space->map()->m_entrylist)
|
if (std::tolower((unsigned char)srtpnt[2]) == 's')
|
||||||
{
|
swapped_cheat = true;
|
||||||
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
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
cheat_region_map cheat_region[100]; // FIXME: magic number
|
||||||
|
unsigned region_count = 0;
|
||||||
|
if (params.size() >= (init ? 3 : 2))
|
||||||
{
|
{
|
||||||
// validate parameters
|
// validate parameters
|
||||||
u64 offset;
|
u64 offset, length;
|
||||||
if (!validate_number_parameter(params[init ? 1 : 0], offset))
|
if (!validate_number_parameter(params[init ? 1 : 0], offset))
|
||||||
return;
|
return;
|
||||||
if (!validate_number_parameter(params[init ? 2 : 1], length))
|
if (!validate_number_parameter(params[init ? 2 : 1], length))
|
||||||
@ -2947,49 +2949,59 @@ void debugger_commands::execute_cheatrange(bool init, const std::vector<std::str
|
|||||||
cheat_region[region_count].disabled = false;
|
cheat_region[region_count].disabled = false;
|
||||||
region_count++;
|
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
|
// determine the writable extent of each region in total
|
||||||
u64 real_length = 0;
|
u64 real_length = 0;
|
||||||
for (u8 i = 0; i < region_count; i++)
|
for (unsigned i = 0; i < region_count; i++)
|
||||||
if (!cheat_region[i].disabled)
|
for (u64 curaddr = cheat_region[i].offset; curaddr <= cheat_region[i].endoffset; curaddr += width)
|
||||||
for (u64 curaddr = cheat_region[i].offset; curaddr <= cheat_region[i].endoffset; curaddr += m_cheat.width)
|
|
||||||
if (cheat_address_is_valid(*space, curaddr))
|
if (cheat_address_is_valid(*space, curaddr))
|
||||||
real_length++;
|
real_length++;
|
||||||
|
|
||||||
if (real_length == 0)
|
if (!real_length)
|
||||||
{
|
{
|
||||||
m_console.printf("No writable bytes found in this area\n");
|
m_console.printf("No writable bytes found in this area\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 active_cheat = 0;
|
size_t active_cheat = 0;
|
||||||
if (init)
|
if (init)
|
||||||
{
|
{
|
||||||
// initialize new cheat system
|
// initialize new cheat system
|
||||||
m_cheat.cheatmap.resize(real_length);
|
m_cheat.space = space;
|
||||||
|
m_cheat.width = width;
|
||||||
m_cheat.undo = 0;
|
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
|
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();
|
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
|
// initialize cheatmap in the selected space
|
||||||
for (u8 i = 0; i < region_count; i++)
|
for (unsigned i = 0; i < region_count; i++)
|
||||||
if (!cheat_region[i].disabled)
|
for (u64 curaddr = cheat_region[i].offset; curaddr <= cheat_region[i].endoffset; curaddr += width)
|
||||||
for (u64 curaddr = cheat_region[i].offset; curaddr <= cheat_region[i].endoffset; curaddr += m_cheat.width)
|
|
||||||
if (cheat_address_is_valid(*space, curaddr))
|
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].previous_value = cheat_read_extended(&m_cheat, *space, curaddr);
|
||||||
@ -3000,8 +3012,13 @@ void debugger_commands::execute_cheatrange(bool init, const std::vector<std::str
|
|||||||
active_cheat++;
|
active_cheat++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// give a detailed init message to avoid searches being mistakingly carried out on the wrong CPU
|
// give a detailed init message to avoid searches being mistakenly 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());
|
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
|
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");
|
m_console.printf("Use cheatinit before cheatnext\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
address_space *space;
|
|
||||||
if (!validate_device_space_parameter(m_cheat.cpu, AS_PROGRAM, space))
|
|
||||||
return;
|
|
||||||
|
|
||||||
u64 comp_value = 0;
|
u64 comp_value = 0;
|
||||||
if (params.size() > 1 && !validate_number_parameter(params[1], comp_value))
|
if (params.size() > 1 && !validate_number_parameter(params[1], comp_value))
|
||||||
return;
|
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)
|
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");
|
m_console.printf("Use cheatinit before cheatlist\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
address_space *space;
|
|
||||||
if (!validate_device_space_parameter(m_cheat.cpu, -1, space))
|
|
||||||
return;
|
|
||||||
|
|
||||||
device_t &cpu = space->device();
|
|
||||||
|
|
||||||
FILE *f = nullptr;
|
FILE *f = nullptr;
|
||||||
if (params.size() > 0)
|
if (params.size() > 0)
|
||||||
|
{
|
||||||
f = fopen(params[0].c_str(), "w");
|
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;
|
char spaceletter;
|
||||||
switch (space->spacenum())
|
switch (space->spacenum())
|
||||||
{
|
{
|
||||||
default:
|
|
||||||
case AS_PROGRAM: spaceletter = 'p'; break;
|
case AS_PROGRAM: spaceletter = 'p'; break;
|
||||||
case AS_DATA: spaceletter = 'd'; break;
|
case AS_DATA: spaceletter = 'd'; break;
|
||||||
case AS_IO: spaceletter = 'i'; 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;
|
char sizeletter;
|
||||||
@ -3240,13 +3260,13 @@ void debugger_commands::execute_cheatlist(const std::vector<std::string> ¶ms
|
|||||||
output.rdbuf()->clear();
|
output.rdbuf()->clear();
|
||||||
stream_format(
|
stream_format(
|
||||||
output,
|
output,
|
||||||
" <cheat desc=\"Possibility %d : %0*X (%0*X)\">\n"
|
" <cheat desc=\"Possibility %d: %0*X (%0*X)\">\n"
|
||||||
" <script state=\"run\">\n"
|
" <script state=\"run\">\n"
|
||||||
" <action>%s.p%c%c@%0*X=%0*X</action>\n"
|
" <action>%s.p%c%c@%0*X=%0*X</action>\n"
|
||||||
" </script>\n"
|
" </script>\n"
|
||||||
" </cheat>\n\n",
|
" </cheat>\n\n",
|
||||||
active_cheat, space->logaddrchars(), address, m_cheat.width * 2, value,
|
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());
|
auto const &text(output.vec());
|
||||||
fprintf(f, "%.*s", int(unsigned(text.size())), &text[0]);
|
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)
|
if (m_cheat.undo > 0)
|
||||||
{
|
{
|
||||||
u32 undo_count = 0;
|
u64 undo_count = 0;
|
||||||
for (u64 cheatindex = 0; cheatindex < m_cheat.cheatmap.size(); cheatindex += 1)
|
for (u64 cheatindex = 0; cheatindex < m_cheat.cheatmap.size(); cheatindex += 1)
|
||||||
{
|
{
|
||||||
if (m_cheat.cheatmap[cheatindex].undo == m_cheat.undo)
|
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);
|
m_console.printf("%u cheat reactivated\n", undo_count);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
m_console.printf("Maximum undo reached\n");
|
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]);
|
sp.dump_maps(entries[0], entries[1]);
|
||||||
for (int mode = 0; mode < 2; mode ++)
|
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])
|
for (memory_entry &entry : entries[mode])
|
||||||
{
|
{
|
||||||
if (octal)
|
if (octal)
|
||||||
|
@ -67,20 +67,20 @@ private:
|
|||||||
// TODO [RH 31 May 2016]: Move this cheat stuff into its own class
|
// TODO [RH 31 May 2016]: Move this cheat stuff into its own class
|
||||||
struct cheat_system
|
struct cheat_system
|
||||||
{
|
{
|
||||||
char cpu[2];
|
address_space *space;
|
||||||
u8 width;
|
u8 width;
|
||||||
std::vector<cheat_map> cheatmap;
|
|
||||||
u8 undo;
|
|
||||||
u8 signed_cheat;
|
u8 signed_cheat;
|
||||||
u8 swapped_cheat;
|
u8 swapped_cheat;
|
||||||
|
std::vector<cheat_map> cheatmap;
|
||||||
|
u8 undo;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cheat_region_map
|
struct cheat_region_map
|
||||||
{
|
{
|
||||||
u64 offset;
|
u64 offset = 0U;
|
||||||
u64 endoffset;
|
u64 endoffset = 0U;
|
||||||
const char *share;
|
const char *share = nullptr;
|
||||||
u8 disabled;
|
u8 disabled = 0U;
|
||||||
};
|
};
|
||||||
|
|
||||||
device_t &get_device_search_base(std::string_view ¶m);
|
device_t &get_device_search_base(std::string_view ¶m);
|
||||||
|
@ -246,8 +246,8 @@ const help_item f_static_help_list[] =
|
|||||||
"Cheat Commands\n"
|
"Cheat Commands\n"
|
||||||
"Type help <command> for further details on each command\n"
|
"Type help <command> for further details on each command\n"
|
||||||
"\n"
|
"\n"
|
||||||
" cheatinit [<sign><width>[<swap>],[<address>,<length>[,<CPU>]]] -- initialize the cheat search to 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 to the cheat search 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"
|
" cheatnext <condition>[,<comparisonvalue>] -- continue cheat search comparing with the previous value\n"
|
||||||
" cheatnextf <condition>[,<comparisonvalue>] -- continue cheat search comparing with the first 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"
|
" 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",
|
"cheatinit",
|
||||||
"\n"
|
"\n"
|
||||||
" cheatinit [<sign><width>[<swap>],[<address>,<length>[,<CPU>]]]\n"
|
" cheatinit [[<sign>[<width>[<swap>]]],[<address>,<length>[,<space>]]]\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The cheatinit command initializes the cheat search to the selected memory area.\n"
|
"The cheatinit command initializes the cheat search to writable RAM areas in the specified "
|
||||||
"If no parameter is specified the cheat search is initialized to all changeable memory of the main CPU.\n"
|
"address space. The device may be specified as a tag or a debugger CPU number; if no "
|
||||||
"<sign> can be s(signed) or u(unsigned)\n"
|
"device is specified, the CPU currently visible in the debugger is assumed. If an address "
|
||||||
"<width> can be b(8 bit), w(16 bit), d(32 bit) or q(64 bit)\n"
|
"space is not specified, the first address space exposed by the device is used.\n"
|
||||||
"<swap> append s for swapped search\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"
|
"\n"
|
||||||
"Examples:\n"
|
"Examples:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"cheatinit ub,0x1000,0x10\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"
|
"\n"
|
||||||
"cheatinit sw,0x2000,0x1000,1\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"
|
"\n"
|
||||||
"cheatinit uds,0x0000,0x1000\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",
|
"cheatrange",
|
||||||
"\n"
|
"\n"
|
||||||
" cheatrange <address>,<length>\n"
|
" cheatrange <address>,<length>\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The cheatrange command adds the selected memory area to the cheat search.\n"
|
"The cheatrange command adds writable RAM areas in the range <address> through "
|
||||||
"Before using cheatrange it is necessary to initialize the cheat search with cheatinit.\n"
|
"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"
|
"\n"
|
||||||
"Examples:\n"
|
"Examples:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"cheatrange 0x1000,0x10\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",
|
"cheatnext",
|
||||||
"\n"
|
"\n"
|
||||||
" cheatnext <condition>[,<comparisonvalue>]\n"
|
" cheatnext <condition>[,<comparisonvalue>]\n"
|
||||||
"\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"
|
"Possible <condition>:\n"
|
||||||
" all\n"
|
" all\n"
|
||||||
" no <comparisonvalue> needed.\n"
|
" Use to update the last value without changing the current matches.\n"
|
||||||
" use to update the previous value without changing the current matches.\n"
|
" The <comparisonvalue> is not used.\n"
|
||||||
" equal [eq]\n"
|
" equal (eq)\n"
|
||||||
" without <comparisonvalue> search for all bytes that are equal to the previous search.\n"
|
" Without <comparisonvalue>**, search for values that are equal to the previous "
|
||||||
" with <comparisonvalue> search for all bytes that are equal to the <comparisonvalue>.\n"
|
"search.\n"
|
||||||
" notequal [ne]\n"
|
" With <comparisonvalue>, search for values that are equal to the <comparisonvalue>.\n"
|
||||||
" without <comparisonvalue> search for all bytes that are not equal to the previous search.\n"
|
" notequal (ne)\n"
|
||||||
" with <comparisonvalue> search for all bytes that are not equal to the <comparisonvalue>.\n"
|
" Without <comparisonvalue>, search for values that are not equal to the previous "
|
||||||
" decrease [de, +]\n"
|
"search.\n"
|
||||||
" without <comparisonvalue> search for all bytes that have decreased since the previous search.\n"
|
" With <comparisonvalue>, search for values that are not equal to the <comparisonvalue>.\n"
|
||||||
" with <comparisonvalue> search for all bytes that have decreased by the <comparisonvalue> since the previous search.\n"
|
" decrease (de, -)\n"
|
||||||
" increase [in, -]\n"
|
" Without <comparisonvalue>, search for values that have decreased since the previous "
|
||||||
" without <comparisonvalue> search for all bytes that have increased since the previous search.\n"
|
"search.\n"
|
||||||
" with <comparisonvalue> search for all bytes that have increased by the <comparisonvalue> since the previous search.\n"
|
" With <comparisonvalue>, search for values that have decreased by the <comparisonvalue> "
|
||||||
" decreaseorequal [deeq]\n"
|
"since the previous search.\n"
|
||||||
" no <comparisonvalue> needed.\n"
|
" increase (in, +)\n"
|
||||||
" search for all bytes that have decreased or have same value since the previous search.\n"
|
" Without <comparisonvalue>, search for values that have increased since the previous "
|
||||||
" increaseorequal [ineq]\n"
|
"search.\n"
|
||||||
" no <comparisonvalue> needed.\n"
|
" With <comparisonvalue>, search for values that have increased by the <comparisonvalue> "
|
||||||
" search for all bytes that have decreased or have same value since the previous search.\n"
|
"since the previous search.\n"
|
||||||
" smallerof [lt]\n"
|
" decreaseorequal (deeq)\n"
|
||||||
" without <comparisonvalue> this condition is invalid\n"
|
" Search for values that have decreased or are unchanged since the previous search.\n"
|
||||||
" with <comparisonvalue> search for all bytes that are smaller than the <comparisonvalue>.\n"
|
" The <comparisonvalue> is not used.\n"
|
||||||
" greaterof [gt]\n"
|
" increaseorequal (ineq)\n"
|
||||||
" without <comparisonvalue> this condition is invalid\n"
|
" Search for values that have increased or are unchanged since the previous search.\n"
|
||||||
" with <comparisonvalue> search for all bytes that are larger than the <comparisonvalue>.\n"
|
" The <comparisonvalue> is not used.\n"
|
||||||
" changedby [ch, ~]\n"
|
" smallerof (lt, <)\n"
|
||||||
" without <comparisonvalue> this condition is invalid\n"
|
" Search for values that are less than the <comparisonvalue>.\n"
|
||||||
" with <comparisonvalue> search for all bytes that have changed by the <comparisonvalue> since the previous search.\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"
|
"\n"
|
||||||
"Examples:\n"
|
"Examples:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"cheatnext increase\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"
|
"\n"
|
||||||
"cheatnext decrease, 1\n"
|
"cheatnext decrease,1\n"
|
||||||
" search for all bytes that have decreased by 1 since the previous search.\n"
|
" Search for all values that have decreased by 1 since the previous search.\n"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cheatnextf",
|
"cheatnextf",
|
||||||
"\n"
|
"\n"
|
||||||
" cheatnextf <condition>[,<comparisonvalue>]\n"
|
" cheatnextf <condition>[,<comparisonvalue>]\n"
|
||||||
"\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"
|
"Possible <condition>:\n"
|
||||||
" all\n"
|
" all\n"
|
||||||
" no <comparisonvalue> needed.\n"
|
" Use to update the last value without changing the current matches.\n"
|
||||||
" use to update the previous value without changing the current matches.\n"
|
" The <comparisonvalue> is not used.\n"
|
||||||
" equal [eq]\n"
|
" equal (eq)\n"
|
||||||
" without <comparisonvalue> search for all bytes that are equal to the initial search.\n"
|
" Without <comparisonvalue>**, search for values that are equal to the initial search.\n"
|
||||||
" with <comparisonvalue> search for all bytes that are equal to the <comparisonvalue>.\n"
|
" With <comparisonvalue>, search for values that are equal to the <comparisonvalue>.\n"
|
||||||
" notequal [ne]\n"
|
" notequal (ne)\n"
|
||||||
" without <comparisonvalue> search for all bytes that are not equal to the initial search.\n"
|
" Without <comparisonvalue>, search for values that are not equal to the initial search.\n"
|
||||||
" with <comparisonvalue> search for all bytes that are not equal to the <comparisonvalue>.\n"
|
" With <comparisonvalue>, search for values that are not equal to the <comparisonvalue>.\n"
|
||||||
" decrease [de, +]\n"
|
" decrease (de, -)\n"
|
||||||
" without <comparisonvalue> search for all bytes that have decreased since the initial search.\n"
|
" Without <comparisonvalue>, search for values that have decreased since the initial "
|
||||||
" with <comparisonvalue> search for all bytes that have decreased by the <comparisonvalue> since the initial search.\n"
|
"search.\n"
|
||||||
" increase [in, -]\n"
|
" With <comparisonvalue>, search for values that have decreased by the <comparisonvalue> "
|
||||||
" without <comparisonvalue> search for all bytes that have increased since the initial search.\n"
|
"since the initial search.\n"
|
||||||
" with <comparisonvalue> search for all bytes that have increased by the <comparisonvalue> since the initial search.\n"
|
" increase (in, +)\n"
|
||||||
" decreaseorequal [deeq]\n"
|
" Without <comparisonvalue>, search for values that have increased since the initial "
|
||||||
" no <comparisonvalue> needed.\n"
|
"search.\n"
|
||||||
" search for all bytes that have decreased or have same value since the initial search.\n"
|
" With <comparisonvalue>, search for values that have increased by the <comparisonvalue> "
|
||||||
" increaseorequal [ineq]\n"
|
"since the initial search.\n"
|
||||||
" no <comparisonvalue> needed.\n"
|
" decreaseorequal (deeq)\n"
|
||||||
" search for all bytes that have decreased or have same value since the initial search.\n"
|
" Search for values that have decreased or are unchanged since the initial search.\n"
|
||||||
" smallerof [lt]\n"
|
" The <comparisonvalue> is not used.\n"
|
||||||
" without <comparisonvalue> this condition is invalid.\n"
|
" increaseorequal (ineq)\n"
|
||||||
" with <comparisonvalue> search for all bytes that are smaller than the <comparisonvalue>.\n"
|
" Search for values that have increased or are unchanged since the initial search.\n"
|
||||||
" greaterof [gt]\n"
|
" The <comparisonvalue> is not used.\n"
|
||||||
" without <comparisonvalue> this condition is invalid.\n"
|
" smallerof (lt, <)\n"
|
||||||
" with <comparisonvalue> search for all bytes that are larger than the <comparisonvalue>.\n"
|
" Search for values that are less than the <comparisonvalue>.\n"
|
||||||
" changedby [ch, ~]\n"
|
" The <comparisonvalue> is required.\n"
|
||||||
" without <comparisonvalue> this condition is invalid\n"
|
" greaterof (gt, >)\n"
|
||||||
" with <comparisonvalue> search for all bytes that have changed by the <comparisonvalue> since the initial search.\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"
|
"\n"
|
||||||
"Examples:\n"
|
"Examples:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"cheatnextf increase\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"
|
"\n"
|
||||||
"cheatnextf decrease, 1\n"
|
"cheatnextf decrease,1\n"
|
||||||
" search for all bytes that have decreased by 1 since the initial search.\n"
|
" Search for all values that have decreased by 1 since the initial search.\n"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cheatlist",
|
"cheatlist",
|
||||||
"\n"
|
"\n"
|
||||||
" cheatlist [<filename>]\n"
|
" cheatlist [<filename>]\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Without <filename> show the list of matches in the debug console.\n"
|
"Without <filename>, show the current cheat matches in the debugger console; with "
|
||||||
"With <filename> save the list of matches in basic xml format to <filename>.\n"
|
"<filename>, save the current cheat matches in basic XML format to the specified file.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Examples:\n"
|
"Examples:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"cheatlist\n"
|
"cheatlist\n"
|
||||||
" Show the current matches in the debug console.\n"
|
" Show the current matches in the console.\n"
|
||||||
"cheatlist cheat.txt\n"
|
"cheatlist cheat.xml\n"
|
||||||
" Save the current matches to cheat.txt.\n"
|
" Save the current matches to cheat.xml in XML format.\n"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cheatundo",
|
"cheatundo",
|
||||||
"\n"
|
"\n"
|
||||||
" cheatundo\n"
|
" cheatundo\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Undo the results of the last search.\n"
|
"Undo filtering of cheat candidates by the most recent cheatnext or cheatnextf command.\n"
|
||||||
"The undo command has no effect on the last value.\n"
|
"Note that the previous values ARE NOT rolled back.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Examples:\n"
|
"Examples:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"cheatundo\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",
|
"images",
|
||||||
|
@ -39,8 +39,19 @@ namespace {
|
|||||||
|
|
||||||
menu_about::menu_about(mame_ui_manager &mui, render_container &container)
|
menu_about::menu_about(mame_ui_manager &mui, render_container &container)
|
||||||
: menu(mui, container)
|
: menu(mui, container)
|
||||||
, m_title(util::string_format(_("%1$s %2$s"), emulator_info::get_appname(), bare_build_version))
|
, m_header{
|
||||||
, m_footer(util::string_format(_("Revision: %1$s"), bare_vcs_revision))
|
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)
|
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
|
// draw the title
|
||||||
tempbuf[0] = m_title;
|
|
||||||
draw_text_box(
|
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(),
|
origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(),
|
||||||
text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false,
|
text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false,
|
||||||
ui().colors().text_color(), UI_GREEN_COLOR, 1.0f);
|
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)
|
void menu_about::populate(float &customtop, float &custombottom)
|
||||||
{
|
{
|
||||||
// make space for the title and revision
|
// make space for the title and revision
|
||||||
customtop = ui().get_line_height() + 3.0f * ui().box_tb_border();
|
customtop = (ui().get_line_height() * m_header.size()) + (ui().box_tb_border() * 3.0f);
|
||||||
custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
@ -34,8 +35,7 @@ private:
|
|||||||
virtual void populate(float &customtop, float &custombottom) override;
|
virtual void populate(float &customtop, float &custombottom) override;
|
||||||
virtual void handle() override;
|
virtual void handle() override;
|
||||||
|
|
||||||
std::string const m_title;
|
std::vector<std::string> const m_header;
|
||||||
std::string const m_footer;
|
|
||||||
std::optional<text_layout> m_layout;
|
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)
|
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