diff options
34 files changed, 1132 insertions, 433 deletions
diff --git a/docs/source/debugger/breakpoint.rst b/docs/source/debugger/breakpoint.rst index 1e61157c854..5dbf6c4effe 100644 --- a/docs/source/debugger/breakpoint.rst +++ b/docs/source/debugger/breakpoint.rst @@ -75,10 +75,10 @@ Back to :ref:`debugger-breakpoint-list` bpclear ------- -**bpclear [<bpnum>]** +**bpclear [<bpnum>[,…]]** -Clear breakpoints. If **<bpnum>** is specified, the breakpoint it -refers to will be cleared. If **<bpnum>** is not specified, all +Clear breakpoints. If **<bpnum>** is specified, the breakpoints +referred to will be cleared. If **<bpnum>** is not specified, all breakpoints will be cleared. Examples: @@ -96,10 +96,10 @@ Back to :ref:`debugger-breakpoint-list` bpdisable --------- -**bpdisable [<bpnum>]** +**bpdisable [<bpnum>[,…]]** -Disable breakpoints. If **<bpnum>** is specified, the breakpoint it -refers to will be disabled. If **<bpnum>** is not specified, all +Disable breakpoints. If **<bpnum>** is specified, the breakpoints +referred to will be disabled. If **<bpnum>** is not specified, all breakpoints will be disabled. Note that disabling a breakpoint does not delete it, it just temporarily @@ -122,10 +122,10 @@ Back to :ref:`debugger-breakpoint-list` bpenable -------- -**bpenable [<bpnum>]** +**bpenable [<bpnum>[,…]]** -Enable breakpoints. If **<bpnum>** is specified, the breakpoint it -refers to will be enabled. If **<bpnum>** is not specified, all +Enable breakpoints. If **<bpnum>** is specified, the breakpoint +referred to will be enabled. If **<bpnum>** is not specified, all breakpoints will be enabled. Examples: diff --git a/docs/source/debugger/execution.rst b/docs/source/debugger/execution.rst index cfcfede1c87..8a99f52f85a 100644 --- a/docs/source/debugger/execution.rst +++ b/docs/source/debugger/execution.rst @@ -285,7 +285,7 @@ Back to :ref:`debugger-execution-list` ignore ------ -**ignore [<CPU>[,<CPU>[,...]]]** +**ignore [<CPU>[,<CPU>[,…]]]** Ignores the specified CPUs in the debugger. CPUs can be specified by tag or debugger CPU number (see :ref:`debugger-devicespec` for details). @@ -316,7 +316,7 @@ Back to :ref:`debugger-execution-list` observe ------- -**observe [<CPU>[,<CPU>[,...]]]** +**observe [<CPU>[,<CPU>[,…]]]** Allow interaction with the specified CPUs in the debugger. CPUs can be specified by tag or debugger CPU number (see :ref:`debugger-devicespec` diff --git a/docs/source/debugger/general.rst b/docs/source/debugger/general.rst index 9d7d206117e..4edc1b413fb 100644 --- a/docs/source/debugger/general.rst +++ b/docs/source/debugger/general.rst @@ -159,7 +159,7 @@ Back to :ref:`debugger-general-list` print ----- -**print <item>[,...]** +**print <item>[,…]** The **print** command prints the results of one or more expressions to the debugger console as hexadecimal numbers. @@ -180,7 +180,7 @@ Back to :ref:`debugger-general-list` printf ------ -**printf <format>[,<argument>[,...]]** +**printf <format>[,<argument>[,…]]** Prints a C-style formatted message to the debugger console. Only a very limited subset of format specifiers and escape sequences are @@ -223,7 +223,7 @@ Back to :ref:`debugger-general-list` logerror -------- -**logerror <format>[,<argument>[,...]]** +**logerror <format>[,<argument>[,…]]** Prints a C-style formatted message to the error log. See :ref:`debugger-command-printf` for details about the limited set of @@ -246,7 +246,7 @@ Back to :ref:`debugger-general-list` tracelog -------- -**tracelog <format>[,<argument>[,...]]** +**tracelog <format>[,<argument>[,…]]** Prints a C-style formatted message to the currently open trace file (see :ref:`debugger-command-trace` for more information). If no trace file @@ -272,7 +272,7 @@ Back to :ref:`debugger-general-list` tracesym -------- -**tracesym <item>[,...]** +**tracesym <item>[,…]** Prints the specified symbols to the currently open trace file (see :ref:`debugger-command-trace` for more information). If no trace file diff --git a/docs/source/debugger/memory.rst b/docs/source/debugger/memory.rst index da3645a6d1e..9988d24551e 100644 --- a/docs/source/debugger/memory.rst +++ b/docs/source/debugger/memory.rst @@ -64,7 +64,7 @@ Back to :ref:`debugger-memory-list` 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 **<address>** is the address to begin searching from, optionally @@ -113,7 +113,7 @@ Back to :ref:`debugger-memory-list` 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. The **<address>** specifies the address to begin writing at, optionally diff --git a/docs/source/debugger/registerpoints.rst b/docs/source/debugger/registerpoints.rst index 355a31c29eb..e228208e600 100644 --- a/docs/source/debugger/registerpoints.rst +++ b/docs/source/debugger/registerpoints.rst @@ -1,120 +1,146 @@ .. _debugger-registerpoints-list: -Registerpoints Debugger Commands +Registerpoint Debugger Commands ================================ +:ref:`debugger-command-rpset` + sets a registerpoint to trigger on a condition +:ref:`debugger-command-rpclear` + clears registerpoints +:ref:`debugger-command-rpdisable` + disables a registerpoint +:ref:`debugger-command-rpenable` + enables registerpoints +:ref:`debugger-command-rplist` + lists registerpoints -You can also type **help <command>** for further details on each command in the MAME Debugger interface. -| :ref:`debugger-command-rpset` -- sets a registerpoint to trigger on <condition> -| :ref:`debugger-command-rpclear` -- clears a given registerpoint or all if no <rpnum> specified -| :ref:`debugger-command-rpdisable` -- disabled a given registerpoint or all if no <rpnum> specified -| :ref:`debugger-command-rpenable` -- enables a given registerpoint or all if no <rpnum> specified -| :ref:`debugger-command-rplist` -- lists all the registerpoints +.. _debugger-command-rpset: +rpset +----- +**rp[set] <condition>[,<action>]** - .. _debugger-command-rpset: +Sets a new registerpoint which will be triggered when the expression +supplied as the **<condition>** evaluates to true (non-zero). Note that +the condition may need to be surrounded with braces ``{ }`` to prevent +it from being interpreted as an assignment. The optional **<action>** +parameter provides a command to be executed whenever the registerpoint +is triggered. Note that you may need to surround the action with braces +``{ }`` to ensure commas and semicolons within the command are not +interpreted in the context of the ``rpset`` command itself. + +Each registerpoint that is set is assigned a numeric index which can be +used to refer to it in other registerpoint commands. Registerpoint +indices are unique throughout a session. + +Examples: + +``rp {PC==150}`` + Set a registerpoint that will halt execution whenever the **PC** + register equals 150. +``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` -rpset ------ -| **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. -| 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. -| Each registerpoint that is set is assigned an index which can be used in other registerpoint commands to reference this registerpoint. -| -| Examples: -| -| rp {PC==0150} -| -| Set a registerpoint that will halt execution whenever the PC register equals 0x150. -| -| temp0=0; rp {PC==0150},{temp0++; g} -| -| Set a registerpoint that will increment the variable temp0 whenever the PC register equals 0x0150. -| -| 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 [<rpnum>]** -| -| The rpclear command clears a registerpoint. If <rpnum> is specified, only the requested registerpoint is cleared, otherwise all registerpoints are cleared. -| -| Examples: -| -| rpclear 3 -| -| Clear registerpoint index 3. -| -| rpclear -| -| Clear all registerpoints. -| -| Back to :ref:`debugger-registerpoints-list` - - - .. _debugger-command-rpdisable: +**rpclear [<rpnum>,[,…]]** + +Clears registerpoints. If **<rpnum>** is specified, the registerpoints +referred to will be cleared. If **<rpnum>** is not specified, all +registerpoints will be cleared. + +Examples: + +``rpclear 3`` + Clear the registerpoint with index 3. +``rpclear`` + Clear all registerpoints. + +Back to :ref:`debugger-registerpoints-list` + + +.. _debugger-command-rpdisable: rpdisable --------- -| **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. -| -| Examples: -| -| rpdisable 3 -| -| Disable registerpoint index 3. -| -| rpdisable -| -| Disable all registerpoints. -| -| Back to :ref:`debugger-registerpoints-list` - - - .. _debugger-command-rpenable: +**rpdisable [<rpnum>[,…]]** + +Disables registerpoints. If **<rpnum>** is specified, the +registerpoints referred to will be disabled. If **<rpnum>** is not +specified, all registerpoints will be disabled. + +Note that disabling a registerpoint does not delete it, it just +temporarily marks the registerpoint as inactive. Disabled +registerpoints will not cause execution to halt, their condition +expressions will not be evaluated, and their associated commands will +not be executed. + +Examples: + +``rpdisable 3`` + Disable the registerpoint with index 3. +``rpdisable`` + Disable all registerpoints. + +Back to :ref:`debugger-registerpoints-list` + + +.. _debugger-command-rpenable: rpenable -------- -| **rpenable [<rpnum>]** -| -| The rpenable command enables a registerpoint. If <rpnum> is specified, only the requested registerpoint is enabled, otherwise all registerpoints are enabled. -| -| Examples: -| -| rpenable 3 -| -| Enable registerpoint index 3. -| -| rpenable -| -| Enable all registerpoints. -| -| Back to :ref:`debugger-registerpoints-list` - - - .. _debugger-command-rplist: +**rpenable [<rpnum>[,…]]** + +Enables registerpoints. If **<rpnum>** is specified, the registerpoints +referred to will be enabled. If **<rpnum>** is not specified, all +registerpoints will be enabled. + +Examples: + +``rpenable 3`` + Enable the registerpoint with index 3. +``rpenable`` + Enable all registerpoints. + +Back to :ref:`debugger-registerpoints-list` + + +.. _debugger-command-rplist: rplist ------ -| **rplist** -| -| The rplist command lists all the current registerpoints, along with their index and any actions attached to them. -| -| Back to :ref:`debugger-registerpoints-list` +**rplist [<CPU>]** + +List current registerpoints, along with their indices and conditions, +and any associated actions actions. If no **<CPU>** is specified, +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` diff --git a/docs/source/debugger/watchpoint.rst b/docs/source/debugger/watchpoint.rst index d9270f13699..c34006f8a5f 100644 --- a/docs/source/debugger/watchpoint.rst +++ b/docs/source/debugger/watchpoint.rst @@ -83,10 +83,10 @@ Back to :ref:`debugger-watchpoints-list` wpclear ------- -**wpclear [<wpnum>]** +**wpclear [<wpnum>[,…]]** -Clear watchpoints. If **<wpnum>** is specified, the watchpoint it -refers to will be cleared. If **<wpnum>** is not specified, all +Clear watchpoints. If **<wpnum>** is specified, the watchpoints +referred to will be cleared. If **<wpnum>** is not specified, all watchpoints will be cleared. Examples: @@ -104,10 +104,10 @@ Back to :ref:`debugger-watchpoints-list` wpdisable --------- -**wpdisable [<wpnum>]** +**wpdisable [<wpnum>[,…]]** -Disable watchpoints. If **<wpnum>** is specified, the watchpoint it -refers to will be disabled. If **<wpnum>** is not specified, all +Disable watchpoints. If **<wpnum>** is specified, the watchpoints +referred to will be disabled. If **<wpnum>** is not specified, all watchpoints will be disabled. Note that disabling a watchpoint does not delete it, it just temporarily @@ -130,10 +130,10 @@ Back to :ref:`debugger-watchpoints-list` wpenable -------- -**wpenable [<wpnum>]** +**wpenable [<wpnum>[,…]]** -Enable watchpoints. If **<wpnum>** is specified, the watchpoint it -refers to will be enabled. If **<wpnum>** is not specified, all +Enable watchpoints. If **<wpnum>** is specified, the watchpoints +referred to will be enabled. If **<wpnum>** is not specified, all watchpoints will be enabled. Examples: @@ -1073,7 +1073,7 @@ endif ifneq ($(GIT_AVAILABLE),git) IGNORE_GIT := 1 endif -ifeq ($(wildcard .git/*),) +ifeq ($(filter .git,$(wildcard .*)),) IGNORE_GIT := 1 endif @@ -1757,17 +1757,23 @@ endif ifeq (posix,$(SHELLTYPE)) $(GENDIR)/version.cpp: makefile $(GENDIR)/git_desc | $(GEN_FOLDERS) @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_vcs_revision[];' >> $@ @echo 'extern const char 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 $(GENDIR)/version.cpp: makefile $(GENDIR)/git_desc | $(GEN_FOLDERS) @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_vcs_revision[]; >> $@ @echo extern const char 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 diff --git a/scripts/src/emu.lua b/scripts/src/emu.lua index dd24030e72d..06b92469c25 100644 --- a/scripts/src/emu.lua +++ b/scripts/src/emu.lua @@ -238,6 +238,8 @@ files { MAME_DIR .. "src/emu/debug/dvmemory.h", MAME_DIR .. "src/emu/debug/dvbpoints.cpp", 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.h", MAME_DIR .. "src/emu/debug/dvstate.cpp", diff --git a/scripts/src/osd/mac.lua b/scripts/src/osd/mac.lua index 8a57b4ab4a3..4b3967b8c3d 100644 --- a/scripts/src/osd/mac.lua +++ b/scripts/src/osd/mac.lua @@ -108,6 +108,8 @@ project ("osd_" .. _OPTIONS["osd"]) 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.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.h", MAME_DIR .. "src/osd/modules/debugger/osx/watchpointsview.mm", diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index fe5bce41841..bcebb63cf92 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -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("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("bpdisable", CMDFLAG_NONE, 0, 1, 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("bpclear", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_bpclear, this, _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, 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("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("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("wpclear", CMDFLAG_NONE, 0, 1, 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("wpenable", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_wpdisenable, this, true, _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, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_wpdisenable, this, false, _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("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("rpclear", CMDFLAG_NONE, 0, 1, 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("rpenable", CMDFLAG_NONE, 0, 1, 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("rpclear", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_rpclear, this, _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, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_rpdisenable, this, true, _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("ss", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_statesave, this, _1)); @@ -1071,6 +1071,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 ¶ms, 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 ¶m : index) + m_console.printf(unused_message, param); +} + + +/*------------------------------------------------- execute_printf - execute the printf command -------------------------------------------------*/ @@ -1740,31 +1771,24 @@ void debugger_commands::execute_bpset(const std::vector<std::string> ¶ms) void debugger_commands::execute_bpclear(const std::vector<std::string> ¶ms) { - u64 bpindex; - if (params.empty()) // if no parameters, clear all { for (device_t &device : device_enumerator(m_machine.root_device())) device.debug()->breakpoint_clear_all(); m_console.printf("Cleared all breakpoints\n"); } - else if (!validate_number_parameter(params[0], bpindex)) // otherwise, clear the specific one - { - return; - } - else + else // otherwise, clear the specific ones { - bool found = false; - for (device_t &device : device_enumerator(m_machine.root_device())) - if (device.debug()->breakpoint_clear(bpindex)) - { - found = true; - break; - } - if (found) - m_console.printf("Breakpoint %X cleared\n", u32(bpindex)); - else - m_console.printf("Invalid breakpoint number %X\n", u32(bpindex)); + execute_index_command( + params, + [this] (device_t &device, u64 param) -> bool + { + if (!device.debug()->breakpoint_clear(param)) + return false; + m_console.printf("Breakpoint %X cleared\n", param); + return true; + }, + "Invalid breakpoint number %X\n"); } } @@ -1776,34 +1800,24 @@ void debugger_commands::execute_bpclear(const std::vector<std::string> ¶ms) void debugger_commands::execute_bpdisenable(bool enable, const std::vector<std::string> ¶ms) { - u64 bpindex; - - if (params.empty()) // if 0 parameters, disable/enable all + if (params.empty()) // if no parameters, disable/enable all { for (device_t &device : device_enumerator(m_machine.root_device())) device.debug()->breakpoint_enable_all(enable); - if (!enable) - 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 - { - return; + m_console.printf(enable ? "Enabled all breakpoints\n" : "Disabled all breakpoints\n"); } - else + else // otherwise, disable/enable the specific ones { - bool found = false; - for (device_t &device : device_enumerator(m_machine.root_device())) - if (device.debug()->breakpoint_enable(bpindex, enable)) - { - found = true; - break; - } - 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)); + execute_index_command( + params, + [this, enable] (device_t &device, u64 param) -> bool + { + if (!device.debug()->breakpoint_enable(param, enable)) + return false; + m_console.printf(enable ? "Breakpoint %X enabled\n" : "Breakpoint %X disabled\n", param); + return true; + }, + "Invalid breakpoint number %X\n"); } } @@ -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> ¶ms) { - u64 wpindex; - - /* if 0 parameters, clear all */ - if (params.empty()) + if (params.empty()) // if no parameters, clear all { for (device_t &device : device_enumerator(m_machine.root_device())) device.debug()->watchpoint_clear_all(); m_console.printf("Cleared all watchpoints\n"); } - - /* otherwise, clear the specific one */ - else if (!validate_number_parameter(params[0], wpindex)) - return; - else + else // otherwise, clear the specific ones { - bool found = false; - for (device_t &device : device_enumerator(m_machine.root_device())) - if (device.debug()->watchpoint_clear(wpindex)) - found = true; - if (found) - m_console.printf("Watchpoint %X cleared\n", u32(wpindex)); - else - m_console.printf("Invalid watchpoint number %X\n", u32(wpindex)); + execute_index_command( + params, + [this] (device_t &device, u64 param) -> bool + { + if (!device.debug()->watchpoint_clear(param)) + return false; + m_console.printf("Watchpoint %X cleared\n", param); + return true; + }, + "Invalid watchpoint number %X\n"); } } @@ -1956,31 +1965,24 @@ void debugger_commands::execute_wpclear(const std::vector<std::string> ¶ms) void debugger_commands::execute_wpdisenable(bool enable, const std::vector<std::string> ¶ms) { - u64 wpindex; - - if (params.empty()) // if no parameters, clear all + if (params.empty()) // if no parameters, disable/enable all { for (device_t &device : device_enumerator(m_machine.root_device())) device.debug()->watchpoint_enable_all(enable); - if (!enable) - 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 - { - return; + m_console.printf(enable ? "Enabled all watchpoints\n" : "Disabled all watchpoints\n"); } - else + else // otherwise, disable/enable the specific ones { - bool found = false; - for (device_t &device : device_enumerator(m_machine.root_device())) - if (device.debug()->watchpoint_enable(wpindex, enable)) - found = true; - if (found) - m_console.printf("Watchpoint %X %s\n", u32(wpindex), enable ? "enabled" : "disabled"); - else - m_console.printf("Invalid watchpoint number %X\n", u32(wpindex)); + execute_index_command( + params, + [this, enable] (device_t &device, u64 param) -> bool + { + if (!device.debug()->watchpoint_enable(param, enable)) + return false; + m_console.printf(enable ? "Watchpoint %X enabled\n" : "Watchpoint %X disabled\n", param); + return true; + }, + "Invalid watchpoint number %X\n"); } } @@ -2070,9 +2072,9 @@ void debugger_commands::execute_rpset(const std::vector<std::string> ¶ms) if (params.size() > 1 && !debug_command_parameter_command(action = params[1].c_str())) return; - // set the breakpoint - int const bpnum = cpu->debug()->registerpoint_set(condition.original_string(), action); - m_console.printf("Registerpoint %X set\n", bpnum); + // set the registerpoint + int const rpnum = cpu->debug()->registerpoint_set(condition.original_string(), action); + m_console.printf("Registerpoint %X set\n", rpnum); } @@ -2083,29 +2085,24 @@ void debugger_commands::execute_rpset(const std::vector<std::string> ¶ms) void debugger_commands::execute_rpclear(const std::vector<std::string> ¶ms) { - u64 rpindex; - - /* if 0 parameters, clear all */ - if (params.empty()) + if (params.empty()) // if no parameters, clear all { for (device_t &device : device_enumerator(m_machine.root_device())) device.debug()->registerpoint_clear_all(); m_console.printf("Cleared all registerpoints\n"); } - - /* otherwise, clear the specific one */ - else if (!validate_number_parameter(params[0], rpindex)) - return; - else + else // otherwise, clear the specific ones { - bool found = false; - for (device_t &device : device_enumerator(m_machine.root_device())) - if (device.debug()->registerpoint_clear(rpindex)) - found = true; - if (found) - m_console.printf("Registerpoint %X cleared\n", u32(rpindex)); - else - m_console.printf("Invalid registerpoint number %X\n", u32(rpindex)); + execute_index_command( + params, + [this] (device_t &device, u64 param) -> bool + { + if (!device.debug()->registerpoint_clear(param)) + return false; + m_console.printf("Registerpoint %X cleared\n", param); + return true; + }, + "Invalid registerpoint number %X\n"); } } @@ -2117,31 +2114,24 @@ void debugger_commands::execute_rpclear(const std::vector<std::string> ¶ms) void debugger_commands::execute_rpdisenable(bool enable, const std::vector<std::string> ¶ms) { - u64 rpindex; - - if (params.empty()) // if no parameters, clear all + if (params.empty()) // if no parameters, disable/enable all { for (device_t &device : device_enumerator(m_machine.root_device())) device.debug()->registerpoint_enable_all(enable); - if (!enable) - 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 - { - return; + m_console.printf(enable ? "Enabled all registerpoints\n" : "Disabled all registerpoints\n"); } - else + else // otherwise, disable/enable the specific ones { - bool found = false; - for (device_t &device : device_enumerator(m_machine.root_device())) - if (device.debug()->registerpoint_enable(rpindex, enable)) - found = true; - if (found) - m_console.printf("Registerpoint %X %s\n", u32(rpindex), enable ? "enabled" : "disabled"); - else - m_console.printf("Invalid registerpoint number %X\n", u32(rpindex)); + execute_index_command( + params, + [this, enable] (device_t &device, u64 param) -> bool + { + if (!device.debug()->registerpoint_enable(param, enable)) + return false; + m_console.printf(enable ? "Registerpoint %X enabled\n" : "Breakpoint %X disabled\n", param); + return true; + }, + "Invalid registerpoint number %X\n"); } } @@ -2155,26 +2145,42 @@ void debugger_commands::execute_rplist(const std::vector<std::string> ¶ms) { int printed = 0; std::string buffer; - - /* loop over all CPUs */ - 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()) + auto const apply = + [this, &printed, &buffer] (device_t &device) { - buffer = string_format("%c%4X if %s", rp.enabled() ? ' ' : 'D', rp.index(), rp.condition()); - if (rp.action() != nullptr) - buffer.append(string_format(" do %s", rp.action())); - m_console.printf("%s\n", buffer); - printed++; - } - } + if (!device.debug()->registerpoint_list().empty()) + { + m_console.printf("Device '%s' registerpoints:\n", device.tag()); + + // loop over the registerpoints + 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 (printed == 0) - m_console.printf("No registerpoints currently installed\n"); + 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"); + } } diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h index 09e4b7ed7a1..0f85e80e705 100644 --- a/src/emu/debug/debugcmd.h +++ b/src/emu/debug/debugcmd.h @@ -99,6 +99,8 @@ private: void global_set(global_entry *global, u64 value); int mini_printf(char *buffer, const char *format, int params, u64 *param); + template <typename T> + void execute_index_command(std::vector<std::string> const ¶ms, T &&apply, char const *unused_message); void execute_help(const std::vector<std::string> ¶ms); void execute_print(const std::vector<std::string> ¶ms); diff --git a/src/emu/debug/debughlp.cpp b/src/emu/debug/debughlp.cpp index ef19f91c3a9..c62b7299ea7 100644 --- a/src/emu/debug/debughlp.cpp +++ b/src/emu/debug/debughlp.cpp @@ -154,9 +154,9 @@ const help_item f_static_help_list[] = "Type help <command> for further details on each command\n" "\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" - " bpdisable [<bpnum>] -- disables a given breakpoint or all if no <bpnum> specified\n" - " bpenable [<bpnum>] -- enables 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 given breakpoints 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" }, { @@ -169,9 +169,9 @@ const help_item f_static_help_list[] = " 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" " 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" - " wpdisable [<wpnum>] -- disables a given watchpoint or all if no <wpnum> specified\n" - " wpenable [<wpnum>] -- enables 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 given watchpoints 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" }, { @@ -180,11 +180,11 @@ const help_item f_static_help_list[] = "Registerpoint Commands\n" "Type help <command> for further details on each command\n" "\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" - " rpdisable [<rpnum>] -- disabled a given registerpoint or all if no <rpnum> specified\n" - " rpenable [<rpnum>] -- enables a given registerpoint or all if no <rpnum> specified\n" - " rplist -- lists all the registerpoints\n" + " rp[set] <condition>[,<action>] -- sets a registerpoint to trigger on <condition>\n" + " rpclear [<rpnum>[,...]] -- clears given registerpoints or all if no <rpnum> specified\n" + " rpdisable [<rpnum>[,...]] -- disabled given registerpoints or all if no <rpnum> specified\n" + " rpenable [<rpnum>[,...]] -- enables given registerpoints or all if no <rpnum> specified\n" + " rplist [<CPU>] -- lists all the registerpoints\n" }, { "expressions", @@ -1206,10 +1206,10 @@ const help_item f_static_help_list[] = { "bpclear", "\n" - " bpclear [<bpnum>]\n" + " bpclear [<bpnum>[,...]]\n" "\n" - "The bpclear command clears a breakpoint. If <bpnum> is specified, only the requested " - "breakpoint is cleared; otherwise all breakpoints are cleared.\n" + "The bpclear command clears breakpoints. If <bpnum> is specified, only the requested " + "breakpoints are cleared; otherwise all breakpoints are cleared.\n" "\n" "Examples:\n" "\n" @@ -1222,10 +1222,10 @@ const help_item f_static_help_list[] = { "bpdisable", "\n" - " bpdisable [<bpnum>]\n" + " bpdisable [<bpnum>,[...]]\n" "\n" - "The bpdisable command disables a breakpoint. If <bpnum> is specified, only the requested " - "breakpoint is disabled; otherwise all breakpoints are disabled. Note that disabling a " + "The bpdisable command disables breakpoints. If <bpnum> is specified, only the requested " + "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" "\n" "Examples:\n" @@ -1239,10 +1239,10 @@ const help_item f_static_help_list[] = { "bpenable", "\n" - " bpenable [<bpnum>]\n" + " bpenable [<bpnum>,[...]]\n" "\n" - "The bpenable command enables a breakpoint. If <bpnum> is specified, only the requested " - "breakpoint is enabled; otherwise all breakpoints are enabled.\n" + "The bpenable command enable breakpoints. If <bpnum> is specified, only the requested " + "breakpoints enabled; otherwise all breakpoints are enabled.\n" "\n" "Examples:\n" "\n" @@ -1331,10 +1331,10 @@ const help_item f_static_help_list[] = { "wpclear", "\n" - " wpclear [<wpnum>]\n" + " wpclear [<wpnum>[,...]]\n" "\n" - "The wpclear command clears a watchpoint. If <wpnum> is specified, only the requested " - "watchpoint is cleared; otherwise all watchpoints are cleared.\n" + "The wpclear command clears watchpoints. If <wpnum> is specified, only the requested " + "watchpoints are cleared; otherwise all watchpoints are cleared.\n" "\n" "Examples:\n" "\n" @@ -1347,10 +1347,10 @@ const help_item f_static_help_list[] = { "wpdisable", "\n" - " wpdisable [<wpnum>]\n" + " wpdisable [<wpnum>[,...]]\n" "\n" - "The wpdisable command disables a watchpoint. If <wpnum> is specified, only the requested " - "watchpoint is disabled; otherwise all watchpoints are disabled. Note that disabling a " + "The wpdisable command disables watchpoints. If <wpnum> is specified, only the requested " + "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" "\n" "Examples:\n" @@ -1364,10 +1364,10 @@ const help_item f_static_help_list[] = { "wpenable", "\n" - " wpenable [<wpnum>]\n" + " wpenable [<wpnum>[,...]]\n" "\n" - "The wpenable command enables a watchpoint. If <wpnum> is specified, only the requested " - "watchpoint is enabled; otherwise all watchpoints are enabled.\n" + "The wpenable command enables watchpoints. If <wpnum> is specified, only the requested " + "watchpoints are enabled; otherwise all watchpoints are enabled.\n" "\n" "Examples:\n" "\n" @@ -1401,26 +1401,26 @@ const help_item f_static_help_list[] = { "rpset", "\n" - " rp[set] {<condition>}[,<action>]]\n" + " rp[set] <condition>[,<action>]\n" "\n" - "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.\n" + "Sets a new registerpoint which will be triggered when <condition> is true (evaluates to a " + "non-zero value). The condition must be embedded in braces { } to prevent it from being " + "interpreted as an assignment.\n" "\n" - "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. Each registerpoint that is set is assigned an index which can be used in other " - "registerpoint commands to reference this registerpoint.\n" + "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. Each registerpoint that is set is assigned an index which can be used in " + "other registerpoint commands to reference this registerpoint.\n" "\n" "Examples:\n" "\n" - "rp {PC==0150}\n" - " Set a registerpoint that will halt execution whenever the PC register equals 0x150.\n" + "rp {PC==150}\n" + " Set a registerpoint that will halt execution whenever the PC register equals 150.\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 " - "equals 0x0150.\n" + "equals 150.\n" "\n" "rp {temp0==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", "\n" - " rpclear [<rpnum>]\n" + " rpclear [<rpnum>[,...]]\n" "\n" - "The rpclear command clears a registerpoint. If <rpnum> is specified, only the requested " - "registerpoint is cleared, otherwise all registerpoints are cleared.\n" + "The rpclear command clears registerpoints. If <rpnum> is specified, only the requested " + "registerpoints are cleared, otherwise all registerpoints are cleared.\n" "\n" "Examples:\n" "\n" "rpclear 3\n" - " Clear registerpoint index 3.\n" + " Clear the registerpoint with index 3.\n" "\n" "rpclear\n" " Clear all registerpoints.\n" @@ -1444,16 +1444,17 @@ const help_item f_static_help_list[] = { "rpdisable", "\n" - " rpdisable [<rpnum>]\n" + " rpdisable [<rpnum>[,...]]\n" "\n" - "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.\n" + "The rpdisable command disables registerpoints. If <rpnum> is specified, only the " + "requested registerpoints are disabled, otherwise all registerpoints are disabled. Note " + "that disabling a registerpoint does not delete it, it just temporarily marks the " + "registerpoint as inactive.\n" "\n" "Examples:\n" "\n" "rpdisable 3\n" - " Disable registerpoint index 3.\n" + " Disable the registerpoint with index 3.\n" "\n" "rpdisable\n" " Disable all registerpoints.\n" @@ -1461,15 +1462,15 @@ const help_item f_static_help_list[] = { "rpenable", "\n" - " rpenable [<rpnum>]\n" + " rpenable [<rpnum>[,...]]\n" "\n" - "The rpenable command enables a registerpoint. If <rpnum> is specified, only the requested " - "registerpoint is enabled, otherwise all registerpoints are enabled.\n" + "The rpenable command enables registerpoints. If <rpnum> is specified, only the requested " + "registerpoints are enabled, otherwise all registerpoints are enabled.\n" "\n" "Examples:\n" "\n" "rpenable 3\n" - " Enable registerpoint index 3.\n" + " Enable the registerpoint with index 3.\n" "\n" "rpenable\n" " Enable all registerpoints.\n" diff --git a/src/emu/debug/debugvw.cpp b/src/emu/debug/debugvw.cpp index 120152b3d5f..5bcc3d057b8 100644 --- a/src/emu/debug/debugvw.cpp +++ b/src/emu/debug/debugvw.cpp @@ -9,16 +9,20 @@ ***************************************************************************/ #include "emu.h" -#include "express.h" #include "debugvw.h" -#include "dvtext.h" -#include "dvstate.h" + +#include "debugcpu.h" +#include "dvbpoints.h" #include "dvdisasm.h" #include "dvmemory.h" -#include "dvbpoints.h" +#include "dvrpoints.h" +#include "dvstate.h" +#include "dvtext.h" #include "dvwpoints.h" -#include "debugcpu.h" +#include "express.h" + #include "debugger.h" + #include <cctype> @@ -362,6 +366,9 @@ debug_view *debug_view_manager::alloc_view(debug_view_type type, debug_view_osd_ case DVT_WATCH_POINTS: return append(new debug_view_watchpoints(machine(), osdupdate, osdprivate)); + case DVT_REGISTER_POINTS: + return append(new debug_view_registerpoints(machine(), osdupdate, osdprivate)); + default: fatalerror("Attempt to create invalid debug view type %d\n", type); } diff --git a/src/emu/debug/debugvw.h b/src/emu/debug/debugvw.h index 91c080bf07f..73f93d14f32 100644 --- a/src/emu/debug/debugvw.h +++ b/src/emu/debug/debugvw.h @@ -34,7 +34,8 @@ enum debug_view_type DVT_MEMORY, DVT_LOG, DVT_BREAK_POINTS, - DVT_WATCH_POINTS + DVT_WATCH_POINTS, + DVT_REGISTER_POINTS }; diff --git a/src/emu/debug/dvbpoints.cpp b/src/emu/debug/dvbpoints.cpp index 258d1dff020..b42b86a0e90 100644 --- a/src/emu/debug/dvbpoints.cpp +++ b/src/emu/debug/dvbpoints.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Aaron Giles +// copyright-holders:Andrew Gardner, Vas Crabb /********************************************************************* dvbpoints.cpp diff --git a/src/emu/debug/dvbpoints.h b/src/emu/debug/dvbpoints.h index 18419434c03..1bf365f521e 100644 --- a/src/emu/debug/dvbpoints.h +++ b/src/emu/debug/dvbpoints.h @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Aaron Giles +// copyright-holders:Andrew Gardner, Vas Crabb /********************************************************************* dvbpoints.h @@ -7,19 +7,15 @@ Breakpoint debugger view. ***************************************************************************/ - #ifndef MAME_EMU_DEBUG_DVBPOINTS_H #define MAME_EMU_DEBUG_DVBPOINTS_H #pragma once -#include "debugvw.h" #include "debugcpu.h" +#include "debugvw.h" - -//************************************************************************** -// CONSTANTS -//************************************************************************** +#include <vector> //************************************************************************** @@ -46,7 +42,6 @@ private: void pad_ostream_to_length(std::ostream& str, int len); void gather_breakpoints(); - // internal state bool (*m_sortType)(const debug_breakpoint *, const debug_breakpoint *); std::vector<const debug_breakpoint *> m_buffer; diff --git a/src/emu/debug/dvrpoints.cpp b/src/emu/debug/dvrpoints.cpp new file mode 100644 index 00000000000..3ecadaec8e5 --- /dev/null +++ b/src/emu/debug/dvrpoints.cpp @@ -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; + } + } + } +} diff --git a/src/emu/debug/dvrpoints.h b/src/emu/debug/dvrpoints.h new file mode 100644 index 00000000000..307ccbc212e --- /dev/null +++ b/src/emu/debug/dvrpoints.h @@ -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 diff --git a/src/emu/debug/dvwpoints.cpp b/src/emu/debug/dvwpoints.cpp index 76e74233988..21d3f30c5ca 100644 --- a/src/emu/debug/dvwpoints.cpp +++ b/src/emu/debug/dvwpoints.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Aaron Giles +// copyright-holders:Andrew Gardner, Vas Crabb /********************************************************************* dvwpoints.cpp @@ -10,6 +10,7 @@ #include "emu.h" #include "dvwpoints.h" + #include "points.h" #include <algorithm> diff --git a/src/emu/debug/dvwpoints.h b/src/emu/debug/dvwpoints.h index 753cbe62356..650a0aefad5 100644 --- a/src/emu/debug/dvwpoints.h +++ b/src/emu/debug/dvwpoints.h @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Aaron Giles +// copyright-holders:Andrew Gardner, Vas Crabb /********************************************************************* dvwpoints.h @@ -7,14 +7,13 @@ Watchpoint debugger view. ***************************************************************************/ - #ifndef MAME_EMU_DEBUG_DVWPOINTS_H #define MAME_EMU_DEBUG_DVWPOINTS_H #pragma once -#include "debugvw.h" #include "debugcpu.h" +#include "debugvw.h" //************************************************************************** diff --git a/src/emu/inpttype.ipp b/src/emu/inpttype.ipp index db3b83b1a3a..8ceaf873e62 100644 --- a/src/emu/inpttype.ipp +++ b/src/emu/inpttype.ipp @@ -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_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_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_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) ) \ diff --git a/src/frontend/mame/mame.h b/src/frontend/mame/mame.h index 037d714b39c..5fb5a2f4a81 100644 --- a/src/frontend/mame/mame.h +++ b/src/frontend/mame/mame.h @@ -92,5 +92,6 @@ private: extern const char build_version[]; extern const char bare_build_version[]; +extern const char bare_vcs_revision[]; #endif // MAME_FRONTEND_MAME_MAME_H diff --git a/src/frontend/mame/ui/about.cpp b/src/frontend/mame/ui/about.cpp index b55267d1b96..bac2c3b4bdc 100644 --- a/src/frontend/mame/ui/about.cpp +++ b/src/frontend/mame/ui/about.cpp @@ -1,21 +1,23 @@ // license:BSD-3-Clause -// copyright-holders:Ryan Holtz +// copyright-holders:Vas Crabb /*************************************************************************** ui/about.cpp - "About" modal + About box ***************************************************************************/ #include "emu.h" - #include "ui/about.h" + #include "ui/ui.h" #include "ui/utils.h" #include "mame.h" -#include "osdcore.h" + +#include <string_view> + namespace ui { @@ -25,10 +27,9 @@ namespace { } // anonymous namespace -/************************************************** - - ABOUT MODAL +/************************************************** + ABOUT BOX **************************************************/ @@ -38,6 +39,8 @@ namespace { menu_about::menu_about(mame_ui_manager &mui, render_container &container) : menu(mui, container) + , m_title(util::string_format(_("%1$s %2$s"), emulator_info::get_appname(), bare_build_version)) + , m_footer(util::string_format(_("Revision: %1$s"), bare_vcs_revision)) { } @@ -52,19 +55,174 @@ menu_about::~menu_about() //------------------------------------------------- -// populate - populates the about modal +// perform our special rendering //------------------------------------------------- -void menu_about::populate(float &customtop, float &custombottom) +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) { - std::string title = string_format(_("%1$s %2$s"), emulator_info::get_appname(), bare_build_version); - item_append(title, 0, nullptr); - item_append(menu_item_type::SEPARATOR); + 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; - for (char const *const *line = copying_text; *line; ++line) - item_append(*line, 0, nullptr); + ui().draw_outlined_box(container(), x1, y1, x2, y2, ui().colors().background_color()); - item_append(menu_item_type::SEPARATOR); + 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 +//------------------------------------------------- + +void menu_about::populate(float &customtop, float &custombottom) +{ + // make space for the title and revision + customtop = ui().get_line_height() + 3.0f * ui().box_tb_border(); + custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border(); } @@ -74,13 +232,35 @@ void menu_about::populate(float &customtop, float &custombottom) void menu_about::handle() { - // process the menu - const event *event = process(0); - - // process the event - if (event && (event->iptkey == IPT_UI_SELECT)) + const event *event = process(PROCESS_CUSTOM_NAV); + if (event) { - 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; + } } } diff --git a/src/frontend/mame/ui/about.h b/src/frontend/mame/ui/about.h index 2e68b7ed090..b96c7ee2055 100644 --- a/src/frontend/mame/ui/about.h +++ b/src/frontend/mame/ui/about.h @@ -1,10 +1,10 @@ // license:BSD-3-Clause -// copyright-holders:Ryan Holtz +// copyright-holders:Vas Crabb /*************************************************************************** ui/about.h - "About" modal + About box ***************************************************************************/ #ifndef MAME_FRONTEND_UI_ABOUT_H @@ -14,7 +14,9 @@ #include "ui/menu.h" -#include <vector> +#include <optional> +#include <string> + namespace ui { @@ -24,9 +26,17 @@ public: menu_about(mame_ui_manager &mui, render_container &container); 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: + virtual void draw(uint32_t flags) override; virtual void populate(float &customtop, float &custombottom) override; virtual void handle() override; + + std::string const m_title; + std::string const m_footer; + std::optional<text_layout> m_layout; }; } // namespace ui diff --git a/src/frontend/mame/ui/datmenu.cpp b/src/frontend/mame/ui/datmenu.cpp index f25ece6015a..d77d3510e00 100644 --- a/src/frontend/mame/ui/datmenu.cpp +++ b/src/frontend/mame/ui/datmenu.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Maurizio Petrarota +// copyright-holders:Maurizio Petrarota, Vas Crabb /********************************************************************* 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) { 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); } else @@ -278,10 +278,13 @@ void menu_dats_view::draw(uint32_t flags) if (!m_layout || (m_layout->width() != effective_width)) { std::string buffer; - if (m_issoft) - get_data_sw(buffer); - else - get_data(buffer); + if (!m_items_list.empty()) + { + if (m_issoft) + get_data_sw(buffer); + else + get_data(buffer); + } m_layout.emplace(ui().create_layout(container(), effective_width)); 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 container().add_line( - visible_left, separator + (0.5f * line_height), - visible_left + visible_width, separator + (0.5f * line_height), + 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); @@ -471,38 +474,41 @@ void menu_dats_view::custom_render(void *selectedref, float top, float bottom, f } // bottom - std::string const revision(util::string_format(_("Revision: %1$s"), m_items_list[m_actual].revision)); - ui().draw_text_full( - container(), - revision, - 0.0f, 0.0f, 1.0f, - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, - mame_ui_manager::NONE, rgb_t::white(), rgb_t::black(), - &width, nullptr); - width += 2 * lr_border; - maxwidth = std::max(origx2 - origx1, width); + if (!m_items_list.empty()) + { + std::string const revision(util::string_format(_("Revision: %1$s"), m_items_list[m_actual].revision)); + ui().draw_text_full( + container(), + revision, + 0.0f, 0.0f, 1.0f, + text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, + mame_ui_manager::NONE, rgb_t::white(), rgb_t::black(), + &width, nullptr); + width += 2 * lr_border; + maxwidth = std::max(origx2 - origx1, width); - // compute our bounds - x1 = 0.5f - 0.5f * maxwidth; - x2 = x1 + maxwidth; - y1 = origy2 + ui().box_tb_border(); - y2 = origy2 + bottom; + // compute our bounds + x1 = 0.5f - 0.5f * maxwidth; + x2 = x1 + maxwidth; + y1 = origy2 + ui().box_tb_border(); + y2 = origy2 + bottom; - // draw a box - ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_GREEN_COLOR); + // draw a box + ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_GREEN_COLOR); - // take off the borders - x1 += lr_border; - x2 -= lr_border; - y1 += ui().box_tb_border(); + // take off the borders + x1 += lr_border; + x2 -= lr_border; + y1 += ui().box_tb_border(); - // draw the text within it - ui().draw_text_full( - container(), - revision, - x1, y1, x2 - x1, - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, - mame_ui_manager::NORMAL, ui().colors().text_color(), ui().colors().text_bg_color()); + // draw the text within it + ui().draw_text_full( + container(), + revision, + x1, y1, x2 - x1, + text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, + mame_ui_manager::NORMAL, ui().colors().text_color(), ui().colors().text_bg_color()); + } } //------------------------------------------------- diff --git a/src/frontend/mame/ui/datmenu.h b/src/frontend/mame/ui/datmenu.h index 33e3d160b84..ccc8bd8b2a4 100644 --- a/src/frontend/mame/ui/datmenu.h +++ b/src/frontend/mame/ui/datmenu.h @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Maurizio Petrarota +// copyright-holders:Maurizio Petrarota, Vas Crabb /*************************************************************************** ui/datmenu.h @@ -76,4 +76,4 @@ private: } // namespace ui -#endif /* MAME_FRONTEND_UI_DATMENU_H */ +#endif // MAME_FRONTEND_UI_DATMENU_H diff --git a/src/frontend/mame/ui/selmenu.cpp b/src/frontend/mame/ui/selmenu.cpp index a66212c020b..303334de17b 100644 --- a/src/frontend/mame/ui/selmenu.cpp +++ b/src/frontend/mame/ui/selmenu.cpp @@ -855,18 +855,10 @@ void menu_select_launch::inkey_dats() ui_software_info const *software; ui_system_info const *system; get_selection(software, system); - if (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); - } + if (software && !software->startempty) + menu::stack_push<menu_dats_view>(ui(), container(), software); else if (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); - } + 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)); for (int z = 0; toolbar_count > z; ++z, x1 += x_spacing) { + auto const bitmap = toolbar_bitmaps[z]; x2 = x1 + x_size; color = rgb_t (0xffcccccc); if (mouse_in_rect(x1, y1, x2, y2)) { - set_hover(HOVER_B_FAV + toolbar_bitmaps[z]); - color = rgb_t::white(); + bool const need_selection = (TOOLBAR_BITMAP_FAVORITE == bitmap) || (TOOLBAR_BITMAP_INFO == bitmap); + 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(); ui().draw_text_box( container(), - _(hover_msg[toolbar_bitmaps[z]]), + _(hover_msg[bitmap]), text_layout::text_justify::CENTER, (x1 + x2) * 0.5f, ypos, ui().colors().background_color()); } container().add_quad( x1, y1, x2, y2, color, - m_cache.toolbar_textures()[toolbar_bitmaps[z]].get(), + m_cache.toolbar_textures()[bitmap].get(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); } } diff --git a/src/mame/drivers/apple2e.cpp b/src/mame/drivers/apple2e.cpp index 51524a2e4e8..aa6eb6eb452 100644 --- a/src/mame/drivers/apple2e.cpp +++ b/src/mame/drivers/apple2e.cpp @@ -1,5 +1,5 @@ -// copyright-holders:R. Belmont // license:BSD-3-Clause +// copyright-holders:R. Belmont /*************************************************************************** apple2e.cpp - Apple IIe/IIc/IIc Plus and clones diff --git a/src/osd/modules/debugger/osx/pointsviewer.mm b/src/osd/modules/debugger/osx/pointsviewer.mm index 8bd4dad3a1b..ca3d9b356a0 100644 --- a/src/osd/modules/debugger/osx/pointsviewer.mm +++ b/src/osd/modules/debugger/osx/pointsviewer.mm @@ -10,6 +10,7 @@ #import "pointsviewer.h" #import "breakpointsview.h" +#import "registerpointsview.h" #import "watchpointsview.h" #include "util/xmlfile.h" @@ -18,9 +19,9 @@ @implementation MAMEPointsViewer - (id)initWithMachine:(running_machine &)m console:(MAMEDebugConsole *)c { - MAMEDebugView *breakView, *watchView; - NSScrollView *breakScroll, *watchScroll; - NSTabViewItem *breakTab, *watchTab; + MAMEDebugView *breakView, *watchView, *registerView; + NSScrollView *breakScroll, *watchScroll, *registerScroll; + NSTabViewItem *breakTab, *watchTab, *registerTab; NSPopUpButton *actionButton; NSRect subviewFrame; @@ -44,6 +45,9 @@ [[[subviewButton menu] addItemWithTitle:@"All Watchpoints" action:NULL keyEquivalent:@""] setTag:1]; + [[[subviewButton menu] addItemWithTitle:@"All Registerpoints" + action:NULL + keyEquivalent:@""] setTag:2]; [subviewButton sizeToFit]; subviewFrame = [subviewButton frame]; subviewFrame.origin.x = subviewFrame.size.height; @@ -82,7 +86,7 @@ [breakTab setView:breakScroll]; [breakScroll release]; - // create the breakpoints view + // create the watchpoints view watchView = [[MAMEWatchpointsView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) machine:*machine]; watchScroll = [[NSScrollView alloc] initWithFrame:[breakScroll frame]]; @@ -98,6 +102,22 @@ [watchTab setView:watchScroll]; [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 tabs = [[NSTabView alloc] initWithFrame:[breakScroll frame]]; [tabs setTabViewType:NSNoTabsNoBorder]; @@ -106,6 +126,8 @@ [breakTab release]; [tabs addTabViewItem:watchTab]; [watchTab release]; + [tabs addTabViewItem:registerTab]; + [registerTab release]; [[window contentView] addSubview:tabs]; [tabs release]; @@ -124,8 +146,12 @@ hasHorizontalScroller:YES hasVerticalScroller:YES borderType:[watchScroll borderType]]; - NSSize const desired = NSMakeSize(std::max(breakDesired.width, watchDesired.width), - std::max(breakDesired.height, watchDesired.height)); + NSSize const registerDesired = [NSScrollView frameSizeForContentSize:[registerView maximumFrameSize] + 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]; // don't forget the result diff --git a/src/osd/modules/debugger/osx/registerpointsview.h b/src/osd/modules/debugger/osx/registerpointsview.h new file mode 100644 index 00000000000..58faf954416 --- /dev/null +++ b/src/osd/modules/debugger/osx/registerpointsview.h @@ -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 diff --git a/src/osd/modules/debugger/osx/registerpointsview.mm b/src/osd/modules/debugger/osx/registerpointsview.mm new file mode 100644 index 00000000000..a701fe733ce --- /dev/null +++ b/src/osd/modules/debugger/osx/registerpointsview.mm @@ -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 diff --git a/src/osd/modules/debugger/qt/breakpointswindow.cpp b/src/osd/modules/debugger/qt/breakpointswindow.cpp index 4f581137476..6af8fe7ba36 100644 --- a/src/osd/modules/debugger/qt/breakpointswindow.cpp +++ b/src/osd/modules/debugger/qt/breakpointswindow.cpp @@ -5,8 +5,6 @@ #include "debug/debugcon.h" #include "debug/debugcpu.h" -#include "debug/dvbpoints.h" -#include "debug/dvwpoints.h" #include <QtWidgets/QActionGroup> #include <QtWidgets/QHBoxLayout> @@ -48,16 +46,25 @@ BreakpointsWindow::BreakpointsWindow(running_machine &machine, QWidget *parent) // QActionGroup *typeGroup = new QActionGroup(this); typeGroup->setObjectName("typegroup"); + QAction *typeBreak = new QAction("Breakpoints", this); typeBreak->setObjectName("typebreak"); + typeBreak->setCheckable(true); + typeBreak->setActionGroup(typeGroup); + typeBreak->setShortcut(QKeySequence("Ctrl+1")); + QAction *typeWatch = new QAction("Watchpoints", this); typeWatch->setObjectName("typewatch"); - typeBreak->setCheckable(true); typeWatch->setCheckable(true); - typeBreak->setActionGroup(typeGroup); typeWatch->setActionGroup(typeGroup); - typeBreak->setShortcut(QKeySequence("Ctrl+1")); 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); 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); 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 QVBoxLayout *layout = findChild<QVBoxLayout *>("vlayout"); @@ -110,6 +122,8 @@ void BreakpointsWindowQtConfig::buildFromQWidget(QWidget *widget) m_bwType = 0; else if (typeGroup->checkedAction()->text() == "Watchpoints") m_bwType = 1; + else if (typeGroup->checkedAction()->text() == "Registerpoints") + m_bwType = 2; } diff --git a/src/osd/modules/debugger/win/debugwininfo.h b/src/osd/modules/debugger/win/debugwininfo.h index b930189fffa..80561dd2a05 100644 --- a/src/osd/modules/debugger/win/debugwininfo.h +++ b/src/osd/modules/debugger/win/debugwininfo.h @@ -97,6 +97,7 @@ protected: ID_SHOW_BREAKPOINTS, ID_SHOW_WATCHPOINTS, + ID_SHOW_REGISTERPOINTS, ID_CLEAR_LOG, diff --git a/src/osd/modules/debugger/win/pointswininfo.cpp b/src/osd/modules/debugger/win/pointswininfo.cpp index eb2ca1875e2..93926a697ae 100644 --- a/src/osd/modules/debugger/win/pointswininfo.cpp +++ b/src/osd/modules/debugger/win/pointswininfo.cpp @@ -31,6 +31,7 @@ pointswin_info::pointswin_info(debugger_windows_interface &debugger) : HMENU const optionsmenu = CreatePopupMenu(); 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_REGISTERPOINTS, TEXT("Registerpoints\tCtrl+3")); AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options")); // compute a client rect @@ -69,6 +70,10 @@ bool pointswin_info::handle_key(WPARAM wparam, LPARAM lparam) case '2': SendMessage(window(), WM_COMMAND, ID_SHOW_WATCHPOINTS, 0); 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()); 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_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"); recompute_children(); 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; } |