diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/emu/debug/debugcmd.cpp | 160 | ||||
-rw-r--r-- | src/emu/debug/debugcmd.h | 5 | ||||
-rw-r--r-- | src/emu/debug/debughlp.cpp | 257 | ||||
-rw-r--r-- | src/emu/debug/express.cpp | 292 | ||||
-rw-r--r-- | src/emu/softlist.cpp | 30 | ||||
-rw-r--r-- | src/emu/softlist.h | 3 | ||||
-rw-r--r-- | src/emu/softlist_dev.cpp | 6 | ||||
-rw-r--r-- | src/emu/softlist_dev.h | 2 | ||||
-rw-r--r-- | src/frontend/mame/clifront.cpp | 4 | ||||
-rw-r--r-- | src/frontend/mame/ui/menu.cpp | 65 | ||||
-rw-r--r-- | src/frontend/mame/ui/submenu.cpp | 26 | ||||
-rw-r--r-- | src/frontend/mame/ui/submenu.h | 3 |
12 files changed, 472 insertions, 381 deletions
diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index 1d2bf4e13b6..e7ca864988d 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -252,7 +252,7 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu 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("bplist", CMDFLAG_NONE, 0, 0, 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("wp", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, -1, _1)); @@ -265,7 +265,7 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu 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("wplist", CMDFLAG_NONE, 0, 0, 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("rp", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_rpset, this, _1)); @@ -337,8 +337,8 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu m_console.register_command("dasm", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_dasm, this, _1)); - m_console.register_command("trace", CMDFLAG_NONE, 1, 4, std::bind(&debugger_commands::execute_trace, this, _1)); - m_console.register_command("traceover", CMDFLAG_NONE, 1, 4, std::bind(&debugger_commands::execute_traceover, this, _1)); + m_console.register_command("trace", CMDFLAG_NONE, 1, 4, std::bind(&debugger_commands::execute_trace, this, _1, false)); + m_console.register_command("traceover", CMDFLAG_NONE, 1, 4, std::bind(&debugger_commands::execute_trace, this, _1, true)); m_console.register_command("traceflush",CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_traceflush, this, _1)); m_console.register_command("history", CMDFLAG_NONE, 0, 2, std::bind(&debugger_commands::execute_history, this, _1)); @@ -1816,29 +1816,45 @@ void debugger_commands::execute_bplist(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()->breakpoint_list().empty()) - { - m_console.printf("Device '%s' breakpoints:\n", device.tag()); - - /* loop over the breakpoints */ - for (const auto &bpp : device.debug()->breakpoint_list()) + auto const apply = + [this, &printed, &buffer] (device_t &device) { - debug_breakpoint &bp = *bpp.second; - buffer = string_format("%c%4X @ %0*X", bp.enabled() ? ' ' : 'D', bp.index(), device.debug()->logaddrchars(), bp.address()); - if (std::string(bp.condition()).compare("1") != 0) - buffer.append(string_format(" if %s", bp.condition())); - if (std::string(bp.action()).compare("") != 0) - buffer.append(string_format(" do %s", bp.action())); - m_console.printf("%s\n", buffer); - printed++; - } - } + if (!device.debug()->breakpoint_list().empty()) + { + m_console.printf("Device '%s' breakpoints:\n", device.tag()); - if (printed == 0) - m_console.printf("No breakpoints currently installed\n"); + // loop over the breakpoints + for (const auto &bpp : device.debug()->breakpoint_list()) + { + debug_breakpoint &bp = *bpp.second; + buffer = string_format("%c%4X @ %0*X", bp.enabled() ? ' ' : 'D', bp.index(), device.debug()->logaddrchars(), bp.address()); + if (std::string(bp.condition()).compare("1") != 0) + buffer.append(string_format(" if %s", bp.condition())); + if (std::string(bp.action()).compare("") != 0) + buffer.append(string_format(" do %s", bp.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 breakpoints 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 breakpoints currently installed\n"); + } } @@ -1977,35 +1993,57 @@ void debugger_commands::execute_wplist(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())) - for (int spacenum = 0; spacenum < device.debug()->watchpoint_space_count(); ++spacenum) - if (!device.debug()->watchpoint_vector(spacenum).empty()) + auto const apply = + [this, &printed, &buffer] (device_t &device) { - static const char *const types[] = { "unkn ", "read ", "write", "r/w " }; + for (int spacenum = 0; spacenum < device.debug()->watchpoint_space_count(); ++spacenum) + { + if (!device.debug()->watchpoint_vector(spacenum).empty()) + { + static const char *const types[] = { "unkn ", "read ", "write", "r/w " }; - m_console.printf("Device '%s' %s space watchpoints:\n", device.tag(), - device.debug()->watchpoint_vector(spacenum).front()->space().name()); + m_console.printf( + "Device '%s' %s space watchpoints:\n", + device.tag(), + device.debug()->watchpoint_vector(spacenum).front()->space().name()); - /* loop over the watchpoints */ - for (const auto &wp : device.debug()->watchpoint_vector(spacenum)) - { - buffer = string_format("%c%4X @ %0*X-%0*X %s", wp->enabled() ? ' ' : 'D', wp->index(), - wp->space().addrchars(), wp->address(), - wp->space().addrchars(), wp->address() + wp->length() - 1, - types[int(wp->type())]); - if (std::string(wp->condition()).compare("1") != 0) - buffer.append(string_format(" if %s", wp->condition())); - if (std::string(wp->action()).compare("") != 0) - buffer.append(string_format(" do %s", wp->action())); - m_console.printf("%s\n", buffer); - printed++; + // loop over the watchpoints + for (const auto &wp : device.debug()->watchpoint_vector(spacenum)) + { + buffer = string_format( + "%c%4X @ %0*X-%0*X %s", + wp->enabled() ? ' ' : 'D', wp->index(), + wp->space().addrchars(), wp->address(), + wp->space().addrchars(), wp->address() + wp->length() - 1, + types[int(wp->type())]); + if (std::string(wp->condition()).compare("1") != 0) + buffer.append(string_format(" if %s", wp->condition())); + if (std::string(wp->action()).compare("") != 0) + buffer.append(string_format(" do %s", wp->action())); + m_console.printf("%s\n", buffer); + printed++; + } + } } - } + }; - if (printed == 0) - m_console.printf("No watchpoints 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 watchpoints 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 watchpoints currently installed\n"); + } } @@ -3576,11 +3614,11 @@ void debugger_commands::execute_dasm(const std::vector<std::string> ¶ms) /*------------------------------------------------- - execute_trace_internal - functionality for + execute_trace - functionality for trace over and trace info -------------------------------------------------*/ -void debugger_commands::execute_trace_internal(const std::vector<std::string> ¶ms, bool trace_over) +void debugger_commands::execute_trace(const std::vector<std::string> ¶ms, bool trace_over) { const char *action = nullptr; bool detect_loops = true; @@ -3648,26 +3686,6 @@ void debugger_commands::execute_trace_internal(const std::vector<std::string> &p /*------------------------------------------------- - execute_trace - execute the trace command --------------------------------------------------*/ - -void debugger_commands::execute_trace(const std::vector<std::string> ¶ms) -{ - execute_trace_internal(params, false); -} - - -/*------------------------------------------------- - execute_traceover - execute the trace over command --------------------------------------------------*/ - -void debugger_commands::execute_traceover(const std::vector<std::string> ¶ms) -{ - execute_trace_internal(params, true); -} - - -/*------------------------------------------------- execute_traceflush - execute the trace flush command -------------------------------------------------*/ diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h index 6c389644df2..09e4b7ed7a1 100644 --- a/src/emu/debug/debugcmd.h +++ b/src/emu/debug/debugcmd.h @@ -100,8 +100,6 @@ private: int mini_printf(char *buffer, const char *format, int params, u64 *param); - void execute_trace_internal(const std::vector<std::string> ¶ms, bool trace_over); - void execute_help(const std::vector<std::string> ¶ms); void execute_print(const std::vector<std::string> ¶ms); void execute_printf(const std::vector<std::string> ¶ms); @@ -160,8 +158,7 @@ private: void execute_dasm(const std::vector<std::string> ¶ms); void execute_find(int spacenum, const std::vector<std::string> ¶ms); void execute_fill(int spacenum, const std::vector<std::string> ¶ms); - void execute_trace(const std::vector<std::string> ¶ms); - void execute_traceover(const std::vector<std::string> ¶ms); + void execute_trace(const std::vector<std::string> ¶ms, bool trace_over); void execute_traceflush(const std::vector<std::string> ¶ms); void execute_history(const std::vector<std::string> ¶ms); void execute_trackpc(const std::vector<std::string> ¶ms); diff --git a/src/emu/debug/debughlp.cpp b/src/emu/debug/debughlp.cpp index 322c760bbbb..13a0b2d1216 100644 --- a/src/emu/debug/debughlp.cpp +++ b/src/emu/debug/debughlp.cpp @@ -157,7 +157,7 @@ const help_item f_static_help_list[] = " 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" - " bplist -- lists all the breakpoints\n" + " bplist [<CPU>] -- lists all the breakpoints\n" }, { "watchpoints", @@ -172,7 +172,7 @@ const help_item f_static_help_list[] = " 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" - " wplist -- lists all the watchpoints\n" + " wplist [<CPU>] -- lists all the watchpoints\n" }, { "registerpoints", @@ -896,7 +896,7 @@ const help_item f_static_help_list[] = "Note that the step out functionality may not be implemented on all CPU types. If it is not " "implemented, then 'out' will behave exactly like 'step'.\n" "\n" - "Examples:\n" + "Example:\n" "\n" "out\n" " Steps until the current subroutine or exception handler returns.\n" @@ -920,35 +920,45 @@ const help_item f_static_help_list[] = " Resume execution, stopping at address 1234 unless something else stops us first.\n" }, { - "gvblank", + "gex", "\n" - " gv[blank]\n" + " ge[x] [<exception>,[<condition>]]\n" "\n" - "The gvblank command resumes execution of the current code. Control will not be returned to " - "the debugger until a breakpoint or watchpoint is hit, or until the next VBLANK occurs in the " - "emulator.\n" + "The gex command resumes execution of the current code. Control will not be returned to " + "the debugger until a breakpoint or watchpoint is hit, or until an exception condition " + "is raised on the current CPU. You can specify <exception> if you wish to stop execution " + "only on a particular exception condition occurring. If <exception> is omitted, then any " + "exception condition will stop execution. The optional <condition> parameter lets you " + "specify an expression that will be evaluated each time the specified exception condition " + "is raised. If the result of the expression is true (non-zero), the exception will halt " + "execution; otherwise, execution will continue with no notification.\n" "\n" "Examples:\n" "\n" - "gv\n" - " Resume execution until the next break/watchpoint or until the next VBLANK.\n" + "gex\n" + " Resume execution until the next break/watchpoint or until any exception condition is " + "raised on the current CPU.\n" + "\n" + "ge 2\n" + " Resume execution until the next break/watchpoint or until exception condition 2 is " + "raised on the current CPU.\n" }, { "gint", "\n" " gi[nt] [<irqline>]\n" "\n" - "The gint command resumes execution of the current code. Control will not be returned to the " - "debugger until a breakpoint or watchpoint is hit, or until an IRQ is asserted and acknowledged " - "on the current CPU. You can specify <irqline> if you wish to stop execution only on a particular " - "IRQ line being asserted and acknowledged. If <irqline> is omitted, then any IRQ line will stop " - "execution.\n" + "The gint command resumes execution of the current code. Control will not be returned to " + "the debugger until a breakpoint or watchpoint is hit, or until an IRQ is asserted and " + "acknowledged on the current CPU. You can specify <irqline> if you wish to stop execution " + "only on a particular IRQ line being asserted and acknowledged. If <irqline> is omitted, " + "then any IRQ line will stop execution.\n" "\n" "Examples:\n" "\n" "gi\n" - " Resume execution until the next break/watchpoint or until any IRQ is asserted and acknowledged " - "on the current CPU.\n" + " Resume execution until the next break/watchpoint or until any IRQ is asserted and " + "acknowledged on the current CPU.\n" "\n" "gint 4\n" " Resume execution until the next break/watchpoint or until IRQ line 4 is asserted and " @@ -968,13 +978,32 @@ const help_item f_static_help_list[] = " Resume execution for ten seconds\n" }, { + "gvblank", + "\n" + " gv[blank]\n" + "\n" + "The gvblank command resumes execution of the current code. Control will not be returned to " + "the debugger until a breakpoint or watchpoint is hit, or until the beginning of the " + " vertical blanking interval for an emulated screen.\n" + "\n" + "Example:\n" + "\n" + "gv\n" + " Resume execution until the next break/watchpoint or until the next VBLANK.\n" + }, + { "next", "\n" " n[ext]\n" "\n" "The next command resumes execution and continues executing until the next time a different " - "CPU is scheduled. Note that if you have used 'ignore' to ignore certain CPUs, you will not " - "stop until a non-'ignore'd CPU is scheduled.\n" + "CPU is scheduled. Note that if you have used 'focus' or 'ignore' to ignore certain CPUs, " + "execution will continue until a non-'ignore'd CPU is scheduled.\n" + "\n" + "Example:\n" + "\n" + "n\n" + " Resume execution, stopping when a different CPU that is not ignored is scheduled.\n" }, { "focus", @@ -988,21 +1017,25 @@ const help_item f_static_help_list[] = "\n" "focus 1\n" " Focus exclusively CPU #1 while ignoring all other CPUs when using the debugger.\n" + "\n" + "focus audiopcb:melodycpu\n" + " Focus exclusively on the CPU ':audiopcb:melodycpu'.\n" }, { "ignore", "\n" " ignore [<CPU>[,<CPU>[,...]]]\n" "\n" - "Ignores the specified <CPU> in the debugger. This means that you won't ever see execution " - "on that CPU, nor will you be able to set breakpoints on that CPU. To undo this change use " - "the 'observe' command. You can specify multiple <CPU>s in a single command. Note also that " - "you are not permitted to ignore all CPUs; at least one must be active at all times.\n" + "Ignores the specified CPUs in the debugger. CPUs can be specified by tag or debugger CPU " + "number. The debugger never shows execution for ignored CPUs, and breakpoints or " + "watchpoints on ignored CPUs have no effect. If no CPUs are specified, currently ignored " + "CPUs will be listed. Use the 'observe' command to stop ignoring a CPU. Note that you " + "cannot ignore all CPUs; at least CPU must be observed at all times.\n" "\n" "Examples:\n" "\n" - "ignore 1\n" - " Ignore CPU #1 when using the debugger.\n" + "ignore audiocpu\n" + " Ignore the CPU ':audiocpu' when using the debugger.\n" "\n" "ignore 2,3,4\n" " Ignore CPU #2, #3 and #4 when using the debugger.\n" @@ -1020,8 +1053,8 @@ const help_item f_static_help_list[] = "\n" "Examples:\n" "\n" - "observe 1\n" - " Stop ignoring CPU #1 when using the debugger.\n" + "observe audiocpu\n" + " Stop ignoring the CPU ':audiocpu' when using the debugger.\n" "\n" "observe 2,3,4\n" " Stop ignoring CPU #2, #3 and #4 when using the debugger.\n" @@ -1032,91 +1065,101 @@ const help_item f_static_help_list[] = { "trace", "\n" - " trace {<filename>|OFF}[,<CPU>[,[noloop|logerror][,<action>]]]\n" + " trace {<filename>|off}[,<CPU>[,[noloop|logerror][,<action>]]]\n" + "\n" + "Starts or stops tracing of the execution of the specified <CPU>, or the currently visible " + "CPU if no CPU is specified. To enable tracing, specify the trace log file name in the " + "<filename> parameter. To disable tracing, use the keyword 'off' for <filename> " + "parameter. If the **<filename>** begins with two right angle brackets (>>), it is treated " + "as a directive to open the file for appending rather than overwriting.\n" "\n" - "Starts or stops tracing of the execution of the specified <CPU>. If <CPU> is omitted, " - "the currently active CPU is specified. When enabling tracing, specify the filename in the " - "<filename> parameter. To disable tracing, substitute the keyword 'off' for <filename>. " - "<detectloops> should be either true or false. If 'noloop' is omitted, the trace " - "will have loops detected and condensed to a single line. If 'noloop' is specified, the trace " - "will contain every opcode as it is executed. If 'logerror' is specified, logerror output " - "will augment the trace. If you " - "wish to log additional information on each trace, you can append an <action> parameter which " - "is a command that is executed before each trace is logged. Generally, this is used to include " - "a 'tracelog' command. 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 trace command " - "itself.\n" + "The optional third parameter is a flags field. The supported flags are 'noloop' and " + "'logerror'. Multiple flags must be separated by | (pipe) characters. By default, loops " + "are detected and condensed to a single line. If the 'noloop' flag is specified, loops " + "will not be detected and every instruction will be logged as executed. If the 'logerror' " + "flag is specified, error log output will be included in the trace log.\n" + "\n" + "The optional <action> parameter is a debugger command to execute before each trace message " + "is logged. Generally, this will include a 'tracelog' or 'tracesym' command to include " + "additional information in the trace log. 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 trace command itself.\n" "\n" "Examples:\n" "\n" "trace joust.tr\n" - " Begin tracing the currently active CPU, logging output to joust.tr.\n" + " Begin tracing the execution of the currently visible CPU, logging output to joust.tr.\n" "\n" - "trace dribling.tr,0\n" - " Begin tracing the execution of CPU #0, logging output to dribling.tr.\n" + "trace dribling.tr,maincpu\n" + " Begin tracing the execution of the CPU ':maincpu', logging output to dribling.tr.\n" "\n" - "trace starswep.tr,0,noloop\n" - " Begin tracing the execution of CPU #0, logging output to starswep.tr, with loop detection disabled.\n" + "trace starswep.tr,,noloop\n" + " Begin tracing the execution of the currently visible CPU, logging output to starswep.tr, " + "with loop detection disabled.\n" "\n" - "trace starswep.tr,0,logerror\n" - " Begin tracing the execution of CPU #0, logging output (along with logerror output) to starswep.tr.\n" + "trace starswep.tr,1,logerror\n" + " Begin tracing the execution of CPU #1, logging output (along with logerror output) to " + "starswep.tr.\n" "\n" "trace starswep.tr,0,logerror|noloop\n" - " Begin tracing the execution of CPU #0, logging output (along with logerror output) to starswep.tr, with loop detection disabled.\n" + " Begin tracing the execution of CPU #0, logging output (along with logerror output) to " + "starswep.tr, with loop detection disabled.\n" "\n" "trace >>pigskin.tr\n" - " Begin tracing the currently active CPU, appending log output to pigskin.tr.\n" + " Begin tracing execution of the currently visible CPU, appending log output to " + "pigskin.tr.\n" "\n" "trace off,0\n" " Turn off tracing on CPU #0.\n" "\n" - "trace asteroid.tr,0,,{tracelog \"A=%02X \",a}\n" - " Begin tracing the execution of CPU #0, logging output to asteroid.tr. Before each line, " - "output A=<aval> to the tracelog.\n" + "trace asteroid.tr,,,{tracelog \"A=%02X \",a}\n" + " Begin tracing the execution of the currently visible CPU, logging output to asteroid.tr. " + "Before each line, output A=<aval> to the trace log.\n" }, { "traceover", "\n" - " traceover {<filename>|OFF}[,<CPU>[,<detectloops>[,<action>]]]\n" - "\n" - "Starts or stops tracing of the execution of the specified <CPU>. When tracing reaches " - "a subroutine or call, tracing will skip over the subroutine. The same algorithm is used as is " - "used in the step over command. This means that traceover will not work properly when calls " - "are recusive or the return address is not immediately following the call instruction. If " - "<detectloops> should be either true or false. If <detectloops> is true or omitted, the trace " - "will have loops detected and condensed to a single line. If it is false, the trace will contain " - "every opcode as it is executed. If <CPU> is omitted, the currently active CPU is specified. When " - "enabling tracing, specify the filename in the <filename> parameter. To disable tracing, substitute " - "the keyword 'off' for <filename>. If you wish to log additional information on each trace, you can " - "append an <action> parameter which is a command that is executed before each trace is logged. " - "Generally, this is used to include a 'tracelog' command. 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 trace command itself.\n" + " traceover {<filename>|off}[,<CPU>[,[noloop|logerror][,<action>]]]\n" + "\n" + "Starts or stops tracing for execution of the specified **<CPU>**, or the currently visible " + "CPU if no CPU is specified. When a subroutine call is encountered, tracing will skip over " + "the subroutine. The same algorithm is used as is used in the step over command. It will " + "not work properly with recursive functions, or if the return address does not immediately " + "follow the call instruction.\n" + "\n" + "This command accepts the same parameters as the 'trace' command. Please refer to the " + "corresponding section for a detailed description of options and more examples.\n" "\n" "Examples:\n" "\n" "traceover joust.tr\n" - " Begin tracing the currently active CPU, logging output to joust.tr.\n" + " Begin tracing the execution of the currently visible CPU, logging output to joust.tr.\n" "\n" - "traceover dribling.tr,0\n" - " Begin tracing the execution of CPU #0, logging output to dribling.tr.\n" + "traceover dribling.tr,maincpu\n" + " Begin tracing the execution of the CPU ':maincpu', logging output to dribling.tr.\n" "\n" - "traceover starswep.tr,0,false\n" - " Begin tracing the execution of CPU #0, logging output to starswep.tr, with loop detection disabled.\n" + "traceover starswep.tr,,noloop\n" + " Begin tracing the execution of the currently visible CPU, logging output to starswep.tr, " + "with loop detection disabled.\n" "\n" "traceover off,0\n" " Turn off tracing on CPU #0.\n" "\n" - "traceover asteroid.tr,0,true,{tracelog \"A=%02X \",a}\n" - " Begin tracing the execution of CPU #0, logging output to asteroid.tr. Before each line, " - "output A=<aval> to the tracelog.\n" + "traceover asteroid.tr,,,{tracelog \"A=%02X \",a}\n" + " Begin tracing the execution of the currently visible CPU, logging output to " + "asteroid.tr. Before each line, output A=<aval> to the trace log.\n" }, { "traceflush", "\n" " traceflush\n" "\n" - "Flushes all open trace files.\n" + "Flushes all open trace log files to disk.\n" + "\n" + "Example:\n" + "\n" + "traceflush\n" + " Flush trace log files.\n" }, { "bpset", @@ -1124,15 +1167,15 @@ const help_item f_static_help_list[] = " bp[set] <address>[:<CPU>][,<condition>[,<action>]]\n" "\n" "Sets a new execution breakpoint at the specified <address>. The <address> may optionally " - "be followed by a colon and the tag or debuggers CPU number to specify a CPU explicitly. " - "If no CPU is specified, the CPU currently visible in the debugger is assumed. The " - "optional <condition> parameter lets you specify an expression that will be evaluated each " - "time the breakpoint is hit. If the result of the expression is true (non-zero), the " - "breakpoint will halt execution; otherwise, execution will continue with no notification. " - "The optional <action> parameter provides a command that is executed whenever the " - "breakpoint is hit and the <condition> is true. 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 'bpset' command itself.\n" + "be followed by a colon and a tag or debugger CPU number to specify a CPU explicitly. If " + "no CPU is specified, the CPU currently visible in the debugger is assumed. The optional " + "<condition> parameter lets you specify an expression that will be evaluated each time the " + "breakpoint is hit. If the result of the expression is true (non-zero), the breakpoint " + "will halt execution; otherwise, execution will continue with no notification. The " + "optional <action> parameter provides a command that is executed whenever the breakpoint is " + "hit and the <condition> is true. 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 " + "'bpset' command itself.\n" "\n" "Each breakpoint that is set is assigned an index which can be used to refer to it in other " "breakpoint commands.\n" @@ -1212,10 +1255,23 @@ const help_item f_static_help_list[] = { "bplist", "\n" - " bplist\n" + " bplist [<CPU>]\n" + "\n" + "The bplist list current breakpoints, along with their indices and any associated " + "conditions or actions. If no <CPU> is specified, breakpoints for all CPUs in the system " + "will be listed; if a <CPU> is specified, only breakpoints for that CPU will be listed. " + "The <CPU> can be specified by tag or by debugger CPU number.\n" + "\n" + "Examples:\n" + "\n" + "bplist\n" + " List all breakpoints.\n" + "\n" + "bplist .\n" + " List all breakpoints for the visible CPU.\n" "\n" - "The bplist command lists all the current breakpoints, along with their indices and any " - "conditions or actions attached to them.\n" + "bplist maincpu\n" + " List all breakpoints for the CPU ':maincpu'.\n" }, { "wpset", @@ -1230,8 +1286,8 @@ const help_item f_static_help_list[] = "suffix sets the address space: 'wpset' defaults to the first address space exposed by the " "CPU, 'wpdset' defaults to the data space, 'wpiset' defaults to the I/O space, and 'wposet' " "defaults to the opcodes space. The <type> parameter specifies the access types to trap " - "on - it can be one of three values: 'r' for read accesses, 'w' for write accesses, and " - "'rw' for both read and write accesses.\n" + "on - it can be one of three values: 'r' for read accesses, 'w' for write accesses, or 'rw' " + "for both read and write accesses.\n" "\n" "The optional <condition> parameter lets you specify an expression that will be evaluated " "each time the watchpoint is triggered. If the result of the expression is true " @@ -1246,7 +1302,7 @@ const help_item f_static_help_list[] = "\n" "To make <condition> expressions more useful, two variables are available: for all " "watchpoints, the variable 'wpaddr' is set to the access address that triggered the " - "watchpoint; for write watchpoints, the variable 'wpdata' is set to the data that is being " + "watchpoint; for write watchpoints, the variable 'wpdata' is set to the data being " "written.\n" "\n" "Examples:\n" @@ -1324,10 +1380,23 @@ const help_item f_static_help_list[] = { "wplist", "\n" - " wplist\n" + " wplist [<CPU>]\n" + "\n" + "The wplist list current watchpoints, along with their indices and any associated " + "conditions or actions. If no <CPU> is specified, watchpoints for all CPUs in the system " + "will be listed; if a <CPU> is specified, only watchpoints for that CPU will be listed. " + "The <CPU> can be specified by tag or by debugger CPU number.\n" + "\n" + "Examples:\n" + "\n" + "wplist\n" + " List all watchpoints.\n" + "\n" + "wplist .\n" + " List all watchpoints for the visible CPU.\n" "\n" - "The wplist command lists all the current watchpoints, along with their indices and any " - "conditions or actions attached to them.\n" + "wplist maincpu\n" + " List all watchpoints for the CPU ':maincpu'.\n" }, { "rpset", diff --git a/src/emu/debug/express.cpp b/src/emu/debug/express.cpp index bc90ddaf52e..3e15ba29a5b 100644 --- a/src/emu/debug/express.cpp +++ b/src/emu/debug/express.cpp @@ -46,6 +46,7 @@ #include "logmacro.h" +namespace { /*************************************************************************** CONSTANTS @@ -103,7 +104,7 @@ enum //************************************************************************** -// TYPE DEFINITIONS +// REGISTER SYMBOL ENTRY //************************************************************************** // a symbol entry representing a register, with read/write callbacks @@ -116,8 +117,8 @@ public: integer_symbol_entry(symbol_table &table, const char *name, symbol_table::getter_func getter, symbol_table::setter_func setter, const std::string &format); // symbol access - virtual bool is_lval() const override; - virtual u64 value() const override; + virtual bool is_lval() const override { return m_setter != nullptr; } + virtual u64 value() const override { return m_getter(); } virtual void set_value(u64 newvalue) override; private: @@ -128,105 +129,6 @@ private: }; -// a symbol entry representing a function -class function_symbol_entry : public symbol_entry -{ -public: - // construction/destruction - function_symbol_entry(symbol_table &table, const char *name, int minparams, int maxparams, symbol_table::execute_func execute); - - // getters - u16 minparams() const { return m_minparams; } - u16 maxparams() const { return m_maxparams; } - - // symbol access - virtual bool is_lval() const override; - virtual u64 value() const override; - virtual void set_value(u64 newvalue) override; - - // execution helper - virtual u64 execute(int numparams, const u64 *paramlist); - -private: - // internal state - u16 m_minparams; - u16 m_maxparams; - symbol_table::execute_func m_execute; -}; - - - -//************************************************************************** -// EXPRESSION ERROR -//************************************************************************** - -//------------------------------------------------- -// code_string - return a friendly string for a -// given expression error -//------------------------------------------------- - -std::string expression_error::code_string() const -{ - switch (m_code) - { - case NOT_LVAL: return "not an lvalue"; - case NOT_RVAL: return "not an rvalue"; - case SYNTAX: return "syntax error"; - case UNKNOWN_SYMBOL: return "unknown symbol"; - case INVALID_NUMBER: return "invalid number"; - case INVALID_TOKEN: return "invalid token"; - case STACK_OVERFLOW: return "stack overflow"; - case STACK_UNDERFLOW: return "stack underflow"; - case UNBALANCED_PARENS: return "unbalanced parentheses"; - case DIVIDE_BY_ZERO: return "divide by zero"; - case OUT_OF_MEMORY: return "out of memory"; - case INVALID_PARAM_COUNT: return "invalid number of parameters"; - case TOO_FEW_PARAMS: return util::string_format("too few parameters (at least %d required)", m_num); - case TOO_MANY_PARAMS: return util::string_format("too many parameters (no more than %d accepted)", m_num); - case UNBALANCED_QUOTES: return "unbalanced quotes"; - case TOO_MANY_STRINGS: return "too many strings"; - case INVALID_MEMORY_SIZE: return "invalid memory size (b/w/d/q expected)"; - case NO_SUCH_MEMORY_SPACE: return "non-existent memory space"; - case INVALID_MEMORY_SPACE: return "invalid memory space (p/d/i/o/r/m expected)"; - case INVALID_MEMORY_NAME: return "invalid memory name"; - case MISSING_MEMORY_NAME: return "missing memory name"; - default: return "unknown error"; - } -} - - - -//************************************************************************** -// SYMBOL ENTRY -//************************************************************************** - -//------------------------------------------------- -// symbol_entry - constructor -//------------------------------------------------- - -symbol_entry::symbol_entry(symbol_table &table, symbol_type type, const char *name, const std::string &format) - : m_table(table), - m_type(type), - m_name(name), - m_format(format) -{ -} - - -//------------------------------------------------- -// ~symbol_entry - destructor -//------------------------------------------------- - -symbol_entry::~symbol_entry() -{ -} - - - -//************************************************************************** -// REGISTER SYMBOL ENTRY -//************************************************************************** - //------------------------------------------------- // integer_symbol_entry - constructor //------------------------------------------------- @@ -265,26 +167,6 @@ integer_symbol_entry::integer_symbol_entry(symbol_table &table, const char *name //------------------------------------------------- -// is_lval - is this symbol allowable as an lval? -//------------------------------------------------- - -bool integer_symbol_entry::is_lval() const -{ - return (m_setter != nullptr); -} - - -//------------------------------------------------- -// value - return the value of this symbol -//------------------------------------------------- - -u64 integer_symbol_entry::value() const -{ - return m_getter(); -} - - -//------------------------------------------------- // set_value - set the value of this symbol //------------------------------------------------- @@ -302,6 +184,33 @@ void integer_symbol_entry::set_value(u64 newvalue) // FUNCTION SYMBOL ENTRY //************************************************************************** +// a symbol entry representing a function +class function_symbol_entry : public symbol_entry +{ +public: + // construction/destruction + function_symbol_entry(symbol_table &table, const char *name, int minparams, int maxparams, symbol_table::execute_func execute); + + // getters + u16 minparams() const { return m_minparams; } + u16 maxparams() const { return m_maxparams; } + + // symbol access + virtual bool is_lval() const override { return false; } + virtual u64 value() const override; + virtual void set_value(u64 newvalue) override; + + // execution helper + virtual u64 execute(int numparams, const u64 *paramlist); + +private: + // internal state + u16 m_minparams; + u16 m_maxparams; + symbol_table::execute_func m_execute; +}; + + //------------------------------------------------- // function_symbol_entry - constructor //------------------------------------------------- @@ -316,16 +225,6 @@ function_symbol_entry::function_symbol_entry(symbol_table &table, const char *na //------------------------------------------------- -// is_lval - is this symbol allowable as an lval? -//------------------------------------------------- - -bool function_symbol_entry::is_lval() const -{ - return false; -} - - -//------------------------------------------------- // value - return the value of this symbol //------------------------------------------------- @@ -360,6 +259,102 @@ u64 function_symbol_entry::execute(int numparams, const u64 *paramlist) +/*************************************************************************** + INLINE FUNCTIONS +***************************************************************************/ + +inline std::pair<device_t &, char const *> get_device_search(running_machine &machine, device_memory_interface *memintf, char const *tag) +{ + if (tag) + { + if (('.' == tag[0]) && (!tag[1] || (':' == tag[1]) || ('^' == tag[1]))) + return std::pair<device_t &, char const *>(memintf ? memintf->device() : machine.root_device(), tag + ((':' == tag[1]) ? 2 : 1)); + else if (('^' == tag[0]) && memintf) + return std::pair<device_t &, char const *>(memintf->device(), tag); + else + return std::pair<device_t &, char const *>(machine.root_device(), tag); + } + else if (memintf) + { + return std::pair<device_t &, char const *>(memintf->device(), ""); + } + else + { + return std::pair<device_t &, char const *>(machine.root_device(), ""); + } +} + +} // anonymous namespace + + + +//************************************************************************** +// EXPRESSION ERROR +//************************************************************************** + +//------------------------------------------------- +// code_string - return a friendly string for a +// given expression error +//------------------------------------------------- + +std::string expression_error::code_string() const +{ + switch (m_code) + { + case NOT_LVAL: return "not an lvalue"; + case NOT_RVAL: return "not an rvalue"; + case SYNTAX: return "syntax error"; + case UNKNOWN_SYMBOL: return "unknown symbol"; + case INVALID_NUMBER: return "invalid number"; + case INVALID_TOKEN: return "invalid token"; + case STACK_OVERFLOW: return "stack overflow"; + case STACK_UNDERFLOW: return "stack underflow"; + case UNBALANCED_PARENS: return "unbalanced parentheses"; + case DIVIDE_BY_ZERO: return "divide by zero"; + case OUT_OF_MEMORY: return "out of memory"; + case INVALID_PARAM_COUNT: return "invalid number of parameters"; + case TOO_FEW_PARAMS: return util::string_format("too few parameters (at least %d required)", m_num); + case TOO_MANY_PARAMS: return util::string_format("too many parameters (no more than %d accepted)", m_num); + case UNBALANCED_QUOTES: return "unbalanced quotes"; + case TOO_MANY_STRINGS: return "too many strings"; + case INVALID_MEMORY_SIZE: return "invalid memory size (b/w/d/q expected)"; + case NO_SUCH_MEMORY_SPACE: return "non-existent memory space"; + case INVALID_MEMORY_SPACE: return "invalid memory space (p/d/i/o/r/m expected)"; + case INVALID_MEMORY_NAME: return "invalid memory name"; + case MISSING_MEMORY_NAME: return "missing memory name"; + default: return "unknown error"; + } +} + + + +//************************************************************************** +// SYMBOL ENTRY +//************************************************************************** + +//------------------------------------------------- +// symbol_entry - constructor +//------------------------------------------------- + +symbol_entry::symbol_entry(symbol_table &table, symbol_type type, const char *name, const std::string &format) + : m_table(table), + m_type(type), + m_name(name), + m_format(format) +{ +} + + +//------------------------------------------------- +// ~symbol_entry - destructor +//------------------------------------------------- + +symbol_entry::~symbol_entry() +{ +} + + + //************************************************************************** // SYMBOL TABLE //************************************************************************** @@ -551,17 +546,13 @@ expression_error symbol_table::expression_get_space(const char *tag, int &spacen if (tag) { // convert to lowercase then lookup the name (tags are enforced to be all lower case) - device_t *base; - if ((('^' == tag[0]) || (('.' == tag[0]) && ((':' == tag[1]) || !tag[1]))) && m_memintf) - base = &m_memintf->device(); - else - base = &m_machine.root_device(); - device = base->subdevice(strmakelower(tag)); + auto base = get_device_search(m_machine, m_memintf, tag); + device = base.first.subdevice(strmakelower(base.second)); // if that failed, treat the last component as an address space if (!device) { - std::string_view t = tag; + std::string_view t = base.second; auto const delimiter = t.find_last_of(":^"); bool const found = std::string_view::npos != delimiter; if (!found || (':' == t[delimiter])) @@ -569,7 +560,7 @@ expression_error symbol_table::expression_get_space(const char *tag, int &spacen spacename = strmakelower(t.substr(found ? (delimiter + 1) : 0)); t = t.substr(0, !found ? 0 : !delimiter ? 1 : delimiter); if (!t.empty()) - device = base->subdevice(strmakelower(t)); + device = base.first.subdevice(strmakelower(t)); else device = m_memintf ? &m_memintf->device() : &m_machine.root_device(); } @@ -740,11 +731,12 @@ u64 symbol_table::read_program_direct(address_space &space, int opcode, offs_t a u64 symbol_table::read_memory_region(const char *rgntag, offs_t address, int size) { - memory_region *region = m_machine.root_device().memregion(rgntag); + auto search = get_device_search(m_machine, m_memintf, rgntag); + memory_region *const region = search.first.memregion(search.second); u64 result = ~u64(0) >> (64 - 8*size); // make sure we get a valid base before proceeding - if (region != nullptr) + if (region) { // call ourself recursively until we are byte-sized if (size > 1) @@ -900,10 +892,11 @@ void symbol_table::write_program_direct(address_space &space, int opcode, offs_t void symbol_table::write_memory_region(const char *rgntag, offs_t address, int size, u64 data) { - memory_region *region = m_machine.root_device().memregion(rgntag); + auto search = get_device_search(m_machine, m_memintf, rgntag); + memory_region *const region = search.first.memregion(search.second); // make sure we get a valid base before proceeding - if (region != nullptr) + if (region) { // call ourself recursively until we are byte-sized if (size > 1) @@ -984,9 +977,16 @@ expression_error::error_code symbol_table::memory_valid(const char *name, expres case EXPSPACE_REGION: if (!name) + { return expression_error::MISSING_MEMORY_NAME; - if (!m_machine.root_device().memregion(name) || !m_machine.root_device().memregion(name)->base()) - return expression_error::INVALID_MEMORY_NAME; + } + else + { + auto search = get_device_search(m_machine, m_memintf, name); + memory_region *const region = search.first.memregion(search.second); + if (!region || !region->base()) + return expression_error::INVALID_MEMORY_NAME; + } break; default: diff --git a/src/emu/softlist.cpp b/src/emu/softlist.cpp index fe9d862ef1f..72f299c4c29 100644 --- a/src/emu/softlist.cpp +++ b/src/emu/softlist.cpp @@ -190,7 +190,6 @@ public: std::string_view filename, std::string &listname, std::string &description, - std::string ¬es, std::list<software_info> &infolist, std::ostream &errors); @@ -241,8 +240,8 @@ private: struct XML_ParserStruct * m_parser; std::string & m_listname; std::string & m_description; - std::string & m_notes; bool m_data_accum_expected; + bool m_ignore_cdata; std::string m_data_accum; software_info * m_current_info; software_part * m_current_part; @@ -259,7 +258,6 @@ softlist_parser::softlist_parser( std::string_view filename, std::string &listname, std::string &description, - std::string ¬es, std::list<software_info> &infolist, std::ostream &errors) : m_filename(filename), @@ -267,8 +265,8 @@ softlist_parser::softlist_parser( m_errors(errors), m_listname(listname), m_description(description), - m_notes(notes), m_data_accum_expected(false), + m_ignore_cdata(false), m_current_info(nullptr), m_current_part(nullptr), m_pos(POS_ROOT) @@ -488,6 +486,7 @@ void softlist_parser::end_handler(void *data, const char *name) // stop accumulating state->m_data_accum_expected = false; + state->m_ignore_cdata = false; state->m_data_accum.clear(); } @@ -500,7 +499,11 @@ void softlist_parser::data_handler(void *data, const char *s, int len) { softlist_parser *state = reinterpret_cast<softlist_parser *>(data); - if (state->m_data_accum_expected) + if (state->m_ignore_cdata) + { + // allowed, but we don't use it + } + else if (state->m_data_accum_expected) { // if we have an std::string to accumulate data in, do it state->m_data_accum.append(s, len); @@ -548,9 +551,9 @@ void softlist_parser::parse_root_start(const char *tagname, const char **attribu void softlist_parser::parse_main_start(const char *tagname, const char **attributes) { - // <software name='' cloneof='' supported=''> if (strcmp(tagname, "software") == 0) { + // <software name='' cloneof='' supported=''> static char const *const attrnames[] = { "name", "cloneof", "supported" }; auto attrvalues = parse_attributes(attributes, attrnames); @@ -562,10 +565,10 @@ void softlist_parser::parse_main_start(const char *tagname, const char **attribu else parse_error("No name defined for item"); } - // <notes> else if (strcmp(tagname, "notes") == 0) { - m_data_accum_expected = true; + // <notes> + m_ignore_cdata = true; } else unknown_tag(tagname); @@ -574,8 +577,6 @@ void softlist_parser::parse_main_start(const char *tagname, const char **attribu void softlist_parser::parse_main_end(const char *tagname) { - if (strcmp(tagname, "notes") == 0) - m_notes = std::move(m_data_accum); } @@ -607,7 +608,7 @@ void softlist_parser::parse_soft_start(const char *tagname, const char **attribu // <notes> else if (strcmp(tagname, "notes") == 0) - m_data_accum_expected = true; + m_ignore_cdata = true; // <info name='' value=''> else if (strcmp(tagname, "info") == 0) @@ -884,10 +885,6 @@ void softlist_parser::parse_soft_end(const char *tagname) else if (strcmp(tagname, "publisher") == 0) m_current_info->m_publisher = std::move(m_data_accum); - // <notes> - else if (strcmp(tagname, "notes") == 0) - m_current_info->m_notes = std::move(m_data_accum); - // </part> else if (strcmp(tagname, "part") == 0) { @@ -915,11 +912,10 @@ void parse_software_list( std::string_view filename, std::string &listname, std::string &description, - std::string ¬es, std::list<software_info> &infolist, std::ostream &errors) { - detail::softlist_parser(file, filename, listname, description, notes, infolist, errors); + detail::softlist_parser(file, filename, listname, description, infolist, errors); } diff --git a/src/emu/softlist.h b/src/emu/softlist.h index e8587dd4505..2fd755c29cc 100644 --- a/src/emu/softlist.h +++ b/src/emu/softlist.h @@ -133,7 +133,6 @@ public: const std::string &parentname() const { return m_parentname; } const std::string &year() const { return m_year; } const std::string &publisher() const { return m_publisher; } - const std::string ¬es() const { return m_notes; } const std::list<software_info_item> &info() const { return m_info; } const software_info_item::set &shared_features() const { return m_shared_features; } software_support supported() const { return m_supported; } @@ -151,7 +150,6 @@ private: std::string m_parentname; std::string m_year; // Copyright year on title screen, actual release dates can be tracked in external resources std::string m_publisher; - std::string m_notes; std::list<software_info_item> m_info; // Here we store info like developer, serial #, etc. which belong to the software entry as a whole software_info_item::set m_shared_features; // Here we store info like TV standard compatibility, or add-on requirements, etc. which get inherited // by each part of this software entry (after loading these are stored in partdata->features) @@ -167,7 +165,6 @@ void parse_software_list( std::string_view filename, std::string &listname, std::string &description, - std::string ¬es, std::list<software_info> &infolist, std::ostream &errors); diff --git a/src/emu/softlist_dev.cpp b/src/emu/softlist_dev.cpp index 7d7e1930089..7d25dd17013 100644 --- a/src/emu/softlist_dev.cpp +++ b/src/emu/softlist_dev.cpp @@ -89,8 +89,7 @@ software_list_device::software_list_device(const machine_config &mconfig, const m_list_type(softlist_type::ORIGINAL_SYSTEM), m_filter(nullptr), m_parsed(false), - m_description(""), - m_notes("") + m_description("") { } @@ -181,7 +180,6 @@ void software_list_device::release() m_filename.clear(); m_shortname.clear(); m_description.clear(); - m_notes.clear(); m_errors.clear(); m_infolist.clear(); } @@ -296,7 +294,7 @@ void software_list_device::parse() { // parse if no error std::ostringstream errs; - parse_software_list(file, m_filename, m_shortname, m_description, m_notes, m_infolist, errs); + parse_software_list(file, m_filename, m_shortname, m_description, m_infolist, errs); file.close(); m_errors = errs.str(); } diff --git a/src/emu/softlist_dev.h b/src/emu/softlist_dev.h index 2de72bd3b8f..e0e912a67f1 100644 --- a/src/emu/softlist_dev.h +++ b/src/emu/softlist_dev.h @@ -116,7 +116,6 @@ public: // getters that may trigger a parse const std::string &description() { if (!m_parsed) parse(); return m_description; } - const std::string ¬es() { if (!m_parsed) parse(); return m_notes; } bool valid() { if (!m_parsed) parse(); return !m_infolist.empty(); } const char *errors_string() { if (!m_parsed) parse(); return m_errors.c_str(); } const std::list<software_info> &get_info() { if (!m_parsed) parse(); return m_infolist; } @@ -153,7 +152,6 @@ private: std::string m_filename; std::string m_shortname; std::string m_description; - std::string m_notes; std::string m_errors; std::list<software_info> m_infolist; }; diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp index 191ae747a4c..19160cc9784 100644 --- a/src/frontend/mame/clifront.cpp +++ b/src/frontend/mame/clifront.cpp @@ -1118,8 +1118,6 @@ const char cli_frontend::s_softlist_xml_dtd[] = void cli_frontend::output_single_softlist(std::ostream &out, software_list_device &swlistdev) { util::stream_format(out, "\t<softwarelist name=\"%s\" description=\"%s\">\n", swlistdev.list_name(), util::xml::normalize_string(swlistdev.description().c_str())); - if (!swlistdev.notes().empty()) - util::stream_format(out, "\t\t<notes>%s</notes>\n", util::xml::normalize_string(swlistdev.notes().c_str())); for (const software_info &swinfo : swlistdev.get_info()) { util::stream_format(out, "\t\t<software name=\"%s\"", util::xml::normalize_string(swinfo.shortname().c_str())); @@ -1133,8 +1131,6 @@ void cli_frontend::output_single_softlist(std::ostream &out, software_list_devic util::stream_format(out, "\t\t\t<description>%s</description>\n", util::xml::normalize_string(swinfo.longname().c_str())); util::stream_format(out, "\t\t\t<year>%s</year>\n", util::xml::normalize_string(swinfo.year().c_str())); util::stream_format(out, "\t\t\t<publisher>%s</publisher>\n", util::xml::normalize_string(swinfo.publisher().c_str())); - if (!swinfo.notes().empty()) - util::stream_format(out, "\t\t\t<notes>%s</notes>\n", util::xml::normalize_string(swinfo.notes().c_str())); for (const auto &flist : swinfo.info()) util::stream_format(out, "\t\t\t<info name=\"%s\" value=\"%s\"/>\n", flist.name(), util::xml::normalize_string(flist.value().c_str())); diff --git a/src/frontend/mame/ui/menu.cpp b/src/frontend/mame/ui/menu.cpp index 14a5c4ae0c1..d3caec1b2c2 100644 --- a/src/frontend/mame/ui/menu.cpp +++ b/src/frontend/mame/ui/menu.cpp @@ -556,20 +556,31 @@ void menu::draw(uint32_t flags) float const line_y0 = visible_top + (float)linenum * line_height; float const line_y1 = line_y0 + line_height; + // work out what we're dealing with + bool const uparrow = !linenum && show_top_arrow; + bool const downarrow = (linenum == (m_visible_lines - 1)) && show_bottom_arrow; + // set the hover if this is our item - if (mouse_in_rect(line_x0, line_y0, line_x1, line_y1) && is_selectable(pitem)) - m_hover = itemnum; + bool const hovered = mouse_in_rect(line_x0, line_y0, line_x1, line_y1); + if (hovered) + { + if (uparrow) + m_hover = HOVER_ARROW_UP; + else if (downarrow) + m_hover = HOVER_ARROW_DOWN; + else if (is_selectable(pitem)) + m_hover = itemnum; + } - // if we're selected, draw with a different background if (is_selected(itemnum)) { + // if we're selected, draw with a different background fgcolor = fgcolor2 = fgcolor3 = ui().colors().selected_color(); bgcolor = ui().colors().selected_bg_color(); } - - // else if the mouse is over this item, draw with a different background - else if (itemnum == m_hover) + else if (hovered && (uparrow || downarrow || is_selectable(pitem))) { + // else if the mouse is over this item, draw with a different background fgcolor = fgcolor2 = fgcolor3 = ui().colors().mouseover_color(); bgcolor = ui().colors().mouseover_bg_color(); } @@ -578,7 +589,7 @@ void menu::draw(uint32_t flags) if (bgcolor != ui().colors().text_bg_color()) highlight(line_x0, line_y0, line_x1, line_y1, bgcolor); - if (linenum == 0 && show_top_arrow) + if (uparrow) { // if we're on the top line, display the up arrow draw_arrow( @@ -588,10 +599,8 @@ void menu::draw(uint32_t flags) line_y0 + 0.75f * line_height, fgcolor, ROT0); - if (m_hover == itemnum) - m_hover = HOVER_ARROW_UP; } - else if (linenum == m_visible_lines - 1 && show_bottom_arrow) + else if (downarrow) { // if we're on the bottom line, display the down arrow draw_arrow( @@ -601,8 +610,6 @@ void menu::draw(uint32_t flags) line_y0 + 0.75f * line_height, fgcolor, ROT0 ^ ORIENTATION_FLIP_Y); - if (m_hover == itemnum) - m_hover = HOVER_ARROW_DOWN; } else if (pitem.type == menu_item_type::SEPARATOR) { @@ -677,23 +684,25 @@ void menu::draw(uint32_t flags) // apply arrows if (is_selected(itemnum) && (pitem.flags & FLAG_LEFT_ARROW)) { + float const l = effective_left + effective_width - subitem_width - gutter_width; + float const r = l + lr_arrow_width; draw_arrow( - effective_left + effective_width - subitem_width - gutter_width, - line_y0 + 0.1f * line_height, - effective_left + effective_width - subitem_width - gutter_width + lr_arrow_width, - line_y0 + 0.9f * line_height, + l, line_y0 + 0.1f * line_height, r, line_y0 + 0.9f * line_height, fgcolor, ROT90 ^ ORIENTATION_FLIP_X); + if (mouse_in_rect(l, line_y0 + 0.1f * line_height, r, line_y0 + 0.9f * line_height)) + m_hover = HOVER_UI_LEFT; } if (is_selected(itemnum) && (pitem.flags & FLAG_RIGHT_ARROW)) { + float const r = effective_left + effective_width + gutter_width; + float const l = r - lr_arrow_width; draw_arrow( - effective_left + effective_width + gutter_width - lr_arrow_width, - line_y0 + 0.1f * line_height, - effective_left + effective_width + gutter_width, - line_y0 + 0.9f * line_height, + l, line_y0 + 0.1f * line_height, r, line_y0 + 0.9f * line_height, fgcolor, ROT90); + if (mouse_in_rect(l, line_y0 + 0.1f * line_height, r, line_y0 + 0.9f * line_height)) + m_hover = HOVER_UI_RIGHT; } } } @@ -856,13 +865,15 @@ void menu::handle_events(uint32_t flags, event &ev) if (custom_mouse_down()) return; - if ((flags & PROCESS_ONLYCHAR) == 0) + if (!(flags & PROCESS_ONLYCHAR)) { if (m_hover >= 0 && m_hover < m_items.size()) + { m_selected = m_hover; + } else if (m_hover == HOVER_ARROW_UP) { - if ((flags & FLAG_UI_DATS) != 0) + if (flags & FLAG_UI_DATS) { top_line -= m_visible_items - (last_item_visible() ? 1 : 0); return; @@ -884,6 +895,16 @@ void menu::handle_events(uint32_t flags, event &ev) m_selected = m_items.size() - 1; top_line += m_visible_lines - 2; } + else if (m_hover == HOVER_UI_LEFT) + { + ev.iptkey = IPT_UI_LEFT; + stop = true; + } + else if (m_hover == HOVER_UI_RIGHT) + { + ev.iptkey = IPT_UI_RIGHT; + stop = true; + } } break; diff --git a/src/frontend/mame/ui/submenu.cpp b/src/frontend/mame/ui/submenu.cpp index d6d237cabd3..382524b636c 100644 --- a/src/frontend/mame/ui/submenu.cpp +++ b/src/frontend/mame/ui/submenu.cpp @@ -152,9 +152,9 @@ submenu::submenu(mame_ui_manager &mui, render_container &container, std::vector< { core_options *opts = nullptr; if (m_driver == nullptr) - opts = dynamic_cast<core_options*>(&mui.machine().options()); + opts = dynamic_cast<core_options *>(&mui.machine().options()); else - opts = dynamic_cast<core_options*>(options); + opts = dynamic_cast<core_options *>(options); for (option & sm_option : m_options) { @@ -358,9 +358,9 @@ void submenu::populate(float &customtop, float &custombottom) { case OPTION_BOOLEAN: item_append_on_off(_(sm_option->description), - sm_option->options->bool_value(sm_option->name), - 0, - static_cast<void*>(&(*sm_option))); + sm_option->options->bool_value(sm_option->name), + 0, + static_cast<void*>(&(*sm_option))); break; case OPTION_INTEGER: { @@ -378,9 +378,9 @@ void submenu::populate(float &customtop, float &custombottom) } arrow_flags = get_arrow_flags(i_min, i_max, i_cur); item_append(_(sm_option->description), - sm_option->entry->value(), - arrow_flags, - static_cast<void*>(&(*sm_option))); + sm_option->entry->value(), + arrow_flags, + static_cast<void*>(&(*sm_option))); } break; case OPTION_FLOAT: @@ -400,9 +400,9 @@ void submenu::populate(float &customtop, float &custombottom) arrow_flags = get_arrow_flags(f_min, f_max, f_cur); std::string tmptxt = string_format("%g", f_cur); item_append(_(sm_option->description), - tmptxt, - arrow_flags, - static_cast<void*>(&(*sm_option))); + tmptxt, + arrow_flags, + static_cast<void*>(&(*sm_option))); } break; case OPTION_STRING: @@ -418,8 +418,8 @@ void submenu::populate(float &customtop, float &custombottom) default: arrow_flags = FLAG_RIGHT_ARROW; item_append(_(sm_option->description), - sm_option->options->value(sm_option->name), - arrow_flags, static_cast<void*>(&(*sm_option))); + sm_option->options->value(sm_option->name), + arrow_flags, static_cast<void*>(&(*sm_option))); break; } break; diff --git a/src/frontend/mame/ui/submenu.h b/src/frontend/mame/ui/submenu.h index 8c7744de391..f5c26c7eecb 100644 --- a/src/frontend/mame/ui/submenu.h +++ b/src/frontend/mame/ui/submenu.h @@ -12,9 +12,10 @@ #pragma once -#include "emuopts.h" #include "ui/menu.h" +#include "emuopts.h" + #include <string> #include <vector> |