diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/devices/cpu/m6502/st2205u.h | 2 | ||||
-rw-r--r-- | src/emu/debug/debugcmd.cpp | 69 | ||||
-rw-r--r-- | src/emu/debug/debugcpu.cpp | 37 | ||||
-rw-r--r-- | src/emu/debug/debugcpu.h | 10 | ||||
-rw-r--r-- | src/emu/debug/debughlp.cpp | 167 | ||||
-rw-r--r-- | src/emu/debug/express.cpp | 319 | ||||
-rw-r--r-- | src/emu/debug/express.h | 10 | ||||
-rw-r--r-- | src/frontend/mame/ui/ui.h | 2 |
8 files changed, 317 insertions, 299 deletions
diff --git a/src/devices/cpu/m6502/st2205u.h b/src/devices/cpu/m6502/st2205u.h index f414234fd7f..4182793a3bb 100644 --- a/src/devices/cpu/m6502/st2205u.h +++ b/src/devices/cpu/m6502/st2205u.h @@ -56,6 +56,8 @@ public: ST_LVCTR }; + static constexpr feature_type imperfect_features() { return feature::SOUND; } + protected: st2205u_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map, int data_bits, bool has_banked_ram); diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index 8bde2af72ea..1d2bf4e13b6 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -9,21 +9,25 @@ *********************************************************************/ #include "emu.h" -#include "emuopts.h" -#include "debugger.h" #include "debugcmd.h" + +#include "debugbuf.h" #include "debugcon.h" #include "debugcpu.h" -#include "debugbuf.h" -#include "express.h" #include "debughlp.h" #include "debugvw.h" +#include "express.h" #include "points.h" + +#include "debugger.h" +#include "emuopts.h" #include "natkeyboard.h" #include "render.h" + #include "corestr.h" -#include <cctype> + #include <algorithm> +#include <cctype> #include <fstream> @@ -2353,6 +2357,7 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string u64 i = 0; // now read the data in, ignore endoffset and load entire file if length has been set to zero (offset-1) + auto dis = space->device().machine().disable_side_effects(); switch (space->addr_shift()) { case -3: @@ -3479,7 +3484,8 @@ void debugger_commands::execute_fill(int spacenum, const std::vector<std::string void debugger_commands::execute_dasm(const std::vector<std::string> ¶ms) { - u64 offset, length, bytes = 1; + u64 offset, length; + bool bytes = true; address_space *space; // validate parameters @@ -3487,7 +3493,7 @@ void debugger_commands::execute_dasm(const std::vector<std::string> ¶ms) return; if (!validate_number_parameter(params[2], length)) return; - if (params.size() > 3 && !validate_number_parameter(params[3], bytes)) + if (params.size() > 3 && !validate_boolean_parameter(params[3], bytes)) return; if (!validate_device_space_parameter(params.size() > 4 ? params[4] : std::string_view(), AS_PROGRAM, space)) return; @@ -3523,11 +3529,11 @@ void debugger_commands::execute_dasm(const std::vector<std::string> ¶ms) topcodes.emplace_back(buffer.data_to_string(offset, size, true)); int osize = topcodes.back().size(); - if(osize > max_opcodes_size) + if (osize > max_opcodes_size) max_opcodes_size = osize; int dsize = instructions.back().size(); - if(dsize > max_disasm_size) + if (dsize > max_disasm_size) max_disasm_size = dsize; i += size; @@ -3544,7 +3550,7 @@ void debugger_commands::execute_dasm(const std::vector<std::string> ¶ms) if (bytes) { - for(unsigned int i=0; i != pcs.size(); i++) + for (unsigned int i=0; i != pcs.size(); i++) { const char *comment = space->device().debug()->comment_text(pcs[i]); if (comment) @@ -3555,7 +3561,7 @@ void debugger_commands::execute_dasm(const std::vector<std::string> ¶ms) } else { - for(unsigned int i=0; i != pcs.size(); i++) + for (unsigned int i=0; i != pcs.size(); i++) { const char *comment = space->device().debug()->comment_text(pcs[i]); if (comment) @@ -3678,8 +3684,8 @@ void debugger_commands::execute_traceflush(const std::vector<std::string> ¶m void debugger_commands::execute_history(const std::vector<std::string> ¶ms) { // validate parameters - address_space *space; - if (!validate_device_space_parameter(!params.empty() ? params[0] : std::string_view(), AS_PROGRAM, space)) + device_t *device; + if (!validate_cpu_parameter(!params.empty() ? params[0] : std::string_view(), device)) return; u64 count = device_debug::HISTORY_SIZE; @@ -3690,34 +3696,31 @@ void debugger_commands::execute_history(const std::vector<std::string> ¶ms) if (count > device_debug::HISTORY_SIZE) count = device_debug::HISTORY_SIZE; - device_execute_interface const *execute; - if (!space->device().interface(execute)) - { - m_console.printf("Device %s is not a CPU\n", space->device().name()); - return; - } - device_debug *const debug = space->device().debug(); + device_debug *const debug = device->debug(); - // loop over lines device_disasm_interface *dasmintf; - if (!space->device().interface(dasmintf)) + if (!device->interface(dasmintf)) { - m_console.printf("No disassembler available for device %s\n", space->device().name()); + m_console.printf("No disassembler available for device %s\n", device->name()); return; } - debug_disasm_buffer buffer(space->device()); - - for (int index = 0; index < (int) count; index++) + // loop over lines + debug_disasm_buffer buffer(*device); + std::string instruction; + for (int index = int(unsigned(count)); index > 0; index--) { - offs_t const pc = debug->history_pc(-index); - std::string instruction; - offs_t next_offset; - offs_t size; - u32 info; - buffer.disassemble(pc, instruction, next_offset, size, info); + auto const pc = debug->history_pc(1 - index); + if (pc.second) + { + offs_t next_offset; + offs_t size; + u32 info; + instruction.clear(); + buffer.disassemble(pc.first, instruction, next_offset, size, info); - m_console.printf("%s: %s\n", buffer.pc_to_string(pc), instruction); + m_console.printf("%s: %s\n", buffer.pc_to_string(pc.first), instruction); + } } } diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp index 04cce887484..403d0b104ee 100644 --- a/src/emu/debug/debugcpu.cpp +++ b/src/emu/debug/debugcpu.cpp @@ -434,6 +434,7 @@ device_debug::device_debug(device_t &device) , m_total_cycles(0) , m_last_total_cycles(0) , m_pc_history_index(0) + , m_pc_history_valid(0) , m_bplist() , m_rplist(std::make_unique<std::forward_list<debug_registerpoint>>()) , m_triggered_breakpoint(nullptr) @@ -722,7 +723,10 @@ void device_debug::instruction_hook(offs_t curpc) debugcpu.set_within_instruction(true); // update the history - m_pc_history[m_pc_history_index++ % HISTORY_SIZE] = curpc; + m_pc_history[m_pc_history_index] = curpc; + m_pc_history_index = (m_pc_history_index + 1) % std::size(m_pc_history); + if (std::size(m_pc_history) > m_pc_history_valid) + ++m_pc_history_valid; // update total cycles m_last_total_cycles = m_total_cycles; @@ -1352,13 +1356,28 @@ void device_debug::registerpoint_enable_all(bool enable) // history //------------------------------------------------- -offs_t device_debug::history_pc(int index) const +std::pair<offs_t, bool> device_debug::history_pc(int index) const { - if (index > 0) - index = 0; - if (index <= -HISTORY_SIZE) - index = -HISTORY_SIZE + 1; - return m_pc_history[(m_pc_history_index + std::size(m_pc_history) - 1 + index) % std::size(m_pc_history)]; + if ((index <= 0) && (-index < m_pc_history_valid)) + { + int const i = (m_pc_history_index + std::size(m_pc_history) - 1 + index) % std::size(m_pc_history); + return std::make_pair(m_pc_history[i], true); + } + else + { + return std::make_pair(offs_t(0), false); + } +} + + +//------------------------------------------------- +// set_track_pc - turn visited PC tracking on or +// off +//------------------------------------------------- + +void device_debug::set_track_pc(bool value) +{ + m_track_pc = value; } @@ -1369,7 +1388,7 @@ offs_t device_debug::history_pc(int index) const // TODO: Take a CPU context as input //------------------------------------------------- -bool device_debug::track_pc_visited(const offs_t& pc) const +bool device_debug::track_pc_visited(offs_t pc) const { if (m_track_pc_set.empty()) return false; @@ -1383,7 +1402,7 @@ bool device_debug::track_pc_visited(const offs_t& pc) const // TODO: Take a CPU context as input //------------------------------------------------- -void device_debug::set_track_pc_visited(const offs_t& pc) +void device_debug::set_track_pc_visited(offs_t pc) { const u32 crc = compute_opcode_crc32(pc); m_track_pc_set.insert(dasm_pc_tag(pc, crc)); diff --git a/src/emu/debug/debugcpu.h b/src/emu/debug/debugcpu.h index eba89367c2c..9e3d23d8d7f 100644 --- a/src/emu/debug/debugcpu.h +++ b/src/emu/debug/debugcpu.h @@ -14,6 +14,7 @@ #pragma once #include <set> +#include <utility> //************************************************************************** @@ -129,12 +130,12 @@ public: u32 compute_opcode_crc32(offs_t pc) const; // history - offs_t history_pc(int index) const; + std::pair<offs_t, bool> history_pc(int index) const; // pc tracking - void set_track_pc(bool value) { m_track_pc = value; } - bool track_pc_visited(const offs_t& pc) const; - void set_track_pc_visited(const offs_t& pc); + void set_track_pc(bool value); + bool track_pc_visited(offs_t pc) const; + void set_track_pc_visited(offs_t pc); void track_pc_data_clear() { m_track_pc_set.clear(); } // memory tracking @@ -200,6 +201,7 @@ private: // history offs_t m_pc_history[HISTORY_SIZE]; // history of recent PCs u32 m_pc_history_index; // current history index + u32 m_pc_history_valid; // number of valid PC history entries // breakpoints and watchpoints std::multimap<offs_t, std::unique_ptr<debug_breakpoint>> m_bplist; // list of breakpoints diff --git a/src/emu/debug/debughlp.cpp b/src/emu/debug/debughlp.cpp index ead08937c15..322c760bbbb 100644 --- a/src/emu/debug/debughlp.cpp +++ b/src/emu/debug/debughlp.cpp @@ -68,7 +68,7 @@ const help_item f_static_help_list[] = " logerror <format>[,<item>[,...]] -- outputs one or more <item>s to the error.log\n" " tracelog <format>[,<item>[,...]] -- outputs one or more <item>s to the trace file using <format>\n" " tracesym <item>[,...]] -- outputs one or more <item>s to the trace file\n" - " history [<CPU>,<length>] -- outputs a brief history of visited opcodes\n" + " history [<CPU>,[<length>]] -- outputs a brief history of visited opcodes\n" " trackpc [<bool>,[<CPU>,[<bool>]]] -- visually track visited opcodes [boolean to turn on and off, for CPU, clear]\n" " trackmem [<bool>,[<CPU>,[<bool>]]] -- record which PC writes to each memory address [boolean to turn on and off, for CPU, clear]\n" " pcatmem <address>[:<space>] -- query which PC wrote to a given memory address\n" @@ -391,21 +391,43 @@ const help_item f_static_help_list[] = "tracelog \"PC=%04X\",pc\n" " Outputs PC=<pcval> where <pcval> is displayed in hexadecimal with 4 digits with zero-fill.\n" "\n" - "printf \"A=%d, B=%d\\nC=%d\",a,b,a+b\n" + "tracelog \"A=%d, B=%d\\nC=%d\",a,b,a+b\n" " Outputs A=<aval>, B=<bval> on one line, and C=<a+bval> on a second line.\n" }, { "tracesym", "\n" " tracesym <item>[,...]\n" - "\n" - "The tracesym command prints the specified symbols and routes the output to the currently open trace " - "file (see the 'trace' command for details). If no file is currently open, tracesym does nothing. " - "\n" - "Examples:\n" - "\n" - "tracelog pc\n" - " Outputs PC=<pcval> where <pcval> is displayed in the default format.\n" + "\n" + "The tracesym command prints the specified symbols and routes the output to the currently open trace " + "file (see the 'trace' command for details). If no file is currently open, tracesym does nothing. " + "\n" + "Examples:\n" + "\n" + "tracesym pc\n" + " Outputs PC=<pcval> where <pcval> is displayed in the default format.\n" + }, + { + "history", + "\n" + " history [<CPU>,[<length>]]\n" + "\n" + "The history command displays recently visited PC addresses, and the disassembly of the " + "instructions at those addresses. If present, the first argument is a CPU selector " + "(either a tag or a CPU number); if no CPU is specified, the current CPU is assumed. " + "The second argument, if present, limits the maximum number of addresses shown. " + "Addresses are shown in order from least to most recently visited.\n" + "\n" + "Examples:\n" + "\n" + "history ,5\n" + " Displays up to five most recently visited PC addresses for the current CPU.\n" + "\n" + "history 3\n" + " Displays recently visited PC addresses for CPU 3.\n" + "\n" + "history audiocpu,1\n" + " Displays the most recently visited PC addresses for the CPU ':audiocpu'.\n" }, { "trackpc", @@ -445,20 +467,21 @@ const help_item f_static_help_list[] = " Begin tracking memory writes for the current CPU.\n" "\n" "trackmem 1, 0, 1\n" - " Continue tracking memory writes on CPU 0, but clear existing track info.\n" + " Continue tracking memory writes on CPU 0, but clear existing tracking data.\n" }, { "pcatmem", "\n" " pcatmem[{d|i|o}] <address>[:<space>]\n" "\n" - "The pcatmem command returns which PC wrote to a given memory address for the current CPU. " - "The argument is the requested address, optionally followed by a colon and a CPU and/or " - "address space. The CPU may be specified as a tag or debugger CPU number; if no CPU is " - "specified, the CPU currently visible in the debugger is assumed. If an address space is " - "not specified, the command suffix sets the address space: 'pcatmem' defaults to the first " - "space exposed by the device, 'pcatmemd' defaults to the data space, 'pcatmemi' defaults to " - "the I/O space, and 'pcatmemo' defaults to the opcodes space.\n" + "The pcatmem command returns which PC value at the time the specified address was most " + "recently written. The argument is the requested address, optionally followed by a colon " + "and a CPU and/or address space. The CPU may be specified as a tag or debugger CPU number; " + "if no CPU is specified, the CPU currently visible in the debugger is assumed. If an " + "address space is not specified, the command suffix sets the address space: 'pcatmem' " + "defaults to the first space exposed by the device, 'pcatmemd' defaults to the data space, " + "'pcatmemi' defaults to the I/O space, and 'pcatmemo' defaults to the opcodes space.\n" + "\n" "Right-clicking in a memory view will also display the logged PC for the given address.\n" "\n" "Examples:\n" @@ -521,22 +544,25 @@ const help_item f_static_help_list[] = { "snap", "\n" - " snap [[<filename>], <scrnum>]\n" + " snap [<filename>[,<scrnum>]]\n" "\n" - "The snap command takes a snapshot of the current video display and saves it to the configured " - "snapshot directory. If <filename> is specified explicitly, a single screenshot for <scrnum> is " - "saved under the requested filename. If <filename> is omitted, all screens are saved using the " - "same default rules as the \"save snapshot\" key in MAME proper.\n" + "Takes a snapshot of the emulated video display and saves it to the configured snapshot " + "directory. If a filename is specified, a single screenshot for the specified screen is " + "saved using the specified filename (or the first emulated screen in the system if a screen " + "is not specified). If a file name is not specified, the configured snapshot view and file " + "name pattern are used.\n" + "\n" + "If a file name is specified, the .png extension is automatically appended. The screen " + "number is specified as a zero-based index.\n" "\n" "Examples:\n" "\n" "snap\n" - " Takes a snapshot of the current video screen and saves to the next non-conflicting filename " - " in the configured snapshot directory.\n" + " Takes a snapshot using the configured snapshot view and file name options.\n" "\n" "snap shinobi\n" - " Takes a snapshot of the current video screen and saves it as 'shinobi.png' in the configured " - " snapshot directory.\n" + " Takes a snapshot of the first emulated video screen and saves it as 'shinobi.png' in the " + " configured snapshot directory.\n" }, { "source", @@ -595,15 +621,14 @@ const help_item f_static_help_list[] = "opcodes space.\n" "\n" "The <data> can either be a quoted string or a numeric value or expression or the wildcard " - "character '?'. By default, strings by default imply a byte-sized search; by default " - "non-string data is searched using the native word size of the address space. To override " - "the search size for non-string data, you can prefix values with b. to force byte-sized " - "search, w. for word-sized search, d. for dword-sized search, and q. for qword-sized " - "search. Overrides propagate to subsequent values, so if you want to search for a sequence " - "of words, you need only prefix the first value with a w. Also note that you can intermix " - "sizes to perform more complex searches. The entire range <address> through " - "<address>+<length>-1, inclusive, will be searched for the sequence, and all occurrences " - "will be displayed.\n" + "character '?'. By default, strings imply a byte-sized search; by default non-string data " + "is searched using the native word size of the address space. To override the search size " + "for non-string data, you can prefix values with b. to force byte-sized search, w. for " + "word-sized search, d. for dword-sized search, and q. for qword-sized search. Overrides " + "propagate to subsequent values, so if you want to search for a sequence of words, you need " + "only prefix the first value with a w. Also note that you can intermix sizes to perform " + "more complex searches. The entire range <address> through <address>+<length>-1, " + "inclusive, will be searched for the sequence, and all occurrences will be displayed.\n" "\n" "Examples:\n" "\n" @@ -613,7 +638,7 @@ const help_item f_static_help_list[] = "\n" "find 300:tms9918a,100,w.abcd,4567\n" " Searches the address range 300-3ff in the first address space exposed by the device " - "':tms9918a' memory for the word-sized value abcd followed by the word-sized value 4567.\n" + "':tms9918a' for the word-sized value abcd followed by the word-sized value 4567.\n" "\n" "find 0,8000,\"AAR\",d.0,\"BEN\",w.0\n" " Searches the address range 0000-7fff for the string \"AAR\" followed by a dword-sized 0 " @@ -640,7 +665,7 @@ const help_item f_static_help_list[] = "non-string data is written using the native word size of the address space. To override " "the data size for non-string data, you can prefix values with b. to force byte-sized fill, " "w. for word-sized fill, d. for dword-sized fill, and q. for qword-sized fill. Overrides " - "propagate to subsequent value, so if you want to fill with a series of words, you need " + "propagate to subsequent values, so if you want to fill with a series of words, you need " "only prefix the first value with a w. Also note that you can intermix sizes to perform " "more complex fills. The fill operation may be truncated if a page fault occurs or if part " "of the sequence or string would fall beyond <address>+<length>-1.\n" @@ -750,10 +775,14 @@ const help_item f_static_help_list[] = "saving from, and the <length> specifies how much memory to save. The range <address> " "through <address>+<length>-1, inclusive, will be output to the file.\n" "\n" - "Example:\n" + "Examples:\n" "\n" - "saver harddriv.bin,80000,40000,:maincpu\n" - " Saves :maincpu region addresses 80000-bffff to the binary file 'harddriv.bin'.\n" + "saver data.bin,200,100,:monitor\n" + " Saves ':monitor' region addresses 200-2ff to the binary file 'data.bin'.\n" + "\n" + "saver cpurom.bin,1000,400,.\n" + " Saves addresses 1000-13ff from the memory region with the same tag as the visible CPU to " + "the binary file 'cpurom.bin'.\n" }, { "load", @@ -773,8 +802,10 @@ const help_item f_static_help_list[] = "file. If the <length> is omitted, if it is zero, or if it is greater than the total " "length of the file, the entire contents of the file will be loaded but no more.\n" "\n" - "NOTE: This will only actually write memory that is possible to overwrite via a memory " - "view.\n" + "NOTE: this has the same effect as writing to the address space from a debugger memory " + "view, or using memory accessors in debugger expressions. Read-only memory will not be " + "overwritten, and writing to I/O addresses may have effects beyond setting register " + "values.\n" "\n" "Examples:\n" "\n" @@ -797,16 +828,20 @@ const help_item f_static_help_list[] = " loadr <filename>,<address>,<length>,<region>\n" "\n" "The loadr command loads raw memory in the memory region <region> from the binary file " - "specified in the <filename> parameter. The <address> indicates the address to start " + "specified by the <filename> parameter. The <address> specifies the address to start " "loading to, and the <length> specifies how much memory to load. The range <address> " "through <address>+<length>-1, inclusive, will be read in from the file. If the <length> " "is zero, or is greater than the total length of the file, the entire contents of the file " "will be loaded but no more.\n" "\n" - "Example:\n" + "Examples:\n" + "\n" + "loadr data.bin,200,100,:monitor\n" + " Loads ':monitor' region addresses 200-2ff from the binary file 'data.bin'.\n" "\n" - "loadr harddriv.bin,80000,40000,:maincpu\n" - " Loads addresses 80000-bffff in the :maincpu region from the binary file 'harddriv.bin'.\n" + "loadr cpurom.bin,1000,400,.\n" + " Loads addresses 1000-13ff in the memory region with the same tag as the visible CPU from " + "the binary file 'cpurom.bin'.\n" }, { "step", @@ -1384,22 +1419,22 @@ const help_item f_static_help_list[] = " map[{d|i|o}] <address>[:<space>]\n" "\n" "The map commands map a logical memory address to the corresponding physical address, as " - "well as specifying the bank. The address may optionally be followed by a colon and device " - "and/or address space. The device may be specified as a tag or a debugger CPU number; if " - "no device is specified, the CPU currently visible in the debugger is assumed. If an " - "address space is not specified, the command suffix sets the address space: 'map' defaults " - "to the first address space exposed by the device, 'mapd' defaults to the data space, " - "'mapi' defaults to the I/O space, and 'mapo' defaults to the opcodes space.\n" + "well as reporting the handler name. The address may optionally be followed by a colon " + "and device and/or address space. The device may be specified as a tag or a debugger CPU " + "number; if no device is specified, the CPU currently visible in the debugger is assumed. " + "If an address space is not specified, the command suffix sets the address space: 'map' " + "defaults to the first address space exposed by the device, 'mapd' defaults to the data " + "space, 'mapi' defaults to the I/O space, and 'mapo' defaults to the opcodes space.\n" "\n" - "Example:\n" + "Examples:\n" "\n" "map 152d0\n" - " Gives physical address and bank for logical address 152d0 in program memory for the " - "currently visible CPU.\n" + " Gives physical address and handler name for logical address 152d0 in program memory for " + "the currently visible CPU.\n" "\n" "map 107:sms_vdp\n" - " Gives physical address and bank for logical address 107 in the first address space for " - "the device ':sms_vdp'.\n" + " Gives physical address and handler name for logical address 107 in the first address " + "space for the device ':sms_vdp'.\n" }, { "mapd", "#map" }, { "mapi", "#map" }, @@ -1410,20 +1445,24 @@ const help_item f_static_help_list[] = " memdump [<filename>,[<device>]]\n" "\n" "Dumps the current memory maps to the file specified by <filename>, or memdump.log if " - "omitted. If <device> is specified it must be the tag of a device, and only memory maps " - "for the part of the device tree rooted on this device will be dumped.\n" + "omitted. If <device> is specified, only memory maps for the part of the device tree " + "rooted at this device will be dumped. Devices may be specified using tags or CPU " + "numbers.\n" "\n" "Examples:\n" "\n" "memdump mylog.log\n" - " Dumps all memory maps to the file mylog.log.\n" + " Dumps memory maps for all devices in the system to the file mylog.log.\n" "\n" "memdump\n" - " Dumps all memory maps to the file memdump.log.\n" + " Dumps memory maps for all devices in the system to the file memdump.log.\n" "\n" "memdump audiomaps.log,audiopcb\n" " Dumps memory maps for device ':audiopcb' and all its child devices to the file " "audiomaps.log.\n" + "\n" + "memdump mylog.log,1\n" + " Dumps memory maps for the CPU 1 and all its child devices to the file mylog.log.\n" }, { "comlist", @@ -1466,10 +1505,10 @@ const help_item f_static_help_list[] = "Examples:\n" "\n" "commit 0, hello world.\n" - " Adds the comment 'hello world.' to the code at address 0x0\n" + " Adds the comment 'hello world.' to the code at address 0x0 and saves comments\n" "\n" "/* 10, undocumented opcode!\n" - " Adds the comment 'undocumented opcode!' to the code at address 0x10\n" + " Adds the comment 'undocumented opcode!' to the code at address 0x10 and saves comments\n" "\n" }, { diff --git a/src/emu/debug/express.cpp b/src/emu/debug/express.cpp index c4b2662e3bb..bc90ddaf52e 100644 --- a/src/emu/debug/express.cpp +++ b/src/emu/debug/express.cpp @@ -540,14 +540,73 @@ void symbol_table::write_memory(address_space &space, offs_t address, u64 data, //------------------------------------------------- -// expression_get_device - return a device +// expression_get_space - return a space // based on a case insensitive tag search //------------------------------------------------- -device_t *symbol_table::expression_get_device(const char *tag) +expression_error symbol_table::expression_get_space(const char *tag, int &spacenum, device_memory_interface *&memory) { - // convert to lowercase then lookup the name (tags are enforced to be all lower case) - return m_machine.root_device().subdevice(strmakelower(tag)); + device_t *device = nullptr; + std::string spacename; + if (tag) + { + // convert to lowercase then lookup the name (tags are enforced to be all lower case) + device_t *base; + if ((('^' == tag[0]) || (('.' == tag[0]) && ((':' == tag[1]) || !tag[1]))) && m_memintf) + base = &m_memintf->device(); + else + base = &m_machine.root_device(); + device = base->subdevice(strmakelower(tag)); + + // if that failed, treat the last component as an address space + if (!device) + { + std::string_view t = tag; + auto const delimiter = t.find_last_of(":^"); + bool const found = std::string_view::npos != delimiter; + if (!found || (':' == t[delimiter])) + { + spacename = strmakelower(t.substr(found ? (delimiter + 1) : 0)); + t = t.substr(0, !found ? 0 : !delimiter ? 1 : delimiter); + if (!t.empty()) + device = base->subdevice(strmakelower(t)); + else + device = m_memintf ? &m_memintf->device() : &m_machine.root_device(); + } + } + } + else if (m_memintf) + { + device = &m_memintf->device(); + } + + // if still no device, report error + if (!device) + { + memory = nullptr; + return expression_error::INVALID_MEMORY_NAME; + } + + // ensure device has memory interface, and check for space if search not required + if (!device->interface(memory) || (spacename.empty() && (0 <= spacenum) && !memory->has_space(spacenum))) + { + memory = nullptr; + return expression_error::NO_SUCH_MEMORY_SPACE; + } + + // find space by name or take first populated space + for (int i = 0; memory->max_space_count() > i; ++i) + { + if (memory->has_space(i) && (spacename.empty() || (memory->space(i).name() == spacename))) + { + spacenum = i; + return expression_error::NONE; + } + } + + // space not found + memory = nullptr; + return expression_error::NO_SUCH_MEMORY_SPACE; } @@ -574,76 +633,45 @@ u64 symbol_table::memory_value(const char *name, expression_space spacenum, u32 { device_memory_interface *memory = m_memintf; + bool logical = true; + int space = -1; switch (spacenum) { - case EXPSPACE_PROGRAM_LOGICAL: - case EXPSPACE_DATA_LOGICAL: - case EXPSPACE_IO_LOGICAL: - case EXPSPACE_SPACE3_LOGICAL: - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory != nullptr && memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL))) - { - address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL)); - auto dis = m_machine.disable_side_effects(disable_se); - return read_memory(space, address, size, true); - } - break; - case EXPSPACE_PROGRAM_PHYSICAL: case EXPSPACE_DATA_PHYSICAL: case EXPSPACE_IO_PHYSICAL: - case EXPSPACE_SPACE3_PHYSICAL: - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL))) - { - address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL)); - auto dis = m_machine.disable_side_effects(disable_se); - return read_memory(space, address, size, false); - } - break; - - case EXPSPACE_RAMWRITE: - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory != nullptr && memory->has_space(AS_PROGRAM)) + case EXPSPACE_OPCODE_PHYSICAL: + spacenum = expression_space(spacenum - (EXPSPACE_PROGRAM_PHYSICAL - EXPSPACE_PROGRAM_LOGICAL)); + logical = false; + [[fallthrough]]; + case EXPSPACE_PROGRAM_LOGICAL: + case EXPSPACE_DATA_LOGICAL: + case EXPSPACE_IO_LOGICAL: + case EXPSPACE_OPCODE_LOGICAL: + space = AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL); + expression_get_space(name, space, memory); + if (memory) { auto dis = m_machine.disable_side_effects(disable_se); - return read_program_direct(memory->space(AS_PROGRAM), (spacenum == EXPSPACE_OPCODE), address, size); + return read_memory(memory->space(space), address, size, logical); } break; - case EXPSPACE_OPCODE: - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory != nullptr && memory->has_space(AS_OPCODES)) + case EXPSPACE_PRGDIRECT: + case EXPSPACE_OPDIRECT: + space = (spacenum == EXPSPACE_OPDIRECT) ? AS_OPCODES : AS_PROGRAM; + expression_get_space(name, space, memory); + if (memory) { auto dis = m_machine.disable_side_effects(disable_se); - return read_program_direct(memory->space(AS_OPCODES), (spacenum == EXPSPACE_OPCODE), address, size); + return read_program_direct(memory->space(space), (spacenum == EXPSPACE_OPDIRECT) ? 1 : 0, address, size); } break; case EXPSPACE_REGION: - if (name == nullptr) - break; - return read_memory_region(name, address, size); + if (name) + return read_memory_region(name, address, size); + break; default: break; @@ -762,78 +790,44 @@ void symbol_table::set_memory_value(const char *name, expression_space spacenum, { device_memory_interface *memory = m_memintf; + bool logical = true; + int space = -1; switch (spacenum) { - case EXPSPACE_PROGRAM_LOGICAL: - case EXPSPACE_DATA_LOGICAL: - case EXPSPACE_IO_LOGICAL: - case EXPSPACE_SPACE3_LOGICAL: - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory != nullptr && memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL))) - { - address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL)); - auto dis = m_machine.disable_side_effects(disable_se); - write_memory(space, address, data, size, true); - } - break; - case EXPSPACE_PROGRAM_PHYSICAL: case EXPSPACE_DATA_PHYSICAL: case EXPSPACE_IO_PHYSICAL: - case EXPSPACE_SPACE3_PHYSICAL: - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory != nullptr && memory->has_space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL))) - { - address_space &space = memory->space(AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL)); - auto dis = m_machine.disable_side_effects(disable_se); - write_memory(space, address, data, size, false); - } - break; - - case EXPSPACE_RAMWRITE: { - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory != nullptr && memory->has_space(AS_PROGRAM)) + case EXPSPACE_OPCODE_PHYSICAL: + spacenum = expression_space(spacenum - (EXPSPACE_PROGRAM_PHYSICAL - EXPSPACE_PROGRAM_LOGICAL)); + logical = false; + [[fallthrough]]; + case EXPSPACE_PROGRAM_LOGICAL: + case EXPSPACE_DATA_LOGICAL: + case EXPSPACE_IO_LOGICAL: + case EXPSPACE_OPCODE_LOGICAL: + space = AS_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL); + expression_get_space(name, space, memory); + if (memory) { auto dis = m_machine.disable_side_effects(disable_se); - write_program_direct(memory->space(AS_PROGRAM), (spacenum == EXPSPACE_OPCODE), address, size, data); + write_memory(memory->space(space), address, data, size, logical); } break; - } - case EXPSPACE_OPCODE: { - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device != nullptr) - device->interface(memory); - } - if (memory != nullptr && memory->has_space(AS_OPCODES)) + case EXPSPACE_PRGDIRECT: + case EXPSPACE_OPDIRECT: + space = (spacenum == EXPSPACE_OPDIRECT) ? AS_OPCODES : AS_PROGRAM; + expression_get_space(name, space, memory); + if (memory) { auto dis = m_machine.disable_side_effects(disable_se); - write_program_direct(memory->space(AS_OPCODES), (spacenum == EXPSPACE_OPCODE), address, size, data); + write_program_direct(memory->space(space), (spacenum == EXPSPACE_OPDIRECT) ? 1 : 0, address, size, data); } break; - } case EXPSPACE_REGION: - if (name == nullptr) - break; - write_memory_region(name, address, size, data); + if (name) + write_memory_region(name, address, size, data); break; default: @@ -966,73 +960,27 @@ expression_error::error_code symbol_table::memory_valid(const char *name, expres { device_memory_interface *memory = m_memintf; + int spaceno = -1; switch (space) { case EXPSPACE_PROGRAM_LOGICAL: case EXPSPACE_DATA_LOGICAL: case EXPSPACE_IO_LOGICAL: - case EXPSPACE_SPACE3_LOGICAL: - if (name != nullptr) - { - device_t *device = expression_get_device(name); - if (device == nullptr) - return expression_error::INVALID_MEMORY_NAME; - if (!device->interface(memory)) - return expression_error::NO_SUCH_MEMORY_SPACE; - } - else if (memory == nullptr) - return expression_error::MISSING_MEMORY_NAME; - if (!memory->has_space(AS_PROGRAM + (space - EXPSPACE_PROGRAM_LOGICAL))) - return expression_error::NO_SUCH_MEMORY_SPACE; - break; + case EXPSPACE_OPCODE_LOGICAL: + spaceno = AS_PROGRAM + (space - EXPSPACE_PROGRAM_LOGICAL); + return expression_get_space(name, spaceno, memory); case EXPSPACE_PROGRAM_PHYSICAL: case EXPSPACE_DATA_PHYSICAL: case EXPSPACE_IO_PHYSICAL: - case EXPSPACE_SPACE3_PHYSICAL: - if (name) - { - device_t *device = expression_get_device(name); - if (device == nullptr) - return expression_error::INVALID_MEMORY_NAME; - if (!device->interface(memory)) - return expression_error::NO_SUCH_MEMORY_SPACE; - } - else if (memory == nullptr) - return expression_error::MISSING_MEMORY_NAME; - if (!memory->has_space(AS_PROGRAM + (space - EXPSPACE_PROGRAM_PHYSICAL))) - return expression_error::NO_SUCH_MEMORY_SPACE; - break; - - case EXPSPACE_RAMWRITE: - if (name) - { - device_t *device = expression_get_device(name); - if (device == nullptr) - return expression_error::INVALID_MEMORY_NAME; - if (!device->interface(memory)) - return expression_error::NO_SUCH_MEMORY_SPACE; - } - else if (memory == nullptr) - return expression_error::MISSING_MEMORY_NAME; - if (!memory->has_space(AS_PROGRAM)) - return expression_error::NO_SUCH_MEMORY_SPACE; - break; + case EXPSPACE_OPCODE_PHYSICAL: + spaceno = AS_PROGRAM + (space - EXPSPACE_PROGRAM_PHYSICAL); + return expression_get_space(name, spaceno, memory); - case EXPSPACE_OPCODE: - if (name) - { - device_t *device = expression_get_device(name); - if (device == nullptr) - return expression_error::INVALID_MEMORY_NAME; - if (!device->interface(memory)) - return expression_error::NO_SUCH_MEMORY_SPACE; - } - else if (memory == nullptr) - return expression_error::MISSING_MEMORY_NAME; - if (!memory->has_space(AS_OPCODES)) - return expression_error::NO_SUCH_MEMORY_SPACE; - break; + case EXPSPACE_PRGDIRECT: + case EXPSPACE_OPDIRECT: + spaceno = (space == EXPSPACE_OPDIRECT) ? AS_OPCODES : AS_PROGRAM; + return expression_get_space(name, spaceno, memory); case EXPSPACE_REGION: if (!name) @@ -1044,6 +992,7 @@ expression_error::error_code symbol_table::memory_valid(const char *name, expres default: return expression_error::NO_SUCH_MEMORY_SPACE; } + return expression_error::NONE; } @@ -1375,12 +1324,15 @@ void parsed_expression::parse_symbol_or_number(parse_token &token, const char *& // check for memory @ and ! operators if (string[0] == '@' || string[0] == '!') { - try { + try + { bool disable_se = string[0] == '@'; parse_memory_operator(token, buffer.c_str(), disable_se); string += 1; return; - } catch(const expression_error &) { + } + catch (const expression_error &) + { // Try some other operator instead } } @@ -1614,13 +1566,13 @@ void parsed_expression::parse_memory_operator(parse_token &token, const char *st string = dot + 1; } - // length 3 means logical/physical, then space, then size int length = (int)strlen(string); bool physical = false; int space = 'p'; int size; if (length == 3) { + // length 3 means logical/physical, then space, then size if (string[0] != 'l' && string[0] != 'p') throw expression_error(expression_error::INVALID_MEMORY_SPACE, token.offset() + (string - startstring)); if (string[1] != 'p' && string[1] != 'd' && string[1] != 'i' && string[1] != '3') @@ -1629,21 +1581,22 @@ void parsed_expression::parse_memory_operator(parse_token &token, const char *st space = string[1]; size = string[2]; } - - // length 2 means space then size else if (length == 2) { + // length 2 means space then size space = string[0]; size = string[1]; } - - // length 1 means size else if (length == 1) + { + // length 1 means size size = string[0]; - - // anything else is invalid + } else + { + // anything else is invalid throw expression_error(expression_error::INVALID_TOKEN, token.offset()); + } // convert the space to flags expression_space memspace; @@ -1652,9 +1605,9 @@ void parsed_expression::parse_memory_operator(parse_token &token, const char *st case 'p': memspace = physical ? EXPSPACE_PROGRAM_PHYSICAL : EXPSPACE_PROGRAM_LOGICAL; break; case 'd': memspace = physical ? EXPSPACE_DATA_PHYSICAL : EXPSPACE_DATA_LOGICAL; break; case 'i': memspace = physical ? EXPSPACE_IO_PHYSICAL : EXPSPACE_IO_LOGICAL; break; - case '3': memspace = physical ? EXPSPACE_SPACE3_PHYSICAL : EXPSPACE_SPACE3_LOGICAL; break; - case 'o': memspace = EXPSPACE_OPCODE; break; - case 'r': memspace = EXPSPACE_RAMWRITE; break; + case '3': memspace = physical ? EXPSPACE_OPCODE_PHYSICAL : EXPSPACE_OPCODE_LOGICAL; break; + case 'r': memspace = EXPSPACE_PRGDIRECT; break; + case 'o': memspace = EXPSPACE_OPDIRECT; break; case 'm': memspace = EXPSPACE_REGION; break; default: throw expression_error(expression_error::INVALID_MEMORY_SPACE, token.offset() + (string - startstring)); } diff --git a/src/emu/debug/express.h b/src/emu/debug/express.h index c87b9370f7d..23284193f47 100644 --- a/src/emu/debug/express.h +++ b/src/emu/debug/express.h @@ -34,13 +34,13 @@ enum expression_space EXPSPACE_PROGRAM_LOGICAL, EXPSPACE_DATA_LOGICAL, EXPSPACE_IO_LOGICAL, - EXPSPACE_SPACE3_LOGICAL, + EXPSPACE_OPCODE_LOGICAL, EXPSPACE_PROGRAM_PHYSICAL, EXPSPACE_DATA_PHYSICAL, EXPSPACE_IO_PHYSICAL, - EXPSPACE_SPACE3_PHYSICAL, - EXPSPACE_OPCODE, - EXPSPACE_RAMWRITE, + EXPSPACE_OPCODE_PHYSICAL, + EXPSPACE_PRGDIRECT, + EXPSPACE_OPDIRECT, EXPSPACE_REGION }; @@ -204,7 +204,7 @@ private: u64 read_memory_region(const char *rgntag, offs_t address, int size); void write_program_direct(address_space &space, int opcode, offs_t address, int size, u64 data); void write_memory_region(const char *rgntag, offs_t address, int size, u64 data); - device_t *expression_get_device(const char *tag); + expression_error expression_get_space(const char *tag, int &spacenum, device_memory_interface *&memory); void notify_memory_modified(); // internal state diff --git a/src/frontend/mame/ui/ui.h b/src/frontend/mame/ui/ui.h index 9607ca24a91..44727703a20 100644 --- a/src/frontend/mame/ui/ui.h +++ b/src/frontend/mame/ui/ui.h @@ -56,7 +56,7 @@ class laserdisc_device; /* handy colors */ #define UI_GREEN_COLOR rgb_t(0xef,0x0a,0x66,0x0a) #define UI_YELLOW_COLOR rgb_t(0xef,0xcc,0x7a,0x28) -#define UI_RED_COLOR rgb_t(0xef,0xcc,0x14,0x14) +#define UI_RED_COLOR rgb_t(0xef,0xb2,0x00,0x00) /* cancel return value for a UI handler */ #define UI_HANDLER_CANCEL ((uint32_t)~0) |