Still more user experience improvements:

Changed the default mapping for UI select to not trigger on Alt+Enter
fullscreen toggle.  (Fullscreen toggle still doesn't work in menus -
actually fixing that is complicated.)

frontend: Made the about box wrap text properly, made the title and
backtrack menu item always visible, and added a footer with the VCS
revision.

frontend: Don't highlight the favourites and info toolbar buttons if
there's no selection (can happen if filters produce no results).  Also
made the info viewer appear even if no info is available - it's less
confusing to see an empty menu than wonder why clicking the button does
nothing.

debugger: Added a register points view to the GUI debuggers, to go with
the breakpoints and watchpoints views.

debugger: Extended [brw]p(clear|(en|dis)able) commands to accept
multiple arguments to perform the same action on multiple
(break|watch|register)points at once.  Also made rplist accept a CPU for
showing a single CPU's register points ([bw]plist already support this).

docs: Updated registerpoints debugger commands page, and updated other
pages for latest extensions to syntax.
This commit is contained in:
Vas Crabb 2021-10-18 08:22:21 +11:00
parent 0a82b82684
commit 40a30af10f
34 changed files with 1125 additions and 426 deletions

View File

@ -75,10 +75,10 @@ Back to :ref:`debugger-breakpoint-list`
bpclear bpclear
------- -------
**bpclear [<bpnum>]** **bpclear [<bpnum>[,…]]**
Clear breakpoints. If **<bpnum>** is specified, the breakpoint it Clear breakpoints. If **<bpnum>** is specified, the breakpoints
refers to will be cleared. If **<bpnum>** is not specified, all referred to will be cleared. If **<bpnum>** is not specified, all
breakpoints will be cleared. breakpoints will be cleared.
Examples: Examples:
@ -96,10 +96,10 @@ Back to :ref:`debugger-breakpoint-list`
bpdisable bpdisable
--------- ---------
**bpdisable [<bpnum>]** **bpdisable [<bpnum>[,…]]**
Disable breakpoints. If **<bpnum>** is specified, the breakpoint it Disable breakpoints. If **<bpnum>** is specified, the breakpoints
refers to will be disabled. If **<bpnum>** is not specified, all referred to will be disabled. If **<bpnum>** is not specified, all
breakpoints will be disabled. breakpoints will be disabled.
Note that disabling a breakpoint does not delete it, it just temporarily Note that disabling a breakpoint does not delete it, it just temporarily
@ -122,10 +122,10 @@ Back to :ref:`debugger-breakpoint-list`
bpenable bpenable
-------- --------
**bpenable [<bpnum>]** **bpenable [<bpnum>[,…]]**
Enable breakpoints. If **<bpnum>** is specified, the breakpoint it Enable breakpoints. If **<bpnum>** is specified, the breakpoint
refers to will be enabled. If **<bpnum>** is not specified, all referred to will be enabled. If **<bpnum>** is not specified, all
breakpoints will be enabled. breakpoints will be enabled.
Examples: Examples:

View File

@ -285,7 +285,7 @@ Back to :ref:`debugger-execution-list`
ignore ignore
------ ------
**ignore [<CPU>[,<CPU>[,...]]]** **ignore [<CPU>[,<CPU>[,]]]**
Ignores the specified CPUs in the debugger. CPUs can be specified by Ignores the specified CPUs in the debugger. CPUs can be specified by
tag or debugger CPU number (see :ref:`debugger-devicespec` for details). tag or debugger CPU number (see :ref:`debugger-devicespec` for details).
@ -316,7 +316,7 @@ Back to :ref:`debugger-execution-list`
observe observe
------- -------
**observe [<CPU>[,<CPU>[,...]]]** **observe [<CPU>[,<CPU>[,]]]**
Allow interaction with the specified CPUs in the debugger. CPUs can be Allow interaction with the specified CPUs in the debugger. CPUs can be
specified by tag or debugger CPU number (see :ref:`debugger-devicespec` specified by tag or debugger CPU number (see :ref:`debugger-devicespec`

View File

@ -159,7 +159,7 @@ Back to :ref:`debugger-general-list`
print print
----- -----
**print <item>[,...]** **print <item>[,]**
The **print** command prints the results of one or more expressions to The **print** command prints the results of one or more expressions to
the debugger console as hexadecimal numbers. the debugger console as hexadecimal numbers.
@ -180,7 +180,7 @@ Back to :ref:`debugger-general-list`
printf printf
------ ------
**printf <format>[,<argument>[,...]]** **printf <format>[,<argument>[,]]**
Prints a C-style formatted message to the debugger console. Only a Prints a C-style formatted message to the debugger console. Only a
very limited subset of format specifiers and escape sequences are very limited subset of format specifiers and escape sequences are
@ -223,7 +223,7 @@ Back to :ref:`debugger-general-list`
logerror logerror
-------- --------
**logerror <format>[,<argument>[,...]]** **logerror <format>[,<argument>[,]]**
Prints a C-style formatted message to the error log. See Prints a C-style formatted message to the error log. See
:ref:`debugger-command-printf` for details about the limited set of :ref:`debugger-command-printf` for details about the limited set of
@ -246,7 +246,7 @@ Back to :ref:`debugger-general-list`
tracelog tracelog
-------- --------
**tracelog <format>[,<argument>[,...]]** **tracelog <format>[,<argument>[,]]**
Prints a C-style formatted message to the currently open trace file (see Prints a C-style formatted message to the currently open trace file (see
:ref:`debugger-command-trace` for more information). If no trace file :ref:`debugger-command-trace` for more information). If no trace file
@ -272,7 +272,7 @@ Back to :ref:`debugger-general-list`
tracesym tracesym
-------- --------
**tracesym <item>[,...]** **tracesym <item>[,]**
Prints the specified symbols to the currently open trace file (see Prints the specified symbols to the currently open trace file (see
:ref:`debugger-command-trace` for more information). If no trace file :ref:`debugger-command-trace` for more information). If no trace file

View File

@ -64,7 +64,7 @@ Back to :ref:`debugger-memory-list`
find find
---- ----
**f[ind][{d|i|o}] <address>[:<space>],<length>[,<data>[,...]]** **f[ind][{d|i|o}] <address>[:<space>],<length>[,<data>[,]]**
Search through memory for the specified sequence of data. The Search through memory for the specified sequence of data. The
**<address>** is the address to begin searching from, optionally **<address>** is the address to begin searching from, optionally
@ -113,7 +113,7 @@ Back to :ref:`debugger-memory-list`
fill fill
---- ----
**fill[{d|i|o}] <address>[:<space>],<length>[,<data>[,...]]** **fill[{d|i|o}] <address>[:<space>],<length>[,<data>[,]]**
Overwrite a block of memory with copies of the supplied data sequence. Overwrite a block of memory with copies of the supplied data sequence.
The **<address>** specifies the address to begin writing at, optionally The **<address>** specifies the address to begin writing at, optionally

View File

@ -1,120 +1,146 @@
.. _debugger-registerpoints-list: .. _debugger-registerpoints-list:
Registerpoints Debugger Commands Registerpoint Debugger Commands
================================ ================================
:ref:`debugger-command-rpset`
You can also type **help <command>** for further details on each command in the MAME Debugger interface. sets a registerpoint to trigger on a condition
:ref:`debugger-command-rpclear`
| :ref:`debugger-command-rpset` -- sets a registerpoint to trigger on <condition> clears registerpoints
| :ref:`debugger-command-rpclear` -- clears a given registerpoint or all if no <rpnum> specified :ref:`debugger-command-rpdisable`
| :ref:`debugger-command-rpdisable` -- disabled a given registerpoint or all if no <rpnum> specified disables a registerpoint
| :ref:`debugger-command-rpenable` -- enables a given registerpoint or all if no <rpnum> specified :ref:`debugger-command-rpenable`
| :ref:`debugger-command-rplist` -- lists all the registerpoints enables registerpoints
:ref:`debugger-command-rplist`
lists registerpoints
.. _debugger-command-rpset:
.. _debugger-command-rpset:
rpset rpset
----- -----
| **rp[set] {<condition>}[,<action>]]** **rp[set] <condition>[,<action>]**
|
| Sets a new registerpoint which will be triggered when <condition> is met. The condition must be specified between curly braces to prevent the condition from being evaluated as an assignment. Sets a new registerpoint which will be triggered when the expression
| The optional <action> parameter provides a command that is executed whenever the registerpoint is hit. Note that you may need to embed the action within braces { } in order to prevent commas and semicolons from being interpreted as applying to the rpset command itself. supplied as the **<condition>** evaluates to true (non-zero). Note that
| Each registerpoint that is set is assigned an index which can be used in other registerpoint commands to reference this registerpoint. the condition may need to be surrounded with braces ``{ }`` to prevent
| it from being interpreted as an assignment. The optional **<action>**
| Examples: parameter provides a command to be executed whenever the registerpoint
| is triggered. Note that you may need to surround the action with braces
| rp {PC==0150} ``{ }`` to ensure commas and semicolons within the command are not
| interpreted in the context of the ``rpset`` command itself.
| Set a registerpoint that will halt execution whenever the PC register equals 0x150.
| Each registerpoint that is set is assigned a numeric index which can be
| temp0=0; rp {PC==0150},{temp0++; g} used to refer to it in other registerpoint commands. Registerpoint
| indices are unique throughout a session.
| Set a registerpoint that will increment the variable temp0 whenever the PC register equals 0x0150.
| Examples:
| rp {temp0==5}
| ``rp {PC==150}``
| Set a registerpoint that will halt execution whenever the temp0 variable equals 5. Set a registerpoint that will halt execution whenever the **PC**
| register equals 150.
| Back to :ref:`debugger-registerpoints-list` ``temp0=0; rp {PC==150},{temp0++; g}``
Set a registerpoint that will increment the variable **temp0**
whenever the **PC** register equals 150.
``rp {temp0==5}``
Set a registerpoint that will halt execution whenever the **temp0**
variable equals 5.
Back to :ref:`debugger-registerpoints-list`
.. _debugger-command-rpclear: .. _debugger-command-rpclear:
rpclear rpclear
------- -------
| **rpclear [<rpnum>]** **rpclear [<rpnum>,[,…]]**
|
| The rpclear command clears a registerpoint. If <rpnum> is specified, only the requested registerpoint is cleared, otherwise all registerpoints are cleared. Clears registerpoints. If **<rpnum>** is specified, the registerpoints
| referred to will be cleared. If **<rpnum>** is not specified, all
| Examples: registerpoints will be cleared.
|
| rpclear 3 Examples:
|
| Clear registerpoint index 3. ``rpclear 3``
| Clear the registerpoint with index 3.
| rpclear ``rpclear``
| Clear all registerpoints.
| Clear all registerpoints.
| Back to :ref:`debugger-registerpoints-list`
| Back to :ref:`debugger-registerpoints-list`
.. _debugger-command-rpdisable: .. _debugger-command-rpdisable:
rpdisable rpdisable
--------- ---------
| **rpdisable [<rpnum>]** **rpdisable [<rpnum>[,…]]**
|
| The rpdisable command disables a registerpoint. If <rpnum> is specified, only the requested registerpoint is disabled, otherwise all registerpoints are disabled. Note that disabling a registerpoint does not delete it, it just temporarily marks the registerpoint as inactive. Disables registerpoints. If **<rpnum>** is specified, the
| registerpoints referred to will be disabled. If **<rpnum>** is not
| Examples: specified, all registerpoints will be disabled.
|
| rpdisable 3 Note that disabling a registerpoint does not delete it, it just
| temporarily marks the registerpoint as inactive. Disabled
| Disable registerpoint index 3. registerpoints will not cause execution to halt, their condition
| expressions will not be evaluated, and their associated commands will
| rpdisable not be executed.
|
| Disable all registerpoints. Examples:
|
| Back to :ref:`debugger-registerpoints-list` ``rpdisable 3``
Disable the registerpoint with index 3.
``rpdisable``
Disable all registerpoints.
Back to :ref:`debugger-registerpoints-list`
.. _debugger-command-rpenable: .. _debugger-command-rpenable:
rpenable rpenable
-------- --------
| **rpenable [<rpnum>]** **rpenable [<rpnum>[,…]]**
|
| The rpenable command enables a registerpoint. If <rpnum> is specified, only the requested registerpoint is enabled, otherwise all registerpoints are enabled. Enables registerpoints. If **<rpnum>** is specified, the registerpoints
| referred to will be enabled. If **<rpnum>** is not specified, all
| Examples: registerpoints will be enabled.
|
| rpenable 3 Examples:
|
| Enable registerpoint index 3. ``rpenable 3``
| Enable the registerpoint with index 3.
| rpenable ``rpenable``
| Enable all registerpoints.
| Enable all registerpoints.
| Back to :ref:`debugger-registerpoints-list`
| Back to :ref:`debugger-registerpoints-list`
.. _debugger-command-rplist: .. _debugger-command-rplist:
rplist rplist
------ ------
| **rplist** **rplist [<CPU>]**
|
| The rplist command lists all the current registerpoints, along with their index and any actions attached to them. List current registerpoints, along with their indices and conditions,
| and any associated actions actions. If no **<CPU>** is specified,
| Back to :ref:`debugger-registerpoints-list` registerpoints for all CPUs in the system will be listed; if a **<CPU>**
is specified, only registerpoints for that CPU will be listed. The
**<CPU>** can be specified by tag or by debugger CPU number (see
:ref:`debugger-devicespec` for details).
Examples:
``rplist``
List all registerpoints.
``rplist .``
List all registerpoints for the visible CPU.
``rplist maincpu``
List all registerpoints for the CPU with the absolute tag path
``:maincpu``.
Back to :ref:`debugger-registerpoints-list`

View File

@ -83,10 +83,10 @@ Back to :ref:`debugger-watchpoints-list`
wpclear wpclear
------- -------
**wpclear [<wpnum>]** **wpclear [<wpnum>[,…]]**
Clear watchpoints. If **<wpnum>** is specified, the watchpoint it Clear watchpoints. If **<wpnum>** is specified, the watchpoints
refers to will be cleared. If **<wpnum>** is not specified, all referred to will be cleared. If **<wpnum>** is not specified, all
watchpoints will be cleared. watchpoints will be cleared.
Examples: Examples:
@ -104,10 +104,10 @@ Back to :ref:`debugger-watchpoints-list`
wpdisable wpdisable
--------- ---------
**wpdisable [<wpnum>]** **wpdisable [<wpnum>[,…]]**
Disable watchpoints. If **<wpnum>** is specified, the watchpoint it Disable watchpoints. If **<wpnum>** is specified, the watchpoints
refers to will be disabled. If **<wpnum>** is not specified, all referred to will be disabled. If **<wpnum>** is not specified, all
watchpoints will be disabled. watchpoints will be disabled.
Note that disabling a watchpoint does not delete it, it just temporarily Note that disabling a watchpoint does not delete it, it just temporarily
@ -130,10 +130,10 @@ Back to :ref:`debugger-watchpoints-list`
wpenable wpenable
-------- --------
**wpenable [<wpnum>]** **wpenable [<wpnum>[,…]]**
Enable watchpoints. If **<wpnum>** is specified, the watchpoint it Enable watchpoints. If **<wpnum>** is specified, the watchpoints
refers to will be enabled. If **<wpnum>** is not specified, all referred to will be enabled. If **<wpnum>** is not specified, all
watchpoints will be enabled. watchpoints will be enabled.
Examples: Examples:

View File

@ -1073,7 +1073,7 @@ endif
ifneq ($(GIT_AVAILABLE),git) ifneq ($(GIT_AVAILABLE),git)
IGNORE_GIT := 1 IGNORE_GIT := 1
endif endif
ifeq ($(wildcard .git/*),) ifeq ($(filter .git,$(wildcard .*)),)
IGNORE_GIT := 1 IGNORE_GIT := 1
endif endif
@ -1757,17 +1757,23 @@ endif
ifeq (posix,$(SHELLTYPE)) ifeq (posix,$(SHELLTYPE))
$(GENDIR)/version.cpp: makefile $(GENDIR)/git_desc | $(GEN_FOLDERS) $(GENDIR)/version.cpp: makefile $(GENDIR)/git_desc | $(GEN_FOLDERS)
@echo '#define BARE_BUILD_VERSION "0.236"' > $@ @echo '#define BARE_BUILD_VERSION "0.236"' > $@
@echo '#define BARE_VCS_REVISION "$(NEW_GIT_VERSION)"' >> $@
@echo 'extern const char bare_build_version[];' >> $@ @echo 'extern const char bare_build_version[];' >> $@
@echo 'extern const char bare_vcs_revision[];' >> $@
@echo 'extern const char build_version[];' >> $@ @echo 'extern const char build_version[];' >> $@
@echo 'const char bare_build_version[] = BARE_BUILD_VERSION;' >> $@ @echo 'const char bare_build_version[] = BARE_BUILD_VERSION;' >> $@
@echo 'const char build_version[] = BARE_BUILD_VERSION " ($(NEW_GIT_VERSION))";' >> $@ @echo 'const char bare_vcs_revision[] = BARE_VCS_REVISION;' >> $@
@echo 'const char build_version[] = BARE_BUILD_VERSION " (" BARE_VCS_REVISION ")";' >> $@
else else
$(GENDIR)/version.cpp: makefile $(GENDIR)/git_desc | $(GEN_FOLDERS) $(GENDIR)/version.cpp: makefile $(GENDIR)/git_desc | $(GEN_FOLDERS)
@echo #define BARE_BUILD_VERSION "0.236" > $@ @echo #define BARE_BUILD_VERSION "0.236" > $@
@echo #define BARE_VCS_REVISION "$(NEW_GIT_VERSION)" >> $@
@echo extern const char bare_build_version[]; >> $@ @echo extern const char bare_build_version[]; >> $@
@echo extern const char bare_vcs_revision[]; >> $@
@echo extern const char build_version[]; >> $@ @echo extern const char build_version[]; >> $@
@echo const char bare_build_version[] = BARE_BUILD_VERSION; >> $@ @echo const char bare_build_version[] = BARE_BUILD_VERSION; >> $@
@echo const char build_version[] = BARE_BUILD_VERSION " ($(NEW_GIT_VERSION))"; >> $@ @echo const char bare_vcs_revision[] = BARE_VCS_REVISION; >> $@
@echo const char build_version[] = BARE_BUILD_VERSION " (" BARE_VCS_REVISION ")"; >> $@
endif endif

View File

@ -238,6 +238,8 @@ files {
MAME_DIR .. "src/emu/debug/dvmemory.h", MAME_DIR .. "src/emu/debug/dvmemory.h",
MAME_DIR .. "src/emu/debug/dvbpoints.cpp", MAME_DIR .. "src/emu/debug/dvbpoints.cpp",
MAME_DIR .. "src/emu/debug/dvbpoints.h", MAME_DIR .. "src/emu/debug/dvbpoints.h",
MAME_DIR .. "src/emu/debug/dvrpoints.cpp",
MAME_DIR .. "src/emu/debug/dvrpoints.h",
MAME_DIR .. "src/emu/debug/dvwpoints.cpp", MAME_DIR .. "src/emu/debug/dvwpoints.cpp",
MAME_DIR .. "src/emu/debug/dvwpoints.h", MAME_DIR .. "src/emu/debug/dvwpoints.h",
MAME_DIR .. "src/emu/debug/dvstate.cpp", MAME_DIR .. "src/emu/debug/dvstate.cpp",

View File

@ -108,6 +108,8 @@ project ("osd_" .. _OPTIONS["osd"])
MAME_DIR .. "src/osd/modules/debugger/osx/memoryviewer.h", MAME_DIR .. "src/osd/modules/debugger/osx/memoryviewer.h",
MAME_DIR .. "src/osd/modules/debugger/osx/pointsviewer.mm", MAME_DIR .. "src/osd/modules/debugger/osx/pointsviewer.mm",
MAME_DIR .. "src/osd/modules/debugger/osx/pointsviewer.h", MAME_DIR .. "src/osd/modules/debugger/osx/pointsviewer.h",
MAME_DIR .. "src/osd/modules/debugger/osx/registerpointsview.mm",
MAME_DIR .. "src/osd/modules/debugger/osx/registerpointsview.h",
MAME_DIR .. "src/osd/modules/debugger/osx/registersview.mm", MAME_DIR .. "src/osd/modules/debugger/osx/registersview.mm",
MAME_DIR .. "src/osd/modules/debugger/osx/registersview.h", MAME_DIR .. "src/osd/modules/debugger/osx/registersview.h",
MAME_DIR .. "src/osd/modules/debugger/osx/watchpointsview.mm", MAME_DIR .. "src/osd/modules/debugger/osx/watchpointsview.mm",

View File

@ -250,9 +250,9 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu
m_console.register_command("bpset", CMDFLAG_NONE, 1, 3, std::bind(&debugger_commands::execute_bpset, this, _1)); m_console.register_command("bpset", CMDFLAG_NONE, 1, 3, std::bind(&debugger_commands::execute_bpset, this, _1));
m_console.register_command("bp", CMDFLAG_NONE, 1, 3, std::bind(&debugger_commands::execute_bpset, this, _1)); m_console.register_command("bp", CMDFLAG_NONE, 1, 3, std::bind(&debugger_commands::execute_bpset, this, _1));
m_console.register_command("bpclear", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_bpclear, this, _1)); m_console.register_command("bpclear", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_bpclear, this, _1));
m_console.register_command("bpdisable", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_bpdisenable, this, false, _1)); m_console.register_command("bpdisable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_bpdisenable, this, false, _1));
m_console.register_command("bpenable", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_bpdisenable, this, true, _1)); m_console.register_command("bpenable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_bpdisenable, this, true, _1));
m_console.register_command("bplist", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_bplist, this, _1)); m_console.register_command("bplist", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_bplist, this, _1));
m_console.register_command("wpset", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, -1, _1)); m_console.register_command("wpset", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, -1, _1));
@ -263,17 +263,17 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu
m_console.register_command("wpi", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, AS_IO, _1)); m_console.register_command("wpi", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, AS_IO, _1));
m_console.register_command("wposet", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, AS_OPCODES, _1)); m_console.register_command("wposet", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, AS_OPCODES, _1));
m_console.register_command("wpo", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, AS_OPCODES, _1)); m_console.register_command("wpo", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, AS_OPCODES, _1));
m_console.register_command("wpclear", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_wpclear, this, _1)); m_console.register_command("wpclear", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_wpclear, this, _1));
m_console.register_command("wpdisable", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_wpdisenable, this, false, _1)); m_console.register_command("wpdisable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_wpdisenable, this, false, _1));
m_console.register_command("wpenable", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_wpdisenable, this, true, _1)); m_console.register_command("wpenable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_wpdisenable, this, true, _1));
m_console.register_command("wplist", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_wplist, this, _1)); m_console.register_command("wplist", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_wplist, this, _1));
m_console.register_command("rpset", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_rpset, this, _1)); m_console.register_command("rpset", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_rpset, this, _1));
m_console.register_command("rp", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_rpset, this, _1)); m_console.register_command("rp", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_rpset, this, _1));
m_console.register_command("rpclear", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_rpclear, this, _1)); m_console.register_command("rpclear", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_rpclear, this, _1));
m_console.register_command("rpdisable", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_rpdisenable, this, false, _1)); m_console.register_command("rpdisable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_rpdisenable, this, false, _1));
m_console.register_command("rpenable", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_rpdisenable, this, true, _1)); m_console.register_command("rpenable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_rpdisenable, this, true, _1));
m_console.register_command("rplist", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_rplist, this, _1)); m_console.register_command("rplist", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_rplist, this, _1));
m_console.register_command("statesave", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_statesave, this, _1)); m_console.register_command("statesave", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_statesave, this, _1));
m_console.register_command("ss", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_statesave, this, _1)); m_console.register_command("ss", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_statesave, this, _1));
@ -1070,6 +1070,37 @@ int debugger_commands::mini_printf(char *buffer, const char *format, int params,
} }
/*-------------------------------------------------
execute_index_command - helper for commands
that take multiple indices as arguments
-------------------------------------------------*/
template <typename T>
void debugger_commands::execute_index_command(std::vector<std::string> const &params, T &&apply, char const *unused_message)
{
std::vector<u64> index(params.size());
for (int paramnum = 0; paramnum < params.size(); paramnum++)
{
if (!validate_number_parameter(params[paramnum], index[paramnum]))
return;
}
for (device_t &device : device_enumerator(m_machine.root_device()))
{
for (auto param = index.begin(); index.end() != param; )
{
if (apply(device, *param))
param = index.erase(param);
else
++param;
}
}
for (auto const &param : index)
m_console.printf(unused_message, param);
}
/*------------------------------------------------- /*-------------------------------------------------
execute_printf - execute the printf command execute_printf - execute the printf command
-------------------------------------------------*/ -------------------------------------------------*/
@ -1740,31 +1771,24 @@ void debugger_commands::execute_bpset(const std::vector<std::string> &params)
void debugger_commands::execute_bpclear(const std::vector<std::string> &params) void debugger_commands::execute_bpclear(const std::vector<std::string> &params)
{ {
u64 bpindex;
if (params.empty()) // if no parameters, clear all if (params.empty()) // if no parameters, clear all
{ {
for (device_t &device : device_enumerator(m_machine.root_device())) for (device_t &device : device_enumerator(m_machine.root_device()))
device.debug()->breakpoint_clear_all(); device.debug()->breakpoint_clear_all();
m_console.printf("Cleared all breakpoints\n"); m_console.printf("Cleared all breakpoints\n");
} }
else if (!validate_number_parameter(params[0], bpindex)) // otherwise, clear the specific one else // otherwise, clear the specific ones
{ {
return; execute_index_command(
} params,
else [this] (device_t &device, u64 param) -> bool
{ {
bool found = false; if (!device.debug()->breakpoint_clear(param))
for (device_t &device : device_enumerator(m_machine.root_device())) return false;
if (device.debug()->breakpoint_clear(bpindex)) m_console.printf("Breakpoint %X cleared\n", param);
{ return true;
found = true; },
break; "Invalid breakpoint number %X\n");
}
if (found)
m_console.printf("Breakpoint %X cleared\n", u32(bpindex));
else
m_console.printf("Invalid breakpoint number %X\n", u32(bpindex));
} }
} }
@ -1776,34 +1800,24 @@ void debugger_commands::execute_bpclear(const std::vector<std::string> &params)
void debugger_commands::execute_bpdisenable(bool enable, const std::vector<std::string> &params) void debugger_commands::execute_bpdisenable(bool enable, const std::vector<std::string> &params)
{ {
u64 bpindex; if (params.empty()) // if no parameters, disable/enable all
if (params.empty()) // if 0 parameters, disable/enable all
{ {
for (device_t &device : device_enumerator(m_machine.root_device())) for (device_t &device : device_enumerator(m_machine.root_device()))
device.debug()->breakpoint_enable_all(enable); device.debug()->breakpoint_enable_all(enable);
if (!enable) m_console.printf(enable ? "Enabled all breakpoints\n" : "Disabled all breakpoints\n");
m_console.printf("Disabled all breakpoints\n");
else
m_console.printf("Enabled all breakpoints\n");
} }
else if (!validate_number_parameter(params[0], bpindex)) // otherwise, disable/enable the specific one else // otherwise, disable/enable the specific ones
{ {
return; execute_index_command(
} params,
else [this, enable] (device_t &device, u64 param) -> bool
{ {
bool found = false; if (!device.debug()->breakpoint_enable(param, enable))
for (device_t &device : device_enumerator(m_machine.root_device())) return false;
if (device.debug()->breakpoint_enable(bpindex, enable)) m_console.printf(enable ? "Breakpoint %X enabled\n" : "Breakpoint %X disabled\n", param);
{ return true;
found = true; },
break; "Invalid breakpoint number %X\n");
}
if (found)
m_console.printf("Breakpoint %X %s\n", u32(bpindex), enable ? "enabled" : "disabled");
else
m_console.printf("Invalid breakpoint number %X\n", u32(bpindex));
} }
} }
@ -1922,29 +1936,24 @@ void debugger_commands::execute_wpset(int spacenum, const std::vector<std::strin
void debugger_commands::execute_wpclear(const std::vector<std::string> &params) void debugger_commands::execute_wpclear(const std::vector<std::string> &params)
{ {
u64 wpindex; if (params.empty()) // if no parameters, clear all
/* if 0 parameters, clear all */
if (params.empty())
{ {
for (device_t &device : device_enumerator(m_machine.root_device())) for (device_t &device : device_enumerator(m_machine.root_device()))
device.debug()->watchpoint_clear_all(); device.debug()->watchpoint_clear_all();
m_console.printf("Cleared all watchpoints\n"); m_console.printf("Cleared all watchpoints\n");
} }
else // otherwise, clear the specific ones
/* otherwise, clear the specific one */
else if (!validate_number_parameter(params[0], wpindex))
return;
else
{ {
bool found = false; execute_index_command(
for (device_t &device : device_enumerator(m_machine.root_device())) params,
if (device.debug()->watchpoint_clear(wpindex)) [this] (device_t &device, u64 param) -> bool
found = true; {
if (found) if (!device.debug()->watchpoint_clear(param))
m_console.printf("Watchpoint %X cleared\n", u32(wpindex)); return false;
else m_console.printf("Watchpoint %X cleared\n", param);
m_console.printf("Invalid watchpoint number %X\n", u32(wpindex)); return true;
},
"Invalid watchpoint number %X\n");
} }
} }
@ -1956,31 +1965,24 @@ void debugger_commands::execute_wpclear(const std::vector<std::string> &params)
void debugger_commands::execute_wpdisenable(bool enable, const std::vector<std::string> &params) void debugger_commands::execute_wpdisenable(bool enable, const std::vector<std::string> &params)
{ {
u64 wpindex; if (params.empty()) // if no parameters, disable/enable all
if (params.empty()) // if no parameters, clear all
{ {
for (device_t &device : device_enumerator(m_machine.root_device())) for (device_t &device : device_enumerator(m_machine.root_device()))
device.debug()->watchpoint_enable_all(enable); device.debug()->watchpoint_enable_all(enable);
if (!enable) m_console.printf(enable ? "Enabled all watchpoints\n" : "Disabled all watchpoints\n");
m_console.printf("Disabled all watchpoints\n");
else
m_console.printf("Enabled all watchpoints\n");
} }
else if (!validate_number_parameter(params[0], wpindex)) // otherwise, clear the specific one else // otherwise, disable/enable the specific ones
{ {
return; execute_index_command(
} params,
else [this, enable] (device_t &device, u64 param) -> bool
{ {
bool found = false; if (!device.debug()->watchpoint_enable(param, enable))
for (device_t &device : device_enumerator(m_machine.root_device())) return false;
if (device.debug()->watchpoint_enable(wpindex, enable)) m_console.printf(enable ? "Watchpoint %X enabled\n" : "Watchpoint %X disabled\n", param);
found = true; return true;
if (found) },
m_console.printf("Watchpoint %X %s\n", u32(wpindex), enable ? "enabled" : "disabled"); "Invalid watchpoint number %X\n");
else
m_console.printf("Invalid watchpoint number %X\n", u32(wpindex));
} }
} }
@ -2070,9 +2072,9 @@ void debugger_commands::execute_rpset(const std::vector<std::string> &params)
if (params.size() > 1 && !debug_command_parameter_command(action = params[1].c_str())) if (params.size() > 1 && !debug_command_parameter_command(action = params[1].c_str()))
return; return;
// set the breakpoint // set the registerpoint
int const bpnum = cpu->debug()->registerpoint_set(condition.original_string(), action); int const rpnum = cpu->debug()->registerpoint_set(condition.original_string(), action);
m_console.printf("Registerpoint %X set\n", bpnum); m_console.printf("Registerpoint %X set\n", rpnum);
} }
@ -2083,29 +2085,24 @@ void debugger_commands::execute_rpset(const std::vector<std::string> &params)
void debugger_commands::execute_rpclear(const std::vector<std::string> &params) void debugger_commands::execute_rpclear(const std::vector<std::string> &params)
{ {
u64 rpindex; if (params.empty()) // if no parameters, clear all
/* if 0 parameters, clear all */
if (params.empty())
{ {
for (device_t &device : device_enumerator(m_machine.root_device())) for (device_t &device : device_enumerator(m_machine.root_device()))
device.debug()->registerpoint_clear_all(); device.debug()->registerpoint_clear_all();
m_console.printf("Cleared all registerpoints\n"); m_console.printf("Cleared all registerpoints\n");
} }
else // otherwise, clear the specific ones
/* otherwise, clear the specific one */
else if (!validate_number_parameter(params[0], rpindex))
return;
else
{ {
bool found = false; execute_index_command(
for (device_t &device : device_enumerator(m_machine.root_device())) params,
if (device.debug()->registerpoint_clear(rpindex)) [this] (device_t &device, u64 param) -> bool
found = true; {
if (found) if (!device.debug()->registerpoint_clear(param))
m_console.printf("Registerpoint %X cleared\n", u32(rpindex)); return false;
else m_console.printf("Registerpoint %X cleared\n", param);
m_console.printf("Invalid registerpoint number %X\n", u32(rpindex)); return true;
},
"Invalid registerpoint number %X\n");
} }
} }
@ -2117,31 +2114,24 @@ void debugger_commands::execute_rpclear(const std::vector<std::string> &params)
void debugger_commands::execute_rpdisenable(bool enable, const std::vector<std::string> &params) void debugger_commands::execute_rpdisenable(bool enable, const std::vector<std::string> &params)
{ {
u64 rpindex; if (params.empty()) // if no parameters, disable/enable all
if (params.empty()) // if no parameters, clear all
{ {
for (device_t &device : device_enumerator(m_machine.root_device())) for (device_t &device : device_enumerator(m_machine.root_device()))
device.debug()->registerpoint_enable_all(enable); device.debug()->registerpoint_enable_all(enable);
if (!enable) m_console.printf(enable ? "Enabled all registerpoints\n" : "Disabled all registerpoints\n");
m_console.printf("Disabled all registerpoints\n");
else
m_console.printf("Enabled all registeroints\n");
} }
else if (!validate_number_parameter(params[0], rpindex)) // otherwise, clear the specific one else // otherwise, disable/enable the specific ones
{ {
return; execute_index_command(
} params,
else [this, enable] (device_t &device, u64 param) -> bool
{ {
bool found = false; if (!device.debug()->registerpoint_enable(param, enable))
for (device_t &device : device_enumerator(m_machine.root_device())) return false;
if (device.debug()->registerpoint_enable(rpindex, enable)) m_console.printf(enable ? "Registerpoint %X enabled\n" : "Breakpoint %X disabled\n", param);
found = true; return true;
if (found) },
m_console.printf("Registerpoint %X %s\n", u32(rpindex), enable ? "enabled" : "disabled"); "Invalid registerpoint number %X\n");
else
m_console.printf("Invalid registerpoint number %X\n", u32(rpindex));
} }
} }
@ -2155,26 +2145,42 @@ void debugger_commands::execute_rplist(const std::vector<std::string> &params)
{ {
int printed = 0; int printed = 0;
std::string buffer; std::string buffer;
auto const apply =
/* loop over all CPUs */ [this, &printed, &buffer] (device_t &device)
for (device_t &device : device_enumerator(m_machine.root_device()))
if (!device.debug()->registerpoint_list().empty())
{
m_console.printf("Device '%s' registerpoints:\n", device.tag());
/* loop over the breakpoints */
for (const debug_registerpoint &rp : device.debug()->registerpoint_list())
{ {
buffer = string_format("%c%4X if %s", rp.enabled() ? ' ' : 'D', rp.index(), rp.condition()); if (!device.debug()->registerpoint_list().empty())
if (rp.action() != nullptr) {
buffer.append(string_format(" do %s", rp.action())); m_console.printf("Device '%s' registerpoints:\n", device.tag());
m_console.printf("%s\n", buffer);
printed++;
}
}
if (printed == 0) // loop over the registerpoints
m_console.printf("No registerpoints currently installed\n"); for (const auto &rp : device.debug()->registerpoint_list())
{
buffer = string_format("%c%4X if %s", rp.enabled() ? ' ' : 'D', rp.index(), rp.condition());
if (rp.action() && *rp.action())
buffer.append(string_format(" do %s", rp.action()));
m_console.printf("%s\n", buffer);
printed++;
}
}
};
if (!params.empty())
{
device_t *cpu;
if (!validate_cpu_parameter(params[0], cpu))
return;
apply(*cpu);
if (!printed)
m_console.printf("No registerpoints currently installed for CPU %s\n", cpu->tag());
}
else
{
// loop over all CPUs
for (device_t &device : device_enumerator(m_machine.root_device()))
apply(device);
if (!printed)
m_console.printf("No registerpoints currently installed\n");
}
} }

View File

@ -99,6 +99,8 @@ private:
void global_set(global_entry *global, u64 value); void global_set(global_entry *global, u64 value);
int mini_printf(char *buffer, const char *format, int params, u64 *param); int mini_printf(char *buffer, const char *format, int params, u64 *param);
template <typename T>
void execute_index_command(std::vector<std::string> const &params, T &&apply, char const *unused_message);
void execute_help(const std::vector<std::string> &params); void execute_help(const std::vector<std::string> &params);
void execute_print(const std::vector<std::string> &params); void execute_print(const std::vector<std::string> &params);

View File

@ -154,9 +154,9 @@ const help_item f_static_help_list[] =
"Type help <command> for further details on each command\n" "Type help <command> for further details on each command\n"
"\n" "\n"
" bp[set] <address>[:<CPU>][,<condition>[,<action>]] -- sets breakpoint at <address>\n" " bp[set] <address>[:<CPU>][,<condition>[,<action>]] -- sets breakpoint at <address>\n"
" bpclear [<bpnum>] -- clears a given breakpoint or all if no <bpnum> specified\n" " bpclear [<bpnum>[,...]] -- clears given breakpoints or all if no <bpnum> specified\n"
" bpdisable [<bpnum>] -- disables a given breakpoint or all if no <bpnum> specified\n" " bpdisable [<bpnum>[,...]] -- disables given breakpoints or all if no <bpnum> specified\n"
" bpenable [<bpnum>] -- enables a given breakpoint or all if no <bpnum> specified\n" " bpenable [<bpnum>[,...]] -- enables given breakpoints or all if no <bpnum> specified\n"
" bplist [<CPU>] -- lists all the breakpoints\n" " bplist [<CPU>] -- lists all the breakpoints\n"
}, },
{ {
@ -169,9 +169,9 @@ const help_item f_static_help_list[] =
" wpd[set] <address>[:<space>],<length>,<type>[,<condition>[,<action>]] -- sets data space watchpoint\n" " wpd[set] <address>[:<space>],<length>,<type>[,<condition>[,<action>]] -- sets data space watchpoint\n"
" wpi[set] <address>[:<space>],<length>,<type>[,<condition>[,<action>]] -- sets I/O space watchpoint\n" " wpi[set] <address>[:<space>],<length>,<type>[,<condition>[,<action>]] -- sets I/O space watchpoint\n"
" wpo[set] <address>[:<space>],<length>,<type>[,<condition>[,<action>]] -- sets opcode space watchpoint\n" " wpo[set] <address>[:<space>],<length>,<type>[,<condition>[,<action>]] -- sets opcode space watchpoint\n"
" wpclear [<wpnum>] -- clears a given watchpoint or all if no <wpnum> specified\n" " wpclear [<wpnum>[,...]] -- clears given watchpoints or all if no <wpnum> specified\n"
" wpdisable [<wpnum>] -- disables a given watchpoint or all if no <wpnum> specified\n" " wpdisable [<wpnum>[,...]] -- disables given watchpoints or all if no <wpnum> specified\n"
" wpenable [<wpnum>] -- enables a given watchpoint or all if no <wpnum> specified\n" " wpenable [<wpnum>[,...]] -- enables given watchpoints or all if no <wpnum> specified\n"
" wplist [<CPU>] -- lists all the watchpoints\n" " wplist [<CPU>] -- lists all the watchpoints\n"
}, },
{ {
@ -180,11 +180,11 @@ const help_item f_static_help_list[] =
"Registerpoint Commands\n" "Registerpoint Commands\n"
"Type help <command> for further details on each command\n" "Type help <command> for further details on each command\n"
"\n" "\n"
" rp[set] {<condition>}[,<action>] -- sets a registerpoint to trigger on <condition>\n" " rp[set] <condition>[,<action>] -- sets a registerpoint to trigger on <condition>\n"
" rpclear [<rpnum>] -- clears a given registerpoint or all if no <rpnum> specified\n" " rpclear [<rpnum>[,...]] -- clears given registerpoints or all if no <rpnum> specified\n"
" rpdisable [<rpnum>] -- disabled a given registerpoint or all if no <rpnum> specified\n" " rpdisable [<rpnum>[,...]] -- disabled given registerpoints or all if no <rpnum> specified\n"
" rpenable [<rpnum>] -- enables a given registerpoint or all if no <rpnum> specified\n" " rpenable [<rpnum>[,...]] -- enables given registerpoints or all if no <rpnum> specified\n"
" rplist -- lists all the registerpoints\n" " rplist [<CPU>] -- lists all the registerpoints\n"
}, },
{ {
"expressions", "expressions",
@ -1206,10 +1206,10 @@ const help_item f_static_help_list[] =
{ {
"bpclear", "bpclear",
"\n" "\n"
" bpclear [<bpnum>]\n" " bpclear [<bpnum>[,...]]\n"
"\n" "\n"
"The bpclear command clears a breakpoint. If <bpnum> is specified, only the requested " "The bpclear command clears breakpoints. If <bpnum> is specified, only the requested "
"breakpoint is cleared; otherwise all breakpoints are cleared.\n" "breakpoints are cleared; otherwise all breakpoints are cleared.\n"
"\n" "\n"
"Examples:\n" "Examples:\n"
"\n" "\n"
@ -1222,10 +1222,10 @@ const help_item f_static_help_list[] =
{ {
"bpdisable", "bpdisable",
"\n" "\n"
" bpdisable [<bpnum>]\n" " bpdisable [<bpnum>,[...]]\n"
"\n" "\n"
"The bpdisable command disables a breakpoint. If <bpnum> is specified, only the requested " "The bpdisable command disables breakpoints. If <bpnum> is specified, only the requested "
"breakpoint is disabled; otherwise all breakpoints are disabled. Note that disabling a " "breakpoints are disabled; otherwise all breakpoints are disabled. Note that disabling a "
"breakpoint does not delete it, it just temporarily marks the breakpoint as inactive.\n" "breakpoint does not delete it, it just temporarily marks the breakpoint as inactive.\n"
"\n" "\n"
"Examples:\n" "Examples:\n"
@ -1239,10 +1239,10 @@ const help_item f_static_help_list[] =
{ {
"bpenable", "bpenable",
"\n" "\n"
" bpenable [<bpnum>]\n" " bpenable [<bpnum>,[...]]\n"
"\n" "\n"
"The bpenable command enables a breakpoint. If <bpnum> is specified, only the requested " "The bpenable command enable breakpoints. If <bpnum> is specified, only the requested "
"breakpoint is enabled; otherwise all breakpoints are enabled.\n" "breakpoints enabled; otherwise all breakpoints are enabled.\n"
"\n" "\n"
"Examples:\n" "Examples:\n"
"\n" "\n"
@ -1331,10 +1331,10 @@ const help_item f_static_help_list[] =
{ {
"wpclear", "wpclear",
"\n" "\n"
" wpclear [<wpnum>]\n" " wpclear [<wpnum>[,...]]\n"
"\n" "\n"
"The wpclear command clears a watchpoint. If <wpnum> is specified, only the requested " "The wpclear command clears watchpoints. If <wpnum> is specified, only the requested "
"watchpoint is cleared; otherwise all watchpoints are cleared.\n" "watchpoints are cleared; otherwise all watchpoints are cleared.\n"
"\n" "\n"
"Examples:\n" "Examples:\n"
"\n" "\n"
@ -1347,10 +1347,10 @@ const help_item f_static_help_list[] =
{ {
"wpdisable", "wpdisable",
"\n" "\n"
" wpdisable [<wpnum>]\n" " wpdisable [<wpnum>[,...]]\n"
"\n" "\n"
"The wpdisable command disables a watchpoint. If <wpnum> is specified, only the requested " "The wpdisable command disables watchpoints. If <wpnum> is specified, only the requested "
"watchpoint is disabled; otherwise all watchpoints are disabled. Note that disabling a " "watchpoints are disabled; otherwise all watchpoints are disabled. Note that disabling a "
"watchpoint does not delete it, it just temporarily marks the watchpoint as inactive.\n" "watchpoint does not delete it, it just temporarily marks the watchpoint as inactive.\n"
"\n" "\n"
"Examples:\n" "Examples:\n"
@ -1364,10 +1364,10 @@ const help_item f_static_help_list[] =
{ {
"wpenable", "wpenable",
"\n" "\n"
" wpenable [<wpnum>]\n" " wpenable [<wpnum>[,...]]\n"
"\n" "\n"
"The wpenable command enables a watchpoint. If <wpnum> is specified, only the requested " "The wpenable command enables watchpoints. If <wpnum> is specified, only the requested "
"watchpoint is enabled; otherwise all watchpoints are enabled.\n" "watchpoints are enabled; otherwise all watchpoints are enabled.\n"
"\n" "\n"
"Examples:\n" "Examples:\n"
"\n" "\n"
@ -1401,26 +1401,26 @@ const help_item f_static_help_list[] =
{ {
"rpset", "rpset",
"\n" "\n"
" rp[set] {<condition>}[,<action>]]\n" " rp[set] <condition>[,<action>]\n"
"\n" "\n"
"Sets a new registerpoint which will be triggered when <condition> is met. The condition must " "Sets a new registerpoint which will be triggered when <condition> is true (evaluates to a "
"be specified between curly braces to prevent the condition from being evaluated as an " "non-zero value). The condition must be embedded in braces { } to prevent it from being "
"assignment.\n" "interpreted as an assignment.\n"
"\n" "\n"
"The optional <action> parameter provides a command that is executed whenever the registerpoint " "The optional <action> parameter provides a command that is executed whenever the "
"is hit. Note that you may need to embed the action within braces { } in " "registerpoint is hit. Note that you may need to embed the action within braces { } in "
"order to prevent commas and semicolons from being interpreted as applying to the rpset command " "order to prevent commas and semicolons from being interpreted as applying to the rpset "
"itself. Each registerpoint that is set is assigned an index which can be used in other " "command itself. Each registerpoint that is set is assigned an index which can be used in "
"registerpoint commands to reference this registerpoint.\n" "other registerpoint commands to reference this registerpoint.\n"
"\n" "\n"
"Examples:\n" "Examples:\n"
"\n" "\n"
"rp {PC==0150}\n" "rp {PC==150}\n"
" Set a registerpoint that will halt execution whenever the PC register equals 0x150.\n" " Set a registerpoint that will halt execution whenever the PC register equals 150.\n"
"\n" "\n"
"temp0=0; rp {PC==0150},{temp0++; g}\n" "temp0=0; rp {PC==150},{temp0++; g}\n"
" Set a registerpoint that will increment the variable temp0 whenever the PC register " " Set a registerpoint that will increment the variable temp0 whenever the PC register "
"equals 0x0150.\n" "equals 150.\n"
"\n" "\n"
"rp {temp0==5}\n" "rp {temp0==5}\n"
" Set a registerpoint that will halt execution whenever the temp0 variable equals 5.\n" " Set a registerpoint that will halt execution whenever the temp0 variable equals 5.\n"
@ -1428,15 +1428,15 @@ const help_item f_static_help_list[] =
{ {
"rpclear", "rpclear",
"\n" "\n"
" rpclear [<rpnum>]\n" " rpclear [<rpnum>[,...]]\n"
"\n" "\n"
"The rpclear command clears a registerpoint. If <rpnum> is specified, only the requested " "The rpclear command clears registerpoints. If <rpnum> is specified, only the requested "
"registerpoint is cleared, otherwise all registerpoints are cleared.\n" "registerpoints are cleared, otherwise all registerpoints are cleared.\n"
"\n" "\n"
"Examples:\n" "Examples:\n"
"\n" "\n"
"rpclear 3\n" "rpclear 3\n"
" Clear registerpoint index 3.\n" " Clear the registerpoint with index 3.\n"
"\n" "\n"
"rpclear\n" "rpclear\n"
" Clear all registerpoints.\n" " Clear all registerpoints.\n"
@ -1444,16 +1444,17 @@ const help_item f_static_help_list[] =
{ {
"rpdisable", "rpdisable",
"\n" "\n"
" rpdisable [<rpnum>]\n" " rpdisable [<rpnum>[,...]]\n"
"\n" "\n"
"The rpdisable command disables a registerpoint. If <rpnum> is specified, only the requested " "The rpdisable command disables registerpoints. If <rpnum> is specified, only the "
"registerpoint is disabled, otherwise all registerpoints are disabled. Note that disabling a " "requested registerpoints are disabled, otherwise all registerpoints are disabled. Note "
"registerpoint does not delete it, it just temporarily marks the registerpoint as inactive.\n" "that disabling a registerpoint does not delete it, it just temporarily marks the "
"registerpoint as inactive.\n"
"\n" "\n"
"Examples:\n" "Examples:\n"
"\n" "\n"
"rpdisable 3\n" "rpdisable 3\n"
" Disable registerpoint index 3.\n" " Disable the registerpoint with index 3.\n"
"\n" "\n"
"rpdisable\n" "rpdisable\n"
" Disable all registerpoints.\n" " Disable all registerpoints.\n"
@ -1461,15 +1462,15 @@ const help_item f_static_help_list[] =
{ {
"rpenable", "rpenable",
"\n" "\n"
" rpenable [<rpnum>]\n" " rpenable [<rpnum>[,...]]\n"
"\n" "\n"
"The rpenable command enables a registerpoint. If <rpnum> is specified, only the requested " "The rpenable command enables registerpoints. If <rpnum> is specified, only the requested "
"registerpoint is enabled, otherwise all registerpoints are enabled.\n" "registerpoints are enabled, otherwise all registerpoints are enabled.\n"
"\n" "\n"
"Examples:\n" "Examples:\n"
"\n" "\n"
"rpenable 3\n" "rpenable 3\n"
" Enable registerpoint index 3.\n" " Enable the registerpoint with index 3.\n"
"\n" "\n"
"rpenable\n" "rpenable\n"
" Enable all registerpoints.\n" " Enable all registerpoints.\n"

View File

@ -9,16 +9,20 @@
***************************************************************************/ ***************************************************************************/
#include "emu.h" #include "emu.h"
#include "express.h"
#include "debugvw.h" #include "debugvw.h"
#include "dvtext.h"
#include "dvstate.h" #include "debugcpu.h"
#include "dvbpoints.h"
#include "dvdisasm.h" #include "dvdisasm.h"
#include "dvmemory.h" #include "dvmemory.h"
#include "dvbpoints.h" #include "dvrpoints.h"
#include "dvstate.h"
#include "dvtext.h"
#include "dvwpoints.h" #include "dvwpoints.h"
#include "debugcpu.h" #include "express.h"
#include "debugger.h" #include "debugger.h"
#include <cctype> #include <cctype>
@ -362,6 +366,9 @@ debug_view *debug_view_manager::alloc_view(debug_view_type type, debug_view_osd_
case DVT_WATCH_POINTS: case DVT_WATCH_POINTS:
return append(new debug_view_watchpoints(machine(), osdupdate, osdprivate)); return append(new debug_view_watchpoints(machine(), osdupdate, osdprivate));
case DVT_REGISTER_POINTS:
return append(new debug_view_registerpoints(machine(), osdupdate, osdprivate));
default: default:
fatalerror("Attempt to create invalid debug view type %d\n", type); fatalerror("Attempt to create invalid debug view type %d\n", type);
} }

View File

@ -34,7 +34,8 @@ enum debug_view_type
DVT_MEMORY, DVT_MEMORY,
DVT_LOG, DVT_LOG,
DVT_BREAK_POINTS, DVT_BREAK_POINTS,
DVT_WATCH_POINTS DVT_WATCH_POINTS,
DVT_REGISTER_POINTS
}; };

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Aaron Giles // copyright-holders:Andrew Gardner, Vas Crabb
/********************************************************************* /*********************************************************************
dvbpoints.cpp dvbpoints.cpp

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Aaron Giles // copyright-holders:Andrew Gardner, Vas Crabb
/********************************************************************* /*********************************************************************
dvbpoints.h dvbpoints.h
@ -7,19 +7,15 @@
Breakpoint debugger view. Breakpoint debugger view.
***************************************************************************/ ***************************************************************************/
#ifndef MAME_EMU_DEBUG_DVBPOINTS_H #ifndef MAME_EMU_DEBUG_DVBPOINTS_H
#define MAME_EMU_DEBUG_DVBPOINTS_H #define MAME_EMU_DEBUG_DVBPOINTS_H
#pragma once #pragma once
#include "debugvw.h"
#include "debugcpu.h" #include "debugcpu.h"
#include "debugvw.h"
#include <vector>
//**************************************************************************
// CONSTANTS
//**************************************************************************
//************************************************************************** //**************************************************************************
@ -46,7 +42,6 @@ private:
void pad_ostream_to_length(std::ostream& str, int len); void pad_ostream_to_length(std::ostream& str, int len);
void gather_breakpoints(); void gather_breakpoints();
// internal state // internal state
bool (*m_sortType)(const debug_breakpoint *, const debug_breakpoint *); bool (*m_sortType)(const debug_breakpoint *, const debug_breakpoint *);
std::vector<const debug_breakpoint *> m_buffer; std::vector<const debug_breakpoint *> m_buffer;

298
src/emu/debug/dvrpoints.cpp Normal file
View File

@ -0,0 +1,298 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
/*********************************************************************
dvrpoints.cpp
Registerpoint debugger view.
***************************************************************************/
#include "emu.h"
#include "dvrpoints.h"
#include "debugger.h"
#include "points.h"
#include <algorithm>
#include <iomanip>
namespace {
bool cIndexAscending(std::pair<device_t *, debug_registerpoint const *> const &a, std::pair<device_t *, debug_registerpoint const *> const &b)
{
return a.second->index() < b.second->index();
}
bool cIndexDescending(std::pair<device_t *, debug_registerpoint const *> const &a, std::pair<device_t *, debug_registerpoint const *> const &b)
{
return a.second->index() > b.second->index();
}
bool cEnabledAscending(std::pair<device_t *, debug_registerpoint const *> const &a, std::pair<device_t *, debug_registerpoint const *> const &b)
{
return !a.second->enabled() && b.second->enabled();
}
bool cEnabledDescending(std::pair<device_t *, debug_registerpoint const *> const &a, std::pair<device_t *, debug_registerpoint const *> const &b)
{
return cEnabledAscending(b, a);
}
bool cCpuAscending(std::pair<device_t *, debug_registerpoint const *> const &a, std::pair<device_t *, debug_registerpoint const *> const &b)
{
return strcmp(a.first->tag(), b.first->tag()) < 0;
}
bool cCpuDescending(std::pair<device_t *, debug_registerpoint const *> const &a, std::pair<device_t *, debug_registerpoint const *> const &b)
{
return cCpuAscending(b, a);
}
bool cConditionAscending(std::pair<device_t *, debug_registerpoint const *> const &a, std::pair<device_t *, debug_registerpoint const *> const &b)
{
return strcmp(a.second->condition(), b.second->condition()) < 0;
}
bool cConditionDescending(std::pair<device_t *, debug_registerpoint const *> const &a, std::pair<device_t *, debug_registerpoint const *> const &b)
{
return cConditionAscending(b, a);
}
bool cActionAscending(std::pair<device_t *, debug_registerpoint const *> const &a, std::pair<device_t *, debug_registerpoint const *> const &b)
{
return strcmp(a.second->action(), b.second->action()) < 0;
}
bool cActionDescending(std::pair<device_t *, debug_registerpoint const *> const &a, std::pair<device_t *, debug_registerpoint const *> const &b)
{
return cActionAscending(b, a);
}
constexpr int TABLE_BREAKS[] = { 5, 9, 31, 49, 66 };
} // anonymous namespace
//**************************************************************************
// DEBUG VIEW REGISTER POINTS
//**************************************************************************
//-------------------------------------------------
// debug_view_registerpoints - constructor
//-------------------------------------------------
debug_view_registerpoints::debug_view_registerpoints(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate)
: debug_view(machine, DVT_REGISTER_POINTS, osdupdate, osdprivate)
, m_sort_type(cIndexAscending)
{
// fail if no available sources
enumerate_sources();
if (m_source_list.empty())
throw std::bad_alloc();
}
//-------------------------------------------------
// ~debug_view_registerpoints - destructor
//-------------------------------------------------
debug_view_registerpoints::~debug_view_registerpoints()
{
}
//-------------------------------------------------
// enumerate_sources - enumerate all possible
// sources for a disassembly view
//-------------------------------------------------
void debug_view_registerpoints::enumerate_sources()
{
// start with an empty list
m_source_list.clear();
// iterate over devices with disassembly interfaces
for (device_disasm_interface &dasm : disasm_interface_enumerator(machine().root_device()))
{
m_source_list.emplace_back(
std::make_unique<debug_view_source>(
util::string_format("%s '%s'", dasm.device().name(), dasm.device().tag()),
&dasm.device()));
}
// reset the source to a known good entry
if (!m_source_list.empty())
set_source(*m_source_list[0]);
}
//-------------------------------------------------
// view_click - handle a mouse click within the
// current view
//-------------------------------------------------
void debug_view_registerpoints::view_click(const int button, const debug_view_xy& pos)
{
bool clickedTopRow = (m_topleft.y == pos.y);
if (clickedTopRow)
{
if (pos.x < TABLE_BREAKS[0])
m_sort_type = (m_sort_type == &cIndexAscending) ? &cIndexDescending : &cIndexAscending;
else if (pos.x < TABLE_BREAKS[1])
m_sort_type = (m_sort_type == &cEnabledAscending) ? &cEnabledDescending : &cEnabledAscending;
else if (pos.x < TABLE_BREAKS[2])
m_sort_type = (m_sort_type == &cCpuAscending) ? &cCpuDescending : &cCpuAscending;
else if (pos.x < TABLE_BREAKS[3])
m_sort_type = (m_sort_type == &cConditionAscending) ? &cConditionDescending : &cConditionAscending;
else if (pos.x < TABLE_BREAKS[4])
m_sort_type = (m_sort_type == &cActionAscending) ? &cActionDescending : &cActionAscending;
}
else
{
// Gather a sorted list of all the breakpoints for all the CPUs
gather_registerpoints();
int rpIndex = pos.y - 1;
if ((rpIndex >= m_buffer.size()) || (rpIndex < 0))
return;
// Enable / disable
m_buffer[rpIndex].first->debug()->registerpoint_enable(
m_buffer[rpIndex].second->index(),
!m_buffer[rpIndex].second->enabled());
}
begin_update();
m_update_pending = true;
end_update();
}
void debug_view_registerpoints::pad_ostream_to_length(std::ostream& str, int len)
{
auto const current = str.tellp();
if (current < decltype(current)(len))
str << std::setw(decltype(current)(len) - current) << "";
}
void debug_view_registerpoints::gather_registerpoints()
{
m_buffer.resize(0);
for (auto &source : m_source_list)
{
// Collect
device_debug &debugInterface = *source->device()->debug();
for (const auto &rp : debugInterface.registerpoint_list())
m_buffer.emplace_back(source->device(), &rp);
}
// And now for the sort
if (!m_buffer.empty())
std::stable_sort(m_buffer.begin(), m_buffer.end(), m_sort_type);
}
//-------------------------------------------------
// view_update - update the contents of the
// registerpoints view
//-------------------------------------------------
void debug_view_registerpoints::view_update()
{
// Gather a list of all the registerpoints for all the CPUs
gather_registerpoints();
// Set the view region so the scroll bars update
m_total.x = TABLE_BREAKS[std::size(TABLE_BREAKS) - 1];
m_total.y = m_buffer.size() + 1;
if (m_total.y < 10)
m_total.y = 10;
// Draw
debug_view_char *dest = &m_viewdata[0];
util::ovectorstream linebuf;
linebuf.reserve(std::size(TABLE_BREAKS) - 1);
// Header
if (m_visible.y > 0)
{
linebuf.clear();
linebuf.rdbuf()->clear();
linebuf << "ID";
if (m_sort_type == &cIndexAscending) linebuf.put('\\');
else if (m_sort_type == &cIndexDescending) linebuf.put('/');
pad_ostream_to_length(linebuf, TABLE_BREAKS[0]);
linebuf << "En";
if (m_sort_type == &cEnabledAscending) linebuf.put('\\');
else if (m_sort_type == &cEnabledDescending) linebuf.put('/');
pad_ostream_to_length(linebuf, TABLE_BREAKS[1]);
linebuf << "CPU";
if (m_sort_type == &cCpuAscending) linebuf.put('\\');
else if (m_sort_type == &cCpuDescending) linebuf.put('/');
pad_ostream_to_length(linebuf, TABLE_BREAKS[2]);
linebuf << "Condition";
if (m_sort_type == &cConditionAscending) linebuf.put('\\');
else if (m_sort_type == &cConditionDescending) linebuf.put('/');
pad_ostream_to_length(linebuf, TABLE_BREAKS[3]);
linebuf << "Action";
if (m_sort_type == &cActionAscending) linebuf.put('\\');
else if (m_sort_type == &cActionDescending) linebuf.put('/');
pad_ostream_to_length(linebuf, TABLE_BREAKS[4]);
auto const &text(linebuf.vec());
for (u32 i = m_topleft.x; i < (m_topleft.x + m_visible.x); i++, dest++)
{
dest->byte = (i < text.size()) ? text[i] : ' ';
dest->attrib = DCA_ANCILLARY;
}
}
for (int row = 1; row < m_visible.y; row++)
{
// Breakpoints
int rpi = row + m_topleft.y - 1;
if ((rpi < m_buffer.size()) && (rpi >= 0))
{
point_pair const &rpp = m_buffer[rpi];
linebuf.clear();
linebuf.rdbuf()->clear();
util::stream_format(linebuf, "%2X", rpp.second->index());
pad_ostream_to_length(linebuf, TABLE_BREAKS[0]);
linebuf.put(rpp.second->enabled() ? 'X' : 'O');
pad_ostream_to_length(linebuf, TABLE_BREAKS[1]);
linebuf << rpp.first->tag();
pad_ostream_to_length(linebuf, TABLE_BREAKS[2]);
linebuf << rpp.second->condition();
pad_ostream_to_length(linebuf, TABLE_BREAKS[3]);
linebuf << rpp.second->action();
pad_ostream_to_length(linebuf, TABLE_BREAKS[4]);
auto const &text(linebuf.vec());
for (u32 i = m_topleft.x; i < (m_topleft.x + m_visible.x); i++, dest++)
{
dest->byte = (i < text.size()) ? text[i] : ' ';
dest->attrib = DCA_NORMAL;
// Color disabled breakpoints red
if ((i >= TABLE_BREAKS[0]) && (i < TABLE_BREAKS[1]) && !rpp.second->enabled())
dest->attrib |= DCA_CHANGED;
}
}
else
{
// Fill the remaining vertical space
for (u32 i = m_topleft.x; i < (m_topleft.x + m_visible.x); i++, dest++)
{
dest->byte = ' ';
dest->attrib = DCA_NORMAL;
}
}
}
}

53
src/emu/debug/dvrpoints.h Normal file
View File

@ -0,0 +1,53 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
/*********************************************************************
dvrpoints.h
Registerpoint debugger view.
***************************************************************************/
#ifndef MAME_EMU_DEBUG_DVRPOINTS_H
#define MAME_EMU_DEBUG_DVRPOINTS_H
#pragma once
#include "debugcpu.h"
#include "debugvw.h"
#include <utility>
#include <vector>
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// debug view for breakpoints
class debug_view_registerpoints : public debug_view
{
friend class debug_view_manager;
// construction/destruction
debug_view_registerpoints(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate);
virtual ~debug_view_registerpoints();
protected:
// view overrides
virtual void view_update() override;
virtual void view_click(int button, debug_view_xy const &pos) override;
private:
using point_pair = std::pair<device_t *, debug_registerpoint const *>;
// internal helpers
void enumerate_sources();
void pad_ostream_to_length(std::ostream& str, int len);
void gather_registerpoints();
// internal state
bool (*m_sort_type)(point_pair const &, point_pair const &);
std::vector<point_pair> m_buffer;
};
#endif // MAME_EMU_DEBUG_DVBPOINTS_H

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Aaron Giles // copyright-holders:Andrew Gardner, Vas Crabb
/********************************************************************* /*********************************************************************
dvwpoints.cpp dvwpoints.cpp
@ -10,6 +10,7 @@
#include "emu.h" #include "emu.h"
#include "dvwpoints.h" #include "dvwpoints.h"
#include "points.h" #include "points.h"
#include <algorithm> #include <algorithm>

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Aaron Giles // copyright-holders:Andrew Gardner, Vas Crabb
/********************************************************************* /*********************************************************************
dvwpoints.h dvwpoints.h
@ -7,14 +7,13 @@
Watchpoint debugger view. Watchpoint debugger view.
***************************************************************************/ ***************************************************************************/
#ifndef MAME_EMU_DEBUG_DVWPOINTS_H #ifndef MAME_EMU_DEBUG_DVWPOINTS_H
#define MAME_EMU_DEBUG_DVWPOINTS_H #define MAME_EMU_DEBUG_DVWPOINTS_H
#pragma once #pragma once
#include "debugvw.h"
#include "debugcpu.h" #include "debugcpu.h"
#include "debugvw.h"
//************************************************************************** //**************************************************************************

View File

@ -838,7 +838,7 @@ namespace {
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAGE_DOWN, N_p("input-name", "UI Page Down"), input_seq(KEYCODE_PGDN) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAGE_DOWN, N_p("input-name", "UI Page Down"), input_seq(KEYCODE_PGDN) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_NEXT, N_p("input-name", "UI Focus Next"), input_seq(KEYCODE_TAB, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_NEXT, N_p("input-name", "UI Focus Next"), input_seq(KEYCODE_TAB, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_PREV, N_p("input-name", "UI Focus Previous"), input_seq(KEYCODE_TAB, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_TAB, KEYCODE_RSHIFT) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_PREV, N_p("input-name", "UI Focus Previous"), input_seq(KEYCODE_TAB, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_TAB, KEYCODE_RSHIFT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SELECT, N_p("input-name", "UI Select"), input_seq(KEYCODE_ENTER, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0), input_seq::or_code, KEYCODE_ENTER_PAD) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SELECT, N_p("input-name", "UI Select"), input_seq(KEYCODE_ENTER, input_seq::not_code, KEYCODE_LALT, input_seq::not_code, KEYCODE_RALT, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0), input_seq::or_code, KEYCODE_ENTER_PAD) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CANCEL, N_p("input-name", "UI Cancel"), input_seq(KEYCODE_ESC) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CANCEL, N_p("input-name", "UI Cancel"), input_seq(KEYCODE_ESC) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DISPLAY_COMMENT, N_p("input-name", "UI Display Comment"), input_seq(KEYCODE_SPACE) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DISPLAY_COMMENT, N_p("input-name", "UI Display Comment"), input_seq(KEYCODE_SPACE) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CLEAR, N_p("input-name", "UI Clear"), input_seq(KEYCODE_DEL) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CLEAR, N_p("input-name", "UI Clear"), input_seq(KEYCODE_DEL) ) \

View File

@ -92,5 +92,6 @@ private:
extern const char build_version[]; extern const char build_version[];
extern const char bare_build_version[]; extern const char bare_build_version[];
extern const char bare_vcs_revision[];
#endif // MAME_FRONTEND_MAME_MAME_H #endif // MAME_FRONTEND_MAME_MAME_H

View File

@ -1,21 +1,23 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Ryan Holtz // copyright-holders:Vas Crabb
/*************************************************************************** /***************************************************************************
ui/about.cpp ui/about.cpp
"About" modal About box
***************************************************************************/ ***************************************************************************/
#include "emu.h" #include "emu.h"
#include "ui/about.h" #include "ui/about.h"
#include "ui/ui.h" #include "ui/ui.h"
#include "ui/utils.h" #include "ui/utils.h"
#include "mame.h" #include "mame.h"
#include "osdcore.h"
#include <string_view>
namespace ui { namespace ui {
@ -25,10 +27,9 @@ namespace {
} // anonymous namespace } // anonymous namespace
/************************************************** /**************************************************
ABOUT BOX
ABOUT MODAL
**************************************************/ **************************************************/
@ -38,6 +39,8 @@ namespace {
menu_about::menu_about(mame_ui_manager &mui, render_container &container) menu_about::menu_about(mame_ui_manager &mui, render_container &container)
: menu(mui, container) : menu(mui, container)
, m_title(util::string_format(_("%1$s %2$s"), emulator_info::get_appname(), bare_build_version))
, m_footer(util::string_format(_("Revision: %1$s"), bare_vcs_revision))
{ {
} }
@ -51,20 +54,175 @@ menu_about::~menu_about()
} }
//-------------------------------------------------
// perform our special rendering
//-------------------------------------------------
void menu_about::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
{
std::string_view tempbuf[1];
// draw the title
tempbuf[0] = m_title;
draw_text_box(
std::begin(tempbuf), std::end(tempbuf),
origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(),
text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false,
ui().colors().text_color(), UI_GREEN_COLOR, 1.0f);
// draw the footer
tempbuf[0] = m_footer;
draw_text_box(
std::begin(tempbuf), std::end(tempbuf),
origx1, origx2, origy2 + ui().box_tb_border(), origy2 + bottom,
text_layout::text_justify::CENTER, text_layout::word_wrapping::NEVER, false,
ui().colors().text_color(), ui().colors().background_color(), 1.0f);
}
//-------------------------------------------------
// draw - draw about
//-------------------------------------------------
void menu_about::draw(uint32_t flags)
{
rgb_t const color = ui().colors().text_color();
float const aspect = machine().render().ui_aspect(&container());
float const line_height = ui().get_line_height();
float const ud_arrow_width = line_height * aspect;
float const gutter_width = 0.52f * line_height * aspect;
float const visible_width = 1.0f - (2.0f * ui().box_lr_border() * aspect);
float const visible_left = (1.0f - visible_width) * 0.5f;
float const extra_height = 2.0f * line_height;
float const visible_extra_menu_height = get_customtop() + get_custombottom() + extra_height;
// determine effective positions taking into account the hilighting arrows
float const maximum_width = visible_width - 2.0f * gutter_width;
draw_background();
map_mouse();
// account for extra space at the top and bottom
float visible_main_menu_height = 1.0f - 2.0f * ui().box_tb_border() - visible_extra_menu_height;
m_visible_lines = int(std::trunc(visible_main_menu_height / line_height));
visible_main_menu_height = float(m_visible_lines) * line_height;
// compute top/left of inner menu area by centering, if the menu is at the bottom of the extra, adjust
float const visible_top = ((1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f) + get_customtop();
// lay out the text if necessary
if (!m_layout || (m_layout->width() != maximum_width))
{
m_layout.emplace(ui().create_layout(container(), maximum_width));
for (char const *const *line = copying_text; *line; ++line)
{
m_layout->add_text(*line, color);
m_layout->add_text("\n", color);
}
}
float const actual_width = m_layout->actual_width();
// compute text box size
float const x1 = visible_left + ((maximum_width - actual_width) * 0.5f);
float const y1 = visible_top - ui().box_tb_border();
float const x2 = visible_left + visible_width - ((maximum_width - actual_width) * 0.5f);
float const y2 = visible_top + visible_main_menu_height + ui().box_tb_border() + extra_height;
float const effective_left = x1 + gutter_width;
float const line_x0 = x1 + 0.5f * UI_LINE_WIDTH;
float const line_x1 = x2 - 0.5f * UI_LINE_WIDTH;
float const separator = visible_top + float(m_visible_lines) * line_height;
ui().draw_outlined_box(container(), x1, y1, x2, y2, ui().colors().background_color());
int const visible_items = m_layout->lines();
m_visible_lines = (std::min)(visible_items, m_visible_lines);
top_line = (std::max)(0, top_line);
if (top_line + m_visible_lines >= visible_items)
top_line = visible_items - m_visible_lines;
clear_hover();
if (top_line)
{
// if we're on the top line, display the up arrow
rgb_t fgcolor = ui().colors().text_color();
if (mouse_in_rect(line_x0, visible_top, line_x1, visible_top + line_height))
{
fgcolor = ui().colors().mouseover_color();
highlight(
line_x0, visible_top,
line_x1, visible_top + line_height,
ui().colors().mouseover_bg_color());
set_hover(HOVER_ARROW_UP);
}
draw_arrow(
0.5f * (x1 + x2) - 0.5f * ud_arrow_width, visible_top + 0.25f * line_height,
0.5f * (x1 + x2) + 0.5f * ud_arrow_width, visible_top + 0.75f * line_height,
fgcolor, ROT0);
}
if ((top_line + m_visible_lines) < visible_items)
{
// if we're on the bottom line, display the down arrow
float const line_y = visible_top + float(m_visible_lines - 1) * line_height;
rgb_t fgcolor = ui().colors().text_color();
if (mouse_in_rect(line_x0, line_y, line_x1, line_y + line_height))
{
fgcolor = ui().colors().mouseover_color();
highlight(
line_x0, line_y,
line_x1, line_y + line_height,
ui().colors().mouseover_bg_color());
set_hover(HOVER_ARROW_DOWN);
}
draw_arrow(
0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height,
0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height,
fgcolor, ROT0 ^ ORIENTATION_FLIP_Y);
}
// return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow
m_visible_items = m_visible_lines - (top_line ? 1 : 0) - (top_line + m_visible_lines != visible_items);
m_layout->emit(
container(),
top_line ? (top_line + 1) : 0, m_visible_items,
effective_left, visible_top + (top_line ? line_height : 0.0f));
// add visual separator before the "return to prevous menu" item
container().add_line(
x1, separator + (0.5f * line_height),
x2, separator + (0.5f * line_height),
UI_LINE_WIDTH, ui().colors().text_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
menu_item const &pitem = item(0);
std::string_view const itemtext = pitem.text;
float const line_y0 = separator + line_height;
float const line_y1 = line_y0 + line_height;
if (mouse_in_rect(line_x0, line_y0, line_x1, line_y1) && is_selectable(pitem))
set_hover(0);
highlight(line_x0, line_y0, line_x1, line_y1, ui().colors().selected_bg_color());
ui().draw_text_full(
container(), itemtext,
effective_left, line_y0, actual_width,
text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE,
mame_ui_manager::NORMAL,
ui().colors().selected_color(), ui().colors().selected_bg_color(),
nullptr, nullptr);
// if there is something special to add, do it by calling the virtual method
custom_render(get_selection_ref(), get_customtop(), get_custombottom(), x1, y1, x2, y2);
}
//------------------------------------------------- //-------------------------------------------------
// populate - populates the about modal // populate - populates the about modal
//------------------------------------------------- //-------------------------------------------------
void menu_about::populate(float &customtop, float &custombottom) void menu_about::populate(float &customtop, float &custombottom)
{ {
std::string title = string_format(_("%1$s %2$s"), emulator_info::get_appname(), bare_build_version); // make space for the title and revision
item_append(title, 0, nullptr); customtop = ui().get_line_height() + 3.0f * ui().box_tb_border();
item_append(menu_item_type::SEPARATOR); custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border();
for (char const *const *line = copying_text; *line; ++line)
item_append(*line, 0, nullptr);
item_append(menu_item_type::SEPARATOR);
} }
@ -74,13 +232,35 @@ void menu_about::populate(float &customtop, float &custombottom)
void menu_about::handle() void menu_about::handle()
{ {
// process the menu const event *event = process(PROCESS_CUSTOM_NAV);
const event *event = process(0); if (event)
// process the event
if (event && (event->iptkey == IPT_UI_SELECT))
{ {
stack_pop(); switch (event->iptkey)
{
case IPT_UI_UP:
--top_line;
break;
case IPT_UI_DOWN:
++top_line;
break;
case IPT_UI_PAGE_UP:
top_line -= m_visible_lines - 3;
break;
case IPT_UI_PAGE_DOWN:
top_line += m_visible_lines - 3;
break;
case IPT_UI_HOME:
top_line = 0;
break;
case IPT_UI_END:
top_line = m_layout->lines() - m_visible_lines;
break;
}
} }
} }

View File

@ -1,10 +1,10 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Ryan Holtz // copyright-holders:Vas Crabb
/*************************************************************************** /***************************************************************************
ui/about.h ui/about.h
"About" modal About box
***************************************************************************/ ***************************************************************************/
#ifndef MAME_FRONTEND_UI_ABOUT_H #ifndef MAME_FRONTEND_UI_ABOUT_H
@ -14,7 +14,9 @@
#include "ui/menu.h" #include "ui/menu.h"
#include <vector> #include <optional>
#include <string>
namespace ui { namespace ui {
@ -24,9 +26,17 @@ public:
menu_about(mame_ui_manager &mui, render_container &container); menu_about(mame_ui_manager &mui, render_container &container);
virtual ~menu_about() override; virtual ~menu_about() override;
protected:
virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
private: private:
virtual void draw(uint32_t flags) override;
virtual void populate(float &customtop, float &custombottom) override; virtual void populate(float &customtop, float &custombottom) override;
virtual void handle() override; virtual void handle() override;
std::string const m_title;
std::string const m_footer;
std::optional<text_layout> m_layout;
}; };
} // namespace ui } // namespace ui

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Maurizio Petrarota // copyright-holders:Maurizio Petrarota, Vas Crabb
/********************************************************************* /*********************************************************************
ui/datmenu.cpp ui/datmenu.cpp
@ -140,7 +140,7 @@ void menu_dats_view::add_info_text(text_layout &layout, std::string_view text, r
if (std::string_view::npos != split) if (std::string_view::npos != split)
{ {
layout.add_text(line.substr(0, split), text_layout::text_justify::LEFT, color, rgb_t::transparent(), size); layout.add_text(line.substr(0, split), text_layout::text_justify::LEFT, color, rgb_t::transparent(), size);
layout.add_text(" ", text_layout::text_layout::text_justify::LEFT, color, rgb_t::transparent(), size); layout.add_text(" ", text_layout::text_justify::LEFT, color, rgb_t::transparent(), size);
layout.add_text(line.substr(split + 1), text_layout::text_justify::RIGHT, color, rgb_t::transparent(), size); layout.add_text(line.substr(split + 1), text_layout::text_justify::RIGHT, color, rgb_t::transparent(), size);
} }
else else
@ -278,10 +278,13 @@ void menu_dats_view::draw(uint32_t flags)
if (!m_layout || (m_layout->width() != effective_width)) if (!m_layout || (m_layout->width() != effective_width))
{ {
std::string buffer; std::string buffer;
if (m_issoft) if (!m_items_list.empty())
get_data_sw(buffer); {
else if (m_issoft)
get_data(buffer); get_data_sw(buffer);
else
get_data(buffer);
}
m_layout.emplace(ui().create_layout(container(), effective_width)); m_layout.emplace(ui().create_layout(container(), effective_width));
add_info_text(*m_layout, buffer, ui().colors().text_color()); add_info_text(*m_layout, buffer, ui().colors().text_color());
} }
@ -339,8 +342,8 @@ void menu_dats_view::draw(uint32_t flags)
// add visual separator before the "return to prevous menu" item // add visual separator before the "return to prevous menu" item
container().add_line( container().add_line(
visible_left, separator + (0.5f * line_height), x1, separator + (0.5f * line_height),
visible_left + visible_width, separator + (0.5f * line_height), x2, separator + (0.5f * line_height),
UI_LINE_WIDTH, ui().colors().text_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); UI_LINE_WIDTH, ui().colors().text_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
menu_item const &pitem = item(0); menu_item const &pitem = item(0);
@ -471,38 +474,41 @@ void menu_dats_view::custom_render(void *selectedref, float top, float bottom, f
} }
// bottom // bottom
std::string const revision(util::string_format(_("Revision: %1$s"), m_items_list[m_actual].revision)); if (!m_items_list.empty())
ui().draw_text_full( {
container(), std::string const revision(util::string_format(_("Revision: %1$s"), m_items_list[m_actual].revision));
revision, ui().draw_text_full(
0.0f, 0.0f, 1.0f, container(),
text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, revision,
mame_ui_manager::NONE, rgb_t::white(), rgb_t::black(), 0.0f, 0.0f, 1.0f,
&width, nullptr); text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE,
width += 2 * lr_border; mame_ui_manager::NONE, rgb_t::white(), rgb_t::black(),
maxwidth = std::max(origx2 - origx1, width); &width, nullptr);
width += 2 * lr_border;
maxwidth = std::max(origx2 - origx1, width);
// compute our bounds // compute our bounds
x1 = 0.5f - 0.5f * maxwidth; x1 = 0.5f - 0.5f * maxwidth;
x2 = x1 + maxwidth; x2 = x1 + maxwidth;
y1 = origy2 + ui().box_tb_border(); y1 = origy2 + ui().box_tb_border();
y2 = origy2 + bottom; y2 = origy2 + bottom;
// draw a box // draw a box
ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_GREEN_COLOR); ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_GREEN_COLOR);
// take off the borders // take off the borders
x1 += lr_border; x1 += lr_border;
x2 -= lr_border; x2 -= lr_border;
y1 += ui().box_tb_border(); y1 += ui().box_tb_border();
// draw the text within it // draw the text within it
ui().draw_text_full( ui().draw_text_full(
container(), container(),
revision, revision,
x1, y1, x2 - x1, x1, y1, x2 - x1,
text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE,
mame_ui_manager::NORMAL, ui().colors().text_color(), ui().colors().text_bg_color()); mame_ui_manager::NORMAL, ui().colors().text_color(), ui().colors().text_bg_color());
}
} }
//------------------------------------------------- //-------------------------------------------------

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Maurizio Petrarota // copyright-holders:Maurizio Petrarota, Vas Crabb
/*************************************************************************** /***************************************************************************
ui/datmenu.h ui/datmenu.h
@ -76,4 +76,4 @@ private:
} // namespace ui } // namespace ui
#endif /* MAME_FRONTEND_UI_DATMENU_H */ #endif // MAME_FRONTEND_UI_DATMENU_H

View File

@ -855,18 +855,10 @@ void menu_select_launch::inkey_dats()
ui_software_info const *software; ui_software_info const *software;
ui_system_info const *system; ui_system_info const *system;
get_selection(software, system); get_selection(software, system);
if (software) if (software && !software->startempty)
{ menu::stack_push<menu_dats_view>(ui(), container(), software);
if (software->startempty && mame_machine_manager::instance()->lua()->call_plugin_check<const char *>("data_list", software->driver->name, true))
menu::stack_push<menu_dats_view>(ui(), container(), system);
else if (mame_machine_manager::instance()->lua()->call_plugin_check<const char *>("data_list", std::string(software->shortname).append(1, ',').append(software->listname).c_str()) || !software->infotext.empty())
menu::stack_push<menu_dats_view>(ui(), container(), software);
}
else if (system) else if (system)
{ menu::stack_push<menu_dats_view>(ui(), container(), system);
if (mame_machine_manager::instance()->lua()->call_plugin_check<const char *>("data_list", system->driver->name, true))
menu::stack_push<menu_dats_view>(ui(), container(), system);
}
} }
@ -1299,23 +1291,28 @@ void menu_select_launch::draw_toolbar(float x1, float y1, float x2, float y2)
x1 = (std::min)(backtrack_pos - (float(toolbar_count) * x_spacing), x1 + ((x2 - x1 - total_width) * 0.5f)); x1 = (std::min)(backtrack_pos - (float(toolbar_count) * x_spacing), x1 + ((x2 - x1 - total_width) * 0.5f));
for (int z = 0; toolbar_count > z; ++z, x1 += x_spacing) for (int z = 0; toolbar_count > z; ++z, x1 += x_spacing)
{ {
auto const bitmap = toolbar_bitmaps[z];
x2 = x1 + x_size; x2 = x1 + x_size;
color = rgb_t (0xffcccccc); color = rgb_t (0xffcccccc);
if (mouse_in_rect(x1, y1, x2, y2)) if (mouse_in_rect(x1, y1, x2, y2))
{ {
set_hover(HOVER_B_FAV + toolbar_bitmaps[z]); bool const need_selection = (TOOLBAR_BITMAP_FAVORITE == bitmap) || (TOOLBAR_BITMAP_INFO == bitmap);
color = rgb_t::white(); if (!need_selection || get_selection_ptr())
{
set_hover(HOVER_B_FAV + bitmap);
color = rgb_t::white();
}
float ypos = y2 + ui().get_line_height() + 2.0f * ui().box_tb_border(); float ypos = y2 + ui().get_line_height() + 2.0f * ui().box_tb_border();
ui().draw_text_box( ui().draw_text_box(
container(), container(),
_(hover_msg[toolbar_bitmaps[z]]), _(hover_msg[bitmap]),
text_layout::text_justify::CENTER, (x1 + x2) * 0.5f, ypos, text_layout::text_justify::CENTER, (x1 + x2) * 0.5f, ypos,
ui().colors().background_color()); ui().colors().background_color());
} }
container().add_quad( container().add_quad(
x1, y1, x2, y2, x1, y1, x2, y2,
color, color,
m_cache.toolbar_textures()[toolbar_bitmaps[z]].get(), m_cache.toolbar_textures()[bitmap].get(),
PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
} }
} }

View File

@ -1,5 +1,5 @@
// copyright-holders:R. Belmont
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:R. Belmont
/*************************************************************************** /***************************************************************************
apple2e.cpp - Apple IIe/IIc/IIc Plus and clones apple2e.cpp - Apple IIe/IIc/IIc Plus and clones

View File

@ -10,6 +10,7 @@
#import "pointsviewer.h" #import "pointsviewer.h"
#import "breakpointsview.h" #import "breakpointsview.h"
#import "registerpointsview.h"
#import "watchpointsview.h" #import "watchpointsview.h"
#include "util/xmlfile.h" #include "util/xmlfile.h"
@ -18,9 +19,9 @@
@implementation MAMEPointsViewer @implementation MAMEPointsViewer
- (id)initWithMachine:(running_machine &)m console:(MAMEDebugConsole *)c { - (id)initWithMachine:(running_machine &)m console:(MAMEDebugConsole *)c {
MAMEDebugView *breakView, *watchView; MAMEDebugView *breakView, *watchView, *registerView;
NSScrollView *breakScroll, *watchScroll; NSScrollView *breakScroll, *watchScroll, *registerScroll;
NSTabViewItem *breakTab, *watchTab; NSTabViewItem *breakTab, *watchTab, *registerTab;
NSPopUpButton *actionButton; NSPopUpButton *actionButton;
NSRect subviewFrame; NSRect subviewFrame;
@ -44,6 +45,9 @@
[[[subviewButton menu] addItemWithTitle:@"All Watchpoints" [[[subviewButton menu] addItemWithTitle:@"All Watchpoints"
action:NULL action:NULL
keyEquivalent:@""] setTag:1]; keyEquivalent:@""] setTag:1];
[[[subviewButton menu] addItemWithTitle:@"All Registerpoints"
action:NULL
keyEquivalent:@""] setTag:2];
[subviewButton sizeToFit]; [subviewButton sizeToFit];
subviewFrame = [subviewButton frame]; subviewFrame = [subviewButton frame];
subviewFrame.origin.x = subviewFrame.size.height; subviewFrame.origin.x = subviewFrame.size.height;
@ -82,7 +86,7 @@
[breakTab setView:breakScroll]; [breakTab setView:breakScroll];
[breakScroll release]; [breakScroll release];
// create the breakpoints view // create the watchpoints view
watchView = [[MAMEWatchpointsView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) watchView = [[MAMEWatchpointsView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)
machine:*machine]; machine:*machine];
watchScroll = [[NSScrollView alloc] initWithFrame:[breakScroll frame]]; watchScroll = [[NSScrollView alloc] initWithFrame:[breakScroll frame]];
@ -98,6 +102,22 @@
[watchTab setView:watchScroll]; [watchTab setView:watchScroll];
[watchScroll release]; [watchScroll release];
// create the registerpoints view
registerView = [[MAMERegisterpointsView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)
machine:*machine];
registerScroll = [[NSScrollView alloc] initWithFrame:[breakScroll frame]];
[registerScroll setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
[registerScroll setHasHorizontalScroller:YES];
[registerScroll setHasVerticalScroller:YES];
[registerScroll setAutohidesScrollers:YES];
[registerScroll setBorderType:NSNoBorder];
[registerScroll setDrawsBackground:NO];
[registerScroll setDocumentView:registerView];
[registerView release];
registerTab = [[NSTabViewItem alloc] initWithIdentifier:@""];
[registerTab setView:registerScroll];
[registerScroll release];
// create a tabless tabview for the two subviews // create a tabless tabview for the two subviews
tabs = [[NSTabView alloc] initWithFrame:[breakScroll frame]]; tabs = [[NSTabView alloc] initWithFrame:[breakScroll frame]];
[tabs setTabViewType:NSNoTabsNoBorder]; [tabs setTabViewType:NSNoTabsNoBorder];
@ -106,6 +126,8 @@
[breakTab release]; [breakTab release];
[tabs addTabViewItem:watchTab]; [tabs addTabViewItem:watchTab];
[watchTab release]; [watchTab release];
[tabs addTabViewItem:registerTab];
[registerTab release];
[[window contentView] addSubview:tabs]; [[window contentView] addSubview:tabs];
[tabs release]; [tabs release];
@ -124,8 +146,12 @@
hasHorizontalScroller:YES hasHorizontalScroller:YES
hasVerticalScroller:YES hasVerticalScroller:YES
borderType:[watchScroll borderType]]; borderType:[watchScroll borderType]];
NSSize const desired = NSMakeSize(std::max(breakDesired.width, watchDesired.width), NSSize const registerDesired = [NSScrollView frameSizeForContentSize:[registerView maximumFrameSize]
std::max(breakDesired.height, watchDesired.height)); hasHorizontalScroller:YES
hasVerticalScroller:YES
borderType:[registerScroll borderType]];
NSSize const desired = NSMakeSize(std::max({ breakDesired.width, watchDesired.width, registerDesired.width }),
std::max({ breakDesired.height, watchDesired.height, registerDesired.height }));
[self cascadeWindowWithDesiredSize:desired forView:tabs]; [self cascadeWindowWithDesiredSize:desired forView:tabs];
// don't forget the result // don't forget the result

View File

@ -0,0 +1,23 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
//============================================================
//
// registerpointsview.h - MacOS X Cocoa debug window handling
//
//============================================================
#import "debugosx.h"
#import "debugview.h"
#import <Cocoa/Cocoa.h>
@interface MAMERegisterpointsView : MAMEDebugView
{
}
- (id)initWithFrame:(NSRect)f machine:(running_machine &)m;
@end

View File

@ -0,0 +1,27 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
//============================================================
//
// registerpointsview.m - MacOS X Cocoa debug window handling
//
//============================================================
#import "registerpointsview.h"
#include "debug/debugvw.h"
@implementation MAMERegisterpointsView
- (id)initWithFrame:(NSRect)f machine:(running_machine &)m {
if (!(self = [super initWithFrame:f type:DVT_REGISTER_POINTS machine:m wholeLineScroll:YES]))
return nil;
return self;
}
- (void)dealloc {
[super dealloc];
}
@end

View File

@ -5,8 +5,6 @@
#include "debug/debugcon.h" #include "debug/debugcon.h"
#include "debug/debugcpu.h" #include "debug/debugcpu.h"
#include "debug/dvbpoints.h"
#include "debug/dvwpoints.h"
#include <QtWidgets/QActionGroup> #include <QtWidgets/QActionGroup>
#include <QtWidgets/QHBoxLayout> #include <QtWidgets/QHBoxLayout>
@ -48,16 +46,25 @@ BreakpointsWindow::BreakpointsWindow(running_machine &machine, QWidget *parent)
// //
QActionGroup *typeGroup = new QActionGroup(this); QActionGroup *typeGroup = new QActionGroup(this);
typeGroup->setObjectName("typegroup"); typeGroup->setObjectName("typegroup");
QAction *typeBreak = new QAction("Breakpoints", this); QAction *typeBreak = new QAction("Breakpoints", this);
typeBreak->setObjectName("typebreak"); typeBreak->setObjectName("typebreak");
typeBreak->setCheckable(true);
typeBreak->setActionGroup(typeGroup);
typeBreak->setShortcut(QKeySequence("Ctrl+1"));
QAction *typeWatch = new QAction("Watchpoints", this); QAction *typeWatch = new QAction("Watchpoints", this);
typeWatch->setObjectName("typewatch"); typeWatch->setObjectName("typewatch");
typeBreak->setCheckable(true);
typeWatch->setCheckable(true); typeWatch->setCheckable(true);
typeBreak->setActionGroup(typeGroup);
typeWatch->setActionGroup(typeGroup); typeWatch->setActionGroup(typeGroup);
typeBreak->setShortcut(QKeySequence("Ctrl+1"));
typeWatch->setShortcut(QKeySequence("Ctrl+2")); typeWatch->setShortcut(QKeySequence("Ctrl+2"));
QAction *typeRegister = new QAction("Registerpoints", this);
typeRegister->setObjectName("typeregister");
typeRegister->setCheckable(true);
typeRegister->setActionGroup(typeGroup);
typeRegister->setShortcut(QKeySequence("Ctrl+3"));
typeBreak->setChecked(true); typeBreak->setChecked(true);
connect(typeGroup, &QActionGroup::triggered, this, &BreakpointsWindow::typeChanged); connect(typeGroup, &QActionGroup::triggered, this, &BreakpointsWindow::typeChanged);
@ -89,6 +96,11 @@ void BreakpointsWindow::typeChanged(QAction* changedTo)
m_breakpointsView = new DebuggerView(DVT_WATCH_POINTS, m_machine, this); m_breakpointsView = new DebuggerView(DVT_WATCH_POINTS, m_machine, this);
setWindowTitle("Debug: All Watchpoints"); setWindowTitle("Debug: All Watchpoints");
} }
else if (changedTo->text() == "Registerpoints")
{
m_breakpointsView = new DebuggerView(DVT_REGISTER_POINTS, m_machine, this);
setWindowTitle("Debug: All Registerpoints");
}
// Re-register // Re-register
QVBoxLayout *layout = findChild<QVBoxLayout *>("vlayout"); QVBoxLayout *layout = findChild<QVBoxLayout *>("vlayout");
@ -110,6 +122,8 @@ void BreakpointsWindowQtConfig::buildFromQWidget(QWidget *widget)
m_bwType = 0; m_bwType = 0;
else if (typeGroup->checkedAction()->text() == "Watchpoints") else if (typeGroup->checkedAction()->text() == "Watchpoints")
m_bwType = 1; m_bwType = 1;
else if (typeGroup->checkedAction()->text() == "Registerpoints")
m_bwType = 2;
} }

View File

@ -97,6 +97,7 @@ protected:
ID_SHOW_BREAKPOINTS, ID_SHOW_BREAKPOINTS,
ID_SHOW_WATCHPOINTS, ID_SHOW_WATCHPOINTS,
ID_SHOW_REGISTERPOINTS,
ID_CLEAR_LOG, ID_CLEAR_LOG,

View File

@ -31,6 +31,7 @@ pointswin_info::pointswin_info(debugger_windows_interface &debugger) :
HMENU const optionsmenu = CreatePopupMenu(); HMENU const optionsmenu = CreatePopupMenu();
AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_BREAKPOINTS, TEXT("Breakpoints\tCtrl+1")); AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_BREAKPOINTS, TEXT("Breakpoints\tCtrl+1"));
AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_WATCHPOINTS, TEXT("Watchpoints\tCtrl+2")); AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_WATCHPOINTS, TEXT("Watchpoints\tCtrl+2"));
AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_REGISTERPOINTS, TEXT("Registerpoints\tCtrl+3"));
AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options")); AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options"));
// compute a client rect // compute a client rect
@ -69,6 +70,10 @@ bool pointswin_info::handle_key(WPARAM wparam, LPARAM lparam)
case '2': case '2':
SendMessage(window(), WM_COMMAND, ID_SHOW_WATCHPOINTS, 0); SendMessage(window(), WM_COMMAND, ID_SHOW_WATCHPOINTS, 0);
return true; return true;
case '3':
SendMessage(window(), WM_COMMAND, ID_SHOW_REGISTERPOINTS, 0);
return true;
} }
} }
@ -83,6 +88,7 @@ void pointswin_info::update_menu()
HMENU const menu = GetMenu(window()); HMENU const menu = GetMenu(window());
CheckMenuItem(menu, ID_SHOW_BREAKPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_BREAK_POINTS ? MF_CHECKED : MF_UNCHECKED)); CheckMenuItem(menu, ID_SHOW_BREAKPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_BREAK_POINTS ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(menu, ID_SHOW_WATCHPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_WATCH_POINTS ? MF_CHECKED : MF_UNCHECKED)); CheckMenuItem(menu, ID_SHOW_WATCHPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_WATCH_POINTS ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(menu, ID_SHOW_REGISTERPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_REGISTER_POINTS ? MF_CHECKED : MF_UNCHECKED));
} }
@ -111,6 +117,15 @@ bool pointswin_info::handle_command(WPARAM wparam, LPARAM lparam)
win_set_window_text_utf8(window(), "All Watchpoints"); win_set_window_text_utf8(window(), "All Watchpoints");
recompute_children(); recompute_children();
return true; return true;
case ID_SHOW_REGISTERPOINTS:
m_views[0].reset();
m_views[0].reset(new debugview_info(debugger(), *this, window(), DVT_REGISTER_POINTS));
if (!m_views[0]->is_valid())
m_views[0].reset();
win_set_window_text_utf8(window(), "All Registerpoints");
recompute_children();
return true;
} }
break; break;
} }