From ca338f73720ec7dedfcf8430d9dc9e481ada6378 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Wed, 13 Oct 2021 10:59:38 +1100 Subject: Various improvements to the user experience: Extended the memory access prefixes in debugger expressions to support address space names. Made the debugger history command aware of how much history it has collected, and added a help topic for it to the built-in debugger help. Started updating the documentation for the web site, and corrected some of the more misleading built-in debugger help. Made some corrections to Chinese localisation after discussion with YuiFAN. Darkened the UI red colour a little. cpu/m6502/st2205u.h: Marked sound imperfect. --- docs/source/commandline/commandline-all.rst | 11 +- docs/source/debugger/annotation.rst | 140 +++--- docs/source/debugger/expressions.rst | 77 --- docs/source/debugger/general.rst | 733 +++++++++++++++++----------- docs/source/debugger/index.rst | 364 +++++++++++++- docs/source/debugger/memory.rst | 506 ++++++++++++++----- language/Chinese_Simplified/strings.po | 10 +- language/Chinese_Traditional/strings.po | 6 +- src/devices/cpu/m6502/st2205u.h | 2 + src/emu/debug/debugcmd.cpp | 69 +-- src/emu/debug/debugcpu.cpp | 37 +- src/emu/debug/debugcpu.h | 10 +- src/emu/debug/debughlp.cpp | 167 ++++--- src/emu/debug/express.cpp | 319 ++++++------ src/emu/debug/express.h | 10 +- src/frontend/mame/ui/ui.h | 2 +- 16 files changed, 1568 insertions(+), 895 deletions(-) delete mode 100644 docs/source/debugger/expressions.rst diff --git a/docs/source/commandline/commandline-all.rst b/docs/source/commandline/commandline-all.rst index aa9cc1dd455..d803692a3bc 100644 --- a/docs/source/commandline/commandline-all.rst +++ b/docs/source/commandline/commandline-all.rst @@ -1544,13 +1544,13 @@ Core State/Playback Options The default is ``NULL`` (no recording). -.. _mame-commandline-snapname: - Example: .. code-block:: bash mame pacman -wavewrite pacsounds +.. _mame-commandline-snapname: + **-snapname** ** Describes how MAME should name files for snapshots. is a string that @@ -3445,9 +3445,10 @@ Debugging Options **-[no]debug** - Activates the integrated debugger. By default, the debugger is entered by - pressing the tilde (**~**) key during emulation. It is also entered - immediately at startup. + Activates the integrated debugger. By default, pressing the tilde + (**~**) key during emulation breaks into the debugger. MAME also + breaks into the debugger after the initial soft reset on startup if + the debugger is active. The default is OFF (**-nodebug**). diff --git a/docs/source/debugger/annotation.rst b/docs/source/debugger/annotation.rst index 9d897d140c9..4e766257099 100644 --- a/docs/source/debugger/annotation.rst +++ b/docs/source/debugger/annotation.rst @@ -3,101 +3,107 @@ Code Annotation Debugger Commands ================================= +:ref:`debugger-command-comadd` + adds a comment to the disassembled code at given address +:ref:`debugger-command-comdelete` + removes a comment from the given address +:ref:`debugger-command-comsave` + save the current comments to file +:ref:`debugger-command-comlist` + list comments stored in the comment file for the system +:ref:`debugger-command-commit` + combined ``comadd`` and ``comsave`` command -You can also type **help ** for further details on each command in the MAME Debugger interface. -| :ref:`debugger-command-comadd` -- adds a comment to the disassembled code at given address -| :ref:`debugger-command-comdelete` -- removes a comment from the given address -| :ref:`debugger-command-comsave` -- save the current comments to a file -| :ref:`debugger-command-comlist` -- print currently available comments from file -| :ref:`debugger-command-commit` -- gives a bulk comadd then comsave command - - - .. _debugger-command-comadd: +.. _debugger-command-comadd: comadd ------ -| **comadd[//]
,** -| -| Adds a string to the disassembled code at
. The shortcut for this command is simply '//' -| -| Examples: -| -| comadd 0, hello world. -| -| Adds the comment 'hello world.' to the code at address 0x0 -| -| // 10, undocumented opcode! -| -| Adds the comment 'undocumented opcode!' to the code at address 0x10 +**comadd
,** + +Sets the specified comment for the specified address in the disassembled +code for the visible CPU. This command may be abbreviated to ``//``. + +Examples: + +``comadd 0,hello world.`` + Adds the comment “hello world.” to the code at address 0. +``// 10,undocumented opcode!`` + Adds the comment “undocumented opcode!” to the code at address 10. - .. _debugger-command-comdelete: +.. _debugger-command-comdelete: comdelete --------- -| **comdelete** -| -| Deletes the comment at the specified memory offset. The comment which is deleted is in the currently active memory bank. -| -| Examples: -| -| comdelete 10 -| -| Deletes the comment at code address 0x10 (using the current memory bank settings) +**comdelete** +Deletes the comment at the specified address for the visible CPU. - .. _debugger-command-comsave: +Examples: + +``comdelete 10`` + Deletes the comment at code address 10 for the visible CPU. + + +.. _debugger-command-comsave: comsave ------- -| **comsave** -| -| Saves the working comments to the driver's XML comment file. -| -| Examples: -| -| comsave -| -| Saves the comments to the driver's comment file +**comsave** + +Saves the current comments to the XML comment file for the emulated +system. This file will be loaded by the debugger the next time the +system is run with debugging enabled. The directory for saving these +files is set using the +:ref:`comment_directory ` option. +Examples: - .. _debugger-command-comlist: +``comsave`` + Saves the current comments to the comment file for the system. + + +.. _debugger-command-comlist: comlist ------- -| **comlist** -| -| Prints the currently available comment file in human readable form in debugger output window. -| -| Examples: -| -| comlist -| -| Shows currently available comments. +**comlist** + +Reads the comments stored in the XML comment file for the emulated +system and prints them to the debugger console. This command does not +affect the comments for the current session, it reads the file directly. +The directory for these files is set using the +:ref:`comment_directory ` option. + +Examples: + +comlist + Shows comments stored in the comment file for the system. - .. _debugger-command-commit: +.. _debugger-command-commit: commit ------ -| **commit[/*]
,** -| -| Adds a string to the disassembled code at
then saves to file. Basically same as comadd + comsave via a single line. -| The shortcut for this command is simply \'\/\*\' -| -| Examples: -| -| commit 0, hello world. -| -| Adds the comment 'hello world.' to the code at address 0x0 -| -| /* 10, undocumented opcode! -| -| Adds the comment 'undocumented opcode!' to the code at address 0x10 +**commit
,** + +Sets the specified comment for the specified address in the disassembled +code for the visible CPU, and saves comments to the file for the current +emulated system (equivalent to :ref:`debugger-command-comadd` followed +by :ref:`debugger-command-comsave`). This command may be abbreviated to +``/*``. + +Examples: +``commit 0,hello world.`` + Adds the comment “hello world.” to the code at address 0 for the + visible CPU and saves comments. +``/* 10,undocumented opcode!`` + Adds the comment “undocumented opcode!” to the code at address 10 + for the visible CPU and saves comments. diff --git a/docs/source/debugger/expressions.rst b/docs/source/debugger/expressions.rst deleted file mode 100644 index cc6ad27377a..00000000000 --- a/docs/source/debugger/expressions.rst +++ /dev/null @@ -1,77 +0,0 @@ -.. _debugger-expressions-list: - -Debugger Expressions Guide -========================== - - -Expressions can be used anywhere a numeric parameter is expected. The syntax for expressions is very close to standard C-style syntax with full operator ordering and parentheses. There are a few operators missing (notably the trinary ? : operator), and a few new ones (memory accessors). The table below lists all the operators in their order, highest precedence operators first. - -| -| ( ) : standard parentheses -| ++ -- : postfix increment/decrement -| ++ -- ~ ! - + b@ w@ d@ q@ : prefix inc/dec, binary NOT, logical NOT, unary +/-, memory access -| * / % : multiply, divide, modulus -| + - : add, subtract -| << >> : shift left/right -| < <= > >= : less than, less than or equal, greater than, greater than or equal -| == != : equal, not equal -| & : binary AND -| ^ : binary XOR -| | : binary OR -| && : logical AND -| || : logical OR -| = \*= /= %= += -= <<= >>= &= \|= ^= : assignment -| , : separate terms, function parameters -| -| - -Numbers -------- - -Numbers are prefixed according to their bases: - -- Hexadecimal (base-16) numbers are prefixed with :code:`$` or :code:`0x`. - -- Decimal (base-10) numbers are prefixed with :code:`#`. - -- Octal (base-8) numbers are prefixed with :code:`0o`. - -- Binary (base-2) numbers are prefixed with :code:`0b`. - -- Unprefixed numbers are hexadecimal (base-16). - -Examples: - -- :code:`123` is 123 hexadecimal (291 decimal). - -- :code:`$123` is 123 hexadecimal (291 decimal). - -- :code:`0x123` is 123 hexadecimal (291 decimal). - -- :code:`#123` is 123 decimal. - -- :code:`0o123` is 123 octal (83 decimal). - -- :code:`0b1001` is 9 decimal. - -- :code:`0b123` is invalid. - -Differences from C Behaviors ----------------------------- - - -- First, all math is performed on full 64-bit unsigned values, so things like **a < 0** won't work as expected. - -- Second, the logical operators **&&** and **||** do not have short-circuit properties -- both halves are always evaluated. - -- Finally, the new memory operators work like this: - - - **b!** refers to the byte at but does *NOT* suppress side effects such as reading a mailbox clearing the pending flag, or reading a FIFO removing an item. - - - **b@** refers to the byte at while suppressing side effects. - - - Similarly, **w@** and **w!** refer to a *word* in memory, **d@** and **d!** refer to a *dword* in memory, and **q@** and **q!** refer to a *qword* in memory. - - The memory operators can be used as both lvalues and rvalues, so you can write **b\@100 = ff** to store a byte in memory. By default these operators read from the program memory space, but you can override that by prefixing them with a 'd' or an 'i'. - - As such, **dw\@300** refers to data memory word at address 300 and **id\@400** refers to an I/O memory dword at address 400. diff --git a/docs/source/debugger/general.rst b/docs/source/debugger/general.rst index 752ec677841..db1a1933149 100644 --- a/docs/source/debugger/general.rst +++ b/docs/source/debugger/general.rst @@ -3,383 +3,532 @@ General Debugger Commands ========================= - -You can also type **help ** for further details on each command in the MAME Debugger interface. - -| :ref:`debugger-command-do` -- evaluates the given expression -| :ref:`debugger-command-symlist` -- lists registered symbols -| :ref:`debugger-command-softreset` -- executes a soft reset -| :ref:`debugger-command-hardreset` -- executes a hard reset -| :ref:`debugger-command-print` -- prints one or more s to the console -| :ref:`debugger-command-printf` -- prints one or more s to the console using -| :ref:`debugger-command-logerror` -- outputs one or more s to the error.log -| :ref:`debugger-command-tracelog` -- outputs one or more s to the trace file using -| :ref:`debugger-command-tracesym` -- outputs one or more s to the trace file -| history -- outputs a brief history of visited opcodes (**to fix: help missing for this command**) -| :ref:`debugger-command-trackpc` -- visually track visited opcodes [boolean to turn on and off, for the given CPU, clear] -| :ref:`debugger-command-trackmem` -- record which PC writes to each memory address [boolean to turn on and off, clear] -| :ref:`debugger-command-pcatmem` -- query which PC wrote to a given memory address for the current CPU -| :ref:`debugger-command-rewind` -- go back in time by loading the most recent rewind state -| :ref:`debugger-command-statesave` -- save a state file for the current driver -| :ref:`debugger-command-stateload` -- load a state file for the current driver -| :ref:`debugger-command-snap` -- save a screen snapshot. -| :ref:`debugger-command-source` -- reads commands from and executes them one by one -| :ref:`debugger-command-quit` -- exits MAME and the debugger - - - .. _debugger-command-do: +:ref:`debugger-command-do` + evaluates the given expression +:ref:`debugger-command-symlist` + lists registered symbols +:ref:`debugger-command-softreset` + executes a soft reset +:ref:`debugger-command-hardreset` + executes a hard reset +:ref:`debugger-command-print` + prints one or more s to the console +:ref:`debugger-command-printf` + prints one or more s to the console using +:ref:`debugger-command-logerror` + outputs one or more s to the error.log +:ref:`debugger-command-tracelog` + outputs one or more s to the trace file using +:ref:`debugger-command-tracesym` + outputs one or more s to the trace file +:ref:`debugger-command-history` + displays recently visited PC addresses and opcodes +:ref:`debugger-command-trackpc` + visually track visited opcodes +:ref:`debugger-command-trackmem` + record which PC writes to each memory address +:ref:`debugger-command-pcatmem` + query which PC wrote to a given memory address +:ref:`debugger-command-rewind` + go back in time by loading the most recent rewind state +:ref:`debugger-command-statesave` + save a state file for the emulated system +:ref:`debugger-command-stateload` + load a state file for the emulated system +:ref:`debugger-command-snap` + save a screen snapshot +:ref:`debugger-command-source` + read commands from file and executes them one by one +:ref:`debugger-command-quit` + exit the debugger and end the emulation session + + +.. _debugger-command-do: do -- -| **do ** -| -| The do command simply evaluates the given . This is typically used to set or modify variables. -| -| Examples: -| -| do pc = 0 -| -| Sets the register 'pc' to 0. -| -| Back to :ref:`debugger-general-list` +**do ** + +The **do** command simply evaluates the supplied expression. This is +often used to set or modify device state variable (e.g. CPU registers), +or to write to memory. See :ref:`debugger-expressions` for details +about expression syntax. + +Examples: + +``do pc = 0`` + Sets the register **pc** to 0. - .. _debugger-command-symlist: +Back to :ref:`debugger-general-list` + + +.. _debugger-command-symlist: symlist ------- -| **symlist []** -| -| Lists registered symbols. If is not specified, then symbols in the global symbol table are displayed; otherwise, the symbols for 's specific CPU are displayed. Symbols are listed alphabetically. Read-only symbols are flagged with an asterisk. -| -| Examples: -| -| symlist -| -| Displays the global symbol table. -| -| symlist 2 -| -| Displays the symbols specific to CPU #2. -| -| Back to :ref:`debugger-general-list` - - - .. _debugger-command-softreset: +**symlist []** + +Lists registered symbols and their values. If **** is not +specified, symbols in the global symbol table are displayed; otherwise, +symbols specific to the device **** are displayed. Symbols are +listed alphabetically. Read-only symbols are noted. See +:ref:`debugger-devicespec` for details on how to specify a CPU. + +Examples: + +``symlist`` + Displays the global symbol table. +``symlist 2`` + Displays the symbols for the third CPU in the system (zero-based + index). +``symlist audiocpu`` + Displays symbols for the CPU with the absolute tag ``:audiocpu``. + +Back to :ref:`debugger-general-list` + + +.. _debugger-command-softreset: softreset --------- -| **softreset** -| -| Executes a soft reset. -| -| Examples: -| -| softreset -| -| Executes a soft reset. -| -| Back to :ref:`debugger-general-list` +**softreset** + +Executes a soft reset. This calls the reset member functions of all the +devices in the system (by default, pressing **F3** during emulation has +the same effect). + +Examples: +``softreset`` + Executes a soft reset. - .. _debugger-command-hardreset: +Back to :ref:`debugger-general-list` + + +.. _debugger-command-hardreset: hardreset --------- -| **hardreset** -| -| Executes a hard reset. -| -| Examples: -| -| hardreset -| -| Executes a hard reset. -| -| Back to :ref:`debugger-general-list` +**hardreset** + +Executes a hard reset. This tears down the emulation session and starts +another session with the same system and options (by default, pressing +**Shift+F3** during emulation has the same effect). Note that this will +lose history in the debugger console and error log. + +Examples: +``hardreset`` + Executes a hard reset. - .. _debugger-command-print: +Back to :ref:`debugger-general-list` + + +.. _debugger-command-print: print ----- -| **print [,...]** -| -| The print command prints the results of one or more expressions to the debugger console as hexadecimal values. -| -| Examples: -| -| print pc -| -| Prints the value of 'pc' to the console as a hex number. -| -| print a,b,a+b -| -| Prints a, b, and the value of a+b to the console as hex numbers. -| -| Back to :ref:`debugger-general-list` - - - .. _debugger-command-printf: +**print [,...]** + +The **print** command prints the results of one or more expressions to +the debugger console as hexadecimal numbers. + +Examples: + +``print pc`` + Prints the value of the **pc** register the console as a hex number. +``print a,b,a+b`` + Prints **a**, **b**, and the value of **a+b** to the console as hex + numbers. + +Back to :ref:`debugger-general-list` + + +.. _debugger-command-printf: printf ------ -| **printf [,[,...]]** -| -| The printf command performs a C-style printf to the debugger console. Only a very limited set of formatting options are available: -| -| %[0][]d -- prints as a decimal value with optional digit count and zero-fill -| %[0][]x -- prints as a hexadecimal value with optional digit count and zero-fill -| -| All remaining formatting options are ignored. Use %% together to output a % character. Multiple lines can be printed by embedding a \\n in the text. -| -| Examples: -| -| printf "PC=%04X",pc -| -| Prints PC= where is displayed in hexadecimal with 4 digits with zero-fill. -| -| printf "A=%d, B=%d\\nC=%d",a,b,a+b -| -| Prints A=, B= on one line, and C= on a second line. -| -| Back to :ref:`debugger-general-list` - - - .. _debugger-command-logerror: +**printf [,[,...]]** + +Prints a C-style formatted message to the debugger console. Only a +very limited subset of format specifiers and escape sequences are +available: + +%c + Prints the corresponding argument as an 8-bit character. +%[0][]d + Prints the corresponding argument as a decimal number with optional + minimum field width and zero fill. +%[0][]o + Prints the corresponding argument as an octal number with optional + minimum field width and zero fill using lowercase letters. +%[0][]x + Prints the corresponding argument as a hexadecimal number with + optional minimum field width and zero fill using uppercase letters. +\%% + Prints a literal percent symbol. +\\n + Prints a line break. +**\\\\** + Prints a literal backslash. + +All other format specifiers are ignored. + +Examples: + +``printf "PC=%04X",pc`` + Prints ``PC=`` where **** is the hexadecimal value of + the **pc** register with a minimum of four digits and zero fill. +``printf "A=%d, B=%d\\nC=%d",a,b,a+b`` + Prints ``A=, B=`` on one line, and ``C=`` on a + second line. + +Back to :ref:`debugger-general-list` + + +.. _debugger-command-logerror: logerror -------- -| **logerror [,[,...]]** -| -| The logerror command performs a C-style printf to the error log. Only a very limited set of formatting options are available: -| -| %[0][]d -- logs as a decimal value with optional digit count and zero-fill -| %[0][]x -- logs as a hexadecimal value with optional digit count and zero-fill -| -| All remaining formatting options are ignored. Use %% together to output a % character. Multiple lines can be printed by embedding a \\n in the text. -| -| Examples: -| -| logerror "PC=%04X",pc -| -| Logs PC= where is displayed in hexadecimal with 4 digits with zero-fill. -| -| logerror "A=%d, B=%d\\nC=%d",a,b,a+b -| -| Logs A=, B= on one line, and C= on a second line. -| -| Back to :ref:`debugger-general-list` - - - .. _debugger-command-tracelog: +**logerror [,[,...]]** + +Prints a C-style formatted message to the error log. See +:ref:`debugger-command-printf` for details about the limited set of +supported format specifiers and escape sequences. + +Examples: + +``logerror "PC=%04X",pc`` + Logs ``PC=`` where **** is the hexadecimal value of + the **pc** register with a minimum of four digits and zero fill. +``logerror "A=%d, B=%d\\nC=%d",a,b,a+b`` + Logs ``A=, B=`` on one line, and ``C=`` on a + second line. + +Back to :ref:`debugger-general-list` + + +.. _debugger-command-tracelog: tracelog -------- -| **tracelog [,[,...]]** -| -| The tracelog command performs a C-style printf and routes the output to the currently open trace file (see the 'trace' command for details). If no file is currently open, tracelog does nothing. Only a very limited set of formatting options are available. See the :ref:`debugger-command-printf` help for details. -| -| Examples: -| -| tracelog "PC=%04X",pc -| -| Outputs PC= where is displayed in hexadecimal with 4 digits with zero-fill. -| -| printf "A=%d, B=%d\\nC=%d",a,b,a+b -| -| Outputs A=, B= on one line, and C= on a second line. -| -| Back to :ref:`debugger-general-list` - - - .. _debugger-command-tracesym: +**tracelog [,[,...]]** + +Prints a C-style formatted message to the currently open trace file (see +:ref:`debugger-command-trace` for more information). If no trace file +is open, this command has no effect. See :ref:`debugger-command-printf` +for details about the limited set of supported format specifiers and +escape sequences. + +Examples: + +``tracelog "PC=%04X",pc`` + Outputs ``PC=`` where **** is the hexadecimal value of + the **pc** register with a minimum of four digits and zero fill if a + trace log file is open. +``tracelog "A=%d, B=%d\\nC=%d",a,b,a+b`` + Outputs ``A=, B=`` on one line, and ``C=`` on a + second line if a trace log file is open. + +Back to :ref:`debugger-general-list` + + +.. _debugger-command-tracesym: tracesym -------- -| **tracesym [,...]** -| -| The tracesym command prints the specified symbols and routes the output to the currently open trace file (see the 'trace' command for details). If no file is currently open, tracesym does nothing. -| -| Examples: -| -| tracelog pc -| -| Outputs PC= where is displayed in the default format. -| -| Back to :ref:`debugger-general-list` +**tracesym [,...]** + +Prints the specified symbols to the currently open trace file (see +:ref:`debugger-command-trace` for more information). If no trace file +is open, this command has no effect. + +Examples: + +``tracesym pc`` + Outputs ``PC=`` where **** is the value of the **pc** + register in its default format if a trace log file is open. + +Back to :ref:`debugger-general-list` + + +.. _debugger-command-history: + +history +------- +**history [[,]]** - .. _debugger-command-trackpc: +Displays recently visited PC addresses, and disassembly of the +instructions at those addresses. If present, the first argument selects +the CPU (see :ref:`debugger-devicespec` for details); if no CPU is +specified, the visible CPU is assumed. The second argument, if present, +limits the maximum number of addresses shown. Addresses are shown in +order from least to most recently visited. + +Examples: + +``history ,5`` + Displays up to five most recently visited PC addresses and + instructions for the visible CPU. +``history 3`` + Displays recently visited PC addresses and instructions for the + fourth CPU in the system (zero-based index). +``history audiocpu,1`` + Displays the most recently visited PC address and instruction for + the CPU with the absolute tag ``:audiocpu``. + + +.. _debugger-command-trackpc: trackpc ------- -| **trackpc [,,]** -| -| The trackpc command displays which program counters have already been visited in all disassembler windows. The first boolean argument toggles the process on and off. The second argument is a CPU selector; if no CPU is specified, the current CPU is automatically selected. The third argument is a boolean denoting if the existing data should be cleared or not. -| -| Examples: -| -| trackpc 1 -| -| Begin tracking the current CPU's pc. -| -| trackpc 1, 0, 1 -| -| Continue tracking pc on CPU 0, but clear existing track info. -| -| Back to :ref:`debugger-general-list` - - - .. _debugger-command-trackmem: +**trackpc [[,[,]]]** + +Turns visited PC address tracking for disassembly views on or off. +Instructions at addresses visited while tracking is on are highlighted +in debugger disassembly views. The first argument is a Boolean +specifying whether tracking should be turned on or off (defaults to on). +The second argument specifies the CPU to enable or disable tracking for +(see :ref:`debugger-devicespec` for details); if no CPU is specified, +the visible CPU is assumed. The third argument is a Boolean specifying +whether existing data should be cleared (defaults to false). + +Examples: + +``trackpc 1`` + Begin or tracking the current CPU’s PC. +``trackpc 1,0,1`` + Begin or continue tracking PC on the first CPU in the system + (zero-based index), but clear the history tracked so far. + +Back to :ref:`debugger-general-list` + + +.. _debugger-command-trackmem: trackmem -------- -| **trackmem [,,]** -| -| The trackmem command logs the PC at each time a memory address is written to. The first boolean argument toggles the process on and off. The second argument is a CPU selector; if no CPU is specified, the current CPU is automatically selected. The third argument is a boolean denoting if the existing data should be cleared or not. Please refer to the pcatmem command for information on how to retrieve this data. Also, right clicking in a memory window will display the logged PC for the given address. -| -| Examples: -| -| trackmem -| -| Begin tracking the current CPU's pc. -| -| trackmem 1, 0, 1 -| -| Continue tracking memory writes on CPU 0, but clear existing track info. -| -| Back to :ref:`debugger-general-list` - - - .. _debugger-command-pcatmem: +**trackmem [,[,[]]]** + +Enables or disables logging the PC address each time a memory address is +written to. The first argument is a Boolean specifying whether tracking +should be enabled or disabled (defaults to enabled). The second +argument specifies the CPU to enable or disable tracking for (see +:ref:`debugger-devicespec` for details); if no CPU is specified, the +visible CPU is assumed. The third argument is a Boolean specifying +whether existing data should be cleared (defaults to false). + +Use :ref:`debugger-command-pcatmem` to retrieve this data. +Right-clicking a debugger memory view will also display the logged PC +value for the given address in some configurations. + +Examples: + +``trackmem`` + Begin or continue tracking memory writes for the visible CPU. +``trackmem 1,0,1`` + Begin or continue tracking memory writes for the first CPU in the + system (zero-based index), but clear existing tracking data. + +Back to :ref:`debugger-general-list` + + +.. _debugger-command-pcatmem: pcatmem ------- -| **pcatmem(p/d/i)
[,]** -| -| **pcatmemp
[,]** -- query which PC wrote to a given program memory address for the current CPU -| **pcatmemd
[,]** -- query which PC wrote to a given data memory address for the current CPU -| **pcatmemi
[,]** -- query which PC wrote to a given I/O memory address for the current CPU (you can also query this info by right clicking in a memory window) -| -| The pcatmem command returns which PC wrote to a given memory address for the current CPU. The first argument is the requested address. The second argument is a CPU selector; if no CPU is specified, the current CPU is automatically selected. Right clicking in a memory window will also display the logged PC for the given address. -| -| Examples: -| -| pcatmem 400000 -| -| Print which PC wrote this CPU's memory location 0x400000. -| -| Back to :ref:`debugger-general-list` - - - .. _debugger-command-rewind: +**pcatmem[{d|i|o}]
[:]** + +Returns the PC value at the time the specified address was most recently +written to. The argument is the requested address, optionally followed +by a colon and a CPU and/or address space (see +:ref:`debugger-devicespec` for details). The optional **d**, **i** or +**o** suffix controls the default address space for the command. + +Tracking must be enabled for the data this command uses to be recorded +(see :ref:`debugger-command-trackmem`). Right-clicking a debugger +memory view will also display the logged PC value for the given address +in some configurations. + +Examples: + +``pcatmem 400000`` + Print the PC value when location 400000 in the visible CPU’s program + space was most recently written. +``pcatmem 3bc:io`` + Print the PC value when location 3bc in the visible CPU’s ``io`` + space was most recently written. +``pcatmem 1400:audiocpu`` + Print the PC value when location 1400 in the CPU ``:audiocpu``’s + program space was most recently written. + +Back to :ref:`debugger-general-list` + + +.. _debugger-command-rewind: rewind ------ -| **rewind[rw]** -| -| The rewind command loads the most recent RAM-based state. Rewind states, when enabled, are saved when "step", "over", or "out" command gets executed, storing the machine state as of the moment before actually stepping. 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" or "reverse-next". All output for this command is currently echoed into the running machine window. Previous memory and PC tracking statistics are cleared, actual reverse execution does not occur. -| -| Back to :ref:`debugger-general-list` +**rewind** + +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. +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. +All output for this command is currently echoed into the running machine +window. + +Previous memory and PC tracking statistics are cleared. Actual reverse +execution does not occur. + +Examples: +``rewind`` + Load the previous RAM-based save state. +``rw`` + Abbreviated form of the command. - .. _debugger-command-statesave: +Back to :ref:`debugger-general-list` + + +.. _debugger-command-statesave: statesave --------- -| **statesave[ss] ** -| -| The statesave command creates a save state at this exact moment in time. The given state file gets written to the standard state directory (sta), and gets .sta added to it - no file extension necessary. All output for this command is currently echoed into the running machine window. -| -| Examples: -| -| statesave foo -| -| Writes file 'foo.sta' in the default state save directory. -| -| Back to :ref:`debugger-general-list` +**statesave ** + +Creates a save state at the current moment in emulated time. The state +file is written to the configured save state directory (see the +:ref:`state_directory ` option), and +the **.sta** extension is automatically appended to the specified file +name. + +All output from this command is currently echoed into the running machine +window. + +Examples: + +``statesave foo`` + Saves the emulated machine state to the file **foo.sta** in the + configured save state directory. +``ss bar`` + Abbreviated form of the command – saves the emulated machine state + to **bar.sta**. + +Back to :ref:`debugger-general-list` - .. _debugger-command-stateload: +.. _debugger-command-stateload: stateload --------- -| **stateload[sl] ** -| -| The stateload command retrieves a save state from disk. The given state file gets read from the standard state directory (sta), and gets .sta added to it - no file extension necessary. All output for this command is currently echoed into the running machine window. Previous memory and PC tracking statistics are cleared. -| -| Examples: -| -| stateload foo -| -| Reads file 'foo.sta' from the default state save directory. -| -| Back to :ref:`debugger-general-list` +**stateload ** +Restores a saved state file from disk. The specified state file is read +from the configured save state directory (see the +:ref:`state_directory ` option), and the +**.sta** extension is automatically appended to the specified file name. - .. _debugger-command-snap: +All output for this command is currently echoed into the running machine +window. Previous memory and PC tracking statistics are cleared. + +Examples: + +``stateload foo`` + Loads state from file **foo.sta** to the configured save state + directory. +``sl bar`` + Abbreviated form of the command – loads the file **bar.sta**. + +Back to :ref:`debugger-general-list` + + +.. _debugger-command-snap: snap ---- -| **snap [[], ]** -| -| The snap command takes a snapshot of the current video display and saves it to the configured snapshot directory. If is specified explicitly, a single screenshot for is saved under the requested filename. If is omitted, all screens are saved using the same default rules as the "save snapshot" key in MAME proper. -| -| Examples: -| -| snap -| -| Takes a snapshot of the current video screen and saves to the next non-conflicting filename in the configured snapshot directory. -| -| snap shinobi -| -| Takes a snapshot of the current video screen and saves it as 'shinobi.png' in the configured snapshot directory. -| -| Back to :ref:`debugger-general-list` - - - .. _debugger-command-source: +**snap [[,]]** + +Takes a snapshot of the emulated video display and saves it to the +configured snapshot directory (see the +:ref:`snapshot_directory ` option). +If a file name is specified, a single screenshot for the specified +screen is saved using the specified filename (or the first emulated +screen in the system if a screen is not specified). If a file name is +not specified, the configured snapshot view and file name pattern are +used (see the :ref:`snapview ` and +:ref:`snapname ` options). + +If a file name is specified, the **.png** extension is automatically +appended. The screen number is specified as a zero-based index, as +seen in the names of automatically-generated single-screen views in +MAME’s video options menus. + +Examples: + +``snap`` + Takes a snapshot using the configured snapshot view and file name + options. +``snap shinobi`` + Takes a snapshot of the first emulated video screen and saves it as + **shinobi.png** in the configured snapshot directory. + +Back to :ref:`debugger-general-list` + + +.. _debugger-command-source: source ------ -| **source ** -| -| The source command reads in a set of debugger commands from a file and executes them one by one, similar to a batch file. -| -| Examples: -| -| source break_and_trace.cmd -| -| Reads in debugger commands from break_and_trace.cmd and executes them. -| -| Back to :ref:`debugger-general-list` +**source ** + +Reads the specified file in text mode and executes each line as a +debugger command. This is similar to running a shell script or batch +file. +Examples: - .. _debugger-command-quit: +``source break_and_trace.cmd`` + Reads and executes debugger commands from **break_and_trace.cmd**. + +Back to :ref:`debugger-general-list` + + +.. _debugger-command-quit: quit ---- -| **quit** -| -| The quit command exits MAME immediately. -| -| Back to :ref:`debugger-general-list` +**quit** + +Closes the debugger and ends the emulation session immediately. Either +exits MAME or returns to the system selection menu, depending on whether +the system was specified on the command line when starting MAME. + +Examples: + +``quit`` + Exits the emulation session immediately. +Back to :ref:`debugger-general-list` diff --git a/docs/source/debugger/index.rst b/docs/source/debugger/index.rst index fb8f3abe3fe..639a1d1d535 100644 --- a/docs/source/debugger/index.rst +++ b/docs/source/debugger/index.rst @@ -1,18 +1,354 @@ +.. _debugger: + MAME Debugger -------------------- +============= + +.. contents:: :local: + + +.. _debugger-intro: + +Introduction +------------ + +MAME includes an interactive low-level debugger that target the emulated +system. This can be a useful tool for diagnosing emulation issues, +developing software to run on vintage systems, creating cheats, ROM +hacking, or just looking at how software works. + +Use the ``-debug`` command line option to start MAME with the debugger +activated. By default, pressing the tilde (**~**) during emulation +breaks into the debugger. + +The exact appearance of the debugger depends on your operating system +and the options MAME was built with. All variants of the debugger +provide a multi-window interface for viewing the contents of memory and +disassembled code. -This section covers the built-in MAME debugger, which is invoked with the -debug switch on the command line. +The debugger console window is a special window that shows the contents +of CPU registers and disassembled code around the current program +counter address, and provides a command-line interface to most of the +debugging functionality. + + +.. _debugger-sections-list: + +Debugger commands +----------------- + +Debugger commands are described in the sections below. You can also +type **help ** in the debugger console, where **** is the +name of a command, to see documentation directly in MAME. .. toctree:: - :titlesonly: - - general - memory - execution - breakpoint - watchpoint - registerpoints - annotation - cheats - image - expressions + :titlesonly: + + general + memory + execution + breakpoint + watchpoint + registerpoints + annotation + cheats + image + + +.. _debugger-devicespec: + +Specifying devices and address spaces +------------------------------------- + +Many debugger commands accept parameters specifying which device to +operate on. If a device is not specified explicitly, the CPU currently +visible in the debugger is used. Devices can be specified by tag, or by +CPU number: + +* Tags are the colon-separated paths that MAME uses to identify devices + within a system. You see them in options for configuring slot + devices, in debugger disassembly and memory viewer source lists, and + various other places within MAME’s UI. +* CPU numbers are monotonically incrementing numbers that the debugger + assigns to CPU-like devices within a system, starting at zero. The + **cpunum** symbol holds the CPU number for the currently visible CPU + in the debugger (you can see it by entering the command + **print cpunum** in the debugger console). + +If a tag starts with a caret (**^**) or dot (**.**), it is interpreted +relative to the CPU currently visible in the debugger, otherwise it is +interpreted relative to the root machine device. If a device argument +is ambiguously valid as both a tag and a CPU number, it will be +interpreted as a tag. + +Examples: + +``maincpu`` + The device with the absolute tag ``:maincpu``. +``^melodypsg`` + The sibling device of the visible CPU with the tag ``melodypsg``. +``.:adc`` + The child device of the visible CPU with the tag ``adc``. +``2`` + The third CPU-like device in the system (zero-based index). + +Commands that operate on memory extend this by allowing the device tag +or CPU number to be optionally followed by an address space identifier. +Address space identifiers are tag-like strings. You can see them in +debugger memory viewer source lists. If the address space identifier is +omitted, a default address space will be used. Usually, this is the +address space that appears first for the device. Many commands have +variants with **d**, **i** and **o** (data, I/O and opcodes) suffixes +that default to the address spaces at indices 1, 2 and 3, respectively, +as these have special significance for CPU-like devices. + +In ambiguous cases, the default address space of a child device will be +used rather than a specific address space. + +Examples: + +``ram`` + The default address space of the device with the absolute tag + ``:ram``, or the ``ram`` space of the visible CPU. +``.:io`` + The default address space of the child device of the visible CPU + with the tag ``io``, or the ``io`` space of the visible CPU. +``:program`` + The default address space of the device with the absolute tag + ``:program``, or the ``program`` space of the root machine device. +``^vdp`` + The default address space of the sibling device of the visible CPU + with the tag ``vdp``. +``^:data`` + The default address space of the sibling device of the visible CPU + with the tag ``data``, or the ``data`` space of the parent device + of the visible CPU. +``1:rom`` + The default address space of the child device of the second CPU in + the system (zero-based index) with the tag ``rom``, or the ``rom`` + space of the second CPU in the system. +``2`` + The default address space of the third CPU-like device in the system + (zero-based index). + +If a command takes an emulated memory address as a parameter, the +address may optionally be followed by an address space specification, as +described above. + +Examples: + +``0220`` + Address 0220 in the default address space for the visible CPU. +``0378:io`` + Address 0378 in the default address space of the device with the + absolute tag ``:io``, or the ``io`` space of the visible CPU. +``1234:.:rom`` + Address 1234 in the default address space of the child device of the + visible CPU with the tag ``:rom``, or the ``rom`` space of the + visible CPU. +``1260:^vdp`` + Address 1260 in the default address space of the sibling device of + the visible CPU with the tag ``vdp``. +``8008:^:data`` + Address 8008 in the default address space of the sibling device of + the visible CPU with the tag ``data``, or the ``data`` space of the + parent device of the visible CPU. +``9660::ram`` + Address 9660 in the default address space of the device with the + absolute tag ``:ram``, or the ``ram`` space of the root machine + device. + +The examples here include a lot of corner cases, but in general the +debugger should take the most likely meaning for a device or address +space specification. + + +.. _debugger-expressions: + +Debugger expression syntax +-------------------------- + +Expressions can be used anywhere a numeric or Boolean parameter is +expected. The syntax for expressions is similar to a subset of C-style +expression syntax, with full operator precedence and parentheses. There +are a few operators missing (notably the ternary conditional operator), +and a few new ones (memory accessors). + +The table below lists all the operators, ordered from highest to lowest +precedence: + +( ) + Standard parentheses +++ -- + Postfix increment/decrement +++ -- ~ ! - + b@ w@ d@ q@ b! w! d! q! + Prefix increment/decrement, binary complement, logical complement, + unary identity/negation, memory access +\* / % + Multiplication, division, modulo +\+ - + Addition, subtraction +<< >> + Bitwise left/right shift +< <= > >= + Less than, less than or equal, greater than, greater than or equal +== != + Equal, not equal +\& + Bitwise intersection (and) +\^ + Bitwise exclusive or +\| + Bitwise union (or) +\&& + Logical conjunction (and) +\|| + Logical disjunction (or) += \*= /= %= += -= <<= >>= &= \|= ^= + Assignment and modifying assignment +\, + Separate terms, function parameters + +Major differences from C expression semantics: + +* All numbers are unsigned 64-bit values. In particular, this means + negative numbers are not possible. +* The logical conjunction and disjunction operators ``&&`` and ``||`` do + not have short-circuit properties – both sides of the expression are + always evaluated. + + +Numbers +~~~~~~~ + +Literal numbers are prefixed according to their bases: + +* Hexadecimal (base-16) with ``$`` or ``0x`` +* Decimal (base-10) with ``#`` +* Octal (base-8) with ``0o`` +* Binary (base-2) with ``0b`` +* Unprefixed numbers are hexadecimal (base-16). + +Examples: + +* ``123`` is 123 hexadecimal (291 decimal) +* ``$123`` is 123 hexadecimal (291 decimal) +* ``0x123`` is 123 hexadecimal (291 decimal) +* ``#123`` is 123 decimal +* ``0o123`` is 123 octal (83 decimal) +* ``0b1001`` is is 1001 binary (9 decimal) +* ``0b123`` is invalid + + +Boolean values +~~~~~~~~~~~~~~ + +Any expression that evaluates to a number can be used where a Boolean +value is required. Zero is treated as false, and all non-zero values +are treated as true. Additionally, the string ``true`` is treated as +true, and the string ``false`` is treated as false. + +An empty string may be supplied as an argument for Boolean parameters to +debugger commands to use the default value, even when subsequent +parameters are specified. + + +Memory accesses +~~~~~~~~~~~~~~~ + +The memory access prefix operators allow reading from and writing to +emulated address spaces. The memory prefix operators specify the +access size and whether side effects are disabled, and may optionally be +preceded by an address space specification. The supported access sizes +and side effect modes are as follows: + +* ``b`` specifies an 8-bit access (byte) +* ``w`` specifies a 16-bit access (word) +* ``d`` specifies a 32-bit access (double word) +* ``q`` specifies a 64-bit access (quadruple word) +* ``@`` suppress side effects +* ``!`` do not suppress side effects + +The size may optionally be preceded by an access type specification: + +* ``p`` or ``lp`` specifies a logical address defaulting to space 0 + (program) +* ``d`` or ``ld`` specifies a logical address defaulting to space 1 + (data) +* ``i`` or ``li`` specifies a logical address defaulting to space 1 + (I/O) +* ``3`` or ``l3`` specifies a logical address defaulting to space 1 + (opcodes) +* ``pp`` specifies a physical address defaulting to space 0 (program) +* ``pd`` specifies a physical address defaulting to space 1 (data) +* ``pi`` specifies a physical address defaulting to space 1 (I/O) +* ``p3`` specifies a physical address defaulting to space 1 (opcodes) +* ``r`` specifies direct read/write pointer access defaulting to space 0 + (program) +* ``o`` specifies direct read/write pointer access defaulting to space 3 + (opcodes) +* ``m`` specifies a memory region + +Finally, this may be preceded by a tag and/or address space name +followed by a dot (``.``). + +That may seem like a lot to digest, so let’s look at the simplest +examples: + +``b@`` + Refers to the byte at **** in the program space of the visible + CPU while suppressing side effects +``b!`` + Refers to the byte at **** in the program space of the visible + CPU, *not* suppressing side effects such as reading a mailbox + clearing the pending flag, or reading a FIFO removing an item +``w@`` and ``w!`` + Refer to the word at **** in the program space of the visible + CPU, suppressing or not suppressing side effects, respectively. +``d@`` and ``d!`` + Refer to the double word at **** in the program space of the + visible CPU, suppressing or not suppressing side effects, + respectively. +``q@`` and ``q!`` + Refer to the quadruple word at **** in the program space of + the visible CPU, suppressing or not suppressing side effects, + respectively. + +Adding access types gives additional possibilities: + +``dw@300`` + Refers to the word at 300 in the data space of the visible CPU while + suppressing side effects +``id@400`` + Refers to the double word at 400 in the I/O space of the visible CPU + CPU while suppressing side effects +``ppd!`` + Refers to the double word at physical address **** in the + program space of the visible CPU while not suppressing side effects +``rw@`` + Refers to the word at address **** in the program space of the + visible CPU using direct read/write pointer access + +If we want to access an address space of a device other than the visible +CPU, an address space beyond the first four indices, or a memory region, +we need to include a tag or name: + +``ramport.b@`` + Refers to the byte at address **** in the ``ramport`` space of + the current CPU +``audiocpu.dw@`` + Refers to the word at address **** in the data space of the + CPU with absolute tag ``:audiocpu`` +``maincpu:status.b@`` + Refers to the byte at address **** in the ``status`` space of + the CPU with the absolute tag ``:maincpu`` +``monitor.mb@78`` + Refers to the byte at 78 in the memory region with the absolute tag + ``:monitor`` + +Some combinations are not useful. For example physical and logical +addresses are equivalent for some CPUs, and direct read/write pointer +accesses never have side effects. Accessing a memory region (``m`` +access type) requires a tag to be specified. + +Memory accesses can be used as both lvalues and rvalues, so you can write +``b@100 = ff`` to store a byte in memory. diff --git a/docs/source/debugger/memory.rst b/docs/source/debugger/memory.rst index 7f9414e085f..da3645a6d1e 100644 --- a/docs/source/debugger/memory.rst +++ b/docs/source/debugger/memory.rst @@ -3,165 +3,405 @@ Memory Debugger Commands ======================== +:ref:`debugger-command-dasm` + disassemble code to a file +:ref:`debugger-command-find` + search emulated memory for data +:ref:`debugger-command-fill` + search emulated memory with specified pattern +:ref:`debugger-command-dump` + dump emulated memory to a file as text +:ref:`debugger-command-strdump` + dump delimited strings from emulated memory to a file +:ref:`debugger-command-save` + save binary data from emulated memory to a file +:ref:`debugger-command-saver` + save binary data from a memory region to a file +:ref:`debugger-command-load` + load binary data from a file to emulated memory +:ref:`debugger-command-loadr` + load binary data from a file to a memory region +:ref:`debugger-command-map` + map a logical address to the corresponding physical address and + handler +:ref:`debugger-command-memdump` + dump current memory maps to a file -You can also type **help ** for further details on each command in the MAME Debugger interface. -| :ref:`debugger-command-dasm` -- disassemble to the given file -| :ref:`debugger-command-find` -- search program memory, data memory, or I/O memory for data -| :ref:`debugger-command-dump` -- dump program memory, data memory, or I/O memory as text -| :ref:`debugger-command-save` -- save binary program, data, or I/O memory to the given file -| :ref:`debugger-command-load` -- load binary program memory, data memory, or I/O memory from the given file -| :ref:`debugger-command-map` -- map logical program, data, or I/O address to physical address and bank +.. _debugger-command-dasm: +dasm +---- +**dasm ,
,[,[,]]** +Disassembles program memory to the file specified by the **** +parameter. The **
** parameter specifies the address to start +disassembling from, and the **** parameter specifies how much +memory to disassemble. The range **
** through +**
+-1**, inclusive, will be disassembled to the file. +By default, raw opcode data is output with each line. The optional +**** parameter is a Boolean that enables disables this feature. +By default, program memory for the visible CPU is disassembled. To +disassemble program memory for a different CPU, specify it using the +optional fifth parameter (see :ref:`debugger-devicespec` for details). - .. _debugger-command-dasm: +Examples: -dasm ----- +``dasm venture.asm,0,10000`` + Disassembles addresses 0-ffff for the visible CPU, including raw + opcode data, to the file **venture.asm**. +``dasm harddriv.asm,3000,1000,0,2`` + Disassembles addresses 3000-3fff for the third CPU in the system + (zero-based index), without raw opcode data, to the file + **harddriv.asm**. + +Back to :ref:`debugger-memory-list` -| **dasm ,
,[,[,]]** -| -| The dasm command disassembles program memory to the file specified in the parameter.
indicates the address of the start of disassembly, and indicates how much memory to disassemble. The range
through
+-1 inclusive will be output to the file. By default, the raw opcode data is output with each line. The optional parameter can be used to enable (1) or disable (0) this feature. Finally, you can disassemble code from another CPU by specifying the parameter. -| -| Examples: -| -| dasm venture.asm,0,10000 -| -| Disassembles addresses 0-ffff in the current CPU, including raw opcode data, to the file 'venture.asm'. -| -| dasm harddriv.asm,3000,1000,0,2 -| -| Disassembles addresses 3000-3fff from CPU #2, with no raw opcode data, to the file 'harddriv.asm'. -| -| Back to :ref:`debugger-memory-list` - - - .. _debugger-command-find: + +.. _debugger-command-find: find ---- -| **f[ind][{d|i}]
,[,[,...]]** -| -| The **find**/**findd**/**findi** commands search through memory for the specified sequence of data. 'find' will search program space memory, while 'findd' will search data space memory and 'findi' will search I/O space memory.
indicates the address to begin searching, and indicates how much memory to search. can either be a quoted string or a numeric value or expression or the wildcard character '?'. Strings by default imply a byte-sized search; non-string data is searched by default in the native word size of the CPU. To override the search size for non-strings, you can prefix the value with b. to force byte- sized search, w. for word-sized search, d. for dword-sized, and q. for qword-sized. Overrides are remembered, so if you want to search for a series of words, you need only to prefix the first value with a w. Note also that you can intermix sizes in order to perform more complex searches. The entire range
through
+-1 inclusive will be searched for the sequence, and all occurrences will be displayed. -| -| Examples: -| -| find 0,10000,"HIGH SCORE",0 -| -| Searches the address range 0-ffff in the current CPU for the string "HIGH SCORE" followed by a 0 byte. -| -| findd 3000,1000,w.abcd,4567 -| -| Searches the data memory address range 3000-3fff for the word-sized value abcd followed by the word-sized value 4567. -| -| find 0,8000,"AAR",d.0,"BEN",w.0 -| -| Searches the address range 0000-7fff for the string "AAR" followed by a dword-sized 0 followed by the string "BEN", followed by a word-sized 0. -| -| Back to :ref:`debugger-memory-list` - - - .. _debugger-command-dump: +**f[ind][{d|i|o}]
[:],[,[,...]]** + +Search through memory for the specified sequence of data. The +**
** is the address to begin searching from, optionally +followed by a device and/or address space (see +:ref:`debugger-devicespec` for details); the **** specifies +how much memory to search. If an address space is not specified, the +command suffix sets the address space: ``find`` defaults to the first +address space exposed by the device, ``findd`` defaults to the space +with index 1 (data), ``findi`` default to the space with index 2 (I/O), +and ``findo`` defaults to the space with index 3 (opcodes). + +The **** can either be a quoted string, a numeric value or +expression, or the wildcard character ``?``. By default, strings imply +a byte-sized search; by default non-string data is searched using the +native word size of the address space. To override the search size for +non-string data, you can prefix values with ``b.`` to force byte-sized +search, ``w.`` for word-sized search, ``d.`` for double word-sized +search, and ``q.`` for quadruple word-sized search. Overrides propagate +to subsequent values, so if you want to search for a sequence of words, +you need only prefix the first value with ``w.``. Also note that you +can intermix sizes to perform more complex searches. + +The entire range **
** through **
+-1**, +inclusive, will be searched for the sequence, and all occurrences will +be displayed. + +Examples: + +``find 0,10000,"HIGH SCORE",0`` + Searches the address range 0-ffff in the program space of the + visible CPU for the string “HIGH SCORE” followed by a 0 byte. +``find 300:tms9918a,100,w.abcd,4567`` + Searches the address range 300-3ff in the first address space + exposed by the device with the absolute tag ``:tms9918a`` for the + word-sized value abcd followed by the word-sized value 4567. +``find 0,8000,"AAR",d.0,"BEN",w.0`` + Searches the address range 0000-7fff for the string “AAR” followed + by a dword-sized 0 followed by the string “BEN”, followed by a + word-sized 0. + +Back to :ref:`debugger-memory-list` + + +.. _debugger-command-fill: + +fill +---- + +**fill[{d|i|o}]
[:],[,[,...]]** + +Overwrite a block of memory with copies of the supplied data sequence. +The **
** specifies the address to begin writing at, optionally +followed by a device and/or address space (see +:ref:`debugger-devicespec` for details); the **** specifies how +much memory to fill. If an address space is not specified, the command +suffix sets the address space: ``fill`` defaults to the first +address space exposed by the device, ``filld`` defaults to the space +with index 1 (data), ``filli`` default to the space with index 2 (I/O), +and ``fillo`` defaults to the space with index 3 (opcodes). + +The **** can either be a quoted string, or a numeric value or +expression. By default, non-string data is written using the native +word size of the address space. To override the data size for non-string +data, you can prefix values with ``b.`` to force byte-sized fill, ``w.`` +for word-sized fill, ``d.`` for double word-sized fill, and ``q.`` for +quadruple word-sized fill. Overrides propagate to subsequent values, so +if you want to fill with a series of words, you need only prefix the +first value with ``w.``. Also note that you can intermix sizes to +perform more complex fills. The fill operation may be truncated if a +page fault occurs or if part of the sequence or string would fall beyond +**
+-1**. + +Back to :ref:`debugger-memory-list` + + +.. _debugger-command-dump: dump ---- -| **dump[{d|i}] ,
,[,[,[,]]]** -| -| The **dump**/**dumpd**/**dumpi** commands dump memory to the text file specified in the parameter. -| 'dump' will dump program space memory, while 'dumpd' will dump data space memory and 'dumpi' will dump I/O space memory. -|
indicates the address of the start of dumping, and indicates how much memory to dump. The range
through
+-1 inclusive will be output to the file. -| By default, the data will be output in byte format, unless the underlying address space is word/dword/qword-only. You can override this by specifying the parameter, which can be used to group the data in 1, 2, 4 or 8-byte chunks. -| The optional parameter can be used to enable (1) or disable (0) the output of ASCII characters to the right of each line; by default, this is enabled. -| Finally, you can dump memory from another CPU by specifying the parameter. -| -| -| Examples: -| -| dump venture.dmp,0,10000 -| -| Dumps addresses 0-ffff in the current CPU in 1-byte chunks, including ASCII data, to the file 'venture.dmp'. -| -| dumpd harddriv.dmp,3000,1000,4,0,3 -| -| Dumps data memory addresses 3000-3fff from CPU #3 in 4-byte chunks, with no ASCII data, to the file 'harddriv.dmp'. -| -| Back to :ref:`debugger-memory-list` - - - .. _debugger-command-save: +**dump[{d|i|o}] ,
[:],[,[,[,]]]** + +Dump memory to the text file specified by the **** parameter. +The **
** specifies the address to start dumping from, +optionally followed by a device and/or address space (see +:ref:`debugger-devicespec` for details); the **** specifies how +much memory to dump. If an address space is not specified, the command +suffix sets the address space: ``dump`` defaults to the first +address space exposed by the device, ``dumpd`` defaults to the space +with index 1 (data), ``dumpi`` default to the space with index 2 (I/O), +and ``dumpo`` defaults to the space with index 3 (opcodes). + +The range **
** through **
+-1**, inclusive, +will be output to the file. By default, the data will be output using +the native word size of the address space. You can override this by +specifying the **** parameter, which can be used to group the +data in 1-, 2-, 4- or 8-byte chunks. The optional **** parameter +is a Boolean value used to enable or disable output of ASCII characters +on the right of each line (enabled by default). The optional +**** parameter specifies the amount of data on each line in +address units (defaults to 16 bytes). + +Examples: + +``dump venture.dmp,0,10000`` + Dumps addresses 0-ffff from the program space of the visible CPU in + 1-byte chunks, including ASCII data, to the file **venture.dmp**. +``dumpd harddriv.dmp,3000:3,1000,4,0`` + Dumps data memory addresses 3000-3fff from the fourth CPU in the + system (zero-based index) in 4-byte chunks, without ASCII data, to + the file **harddriv.dmp**. +``dump vram.dmp,0:sms_vdp:videoram,4000,1,false,8`` + Dumps ``videoram`` space addresses 0000-3fff from the device with + the absolute tag path ``:sms_vdp`` in 1-byte chunks, without ASCII + data, with 8 bytes per line, to the file **vram.dmp**. + +Back to :ref:`debugger-memory-list` + + +.. _debugger-command-strdump: + +strdump +------- + +**strdump[{d|i|o}] ,
[:],[,]** + +Dump memory to the text file specified by the **** parameter. +The **
** specifies the address to start dumping from, +optionally followed by a device and/or address space (see +:ref:`debugger-devicespec` for details); the **** specifies how +much memory to dump. If an address space is not specified, the command +suffix sets the address space: ``strdump`` defaults to the first +address space exposed by the device, ``strdumpd`` defaults to the space +with index 1 (data), ``strdumpi`` default to the space with index 2 +(I/O), and ``strdumpo`` defaults to the space with index 3 (opcodes). + +By default, the data will be interpreted as a series of NUL-terminated +(ASCIIZ) strings, the dump will have one string per line, and C-style +escapes sequences will be used for bytes that do not represent printable +ASCII characters. The optional **** parameter can be used to +specify a different string terminator character. + +Back to :ref:`debugger-memory-list` + + +.. _debugger-command-save: save ---- -| **save[{d|i}] ,
,[,]** -| -| The **save**/**saved**/**savei** commands save raw memory to the binary file specified in the parameter. -| 'save' will save program space memory, while 'saved' will save data space memory and 'savei' will save I/O space memory. -|
indicates the address of the start of saving, and indicates how much memory to save. The range
through
+-1 inclusive will be output to the file. -| You can also save memory from another CPU by specifying the parameter. -| -| -| Examples: -| -| save venture.bin,0,10000 -| -| Saves addresses 0-ffff in the current CPU to the binary file 'venture.bin'. -| -| saved harddriv.bin,3000,1000,3 -| -| Saves data memory addresses 3000-3fff from CPU #3 to the binary file 'harddriv.bin'. -| -| Back to :ref:`debugger-memory-list` - - - .. _debugger-command-load: +**save[{d|i|o}] ,
[:],** + +Save raw memory to the binary file specified by the **** +parameter. The **
** specifies the address to start saving +from, optionally followed by a device and/or address space (see +:ref:`debugger-devicespec` for details); the **** specifies how +much memory to save. If an address space is not specified, the command +suffix sets the address space: ``save`` defaults to the first address +space exposed by the device, ``saved`` defaults to the space with index +1 (data), ``savei`` default to the space with index 2 (I/O), and +``saveo`` defaults to the space with index 3 (opcodes). + +The range **
** through **
+-1**, inclusive, +will be output to the file. + +Examples: + +``save venture.bin,0,10000`` + Saves addresses 0-ffff from the program space of the current CPU to + the binary file **venture.bin** +``saved harddriv.bin,3000:3,1000`` + Saves data memory addresses 3000-3fff from the fourth CPU in the + system (zero-based index) to the binary file **harddriv.bin**. +``save vram.bin,0:sms_vdp:videoram,4000`` + Saves ``videoram`` space addresses 0000-3fff from the device with + the absolute tag path ``:sms_vdp`` to the binary file **vram.bin**. + +Back to :ref:`debugger-memory-list` + + +.. _debugger-command-saver: + +saver +----- + +**saver ,
,,** + +Save raw content of memory region specified by the **** +parameter to the binary file specified by the **** parameter. +Regions tags follow the same rules as device tags (see +:ref:`debugger-devicespec`). The **
** specifies the address to +start saving from, and the **** specifies how much memory to +save. The range **
** through **
+-1**, +inclusive, will be output to the file. + +Examples: + +``saver data.bin,200,100,:monitor`` + Saves ``:monitor`` region addresses 200-2ff to the binary file + **data.bin**. +``saver cpurom.bin,1000,400,.`` + Saves addresses 1000-13ff from the memory region with the same tag + as the visible CPU to the binary file **cpurom.bin**. + +Back to :ref:`debugger-memory-list` + + +.. _debugger-command-load: load ---- -| **load[{d|i}] ,
[,,]** -| -| The **load**/**loadd**/**loadi** commands load raw memory from the binary file specified in the parameter. -| 'load' will load program space memory, while 'loadd' will load data space memory and 'loadi' will load I/O space memory. -|
indicates the address of the start of saving, and indicates how much memory to load. The range
through
+-1 inclusive will be read in from the file. -| If you specify = 0 or a length greater than the total length of the file it will load the entire contents of the file and no more. -| You can also load memory from another CPU by specifying the parameter. -| -| NOTE: This will only actually write memory that is possible to overwrite in the Memory Window -| -| -| Examples: -| -| load venture.bin,0,10000 -| -| Loads addresses 0-ffff in the current CPU from the binary file 'venture.bin'. -| -| loadd harddriv.bin,3000,1000,3 -| -| Loads data memory addresses 3000-3fff from CPU #3 from the binary file 'harddriv.bin'. -| -| Back to :ref:`debugger-memory-list` - - - .. _debugger-command-map: +**load[{d|i|o}] ,
[:][,]** + +Load raw memory from the binary file specified by the **** +parameter. The **
** specifies the address to start loading to, +optionally followed by a device and/or address space (see +:ref:`debugger-devicespec` for details); the **** specifies how +much memory to load. If an address space is not specified, the command +suffix sets the address space: ``load`` defaults to the first address +space exposed by the device, ``loadd`` defaults to the space with index +1 (data), ``loadi`` default to the space with index 2 (I/O), and +``loado`` defaults to the space with index 3 (opcodes). + +The range **
** through **
+-1**, inclusive, +will be read in from the file. If the **** is omitted, if it is +zero, or if it is greater than the total length of the file, the entire +contents of the file will be loaded but no more. + +Note that this has the same effect as writing to the address space from +a debugger memory view, or using the ``b@``, ``w@``, ``d@`` or ``q@`` +memory accessors in debugger expressions. Read-only memory will not be +overwritten, and writing to I/O addresses may have effects beyond +setting register values. + +Examples: + +``load venture.bin,0,10000`` + Loads addresses 0-ffff in the program space for the visible CPU from + the binary file **venture.bin**. +``loadd harddriv.bin,3000,1000,3`` + Loads data memory addresses 3000-3fff in the program space for the + fourth CPU in the system (zero-based index) from the binary file + **harddriv.bin**. +``load vram.bin,0:sms_vdp:videoram`` + Loads the ``videoram`` space for the device with the absolute tag + path ``:sms_vdp`` starting at address 0000 with the entire content + of the binary file **vram.bin**. + +Back to :ref:`debugger-memory-list` + + +.. _debugger-command-loadr: + +loadr +----- + +**loadr ,
,,** + +Load memory in the memory region specified by the **** with raw +data from the binary file specified by the **** parameter. +Regions tags follow the same rules as device tags (see +:ref:`debugger-devicespec`). The **
** specifies the address to +start loading to, and the +**** specifies how much memory to load. The range **
** +through **
+-1**, inclusive, will be read in from the +file. If the **** is zero, or is greater than the total length +of the file, the entire contents of the file will be loaded but no more. + +Examples: + +``loadr data.bin,200,100,:monitor`` + Loads ``:monitor`` region addresses 200-2ff from the binary file + **data.bin**. +``loadr cpurom.bin,1000,400,.`` + Loads addresses 1000-13ff in the memory region with the same tag as + the visible CPU from the binary file **cpurom.bin**. + +Back to :ref:`debugger-memory-list` + + +.. _debugger-command-map: map --- -| **map[{d|i}]
** -| -| The map/mapd/mapi commands map a logical address in memory to the correct physical address, as well as specifying the bank. -| 'map' will map program space memory, while 'mapd' will map data space memory and 'mapi' will map I/O space memory. -| -| Example: -| -| map 152d0 -| -| Gives physical address and bank for logical address 152d0 in program memory -| -| Back to :ref:`debugger-memory-list` +**map[{d|i|o}]
[:]** + +Map a logical memory address to the corresponding physical address, as +well as reporting the handler name. The address may optionally be +followed by a colon and device and/or address space (see +:ref:`debugger-devicespec` for details). If an address space is not +specified, the command suffix sets the address space: ``map`` defaults +to the first address space exposed by the device, ``mapd`` defaults to +the space with index 1 (data), ``mapi`` default to the space with index +2 (I/O), and ``mapo`` defaults to the space with index 3 (opcodes). + +Examples: + +``map 152d0`` + Gives the physical address and handler name for logical address + 152d0 in program memory for the visible CPU. +``map 107:sms_vdp`` + Gives the physical address and handler name for logical address 107 + in the first address space for the device with the absolute tag path + ``:sms_vdp``. + +Back to :ref:`debugger-memory-list` + + +.. _debugger-command-memdump: + +memdump +------- + +**memdump [,[]]** + +Dumps the current memory maps to the file specified by ****, +or **memdump.log** if omitted. If **** is specified (see +:ref:`debugger-devicespec`), only memory maps for the part of the device +tree rooted at this device will be dumped. + +Examples: + +``memdump mylog.log`` + Dumps memory maps for all devices in the system to the file + **mylog.log**. +``memdump`` + Dumps memory maps for all devices in the system to the file + **memdump.log**. +``memdump audiomaps.log,audiopcb`` + Dumps memory maps for the device with the absolute tag path + ``:audiopcb`` and all its child devices to the file + **audiomaps.log**. +``memdump mylog.log,1`` + Dumps memory maps for the second CPU device in the system + (zero-based index) and all its child devices to the file + **mylog.log**. +Back to :ref:`debugger-memory-list` diff --git a/language/Chinese_Simplified/strings.po b/language/Chinese_Simplified/strings.po index 1932e0c3f73..99dd0774b03 100644 --- a/language/Chinese_Simplified/strings.po +++ b/language/Chinese_Simplified/strings.po @@ -5025,7 +5025,7 @@ msgstr "" #: src/frontend/mame/ui/utils.cpp:71 msgctxt "swlist-info" msgid "Original Publisher" -msgstr "" +msgstr "原出版商" #: src/frontend/mame/ui/utils.cpp:72 msgctxt "swlist-info" @@ -5065,7 +5065,7 @@ msgstr "版本" #: src/frontend/mame/ui/utils.cpp:84 msgctxt "machine-filter" msgid "Unfiltered" -msgstr "未过滤" +msgstr "未筛选" #: src/frontend/mame/ui/utils.cpp:85 msgctxt "machine-filter" @@ -5175,7 +5175,7 @@ msgstr "自订过滤" #: src/frontend/mame/ui/utils.cpp:109 msgctxt "software-filter" msgid "Unfiltered" -msgstr "未过滤" +msgstr "未筛选" #: src/frontend/mame/ui/utils.cpp:110 msgctxt "software-filter" @@ -5833,7 +5833,7 @@ msgstr "装饰图预览" #: src/frontend/mame/ui/dirmenu.cpp:61 msgctxt "path-option" msgid "Select" -msgstr "" +msgstr "精选" #: src/frontend/mame/ui/dirmenu.cpp:62 msgctxt "path-option" @@ -6412,7 +6412,7 @@ msgstr "得分" #: src/frontend/mame/ui/selmenu.cpp:90 msgctxt "selmenu-artwork" msgid "Select" -msgstr "" +msgstr "精选" #: src/frontend/mame/ui/selmenu.cpp:91 msgctxt "selmenu-artwork" diff --git a/language/Chinese_Traditional/strings.po b/language/Chinese_Traditional/strings.po index 5734f8dde36..9c028f92c60 100644 --- a/language/Chinese_Traditional/strings.po +++ b/language/Chinese_Traditional/strings.po @@ -5025,7 +5025,7 @@ msgstr "" #: src/frontend/mame/ui/utils.cpp:71 msgctxt "swlist-info" msgid "Original Publisher" -msgstr "" +msgstr "原出版商" #: src/frontend/mame/ui/utils.cpp:72 msgctxt "swlist-info" @@ -5836,7 +5836,7 @@ msgstr "裝飾圖預覽" #: src/frontend/mame/ui/dirmenu.cpp:61 msgctxt "path-option" msgid "Select" -msgstr "" +msgstr "精選" #: src/frontend/mame/ui/dirmenu.cpp:62 msgctxt "path-option" @@ -6415,7 +6415,7 @@ msgstr "得分" #: src/frontend/mame/ui/selmenu.cpp:90 msgctxt "selmenu-artwork" msgid "Select" -msgstr "" +msgstr "精選" #: src/frontend/mame/ui/selmenu.cpp:91 msgctxt "selmenu-artwork" diff --git a/src/devices/cpu/m6502/st2205u.h b/src/devices/cpu/m6502/st2205u.h index f414234fd7f..4182793a3bb 100644 --- a/src/devices/cpu/m6502/st2205u.h +++ b/src/devices/cpu/m6502/st2205u.h @@ -56,6 +56,8 @@ public: ST_LVCTR }; + static constexpr feature_type imperfect_features() { return feature::SOUND; } + protected: st2205u_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map, int data_bits, bool has_banked_ram); diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index 8bde2af72ea..1d2bf4e13b6 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -9,21 +9,25 @@ *********************************************************************/ #include "emu.h" -#include "emuopts.h" -#include "debugger.h" #include "debugcmd.h" + +#include "debugbuf.h" #include "debugcon.h" #include "debugcpu.h" -#include "debugbuf.h" -#include "express.h" #include "debughlp.h" #include "debugvw.h" +#include "express.h" #include "points.h" + +#include "debugger.h" +#include "emuopts.h" #include "natkeyboard.h" #include "render.h" + #include "corestr.h" -#include + #include +#include #include @@ -2353,6 +2357,7 @@ void debugger_commands::execute_load(int spacenum, const std::vectordevice().machine().disable_side_effects(); switch (space->addr_shift()) { case -3: @@ -3479,7 +3484,8 @@ void debugger_commands::execute_fill(int spacenum, const std::vector ¶ms) { - u64 offset, length, bytes = 1; + u64 offset, length; + bool bytes = true; address_space *space; // validate parameters @@ -3487,7 +3493,7 @@ void debugger_commands::execute_dasm(const std::vector ¶ms) return; if (!validate_number_parameter(params[2], length)) return; - if (params.size() > 3 && !validate_number_parameter(params[3], bytes)) + if (params.size() > 3 && !validate_boolean_parameter(params[3], bytes)) return; if (!validate_device_space_parameter(params.size() > 4 ? params[4] : std::string_view(), AS_PROGRAM, space)) return; @@ -3523,11 +3529,11 @@ void debugger_commands::execute_dasm(const std::vector ¶ms) topcodes.emplace_back(buffer.data_to_string(offset, size, true)); int osize = topcodes.back().size(); - if(osize > max_opcodes_size) + if (osize > max_opcodes_size) max_opcodes_size = osize; int dsize = instructions.back().size(); - if(dsize > max_disasm_size) + if (dsize > max_disasm_size) max_disasm_size = dsize; i += size; @@ -3544,7 +3550,7 @@ void debugger_commands::execute_dasm(const std::vector ¶ms) if (bytes) { - for(unsigned int i=0; i != pcs.size(); i++) + for (unsigned int i=0; i != pcs.size(); i++) { const char *comment = space->device().debug()->comment_text(pcs[i]); if (comment) @@ -3555,7 +3561,7 @@ void debugger_commands::execute_dasm(const std::vector ¶ms) } else { - for(unsigned int i=0; i != pcs.size(); i++) + for (unsigned int i=0; i != pcs.size(); i++) { const char *comment = space->device().debug()->comment_text(pcs[i]); if (comment) @@ -3678,8 +3684,8 @@ void debugger_commands::execute_traceflush(const std::vector ¶m void debugger_commands::execute_history(const std::vector ¶ms) { // validate parameters - address_space *space; - if (!validate_device_space_parameter(!params.empty() ? params[0] : std::string_view(), AS_PROGRAM, space)) + device_t *device; + if (!validate_cpu_parameter(!params.empty() ? params[0] : std::string_view(), device)) return; u64 count = device_debug::HISTORY_SIZE; @@ -3690,34 +3696,31 @@ void debugger_commands::execute_history(const std::vector ¶ms) if (count > device_debug::HISTORY_SIZE) count = device_debug::HISTORY_SIZE; - device_execute_interface const *execute; - if (!space->device().interface(execute)) - { - m_console.printf("Device %s is not a CPU\n", space->device().name()); - return; - } - device_debug *const debug = space->device().debug(); + device_debug *const debug = device->debug(); - // loop over lines device_disasm_interface *dasmintf; - if (!space->device().interface(dasmintf)) + if (!device->interface(dasmintf)) { - m_console.printf("No disassembler available for device %s\n", space->device().name()); + m_console.printf("No disassembler available for device %s\n", device->name()); return; } - debug_disasm_buffer buffer(space->device()); - - for (int index = 0; index < (int) count; index++) + // loop over lines + debug_disasm_buffer buffer(*device); + std::string instruction; + for (int index = int(unsigned(count)); index > 0; index--) { - offs_t const pc = debug->history_pc(-index); - std::string instruction; - offs_t next_offset; - offs_t size; - u32 info; - buffer.disassemble(pc, instruction, next_offset, size, info); + auto const pc = debug->history_pc(1 - index); + if (pc.second) + { + offs_t next_offset; + offs_t size; + u32 info; + instruction.clear(); + buffer.disassemble(pc.first, instruction, next_offset, size, info); - m_console.printf("%s: %s\n", buffer.pc_to_string(pc), instruction); + m_console.printf("%s: %s\n", buffer.pc_to_string(pc.first), instruction); + } } } diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp index 04cce887484..403d0b104ee 100644 --- a/src/emu/debug/debugcpu.cpp +++ b/src/emu/debug/debugcpu.cpp @@ -434,6 +434,7 @@ device_debug::device_debug(device_t &device) , m_total_cycles(0) , m_last_total_cycles(0) , m_pc_history_index(0) + , m_pc_history_valid(0) , m_bplist() , m_rplist(std::make_unique>()) , m_triggered_breakpoint(nullptr) @@ -722,7 +723,10 @@ void device_debug::instruction_hook(offs_t curpc) debugcpu.set_within_instruction(true); // update the history - m_pc_history[m_pc_history_index++ % HISTORY_SIZE] = curpc; + m_pc_history[m_pc_history_index] = curpc; + m_pc_history_index = (m_pc_history_index + 1) % std::size(m_pc_history); + if (std::size(m_pc_history) > m_pc_history_valid) + ++m_pc_history_valid; // update total cycles m_last_total_cycles = m_total_cycles; @@ -1352,13 +1356,28 @@ void device_debug::registerpoint_enable_all(bool enable) // history //------------------------------------------------- -offs_t device_debug::history_pc(int index) const +std::pair device_debug::history_pc(int index) const { - if (index > 0) - index = 0; - if (index <= -HISTORY_SIZE) - index = -HISTORY_SIZE + 1; - return m_pc_history[(m_pc_history_index + std::size(m_pc_history) - 1 + index) % std::size(m_pc_history)]; + if ((index <= 0) && (-index < m_pc_history_valid)) + { + int const i = (m_pc_history_index + std::size(m_pc_history) - 1 + index) % std::size(m_pc_history); + return std::make_pair(m_pc_history[i], true); + } + else + { + return std::make_pair(offs_t(0), false); + } +} + + +//------------------------------------------------- +// set_track_pc - turn visited PC tracking on or +// off +//------------------------------------------------- + +void device_debug::set_track_pc(bool value) +{ + m_track_pc = value; } @@ -1369,7 +1388,7 @@ offs_t device_debug::history_pc(int index) const // TODO: Take a CPU context as input //------------------------------------------------- -bool device_debug::track_pc_visited(const offs_t& pc) const +bool device_debug::track_pc_visited(offs_t pc) const { if (m_track_pc_set.empty()) return false; @@ -1383,7 +1402,7 @@ bool device_debug::track_pc_visited(const offs_t& pc) const // TODO: Take a CPU context as input //------------------------------------------------- -void device_debug::set_track_pc_visited(const offs_t& pc) +void device_debug::set_track_pc_visited(offs_t pc) { const u32 crc = compute_opcode_crc32(pc); m_track_pc_set.insert(dasm_pc_tag(pc, crc)); diff --git a/src/emu/debug/debugcpu.h b/src/emu/debug/debugcpu.h index eba89367c2c..9e3d23d8d7f 100644 --- a/src/emu/debug/debugcpu.h +++ b/src/emu/debug/debugcpu.h @@ -14,6 +14,7 @@ #pragma once #include +#include //************************************************************************** @@ -129,12 +130,12 @@ public: u32 compute_opcode_crc32(offs_t pc) const; // history - offs_t history_pc(int index) const; + std::pair history_pc(int index) const; // pc tracking - void set_track_pc(bool value) { m_track_pc = value; } - bool track_pc_visited(const offs_t& pc) const; - void set_track_pc_visited(const offs_t& pc); + void set_track_pc(bool value); + bool track_pc_visited(offs_t pc) const; + void set_track_pc_visited(offs_t pc); void track_pc_data_clear() { m_track_pc_set.clear(); } // memory tracking @@ -200,6 +201,7 @@ private: // history offs_t m_pc_history[HISTORY_SIZE]; // history of recent PCs u32 m_pc_history_index; // current history index + u32 m_pc_history_valid; // number of valid PC history entries // breakpoints and watchpoints std::multimap> m_bplist; // list of breakpoints diff --git a/src/emu/debug/debughlp.cpp b/src/emu/debug/debughlp.cpp index ead08937c15..322c760bbbb 100644 --- a/src/emu/debug/debughlp.cpp +++ b/src/emu/debug/debughlp.cpp @@ -68,7 +68,7 @@ const help_item f_static_help_list[] = " logerror [,[,...]] -- outputs one or more s to the error.log\n" " tracelog [,[,...]] -- outputs one or more s to the trace file using \n" " tracesym [,...]] -- outputs one or more s to the trace file\n" - " history [,] -- outputs a brief history of visited opcodes\n" + " history [,[]] -- outputs a brief history of visited opcodes\n" " trackpc [,[,[]]] -- visually track visited opcodes [boolean to turn on and off, for CPU, clear]\n" " trackmem [,[,[]]] -- record which PC writes to each memory address [boolean to turn on and off, for CPU, clear]\n" " pcatmem
[:] -- query which PC wrote to a given memory address\n" @@ -391,21 +391,43 @@ const help_item f_static_help_list[] = "tracelog \"PC=%04X\",pc\n" " Outputs PC= where is displayed in hexadecimal with 4 digits with zero-fill.\n" "\n" - "printf \"A=%d, B=%d\\nC=%d\",a,b,a+b\n" + "tracelog \"A=%d, B=%d\\nC=%d\",a,b,a+b\n" " Outputs A=, B= on one line, and C= on a second line.\n" }, { "tracesym", "\n" " tracesym [,...]\n" - "\n" - "The tracesym command prints the specified symbols and routes the output to the currently open trace " - "file (see the 'trace' command for details). If no file is currently open, tracesym does nothing. " - "\n" - "Examples:\n" - "\n" - "tracelog pc\n" - " Outputs PC= where is displayed in the default format.\n" + "\n" + "The tracesym command prints the specified symbols and routes the output to the currently open trace " + "file (see the 'trace' command for details). If no file is currently open, tracesym does nothing. " + "\n" + "Examples:\n" + "\n" + "tracesym pc\n" + " Outputs PC= where is displayed in the default format.\n" + }, + { + "history", + "\n" + " history [,[]]\n" + "\n" + "The history command displays recently visited PC addresses, and the disassembly of the " + "instructions at those addresses. If present, the first argument is a CPU selector " + "(either a tag or a CPU number); if no CPU is specified, the current CPU is assumed. " + "The second argument, if present, limits the maximum number of addresses shown. " + "Addresses are shown in order from least to most recently visited.\n" + "\n" + "Examples:\n" + "\n" + "history ,5\n" + " Displays up to five most recently visited PC addresses for the current CPU.\n" + "\n" + "history 3\n" + " Displays recently visited PC addresses for CPU 3.\n" + "\n" + "history audiocpu,1\n" + " Displays the most recently visited PC addresses for the CPU ':audiocpu'.\n" }, { "trackpc", @@ -445,20 +467,21 @@ const help_item f_static_help_list[] = " Begin tracking memory writes for the current CPU.\n" "\n" "trackmem 1, 0, 1\n" - " Continue tracking memory writes on CPU 0, but clear existing track info.\n" + " Continue tracking memory writes on CPU 0, but clear existing tracking data.\n" }, { "pcatmem", "\n" " pcatmem[{d|i|o}]
[:]\n" "\n" - "The pcatmem command returns which PC wrote to a given memory address for the current CPU. " - "The argument is the requested address, optionally followed by a colon and a CPU and/or " - "address space. The CPU may be specified as a tag or debugger CPU number; if no CPU is " - "specified, the CPU currently visible in the debugger is assumed. If an address space is " - "not specified, the command suffix sets the address space: 'pcatmem' defaults to the first " - "space exposed by the device, 'pcatmemd' defaults to the data space, 'pcatmemi' defaults to " - "the I/O space, and 'pcatmemo' defaults to the opcodes space.\n" + "The pcatmem command returns which PC value at the time the specified address was most " + "recently written. The argument is the requested address, optionally followed by a colon " + "and a CPU and/or address space. The CPU may be specified as a tag or debugger CPU number; " + "if no CPU is specified, the CPU currently visible in the debugger is assumed. If an " + "address space is not specified, the command suffix sets the address space: 'pcatmem' " + "defaults to the first space exposed by the device, 'pcatmemd' defaults to the data space, " + "'pcatmemi' defaults to the I/O space, and 'pcatmemo' defaults to the opcodes space.\n" + "\n" "Right-clicking in a memory view will also display the logged PC for the given address.\n" "\n" "Examples:\n" @@ -521,22 +544,25 @@ const help_item f_static_help_list[] = { "snap", "\n" - " snap [[], ]\n" + " snap [[,]]\n" "\n" - "The snap command takes a snapshot of the current video display and saves it to the configured " - "snapshot directory. If is specified explicitly, a single screenshot for is " - "saved under the requested filename. If is omitted, all screens are saved using the " - "same default rules as the \"save snapshot\" key in MAME proper.\n" + "Takes a snapshot of the emulated video display and saves it to the configured snapshot " + "directory. If a filename is specified, a single screenshot for the specified screen is " + "saved using the specified filename (or the first emulated screen in the system if a screen " + "is not specified). If a file name is not specified, the configured snapshot view and file " + "name pattern are used.\n" + "\n" + "If a file name is specified, the .png extension is automatically appended. The screen " + "number is specified as a zero-based index.\n" "\n" "Examples:\n" "\n" "snap\n" - " Takes a snapshot of the current video screen and saves to the next non-conflicting filename " - " in the configured snapshot directory.\n" + " Takes a snapshot using the configured snapshot view and file name options.\n" "\n" "snap shinobi\n" - " Takes a snapshot of the current video screen and saves it as 'shinobi.png' in the configured " - " snapshot directory.\n" + " Takes a snapshot of the first emulated video screen and saves it as 'shinobi.png' in the " + " configured snapshot directory.\n" }, { "source", @@ -595,15 +621,14 @@ const help_item f_static_help_list[] = "opcodes space.\n" "\n" "The can either be a quoted string or a numeric value or expression or the wildcard " - "character '?'. By default, strings by default imply a byte-sized search; by default " - "non-string data is searched using the native word size of the address space. To override " - "the search size for non-string data, you can prefix values with b. to force byte-sized " - "search, w. for word-sized search, d. for dword-sized search, and q. for qword-sized " - "search. Overrides propagate to subsequent values, so if you want to search for a sequence " - "of words, you need only prefix the first value with a w. Also note that you can intermix " - "sizes to perform more complex searches. The entire range
through " - "
+-1, inclusive, will be searched for the sequence, and all occurrences " - "will be displayed.\n" + "character '?'. By default, strings imply a byte-sized search; by default non-string data " + "is searched using the native word size of the address space. To override the search size " + "for non-string data, you can prefix values with b. to force byte-sized search, w. for " + "word-sized search, d. for dword-sized search, and q. for qword-sized search. Overrides " + "propagate to subsequent values, so if you want to search for a sequence of words, you need " + "only prefix the first value with a w. Also note that you can intermix sizes to perform " + "more complex searches. The entire range
through
+-1, " + "inclusive, will be searched for the sequence, and all occurrences will be displayed.\n" "\n" "Examples:\n" "\n" @@ -613,7 +638,7 @@ const help_item f_static_help_list[] = "\n" "find 300:tms9918a,100,w.abcd,4567\n" " Searches the address range 300-3ff in the first address space exposed by the device " - "':tms9918a' memory for the word-sized value abcd followed by the word-sized value 4567.\n" + "':tms9918a' for the word-sized value abcd followed by the word-sized value 4567.\n" "\n" "find 0,8000,\"AAR\",d.0,\"BEN\",w.0\n" " Searches the address range 0000-7fff for the string \"AAR\" followed by a dword-sized 0 " @@ -640,7 +665,7 @@ const help_item f_static_help_list[] = "non-string data is written using the native word size of the address space. To override " "the data size for non-string data, you can prefix values with b. to force byte-sized fill, " "w. for word-sized fill, d. for dword-sized fill, and q. for qword-sized fill. Overrides " - "propagate to subsequent value, so if you want to fill with a series of words, you need " + "propagate to subsequent values, so if you want to fill with a series of words, you need " "only prefix the first value with a w. Also note that you can intermix sizes to perform " "more complex fills. The fill operation may be truncated if a page fault occurs or if part " "of the sequence or string would fall beyond
+-1.\n" @@ -750,10 +775,14 @@ const help_item f_static_help_list[] = "saving from, and the specifies how much memory to save. The range
" "through
+-1, inclusive, will be output to the file.\n" "\n" - "Example:\n" + "Examples:\n" "\n" - "saver harddriv.bin,80000,40000,:maincpu\n" - " Saves :maincpu region addresses 80000-bffff to the binary file 'harddriv.bin'.\n" + "saver data.bin,200,100,:monitor\n" + " Saves ':monitor' region addresses 200-2ff to the binary file 'data.bin'.\n" + "\n" + "saver cpurom.bin,1000,400,.\n" + " Saves addresses 1000-13ff from the memory region with the same tag as the visible CPU to " + "the binary file 'cpurom.bin'.\n" }, { "load", @@ -773,8 +802,10 @@ const help_item f_static_help_list[] = "file. If the is omitted, if it is zero, or if it is greater than the total " "length of the file, the entire contents of the file will be loaded but no more.\n" "\n" - "NOTE: This will only actually write memory that is possible to overwrite via a memory " - "view.\n" + "NOTE: this has the same effect as writing to the address space from a debugger memory " + "view, or using memory accessors in debugger expressions. Read-only memory will not be " + "overwritten, and writing to I/O addresses may have effects beyond setting register " + "values.\n" "\n" "Examples:\n" "\n" @@ -797,16 +828,20 @@ const help_item f_static_help_list[] = " loadr ,
,,\n" "\n" "The loadr command loads raw memory in the memory region from the binary file " - "specified in the parameter. The
indicates the address to start " + "specified by the parameter. The
specifies the address to start " "loading to, and the specifies how much memory to load. The range
" "through
+-1, inclusive, will be read in from the file. If the " "is zero, or is greater than the total length of the file, the entire contents of the file " "will be loaded but no more.\n" "\n" - "Example:\n" + "Examples:\n" + "\n" + "loadr data.bin,200,100,:monitor\n" + " Loads ':monitor' region addresses 200-2ff from the binary file 'data.bin'.\n" "\n" - "loadr harddriv.bin,80000,40000,:maincpu\n" - " Loads addresses 80000-bffff in the :maincpu region from the binary file 'harddriv.bin'.\n" + "loadr cpurom.bin,1000,400,.\n" + " Loads addresses 1000-13ff in the memory region with the same tag as the visible CPU from " + "the binary file 'cpurom.bin'.\n" }, { "step", @@ -1384,22 +1419,22 @@ const help_item f_static_help_list[] = " map[{d|i|o}]
[:]\n" "\n" "The map commands map a logical memory address to the corresponding physical address, as " - "well as specifying the bank. The address may optionally be followed by a colon and device " - "and/or address space. The device may be specified as a tag or a debugger CPU number; if " - "no device is specified, the CPU currently visible in the debugger is assumed. If an " - "address space is not specified, the command suffix sets the address space: 'map' defaults " - "to the first address space exposed by the device, 'mapd' defaults to the data space, " - "'mapi' defaults to the I/O space, and 'mapo' defaults to the opcodes space.\n" + "well as reporting the handler name. The address may optionally be followed by a colon " + "and device and/or address space. The device may be specified as a tag or a debugger CPU " + "number; if no device is specified, the CPU currently visible in the debugger is assumed. " + "If an address space is not specified, the command suffix sets the address space: 'map' " + "defaults to the first address space exposed by the device, 'mapd' defaults to the data " + "space, 'mapi' defaults to the I/O space, and 'mapo' defaults to the opcodes space.\n" "\n" - "Example:\n" + "Examples:\n" "\n" "map 152d0\n" - " Gives physical address and bank for logical address 152d0 in program memory for the " - "currently visible CPU.\n" + " Gives physical address and handler name for logical address 152d0 in program memory for " + "the currently visible CPU.\n" "\n" "map 107:sms_vdp\n" - " Gives physical address and bank for logical address 107 in the first address space for " - "the device ':sms_vdp'.\n" + " Gives physical address and handler name for logical address 107 in the first address " + "space for the device ':sms_vdp'.\n" }, { "mapd", "#map" }, { "mapi", "#map" }, @@ -1410,20 +1445,24 @@ const help_item f_static_help_list[] = " memdump [,[]]\n" "\n" "Dumps the current memory maps to the file specified by , or memdump.log if " - "omitted. If is specified it must be the tag of a device, and only memory maps " - "for the part of the device tree rooted on this device will be dumped.\n" + "omitted. If is specified, only memory maps for the part of the device tree " + "rooted at this device will be dumped. Devices may be specified using tags or CPU " + "numbers.\n" "\n" "Examples:\n" "\n" "memdump mylog.log\n" - " Dumps all memory maps to the file mylog.log.\n" + " Dumps memory maps for all devices in the system to the file mylog.log.\n" "\n" "memdump\n" - " Dumps all memory maps to the file memdump.log.\n" + " Dumps memory maps for all devices in the system to the file memdump.log.\n" "\n" "memdump audiomaps.log,audiopcb\n" " Dumps memory maps for device ':audiopcb' and all its child devices to the file " "audiomaps.log.\n" + "\n" + "memdump mylog.log,1\n" + " Dumps memory maps for the CPU 1 and all its child devices to the file mylog.log.\n" }, { "comlist", @@ -1466,10 +1505,10 @@ const help_item f_static_help_list[] = "Examples:\n" "\n" "commit 0, hello world.\n" - " Adds the comment 'hello world.' to the code at address 0x0\n" + " Adds the comment 'hello world.' to the code at address 0x0 and saves comments\n" "\n" "/* 10, undocumented opcode!\n" - " Adds the comment 'undocumented opcode!' to the code at address 0x10\n" + " Adds the comment 'undocumented opcode!' to the code at address 0x10 and saves comments\n" "\n" }, { diff --git a/src/emu/debug/express.cpp b/src/emu/debug/express.cpp index c4b2662e3bb..bc90ddaf52e 100644 --- a/src/emu/debug/express.cpp +++ b/src/emu/debug/express.cpp @@ -540,14 +540,73 @@ void symbol_table::write_memory(address_space &space, offs_t address, u64 data, //------------------------------------------------- -// expression_get_device - return a device +// expression_get_space - return a space // based on a case insensitive tag search //------------------------------------------------- -device_t *symbol_table::expression_get_device(const char *tag) +expression_error symbol_table::expression_get_space(const char *tag, int &spacenum, device_memory_interface *&memory) { - // convert to lowercase then lookup the name (tags are enforced to be all lower case) - return m_machine.root_device().subdevice(strmakelower(tag)); + device_t *device = nullptr; + std::string spacename; + if (tag) + { + // convert to lowercase then lookup the name (tags are enforced to be all lower case) + device_t *base; + if ((('^' == tag[0]) || (('.' == tag[0]) && ((':' == tag[1]) || !tag[1]))) && m_memintf) + base = &m_memintf->device(); + else + base = &m_machine.root_device(); + device = base->subdevice(strmakelower(tag)); + + // if that failed, treat the last component as an address space + if (!device) + { + std::string_view t = tag; + auto const delimiter = t.find_last_of(":^"); + bool const found = std::string_view::npos != delimiter; + if (!found || (':' == t[delimiter])) + { + spacename = strmakelower(t.substr(found ? (delimiter + 1) : 0)); + t = t.substr(0, !found ? 0 : !delimiter ? 1 : delimiter); + if (!t.empty()) + device = base->subdevice(strmakelower(t)); + else + device = m_memintf ? &m_memintf->device() : &m_machine.root_device(); + } + } + } + else if (m_memintf) + { + device = &m_memintf->device(); + } + + // if still no device, report error + if (!device) + { + memory = nullptr; + return expression_error::INVALID_MEMORY_NAME; + } + + // ensure device has memory interface, and check for space if search not required + if (!device->interface(memory) || (spacename.empty() && (0 <= spacenum) && !memory->has_space(spacenum))) + { + memory = nullptr; + return expression_error::NO_SUCH_MEMORY_SPACE; + } + + // find space by name or take first populated space + for (int i = 0; memory->max_space_count() > i; ++i) + { + if (memory->has_space(i) && (spacename.empty() || (memory->space(i).name() == spacename))) + { + spacenum = i; + return expression_error::NONE; + } + } + + // space not found + memory = nullptr; + return expression_error::NO_SUCH_MEMORY_SPACE; } @@ -574,76 +633,45 @@ u64 symbol_table::memory_value(const char *name, expression_space spacenum, u32 { device_memory_interface *memory = m_memintf; + bool logical = true; + int space = -1; switch (spacenum) { - case EXPSPACE_PROGRAM_LOGICAL: - case EXPSPACE_DATA_LOGICAL: - case EXPSPACE_IO_LOGICAL: - case EXPSPACE_SPACE3_LOGICAL: - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory != nullptr && memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL))) - { - address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL)); - auto dis = m_machine.disable_side_effects(disable_se); - return read_memory(space, address, size, true); - } - break; - case EXPSPACE_PROGRAM_PHYSICAL: case EXPSPACE_DATA_PHYSICAL: case EXPSPACE_IO_PHYSICAL: - case EXPSPACE_SPACE3_PHYSICAL: - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL))) - { - address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL)); - auto dis = m_machine.disable_side_effects(disable_se); - return read_memory(space, address, size, false); - } - break; - - case EXPSPACE_RAMWRITE: - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory != nullptr && memory->has_space(AS_PROGRAM)) + case EXPSPACE_OPCODE_PHYSICAL: + spacenum = expression_space(spacenum - (EXPSPACE_PROGRAM_PHYSICAL - EXPSPACE_PROGRAM_LOGICAL)); + logical = false; + [[fallthrough]]; + case EXPSPACE_PROGRAM_LOGICAL: + case EXPSPACE_DATA_LOGICAL: + case EXPSPACE_IO_LOGICAL: + case EXPSPACE_OPCODE_LOGICAL: + space = AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL); + expression_get_space(name, space, memory); + if (memory) { auto dis = m_machine.disable_side_effects(disable_se); - return read_program_direct(memory->space(AS_PROGRAM), (spacenum == EXPSPACE_OPCODE), address, size); + return read_memory(memory->space(space), address, size, logical); } break; - case EXPSPACE_OPCODE: - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory != nullptr && memory->has_space(AS_OPCODES)) + case EXPSPACE_PRGDIRECT: + case EXPSPACE_OPDIRECT: + space = (spacenum == EXPSPACE_OPDIRECT) ? AS_OPCODES : AS_PROGRAM; + expression_get_space(name, space, memory); + if (memory) { auto dis = m_machine.disable_side_effects(disable_se); - return read_program_direct(memory->space(AS_OPCODES), (spacenum == EXPSPACE_OPCODE), address, size); + return read_program_direct(memory->space(space), (spacenum == EXPSPACE_OPDIRECT) ? 1 : 0, address, size); } break; case EXPSPACE_REGION: - if (name == nullptr) - break; - return read_memory_region(name, address, size); + if (name) + return read_memory_region(name, address, size); + break; default: break; @@ -762,78 +790,44 @@ void symbol_table::set_memory_value(const char *name, expression_space spacenum, { device_memory_interface *memory = m_memintf; + bool logical = true; + int space = -1; switch (spacenum) { - case EXPSPACE_PROGRAM_LOGICAL: - case EXPSPACE_DATA_LOGICAL: - case EXPSPACE_IO_LOGICAL: - case EXPSPACE_SPACE3_LOGICAL: - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory != nullptr && memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL))) - { - address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL)); - auto dis = m_machine.disable_side_effects(disable_se); - write_memory(space, address, data, size, true); - } - break; - case EXPSPACE_PROGRAM_PHYSICAL: case EXPSPACE_DATA_PHYSICAL: case EXPSPACE_IO_PHYSICAL: - case EXPSPACE_SPACE3_PHYSICAL: - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory != nullptr && memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL))) - { - address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL)); - auto dis = m_machine.disable_side_effects(disable_se); - write_memory(space, address, data, size, false); - } - break; - - case EXPSPACE_RAMWRITE: { - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory != nullptr && memory->has_space(AS_PROGRAM)) + case EXPSPACE_OPCODE_PHYSICAL: + spacenum = expression_space(spacenum - (EXPSPACE_PROGRAM_PHYSICAL - EXPSPACE_PROGRAM_LOGICAL)); + logical = false; + [[fallthrough]]; + case EXPSPACE_PROGRAM_LOGICAL: + case EXPSPACE_DATA_LOGICAL: + case EXPSPACE_IO_LOGICAL: + case EXPSPACE_OPCODE_LOGICAL: + space = AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL); + expression_get_space(name, space, memory); + if (memory) { auto dis = m_machine.disable_side_effects(disable_se); - write_program_direct(memory->space(AS_PROGRAM), (spacenum == EXPSPACE_OPCODE), address, size, data); + write_memory(memory->space(space), address, data, size, logical); } break; - } - case EXPSPACE_OPCODE: { - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory != nullptr && memory->has_space(AS_OPCODES)) + case EXPSPACE_PRGDIRECT: + case EXPSPACE_OPDIRECT: + space = (spacenum == EXPSPACE_OPDIRECT) ? AS_OPCODES : AS_PROGRAM; + expression_get_space(name, space, memory); + if (memory) { auto dis = m_machine.disable_side_effects(disable_se); - write_program_direct(memory->space(AS_OPCODES), (spacenum == EXPSPACE_OPCODE), address, size, data); + write_program_direct(memory->space(space), (spacenum == EXPSPACE_OPDIRECT) ? 1 : 0, address, size, data); } break; - } case EXPSPACE_REGION: - if (name == nullptr) - break; - write_memory_region(name, address, size, data); + if (name) + write_memory_region(name, address, size, data); break; default: @@ -966,73 +960,27 @@ expression_error::error_code symbol_table::memory_valid(const char *name, expres { device_memory_interface *memory = m_memintf; + int spaceno = -1; switch (space) { case EXPSPACE_PROGRAM_LOGICAL: case EXPSPACE_DATA_LOGICAL: case EXPSPACE_IO_LOGICAL: - case EXPSPACE_SPACE3_LOGICAL: - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device == nullptr) - return expression_error::INVALID_MEMORY_NAME; - if (!device->interface(memory)) - return expression_error::NO_SUCH_MEMORY_SPACE; - } - else if (memory == nullptr) - return expression_error::MISSING_MEMORY_NAME; - if (!memory->has_space(AS_PROGRAM + (space - EXPSPACE_PROGRAM_LOGICAL))) - return expression_error::NO_SUCH_MEMORY_SPACE; - break; + case EXPSPACE_OPCODE_LOGICAL: + spaceno = AS_PROGRAM + (space - EXPSPACE_PROGRAM_LOGICAL); + return expression_get_space(name, spaceno, memory); case EXPSPACE_PROGRAM_PHYSICAL: case EXPSPACE_DATA_PHYSICAL: case EXPSPACE_IO_PHYSICAL: - case EXPSPACE_SPACE3_PHYSICAL: - if (name) - { - device_t *device = expression_get_device(name); - if (device == nullptr) - return expression_error::INVALID_MEMORY_NAME; - if (!device->interface(memory)) - return expression_error::NO_SUCH_MEMORY_SPACE; - } - else if (memory == nullptr) - return expression_error::MISSING_MEMORY_NAME; - if (!memory->has_space(AS_PROGRAM + (space - EXPSPACE_PROGRAM_PHYSICAL))) - return expression_error::NO_SUCH_MEMORY_SPACE; - break; - - case EXPSPACE_RAMWRITE: - if (name) - { - device_t *device = expression_get_device(name); - if (device == nullptr) - return expression_error::INVALID_MEMORY_NAME; - if (!device->interface(memory)) - return expression_error::NO_SUCH_MEMORY_SPACE; - } - else if (memory == nullptr) - return expression_error::MISSING_MEMORY_NAME; - if (!memory->has_space(AS_PROGRAM)) - return expression_error::NO_SUCH_MEMORY_SPACE; - break; + case EXPSPACE_OPCODE_PHYSICAL: + spaceno = AS_PROGRAM + (space - EXPSPACE_PROGRAM_PHYSICAL); + return expression_get_space(name, spaceno, memory); - case EXPSPACE_OPCODE: - if (name) - { - device_t *device = expression_get_device(name); - if (device == nullptr) - return expression_error::INVALID_MEMORY_NAME; - if (!device->interface(memory)) - return expression_error::NO_SUCH_MEMORY_SPACE; - } - else if (memory == nullptr) - return expression_error::MISSING_MEMORY_NAME; - if (!memory->has_space(AS_OPCODES)) - return expression_error::NO_SUCH_MEMORY_SPACE; - break; + case EXPSPACE_PRGDIRECT: + case EXPSPACE_OPDIRECT: + spaceno = (space == EXPSPACE_OPDIRECT) ? AS_OPCODES : AS_PROGRAM; + return expression_get_space(name, spaceno, memory); case EXPSPACE_REGION: if (!name) @@ -1044,6 +992,7 @@ expression_error::error_code symbol_table::memory_valid(const char *name, expres default: return expression_error::NO_SUCH_MEMORY_SPACE; } + return expression_error::NONE; } @@ -1375,12 +1324,15 @@ void parsed_expression::parse_symbol_or_number(parse_token &token, const char *& // check for memory @ and ! operators if (string[0] == '@' || string[0] == '!') { - try { + try + { bool disable_se = string[0] == '@'; parse_memory_operator(token, buffer.c_str(), disable_se); string += 1; return; - } catch(const expression_error &) { + } + catch (const expression_error &) + { // Try some other operator instead } } @@ -1614,13 +1566,13 @@ void parsed_expression::parse_memory_operator(parse_token &token, const char *st string = dot + 1; } - // length 3 means logical/physical, then space, then size int length = (int)strlen(string); bool physical = false; int space = 'p'; int size; if (length == 3) { + // length 3 means logical/physical, then space, then size if (string[0] != 'l' && string[0] != 'p') throw expression_error(expression_error::INVALID_MEMORY_SPACE, token.offset() + (string - startstring)); if (string[1] != 'p' && string[1] != 'd' && string[1] != 'i' && string[1] != '3') @@ -1629,21 +1581,22 @@ void parsed_expression::parse_memory_operator(parse_token &token, const char *st space = string[1]; size = string[2]; } - - // length 2 means space then size else if (length == 2) { + // length 2 means space then size space = string[0]; size = string[1]; } - - // length 1 means size else if (length == 1) + { + // length 1 means size size = string[0]; - - // anything else is invalid + } else + { + // anything else is invalid throw expression_error(expression_error::INVALID_TOKEN, token.offset()); + } // convert the space to flags expression_space memspace; @@ -1652,9 +1605,9 @@ void parsed_expression::parse_memory_operator(parse_token &token, const char *st case 'p': memspace = physical ? EXPSPACE_PROGRAM_PHYSICAL : EXPSPACE_PROGRAM_LOGICAL; break; case 'd': memspace = physical ? EXPSPACE_DATA_PHYSICAL : EXPSPACE_DATA_LOGICAL; break; case 'i': memspace = physical ? EXPSPACE_IO_PHYSICAL : EXPSPACE_IO_LOGICAL; break; - case '3': memspace = physical ? EXPSPACE_SPACE3_PHYSICAL : EXPSPACE_SPACE3_LOGICAL; break; - case 'o': memspace = EXPSPACE_OPCODE; break; - case 'r': memspace = EXPSPACE_RAMWRITE; break; + case '3': memspace = physical ? EXPSPACE_OPCODE_PHYSICAL : EXPSPACE_OPCODE_LOGICAL; break; + case 'r': memspace = EXPSPACE_PRGDIRECT; break; + case 'o': memspace = EXPSPACE_OPDIRECT; break; case 'm': memspace = EXPSPACE_REGION; break; default: throw expression_error(expression_error::INVALID_MEMORY_SPACE, token.offset() + (string - startstring)); } diff --git a/src/emu/debug/express.h b/src/emu/debug/express.h index c87b9370f7d..23284193f47 100644 --- a/src/emu/debug/express.h +++ b/src/emu/debug/express.h @@ -34,13 +34,13 @@ enum expression_space EXPSPACE_PROGRAM_LOGICAL, EXPSPACE_DATA_LOGICAL, EXPSPACE_IO_LOGICAL, - EXPSPACE_SPACE3_LOGICAL, + EXPSPACE_OPCODE_LOGICAL, EXPSPACE_PROGRAM_PHYSICAL, EXPSPACE_DATA_PHYSICAL, EXPSPACE_IO_PHYSICAL, - EXPSPACE_SPACE3_PHYSICAL, - EXPSPACE_OPCODE, - EXPSPACE_RAMWRITE, + EXPSPACE_OPCODE_PHYSICAL, + EXPSPACE_PRGDIRECT, + EXPSPACE_OPDIRECT, EXPSPACE_REGION }; @@ -204,7 +204,7 @@ private: u64 read_memory_region(const char *rgntag, offs_t address, int size); void write_program_direct(address_space &space, int opcode, offs_t address, int size, u64 data); void write_memory_region(const char *rgntag, offs_t address, int size, u64 data); - device_t *expression_get_device(const char *tag); + expression_error expression_get_space(const char *tag, int &spacenum, device_memory_interface *&memory); void notify_memory_modified(); // internal state diff --git a/src/frontend/mame/ui/ui.h b/src/frontend/mame/ui/ui.h index 9607ca24a91..44727703a20 100644 --- a/src/frontend/mame/ui/ui.h +++ b/src/frontend/mame/ui/ui.h @@ -56,7 +56,7 @@ class laserdisc_device; /* handy colors */ #define UI_GREEN_COLOR rgb_t(0xef,0x0a,0x66,0x0a) #define UI_YELLOW_COLOR rgb_t(0xef,0xcc,0x7a,0x28) -#define UI_RED_COLOR rgb_t(0xef,0xcc,0x14,0x14) +#define UI_RED_COLOR rgb_t(0xef,0xb2,0x00,0x00) /* cancel return value for a UI handler */ #define UI_HANDLER_CANCEL ((uint32_t)~0) -- cgit v1.2.3