diff options
Diffstat (limited to 'src/emu/debug/debugcmd.cpp')
-rw-r--r-- | src/emu/debug/debugcmd.cpp | 3571 |
1 files changed, 2145 insertions, 1426 deletions
diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index cd9d9dcf743..0b7efa44a93 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -2,27 +2,37 @@ // copyright-holders:Aaron Giles /********************************************************************* - debugcmd.c + debugcmd.cpp Debugger command interface engine. *********************************************************************/ #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 "fileio.h" #include "natkeyboard.h" #include "render.h" -#include <ctype.h> +#include "screen.h" +#include "softlist.h" + +#include "corestr.h" + #include <algorithm> +#include <cctype> #include <fstream> +#include <sstream> @@ -43,7 +53,8 @@ const size_t debugger_commands::MAX_GLOBALS = 1000; bool debugger_commands::cheat_address_is_valid(address_space &space, offs_t address) { - return space.device().memory().translate(space.spacenum(), TRANSLATE_READ, address) && (space.get_write_ptr(address) != nullptr); + address_space *tspace; + return space.device().memory().translate(space.spacenum(), device_memory_interface::TR_READ, address, tspace) && (tspace->get_write_ptr(address) != nullptr); } @@ -52,15 +63,15 @@ bool debugger_commands::cheat_address_is_valid(address_space &space, offs_t addr the current cheat width, if signed -------------------------------------------------*/ -u64 debugger_commands::cheat_sign_extend(const cheat_system *cheatsys, u64 value) +inline u64 debugger_commands::cheat_system::sign_extend(u64 value) const { - if (cheatsys->signed_cheat) + if (signed_cheat) { - switch (cheatsys->width) + switch (width) { - case 1: value = s8(value); break; - case 2: value = s16(value); break; - case 4: value = s32(value); break; + case 1: value = s8(value); break; + case 2: value = s16(value); break; + case 4: value = s32(value); break; } } return value; @@ -70,16 +81,15 @@ u64 debugger_commands::cheat_sign_extend(const cheat_system *cheatsys, u64 value cheat_byte_swap - swap a value -------------------------------------------------*/ -u64 debugger_commands::cheat_byte_swap(const cheat_system *cheatsys, u64 value) +inline u64 debugger_commands::cheat_system::byte_swap(u64 value) const { - if (cheatsys->swapped_cheat) + if (swapped_cheat) { - switch (cheatsys->width) + switch (width) { - case 2: value = ((value >> 8) & 0x00ff) | ((value << 8) & 0xff00); break; - case 4: value = ((value >> 24) & 0x000000ff) | ((value >> 8) & 0x0000ff00) | ((value << 8) & 0x00ff0000) | ((value << 24) & 0xff000000); break; - case 8: value = ((value >> 56) & 0x00000000000000ffU) | ((value >> 40) & 0x000000000000ff00U) | ((value >> 24) & 0x0000000000ff0000U) | ((value >> 8) & 0x00000000ff000000U) | - ((value << 8) & 0x000000ff00000000U) | ((value << 24) & 0x0000ff0000000000U) | ((value << 40) & 0x00ff000000000000U) | ((value << 56) & 0xff00000000000000U); break; + case 2: value = swapendian_int16(value); break; + case 4: value = swapendian_int32(value); break; + case 8: value = swapendian_int64(value); break; } } return value; @@ -91,247 +101,296 @@ u64 debugger_commands::cheat_byte_swap(const cheat_system *cheatsys, u64 value) and swapping if necessary -------------------------------------------------*/ -u64 debugger_commands::cheat_read_extended(const cheat_system *cheatsys, address_space &space, offs_t address) +u64 debugger_commands::cheat_system::read_extended(offs_t address) const { - return cheat_sign_extend(cheatsys, cheat_byte_swap(cheatsys, m_cpu.read_memory(space, address, cheatsys->width, true))); + address &= space->logaddrmask(); + u64 value = space->unmap(); + address_space *tspace; + if (space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, address, tspace)) + { + switch (width) + { + case 1: value = tspace->read_byte(address); break; + case 2: value = tspace->read_word_unaligned(address); break; + case 4: value = tspace->read_dword_unaligned(address); break; + case 8: value = tspace->read_qword_unaligned(address); break; + } + } + return sign_extend(byte_swap(value)); } debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu, debugger_console& console) : m_machine(machine) - , m_cpu(cpu) , m_console(console) { - m_global_array = std::make_unique<global_entry []>(MAX_GLOBALS); - - symbol_table *symtable = m_cpu.get_global_symtable(); - - /* add a few simple global functions */ using namespace std::placeholders; - symtable->add("min", 2, 2, std::bind(&debugger_commands::execute_min, this, _1, _2, _3)); - symtable->add("max", 2, 2, std::bind(&debugger_commands::execute_max, this, _1, _2, _3)); - symtable->add("if", 3, 3, std::bind(&debugger_commands::execute_if, this, _1, _2, _3)); + m_global_array = std::make_unique<global_entry []>(MAX_GLOBALS); - /* add all single-entry save state globals */ + symbol_table &symtable = cpu.global_symtable(); + + // add a few simple global functions + symtable.add("min", 2, 2, // lower of two values + [] (int params, const u64 *param) -> u64 + { return (std::min)(param[0], param[1]); }); + symtable.add("max", 2, 2, // higher of two values + [] (int params, const u64 *param) -> u64 + { return (std::max)(param[0], param[1]); }); + symtable.add("if", 3, 3, // a ? b : c + [] (int params, const u64 *param) -> u64 + { return param[0] ? param[1] : param[2]; }); + symtable.add("abs", 1, 1, // absolute value of signed number + [] (int params, const u64 *param) -> u64 + { return std::abs(s64(param[0])); }); + symtable.add("bit", 2, 3, // extract bit field + [] (int params, const u64 *param) -> u64 + { return (params == 2) ? BIT(param[0], param[1]) : BIT(param[0], param[1], param[2]); }); + symtable.add("s8", 1, 1, // sign-extend from 8 bits + [] (int params, const u64 *param) -> u64 + { return s64(s8(u8(param[0]))); }); + symtable.add("s16", 1, 1, // sign-extend from 16 bits + [] (int params, const u64 *param) -> u64 + { return s64(s16(u16(param[0]))); }); + symtable.add("s32", 1, 1, // sign-extend from 32 bits + [] (int params, const u64 *param) -> u64 + { return s64(s32(u32(param[0]))); }); + symtable.add("cpunum", std::bind(&debugger_commands::get_cpunum, this)); + + // add all single-entry save state globals for (int itemnum = 0; itemnum < MAX_GLOBALS; itemnum++) { - u32 valsize, valcount; void *base; + u32 valsize, valcount, blockcount, stride; - /* stop when we run out of items */ - const char* name = m_machine.save().indexed_item(itemnum, base, valsize, valcount); - if (name == nullptr) + // stop when we run out of items + const char* name = m_machine.save().indexed_item(itemnum, base, valsize, valcount, blockcount, stride); + if (!name) break; - /* if this is a single-entry global, add it */ - if (valcount == 1 && strstr(name, "/globals/")) + // if this is a single-entry global, add it + if ((valcount == 1) && (blockcount == 1) && strstr(name, "/globals/")) { char symname[100]; - sprintf(symname, ".%s", strrchr(name, '/') + 1); + snprintf(symname, 100, ".%s", strrchr(name, '/') + 1); m_global_array[itemnum].base = base; m_global_array[itemnum].size = valsize; - symtable->add( + symtable.add( symname, - std::bind(&debugger_commands::global_get, this, _1, &m_global_array[itemnum]), - std::bind(&debugger_commands::global_set, this, _1, &m_global_array[itemnum], _2)); - } - } - - /* add all the commands */ - m_console.register_command("help", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_help, this, _1, _2)); - m_console.register_command("print", CMDFLAG_NONE, 0, 1, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_print, this, _1, _2)); - m_console.register_command("printf", CMDFLAG_NONE, 0, 1, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_printf, this, _1, _2)); - m_console.register_command("logerror", CMDFLAG_NONE, 0, 1, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_logerror, this, _1, _2)); - m_console.register_command("tracelog", CMDFLAG_NONE, 0, 1, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_tracelog, this, _1, _2)); - m_console.register_command("tracesym", CMDFLAG_NONE, 0, 1, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_tracesym, this, _1, _2)); - m_console.register_command("quit", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_quit, this, _1, _2)); - m_console.register_command("exit", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_quit, this, _1, _2)); - m_console.register_command("do", CMDFLAG_NONE, 0, 1, 1, std::bind(&debugger_commands::execute_do, this, _1, _2)); - m_console.register_command("step", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_step, this, _1, _2)); - m_console.register_command("s", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_step, this, _1, _2)); - m_console.register_command("over", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_over, this, _1, _2)); - m_console.register_command("o", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_over, this, _1, _2)); - m_console.register_command("out" , CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_out, this, _1, _2)); - m_console.register_command("go", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_go, this, _1, _2)); - m_console.register_command("g", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_go, this, _1, _2)); - m_console.register_command("gvblank", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_go_vblank, this, _1, _2)); - m_console.register_command("gv", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_go_vblank, this, _1, _2)); - m_console.register_command("gint", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_go_interrupt, this, _1, _2)); - m_console.register_command("gi", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_go_interrupt, this, _1, _2)); - m_console.register_command("gex", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_go_exception, this, _1, _2)); - m_console.register_command("ge", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_go_exception, this, _1, _2)); - m_console.register_command("gtime", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_go_time, this, _1, _2)); - m_console.register_command("gt", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_go_time, this, _1, _2)); - m_console.register_command("gp", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_go_privilege, this, _1, _2)); - m_console.register_command("next", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_next, this, _1, _2)); - m_console.register_command("n", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_next, this, _1, _2)); - m_console.register_command("focus", CMDFLAG_NONE, 0, 1, 1, std::bind(&debugger_commands::execute_focus, this, _1, _2)); - m_console.register_command("ignore", CMDFLAG_NONE, 0, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_ignore, this, _1, _2)); - m_console.register_command("observe", CMDFLAG_NONE, 0, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_observe, this, _1, _2)); - m_console.register_command("suspend", CMDFLAG_NONE, 0, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_suspend, this, _1, _2)); - m_console.register_command("resume", CMDFLAG_NONE, 0, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_resume, this, _1, _2)); - - m_console.register_command("comadd", CMDFLAG_NONE, 0, 1, 2, std::bind(&debugger_commands::execute_comment_add, this, _1, _2)); - m_console.register_command("//", CMDFLAG_NONE, 0, 1, 2, std::bind(&debugger_commands::execute_comment_add, this, _1, _2)); - m_console.register_command("comdelete", CMDFLAG_NONE, 0, 1, 1, std::bind(&debugger_commands::execute_comment_del, this, _1, _2)); - m_console.register_command("comsave", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_comment_save, this, _1, _2)); - m_console.register_command("comlist", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_comment_list, this, _1, _2)); - m_console.register_command("commit", CMDFLAG_NONE, 0, 1, 2, std::bind(&debugger_commands::execute_comment_commit, this, _1, _2)); - m_console.register_command("/*", CMDFLAG_NONE, 0, 1, 2, std::bind(&debugger_commands::execute_comment_commit, this, _1, _2)); - - m_console.register_command("bpset", CMDFLAG_NONE, 0, 1, 3, std::bind(&debugger_commands::execute_bpset, this, _1, _2)); - m_console.register_command("bp", CMDFLAG_NONE, 0, 1, 3, std::bind(&debugger_commands::execute_bpset, this, _1, _2)); - m_console.register_command("bpclear", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_bpclear, this, _1, _2)); - m_console.register_command("bpdisable", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_bpdisenable, this, _1, _2)); - m_console.register_command("bpenable", CMDFLAG_NONE, 1, 0, 1, std::bind(&debugger_commands::execute_bpdisenable, this, _1, _2)); - m_console.register_command("bplist", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_bplist, this, _1, _2)); - - m_console.register_command("wpset", CMDFLAG_NONE, AS_PROGRAM, 3, 5, std::bind(&debugger_commands::execute_wpset, this, _1, _2)); - m_console.register_command("wp", CMDFLAG_NONE, AS_PROGRAM, 3, 5, std::bind(&debugger_commands::execute_wpset, this, _1, _2)); - m_console.register_command("wpdset", CMDFLAG_NONE, AS_DATA, 3, 5, std::bind(&debugger_commands::execute_wpset, this, _1, _2)); - m_console.register_command("wpd", CMDFLAG_NONE, AS_DATA, 3, 5, std::bind(&debugger_commands::execute_wpset, this, _1, _2)); - m_console.register_command("wpiset", CMDFLAG_NONE, AS_IO, 3, 5, std::bind(&debugger_commands::execute_wpset, this, _1, _2)); - m_console.register_command("wpi", CMDFLAG_NONE, AS_IO, 3, 5, std::bind(&debugger_commands::execute_wpset, this, _1, _2)); - m_console.register_command("wposet", CMDFLAG_NONE, AS_OPCODES, 3, 5, std::bind(&debugger_commands::execute_wpset, this, _1, _2)); - m_console.register_command("wpo", CMDFLAG_NONE, AS_OPCODES, 3, 5, std::bind(&debugger_commands::execute_wpset, this, _1, _2)); - m_console.register_command("wpclear", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_wpclear, this, _1, _2)); - m_console.register_command("wpdisable", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_wpdisenable, this, _1, _2)); - m_console.register_command("wpenable", CMDFLAG_NONE, 1, 0, 1, std::bind(&debugger_commands::execute_wpdisenable, this, _1, _2)); - m_console.register_command("wplist", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_wplist, this, _1, _2)); - - m_console.register_command("rpset", CMDFLAG_NONE, 0, 1, 2, std::bind(&debugger_commands::execute_rpset, this, _1, _2)); - m_console.register_command("rp", CMDFLAG_NONE, 0, 1, 2, std::bind(&debugger_commands::execute_rpset, this, _1, _2)); - m_console.register_command("rpclear", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_rpclear, this, _1, _2)); - m_console.register_command("rpdisable", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_rpdisenable, this, _1, _2)); - m_console.register_command("rpenable", CMDFLAG_NONE, 1, 0, 1, std::bind(&debugger_commands::execute_rpdisenable, this, _1, _2)); - m_console.register_command("rplist", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_rplist, this, _1, _2)); - - m_console.register_command("hotspot", CMDFLAG_NONE, 0, 0, 3, std::bind(&debugger_commands::execute_hotspot, this, _1, _2)); - - m_console.register_command("statesave", CMDFLAG_NONE, 0, 1, 1, std::bind(&debugger_commands::execute_statesave, this, _1, _2)); - m_console.register_command("ss", CMDFLAG_NONE, 0, 1, 1, std::bind(&debugger_commands::execute_statesave, this, _1, _2)); - m_console.register_command("stateload", CMDFLAG_NONE, 0, 1, 1, std::bind(&debugger_commands::execute_stateload, this, _1, _2)); - m_console.register_command("sl", CMDFLAG_NONE, 0, 1, 1, std::bind(&debugger_commands::execute_stateload, this, _1, _2)); - - m_console.register_command("rewind", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_rewind, this, _1, _2)); - m_console.register_command("rw", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_rewind, this, _1, _2)); - - m_console.register_command("save", CMDFLAG_NONE, AS_PROGRAM, 3, 4, std::bind(&debugger_commands::execute_save, this, _1, _2)); - m_console.register_command("saved", CMDFLAG_NONE, AS_DATA, 3, 4, std::bind(&debugger_commands::execute_save, this, _1, _2)); - m_console.register_command("savei", CMDFLAG_NONE, AS_IO, 3, 4, std::bind(&debugger_commands::execute_save, this, _1, _2)); - m_console.register_command("saveo", CMDFLAG_NONE, AS_OPCODES, 3, 4, std::bind(&debugger_commands::execute_save, this, _1, _2)); - - m_console.register_command("load", CMDFLAG_NONE, AS_PROGRAM, 2, 4, std::bind(&debugger_commands::execute_load, this, _1, _2)); - m_console.register_command("loadd", CMDFLAG_NONE, AS_DATA, 2, 4, std::bind(&debugger_commands::execute_load, this, _1, _2)); - m_console.register_command("loadi", CMDFLAG_NONE, AS_IO, 2, 4, std::bind(&debugger_commands::execute_load, this, _1, _2)); - m_console.register_command("loado", CMDFLAG_NONE, AS_OPCODES, 2, 4, std::bind(&debugger_commands::execute_load, this, _1, _2)); - - m_console.register_command("dump", CMDFLAG_NONE, AS_PROGRAM, 3, 7, std::bind(&debugger_commands::execute_dump, this, _1, _2)); - m_console.register_command("dumpd", CMDFLAG_NONE, AS_DATA, 3, 7, std::bind(&debugger_commands::execute_dump, this, _1, _2)); - m_console.register_command("dumpi", CMDFLAG_NONE, AS_IO, 3, 7, std::bind(&debugger_commands::execute_dump, this, _1, _2)); - m_console.register_command("dumpo", CMDFLAG_NONE, AS_OPCODES, 3, 7, std::bind(&debugger_commands::execute_dump, this, _1, _2)); - - m_console.register_command("cheatinit", CMDFLAG_NONE, 0, 0, 4, std::bind(&debugger_commands::execute_cheatinit, this, _1, _2)); - m_console.register_command("ci", CMDFLAG_NONE, 0, 0, 4, std::bind(&debugger_commands::execute_cheatinit, this, _1, _2)); - - m_console.register_command("cheatrange",CMDFLAG_NONE, 1, 2, 2, std::bind(&debugger_commands::execute_cheatinit, this, _1, _2)); - m_console.register_command("cr", CMDFLAG_NONE, 1, 2, 2, std::bind(&debugger_commands::execute_cheatinit, this, _1, _2)); - - m_console.register_command("cheatnext", CMDFLAG_NONE, 0, 1, 2, std::bind(&debugger_commands::execute_cheatnext, this, _1, _2)); - m_console.register_command("cn", CMDFLAG_NONE, 0, 1, 2, std::bind(&debugger_commands::execute_cheatnext, this, _1, _2)); - m_console.register_command("cheatnextf",CMDFLAG_NONE, 1, 1, 2, std::bind(&debugger_commands::execute_cheatnext, this, _1, _2)); - m_console.register_command("cnf", CMDFLAG_NONE, 1, 1, 2, std::bind(&debugger_commands::execute_cheatnext, this, _1, _2)); - - m_console.register_command("cheatlist", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_cheatlist, this, _1, _2)); - m_console.register_command("cl", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_cheatlist, this, _1, _2)); - - m_console.register_command("cheatundo", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_cheatundo, this, _1, _2)); - m_console.register_command("cu", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_cheatundo, this, _1, _2)); - - m_console.register_command("f", CMDFLAG_KEEP_QUOTES, AS_PROGRAM, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, _1, _2)); - m_console.register_command("find", CMDFLAG_KEEP_QUOTES, AS_PROGRAM, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, _1, _2)); - m_console.register_command("fd", CMDFLAG_KEEP_QUOTES, AS_DATA, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, _1, _2)); - m_console.register_command("findd", CMDFLAG_KEEP_QUOTES, AS_DATA, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, _1, _2)); - m_console.register_command("fi", CMDFLAG_KEEP_QUOTES, AS_IO, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, _1, _2)); - m_console.register_command("findi", CMDFLAG_KEEP_QUOTES, AS_IO, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, _1, _2)); - m_console.register_command("fo", CMDFLAG_KEEP_QUOTES, AS_OPCODES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, _1, _2)); - m_console.register_command("findo", CMDFLAG_KEEP_QUOTES, AS_OPCODES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, _1, _2)); - - m_console.register_command("dasm", CMDFLAG_NONE, 0, 3, 5, std::bind(&debugger_commands::execute_dasm, this, _1, _2)); - - m_console.register_command("trace", CMDFLAG_NONE, 0, 1, 4, std::bind(&debugger_commands::execute_trace, this, _1, _2)); - m_console.register_command("traceover", CMDFLAG_NONE, 0, 1, 4, std::bind(&debugger_commands::execute_traceover, this, _1, _2)); - m_console.register_command("traceflush",CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_traceflush, this, _1, _2)); - - m_console.register_command("history", CMDFLAG_NONE, 0, 0, 2, std::bind(&debugger_commands::execute_history, this, _1, _2)); - m_console.register_command("trackpc", CMDFLAG_NONE, 0, 0, 3, std::bind(&debugger_commands::execute_trackpc, this, _1, _2)); - - m_console.register_command("trackmem", CMDFLAG_NONE, 0, 0, 3, std::bind(&debugger_commands::execute_trackmem, this, _1, _2)); - m_console.register_command("pcatmemp", CMDFLAG_NONE, AS_PROGRAM, 1, 2, std::bind(&debugger_commands::execute_pcatmem, this, _1, _2)); - m_console.register_command("pcatmemd", CMDFLAG_NONE, AS_DATA, 1, 2, std::bind(&debugger_commands::execute_pcatmem, this, _1, _2)); - m_console.register_command("pcatmemi", CMDFLAG_NONE, AS_IO, 1, 2, std::bind(&debugger_commands::execute_pcatmem, this, _1, _2)); - m_console.register_command("pcatmemo", CMDFLAG_NONE, AS_OPCODES, 1, 2, std::bind(&debugger_commands::execute_pcatmem, this, _1, _2)); - - m_console.register_command("snap", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_snap, this, _1, _2)); - - m_console.register_command("source", CMDFLAG_NONE, 0, 1, 1, std::bind(&debugger_commands::execute_source, this, _1, _2)); - - m_console.register_command("map", CMDFLAG_NONE, AS_PROGRAM, 1, 1, std::bind(&debugger_commands::execute_map, this, _1, _2)); - m_console.register_command("mapd", CMDFLAG_NONE, AS_DATA, 1, 1, std::bind(&debugger_commands::execute_map, this, _1, _2)); - m_console.register_command("mapi", CMDFLAG_NONE, AS_IO, 1, 1, std::bind(&debugger_commands::execute_map, this, _1, _2)); - m_console.register_command("mapo", CMDFLAG_NONE, AS_OPCODES, 1, 1, std::bind(&debugger_commands::execute_map, this, _1, _2)); - m_console.register_command("memdump", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_memdump, this, _1, _2)); - - m_console.register_command("symlist", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_symlist, this, _1, _2)); - - m_console.register_command("softreset", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_softreset, this, _1, _2)); - m_console.register_command("hardreset", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_hardreset, this, _1, _2)); - - m_console.register_command("images", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_images, this, _1, _2)); - m_console.register_command("mount", CMDFLAG_NONE, 0, 2, 2, std::bind(&debugger_commands::execute_mount, this, _1, _2)); - m_console.register_command("unmount", CMDFLAG_NONE, 0, 1, 1, std::bind(&debugger_commands::execute_unmount, this, _1, _2)); - - m_console.register_command("input", CMDFLAG_NONE, 0, 1, 1, std::bind(&debugger_commands::execute_input, this, _1, _2)); - m_console.register_command("dumpkbd", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_dumpkbd, this, _1, _2)); + std::bind(&debugger_commands::global_get, this, &m_global_array[itemnum]), + std::bind(&debugger_commands::global_set, this, &m_global_array[itemnum], _1)); + } + } + + // add all the commands + m_console.register_command("help", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_help, this, _1)); + m_console.register_command("print", CMDFLAG_NONE, 1, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_print, this, _1)); + m_console.register_command("printf", CMDFLAG_NONE, 1, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_printf, this, _1)); + m_console.register_command("logerror", CMDFLAG_NONE, 1, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_logerror, this, _1)); + m_console.register_command("tracelog", CMDFLAG_NONE, 1, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_tracelog, this, _1)); + m_console.register_command("tracesym", CMDFLAG_NONE, 1, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_tracesym, this, _1)); + m_console.register_command("cls", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_cls, this, _1)); + m_console.register_command("quit", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_quit, this, _1)); + m_console.register_command("exit", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_quit, this, _1)); + m_console.register_command("do", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_do, this, _1)); + m_console.register_command("step", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_step, this, _1)); + m_console.register_command("s", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_step, this, _1)); + m_console.register_command("over", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_over, this, _1)); + m_console.register_command("o", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_over, this, _1)); + m_console.register_command("out" , CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_out, this, _1)); + m_console.register_command("go", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go, this, _1)); + m_console.register_command("g", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go, this, _1)); + m_console.register_command("gvblank", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_go_vblank, this, _1)); + m_console.register_command("gv", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_go_vblank, this, _1)); + m_console.register_command("gint", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go_interrupt, this, _1)); + m_console.register_command("gi", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go_interrupt, this, _1)); + m_console.register_command("gex", CMDFLAG_NONE, 0, 2, std::bind(&debugger_commands::execute_go_exception, this, _1)); + m_console.register_command("ge", CMDFLAG_NONE, 0, 2, std::bind(&debugger_commands::execute_go_exception, this, _1)); + m_console.register_command("gtime", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go_time, this, _1)); + m_console.register_command("gt", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go_time, this, _1)); + m_console.register_command("gp", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go_privilege, this, _1)); + m_console.register_command("gbt", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go_branch, this, true, _1)); + m_console.register_command("gbf", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go_branch, this, false, _1)); + m_console.register_command("gni", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_go_next_instruction, this, _1)); + m_console.register_command("next", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_next, this, _1)); + m_console.register_command("n", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_next, this, _1)); + m_console.register_command("focus", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_focus, this, _1)); + m_console.register_command("ignore", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_ignore, this, _1)); + m_console.register_command("observe", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_observe, this, _1)); + m_console.register_command("suspend", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_suspend, this, _1)); + m_console.register_command("resume", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_resume, this, _1)); + m_console.register_command("cpulist", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_cpulist, this, _1)); + m_console.register_command("time", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_time, this, _1)); + + m_console.register_command("comadd", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_comment_add, this, _1)); + m_console.register_command("//", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_comment_add, this, _1)); + m_console.register_command("comdelete", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_comment_del, this, _1)); + m_console.register_command("comsave", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_comment_save, this, _1)); + m_console.register_command("comlist", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_comment_list, this, _1)); + m_console.register_command("commit", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_comment_commit, this, _1)); + m_console.register_command("/*", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_comment_commit, this, _1)); + + m_console.register_command("bpset", CMDFLAG_NONE, 1, 3, std::bind(&debugger_commands::execute_bpset, this, _1)); + m_console.register_command("bp", CMDFLAG_NONE, 1, 3, std::bind(&debugger_commands::execute_bpset, this, _1)); + m_console.register_command("bpclear", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_bpclear, this, _1)); + m_console.register_command("bpdisable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_bpdisenable, this, false, _1)); + m_console.register_command("bpenable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_bpdisenable, this, true, _1)); + m_console.register_command("bplist", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_bplist, this, _1)); + + m_console.register_command("wpset", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, -1, _1)); + m_console.register_command("wp", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, -1, _1)); + m_console.register_command("wpdset", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, AS_DATA, _1)); + m_console.register_command("wpd", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, AS_DATA, _1)); + m_console.register_command("wpiset", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, AS_IO, _1)); + m_console.register_command("wpi", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, AS_IO, _1)); + m_console.register_command("wposet", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, AS_OPCODES, _1)); + m_console.register_command("wpo", CMDFLAG_NONE, 3, 5, std::bind(&debugger_commands::execute_wpset, this, AS_OPCODES, _1)); + m_console.register_command("wpclear", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_wpclear, this, _1)); + m_console.register_command("wpdisable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_wpdisenable, this, false, _1)); + m_console.register_command("wpenable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_wpdisenable, this, true, _1)); + m_console.register_command("wplist", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_wplist, this, _1)); + + m_console.register_command("rpset", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_rpset, this, _1)); + m_console.register_command("rp", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_rpset, this, _1)); + m_console.register_command("rpclear", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_rpclear, this, _1)); + m_console.register_command("rpdisable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_rpdisenable, this, false, _1)); + m_console.register_command("rpenable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_rpdisenable, this, true, _1)); + m_console.register_command("rplist", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_rplist, this, _1)); + + m_console.register_command("epset", CMDFLAG_NONE, 1, 3, std::bind(&debugger_commands::execute_epset, this, _1)); + m_console.register_command("ep", CMDFLAG_NONE, 1, 3, std::bind(&debugger_commands::execute_epset, this, _1)); + m_console.register_command("epclear", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_epclear, this, _1)); + m_console.register_command("epdisable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_epdisenable, this, false, _1)); + m_console.register_command("epenable", CMDFLAG_NONE, 0, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_epdisenable, this, true, _1)); + m_console.register_command("eplist", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_eplist, this, _1)); + + m_console.register_command("statesave", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_statesave, this, _1)); + m_console.register_command("ss", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_statesave, this, _1)); + m_console.register_command("stateload", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_stateload, this, _1)); + m_console.register_command("sl", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_stateload, this, _1)); + + m_console.register_command("rewind", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_rewind, this, _1)); + m_console.register_command("rw", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_rewind, this, _1)); + + m_console.register_command("save", CMDFLAG_NONE, 3, 3, std::bind(&debugger_commands::execute_save, this, -1, _1)); + m_console.register_command("saved", CMDFLAG_NONE, 3, 3, std::bind(&debugger_commands::execute_save, this, AS_DATA, _1)); + m_console.register_command("savei", CMDFLAG_NONE, 3, 3, std::bind(&debugger_commands::execute_save, this, AS_IO, _1)); + m_console.register_command("saveo", CMDFLAG_NONE, 3, 3, std::bind(&debugger_commands::execute_save, this, AS_OPCODES, _1)); + m_console.register_command("saver", CMDFLAG_NONE, 4, 4, std::bind(&debugger_commands::execute_saveregion, this, _1)); + + m_console.register_command("load", CMDFLAG_NONE, 2, 3, std::bind(&debugger_commands::execute_load, this, -1, _1)); + m_console.register_command("loadd", CMDFLAG_NONE, 2, 3, std::bind(&debugger_commands::execute_load, this, AS_DATA, _1)); + m_console.register_command("loadi", CMDFLAG_NONE, 2, 3, std::bind(&debugger_commands::execute_load, this, AS_IO, _1)); + m_console.register_command("loado", CMDFLAG_NONE, 2, 3, std::bind(&debugger_commands::execute_load, this, AS_OPCODES, _1)); + m_console.register_command("loadr", CMDFLAG_NONE, 4, 4, std::bind(&debugger_commands::execute_loadregion, this, _1)); + + m_console.register_command("dump", CMDFLAG_NONE, 3, 6, std::bind(&debugger_commands::execute_dump, this, -1, _1)); + m_console.register_command("dumpd", CMDFLAG_NONE, 3, 6, std::bind(&debugger_commands::execute_dump, this, AS_DATA, _1)); + m_console.register_command("dumpi", CMDFLAG_NONE, 3, 6, std::bind(&debugger_commands::execute_dump, this, AS_IO, _1)); + m_console.register_command("dumpo", CMDFLAG_NONE, 3, 6, std::bind(&debugger_commands::execute_dump, this, AS_OPCODES, _1)); + + m_console.register_command("strdump", CMDFLAG_NONE, 3, 4, std::bind(&debugger_commands::execute_strdump, this, -1, _1)); + m_console.register_command("strdumpd", CMDFLAG_NONE, 3, 4, std::bind(&debugger_commands::execute_strdump, this, AS_DATA, _1)); + m_console.register_command("strdumpi", CMDFLAG_NONE, 3, 4, std::bind(&debugger_commands::execute_strdump, this, AS_IO, _1)); + m_console.register_command("strdumpo", CMDFLAG_NONE, 3, 4, std::bind(&debugger_commands::execute_strdump, this, AS_OPCODES, _1)); + + m_console.register_command("cheatinit", CMDFLAG_NONE, 0, 4, std::bind(&debugger_commands::execute_cheatrange, this, true, _1)); + m_console.register_command("ci", CMDFLAG_NONE, 0, 4, std::bind(&debugger_commands::execute_cheatrange, this, true, _1)); + + m_console.register_command("cheatrange",CMDFLAG_NONE, 2, 2, std::bind(&debugger_commands::execute_cheatrange, this, false, _1)); + m_console.register_command("cr", CMDFLAG_NONE, 2, 2, std::bind(&debugger_commands::execute_cheatrange, this, false, _1)); + + m_console.register_command("cheatnext", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_cheatnext, this, false, _1)); + m_console.register_command("cn", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_cheatnext, this, false, _1)); + m_console.register_command("cheatnextf",CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_cheatnext, this, true, _1)); + m_console.register_command("cnf", CMDFLAG_NONE, 1, 2, std::bind(&debugger_commands::execute_cheatnext, this, true, _1)); + + m_console.register_command("cheatlist", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_cheatlist, this, _1)); + m_console.register_command("cl", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_cheatlist, this, _1)); + + m_console.register_command("cheatundo", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_cheatundo, this, _1)); + m_console.register_command("cu", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_cheatundo, this, _1)); + + m_console.register_command("f", CMDFLAG_KEEP_QUOTES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, -1, _1)); + m_console.register_command("find", CMDFLAG_KEEP_QUOTES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, -1, _1)); + m_console.register_command("fd", CMDFLAG_KEEP_QUOTES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, AS_DATA, _1)); + m_console.register_command("findd", CMDFLAG_KEEP_QUOTES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, AS_DATA, _1)); + m_console.register_command("fi", CMDFLAG_KEEP_QUOTES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, AS_IO, _1)); + m_console.register_command("findi", CMDFLAG_KEEP_QUOTES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, AS_IO, _1)); + m_console.register_command("fo", CMDFLAG_KEEP_QUOTES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, AS_OPCODES, _1)); + m_console.register_command("findo", CMDFLAG_KEEP_QUOTES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_find, this, AS_OPCODES, _1)); + + m_console.register_command("fill", CMDFLAG_KEEP_QUOTES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_fill, this, -1, _1)); + m_console.register_command("filld", CMDFLAG_KEEP_QUOTES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_fill, this, AS_DATA, _1)); + m_console.register_command("filli", CMDFLAG_KEEP_QUOTES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_fill, this, AS_IO, _1)); + m_console.register_command("fillo", CMDFLAG_KEEP_QUOTES, 3, MAX_COMMAND_PARAMS, std::bind(&debugger_commands::execute_fill, this, AS_OPCODES, _1)); + + 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, 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)); + m_console.register_command("trackpc", CMDFLAG_NONE, 0, 3, std::bind(&debugger_commands::execute_trackpc, this, _1)); + + m_console.register_command("trackmem", CMDFLAG_NONE, 0, 3, std::bind(&debugger_commands::execute_trackmem, this, _1)); + m_console.register_command("pcatmem", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_pcatmem, this, -1, _1)); + m_console.register_command("pcatmemd", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_pcatmem, this, AS_DATA, _1)); + m_console.register_command("pcatmemi", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_pcatmem, this, AS_IO, _1)); + m_console.register_command("pcatmemo", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_pcatmem, this, AS_OPCODES, _1)); + + m_console.register_command("snap", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_snap, this, _1)); + + m_console.register_command("source", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_source, this, _1)); + + m_console.register_command("map", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_map, this, -1, _1)); + m_console.register_command("mapd", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_map, this, AS_DATA, _1)); + m_console.register_command("mapi", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_map, this, AS_IO, _1)); + m_console.register_command("mapo", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_map, this, AS_OPCODES, _1)); + m_console.register_command("memdump", CMDFLAG_NONE, 0, 2, std::bind(&debugger_commands::execute_memdump, this, _1)); + + m_console.register_command("symlist", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_symlist, this, _1)); + + m_console.register_command("softreset", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_softreset, this, _1)); + m_console.register_command("hardreset", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_hardreset, this, _1)); + + m_console.register_command("images", CMDFLAG_NONE, 0, 0, std::bind(&debugger_commands::execute_images, this, _1)); + m_console.register_command("mount", CMDFLAG_NONE, 2, 2, std::bind(&debugger_commands::execute_mount, this, _1)); + m_console.register_command("unmount", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_unmount, this, _1)); + + m_console.register_command("input", CMDFLAG_NONE, 1, 1, std::bind(&debugger_commands::execute_input, this, _1)); + m_console.register_command("dumpkbd", CMDFLAG_NONE, 0, 1, std::bind(&debugger_commands::execute_dumpkbd, this, _1)); - /* set up the initial debugscript if specified */ + // set up the initial debugscript if specified const char* name = m_machine.options().debug_script(); if (name[0] != 0) m_console.source_script(name); - m_cheat.cpu[0] = m_cheat.cpu[1] = 0; + m_cheat.space = nullptr; } -/*------------------------------------------------- - execute_min - return the minimum of two values --------------------------------------------------*/ - -u64 debugger_commands::execute_min(symbol_table &table, int params, const u64 *param) -{ - return (param[0] < param[1]) ? param[0] : param[1]; -} +//------------------------------------------------- +// get_cpunum - getter callback for the +// 'cpunum' symbol +//------------------------------------------------- -/*------------------------------------------------- - execute_max - return the maximum of two values --------------------------------------------------*/ - -u64 debugger_commands::execute_max(symbol_table &table, int params, const u64 *param) +u64 debugger_commands::get_cpunum() { - return (param[0] > param[1]) ? param[0] : param[1]; -} - - -/*------------------------------------------------- - execute_if - if (a) return b; else return c; --------------------------------------------------*/ + unsigned index = 0; + for (device_execute_interface &exec : execute_interface_enumerator(m_machine.root_device())) + { + if (m_console.get_visible_cpu() == &exec.device()) + return index; -u64 debugger_commands::execute_if(symbol_table &table, int params, const u64 *param) -{ - return param[0] ? param[1] : param[2]; + // real CPUs should have pcbase + device_state_interface const *state; + if (exec.device().interface(state) && state->state_find_entry(STATE_GENPCBASE)) + ++index; + } + return u64(s64(-1)); } - /*************************************************************************** GLOBAL ACCESSORS ***************************************************************************/ @@ -340,14 +399,14 @@ u64 debugger_commands::execute_if(symbol_table &table, int params, const u64 *pa global_get - symbol table getter for globals -------------------------------------------------*/ -u64 debugger_commands::global_get(symbol_table &table, global_entry *global) +u64 debugger_commands::global_get(global_entry *global) { switch (global->size) { - case 1: return *(u8 *)global->base; - case 2: return *(u16 *)global->base; - case 4: return *(u32 *)global->base; - case 8: return *(u64 *)global->base; + case 1: return *(u8 *)global->base; + case 2: return *(u16 *)global->base; + case 4: return *(u32 *)global->base; + case 8: return *(u64 *)global->base; } return ~0; } @@ -357,210 +416,33 @@ u64 debugger_commands::global_get(symbol_table &table, global_entry *global) global_set - symbol table setter for globals -------------------------------------------------*/ -void debugger_commands::global_set(symbol_table &table, global_entry *global, u64 value) +void debugger_commands::global_set(global_entry *global, u64 value) { switch (global->size) { - case 1: *(u8 *)global->base = value; break; - case 2: *(u16 *)global->base = value; break; - case 4: *(u32 *)global->base = value; break; - case 8: *(u64 *)global->base = value; break; - } -} - - - -/*************************************************************************** - PARAMETER VALIDATION HELPERS -***************************************************************************/ - -/*------------------------------------------------- - validate_number_parameter - validates a - number parameter --------------------------------------------------*/ - -bool debugger_commands::validate_number_parameter(const std::string ¶m, u64 &result) -{ - /* evaluate the expression; success if no error */ - try - { - parsed_expression expression(m_cpu.get_visible_symtable(), param.c_str(), &result); - return true; - } - catch (expression_error &error) - { - /* print an error pointing to the character that caused it */ - m_console.printf("Error in expression: %s\n", param); - m_console.printf(" %*s^", error.offset(), ""); - m_console.printf("%s\n", error.code_string()); - return false; + case 1: *(u8 *)global->base = value; break; + case 2: *(u16 *)global->base = value; break; + case 4: *(u32 *)global->base = value; break; + case 8: *(u64 *)global->base = value; break; } } -/*------------------------------------------------- - validate_boolean_parameter - validates a - boolean parameter --------------------------------------------------*/ - -bool debugger_commands::validate_boolean_parameter(const std::string ¶m, bool &result) -{ - /* nullptr parameter does nothing and returns no error */ - if (param.empty()) - return true; - - /* evaluate the expression; success if no error */ - bool is_true = core_stricmp(param.c_str(), "true") == 0 || param == "1"; - bool is_false = core_stricmp(param.c_str(), "false") == 0 || param == "0"; - - if (!is_true && !is_false) - { - m_console.printf("Invalid boolean '%s'\n", param); - return false; - } - - result = is_true; - - return true; -} - -/*------------------------------------------------- - validate_cpu_parameter - validates a - parameter as a cpu --------------------------------------------------*/ - -bool debugger_commands::validate_cpu_parameter(const char *param, device_t *&result) -{ - /* if no parameter, use the visible CPU */ - if (param == nullptr) - { - result = m_cpu.get_visible_cpu(); - if (!result) - { - m_console.printf("No valid CPU is currently selected\n"); - return false; - } - return true; - } - - /* first look for a tag match */ - result = m_machine.root_device().subdevice(param); - if (result) - return true; - - /* then evaluate as an expression; on an error assume it was a tag */ - u64 cpunum; - try - { - parsed_expression expression(m_cpu.get_visible_symtable(), param, &cpunum); - } - catch (expression_error &) - { - m_console.printf("Unable to find CPU '%s'\n", param); - return false; - } - - // attempt to find by numerical index - int index = 0; - for (device_execute_interface &exec : execute_interface_iterator(m_machine.root_device())) - { - // real CPUs should have pcbase - const device_state_interface *state; - if (exec.device().interface(state) && state->state_find_entry(STATE_GENPCBASE) != nullptr && index++ == cpunum) - { - result = &exec.device(); - return true; - } - } - - /* if out of range, complain */ - m_console.printf("Invalid CPU index %d\n", (int)cpunum); - return false; -} - - -/*------------------------------------------------- - validate_cpu_space_parameter - validates - a parameter as a cpu and retrieves the given - address space --------------------------------------------------*/ - -bool debugger_commands::validate_cpu_space_parameter(const char *param, int spacenum, address_space *&result) -{ - /* first do the standard CPU thing */ - device_t *cpu; - if (!validate_cpu_parameter(param, cpu)) - return false; - - /* fetch the space pointer */ - if (!cpu->memory().has_space(spacenum)) - { - m_console.printf("No matching memory space found for CPU '%s'\n", cpu->tag()); - return false; - } - result = &cpu->memory().space(spacenum); - return true; -} - - -/*------------------------------------------------- - debug_command_parameter_expression - validates - an expression parameter --------------------------------------------------*/ - -bool debugger_commands::debug_command_parameter_expression(const std::string ¶m, parsed_expression &result) -{ - /* parse the expression; success if no error */ - try - { - result.parse(param.c_str()); - return true; - } - catch (expression_error &err) - { - /* output an error */ - m_console.printf("Error in expression: %s\n", param); - m_console.printf(" %*s^", err.offset(), ""); - m_console.printf("%s\n", err.code_string()); - return false; - } -} - - -/*------------------------------------------------- - debug_command_parameter_command - validates a - command parameter --------------------------------------------------*/ - -bool debugger_commands::debug_command_parameter_command(const char *param) -{ - /* nullptr parameter does nothing and returns no error */ - if (param == nullptr) - return true; - - /* validate the comment; success if no error */ - CMDERR err = m_console.validate_command(param); - if (err == CMDERR_NONE) - return true; - - /* output an error */ - m_console.printf("Error in command: %s\n", param); - m_console.printf(" %*s^", CMDERR_ERROR_OFFSET(err), ""); - m_console.printf("%s\n", debugger_console::cmderr_to_string(err)); - return 0; -} +//************************************************************************** +// COMMAND IMPLEMENTATIONS +//************************************************************************** /*------------------------------------------------- execute_help - execute the help command -------------------------------------------------*/ -void debugger_commands::execute_help(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_help(const std::vector<std::string_view> ¶ms) { if (params.size() == 0) - m_console.printf_wrap(80, "%s\n", debug_get_help("")); + m_console.printf_wrap(80, "%s\n", debug_get_help(std::string_view())); else - m_console.printf_wrap(80, "%s\n", debug_get_help(params[0].c_str())); + m_console.printf_wrap(80, "%s\n", debug_get_help(params[0])); } @@ -568,12 +450,12 @@ void debugger_commands::execute_help(int ref, const std::vector<std::string> &pa execute_print - execute the print command -------------------------------------------------*/ -void debugger_commands::execute_print(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_print(const std::vector<std::string_view> ¶ms) { /* validate the other parameters */ u64 values[MAX_COMMAND_PARAMS]; for (int i = 0; i < params.size(); i++) - if (!validate_number_parameter(params[i], values[i])) + if (!m_console.validate_number_parameter(params[i], values[i])) return; /* then print each one */ @@ -587,124 +469,221 @@ void debugger_commands::execute_print(int ref, const std::vector<std::string> &p mini_printf - safe printf to a buffer -------------------------------------------------*/ -int debugger_commands::mini_printf(char *buffer, const char *format, int params, u64 *param) +bool debugger_commands::mini_printf(std::ostream &stream, const std::vector<std::string_view> ¶ms) { - const char *f = format; - char *p = buffer; + std::string_view const format(params[0]); + auto f = format.begin(); - /* parse the string looking for % signs */ - for (;;) + int param = 1; + u64 number; + + // parse the string looking for % signs + while (f != format.end()) { char c = *f++; - if (!c) break; - /* escape sequences */ + // escape sequences if (c == '\\') { + if (f == format.end()) break; c = *f++; - if (!c) break; switch (c) { - case '\\': *p++ = c; break; - case 'n': *p++ = '\n'; break; + case '\\': stream << c; break; + case 'n': stream << '\n'; break; default: break; } continue; } - /* formatting */ + // formatting else if (c == '%') { + bool left_justify = false; + bool zero_fill = false; int width = 0; - int zerofill = 0; + int precision = 0; + + // parse optional left justification flag + if (f != format.end() && *f == '-') + { + left_justify = true; + f++; + } - /* parse out the width */ - for (;;) + // parse optional zero fill flag + if (f != format.end() && *f == '0') { - c = *f++; - if (!c || c < '0' || c > '9') break; - if (c == '0' && width == 0) - zerofill = 1; - width = width * 10 + (c - '0'); + zero_fill = true; + f++; + } + + // parse optional width + while (f != format.end() && isdigit(*f)) + width = width * 10 + (*f++ - '0'); + if (f == format.end()) + break; + + // apply left justification + if (left_justify) + width = -width; + + if ((c = *f++) == '.') + { + // parse optional precision + while (f != format.end() && isdigit(*f)) + precision = precision * 10 + (*f++ - '0'); + + // get the format + if (f != format.end()) + c = *f++; + else + break; } - if (!c) break; - /* get the format */ switch (c) { case '%': - *p++ = c; + stream << c; break; case 'X': + if (param < params.size() && m_console.validate_number_parameter(params[param++], number)) + util::stream_format(stream, zero_fill ? "%0*X" : "%*X", width, number); + else + { + m_console.printf("Not enough parameters for format!\n"); + return false; + } + break; case 'x': - if (params == 0) + if (param < params.size() && m_console.validate_number_parameter(params[param++], number)) + util::stream_format(stream, zero_fill ? "%0*x" : "%*x", width, number); + else { m_console.printf("Not enough parameters for format!\n"); - return 0; + return false; + } + break; + + case 'O': + case 'o': + if (param < params.size() && m_console.validate_number_parameter(params[param++], number)) + util::stream_format(stream, zero_fill ? "%0*o" : "%*o", width, number); + else + { + m_console.printf("Not enough parameters for format!\n"); + return false; } - if (u32(*param >> 32) != 0) - p += sprintf(p, zerofill ? "%0*X" : "%*X", (width <= 8) ? 1 : width - 8, u32(*param >> 32)); - else if (width > 8) - p += sprintf(p, zerofill ? "%0*X" : "%*X", width - 8, 0); - p += sprintf(p, zerofill ? "%0*X" : "%*X", (width < 8) ? width : 8, u32(*param)); - param++; - params--; break; case 'D': case 'd': - if (params == 0) + if (param < params.size() && m_console.validate_number_parameter(params[param++], number)) + util::stream_format(stream, zero_fill ? "%0*d" : "%*d", width, number); + else { m_console.printf("Not enough parameters for format!\n"); - return 0; + return false; } - p += sprintf(p, zerofill ? "%0*d" : "%*d", width, u32(*param)); - param++; - params--; break; + case 'C': case 'c': - if (params == 0) + if (param < params.size() && m_console.validate_number_parameter(params[param++], number)) + stream << char(number); + else { m_console.printf("Not enough parameters for format!\n"); - return 0; + return false; } - p += sprintf(p, "%c", char(*param)); - param++; - params--; break; + case 's': + { + address_space *space; + if (param < params.size() && m_console.validate_target_address_parameter(params[param++], -1, space, number)) + { + address_space *tspace; + std::string s; + + for (u32 address = u32(number), taddress; space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, taddress = address, tspace); address++) + { + u8 const data = tspace->read_byte(taddress); + + if (!data) + break; + + s += data; + + if (precision == 1) + break; + else if (precision) + precision--; + } + + util::stream_format(stream, "%*s", width, s); + } + else + { + m_console.printf("Not enough parameters for format!\n"); + return false; + } + } + break; } } - /* normal stuff */ + // normal stuff else - *p++ = c; + stream << c; } - /* NULL-terminate and exit */ - *p = 0; - return 1; + return true; } /*------------------------------------------------- - execute_printf - execute the printf command + execute_index_command - helper for commands + that take multiple indices as arguments -------------------------------------------------*/ -void debugger_commands::execute_printf(int ref, const std::vector<std::string> ¶ms) +template <typename T> +void debugger_commands::execute_index_command(std::vector<std::string_view> const ¶ms, T &&apply, char const *unused_message) { - /* validate the other parameters */ - u64 values[MAX_COMMAND_PARAMS]; - for (int i = 1; i < params.size(); i++) - if (!validate_number_parameter(params[i], values[i])) + std::vector<u64> index(params.size()); + for (int paramnum = 0; paramnum < params.size(); paramnum++) + { + if (!m_console.validate_number_parameter(params[paramnum], index[paramnum])) return; + } + for (device_t &device : device_enumerator(m_machine.root_device())) + { + for (auto param = index.begin(); index.end() != param; ) + { + if (apply(device, *param)) + param = index.erase(param); + else + ++param; + } + } + + for (auto const ¶m : index) + m_console.printf(unused_message, param); +} + + +/*------------------------------------------------- + execute_printf - execute the printf command +-------------------------------------------------*/ + +void debugger_commands::execute_printf(const std::vector<std::string_view> ¶ms) +{ /* then do a printf */ - char buffer[1024]; - if (mini_printf(buffer, params[0].c_str(), params.size() - 1, &values[1])) - m_console.printf("%s\n", buffer); + std::ostringstream buffer; + if (mini_printf(buffer, params)) + m_console.printf("%s\n", std::move(buffer).str()); } @@ -712,18 +691,12 @@ void debugger_commands::execute_printf(int ref, const std::vector<std::string> & execute_logerror - execute the logerror command -------------------------------------------------*/ -void debugger_commands::execute_logerror(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_logerror(const std::vector<std::string_view> ¶ms) { - /* validate the other parameters */ - u64 values[MAX_COMMAND_PARAMS]; - for (int i = 1; i < params.size(); i++) - if (!validate_number_parameter(params[i], values[i])) - return; - /* then do a printf */ - char buffer[1024]; - if (mini_printf(buffer, params[0].c_str(), params.size() - 1, &values[1])) - m_machine.logerror("%s", buffer); + std::ostringstream buffer; + if (mini_printf(buffer, params)) + m_machine.logerror("%s", std::move(buffer).str()); } @@ -731,18 +704,12 @@ void debugger_commands::execute_logerror(int ref, const std::vector<std::string> execute_tracelog - execute the tracelog command -------------------------------------------------*/ -void debugger_commands::execute_tracelog(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_tracelog(const std::vector<std::string_view> ¶ms) { - /* validate the other parameters */ - u64 values[MAX_COMMAND_PARAMS]; - for (int i = 1; i < params.size(); i++) - if (!validate_number_parameter(params[i], values[i])) - return; - /* then do a printf */ - char buffer[1024]; - if (mini_printf(buffer, params[0].c_str(), params.size() - 1, &values[1])) - m_cpu.get_visible_cpu()->debug()->trace_printf("%s", buffer); + std::ostringstream buffer; + if (mini_printf(buffer, params)) + m_console.get_visible_cpu()->debug()->trace_printf("%s", std::move(buffer).str()); } @@ -750,18 +717,17 @@ void debugger_commands::execute_tracelog(int ref, const std::vector<std::string> execute_tracesym - execute the tracesym command -------------------------------------------------*/ -void debugger_commands::execute_tracesym(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_tracesym(const std::vector<std::string_view> ¶ms) { // build a format string appropriate for the parameters and validate them - std::stringstream format; - u64 values[MAX_COMMAND_PARAMS]; + std::ostringstream format; for (int i = 0; i < params.size(); i++) { // find this symbol - symbol_entry *sym = m_cpu.get_visible_symtable()->find(params[i].c_str()); + symbol_entry *const sym = m_console.visible_symtable().find(strmakelower(params[i]).c_str()); if (!sym) { - m_console.printf("Unknown symbol: %s\n", params[i].c_str()); + m_console.printf("Unknown symbol: %s\n", params[i]); return; } @@ -769,16 +735,29 @@ void debugger_commands::execute_tracesym(int ref, const std::vector<std::string> util::stream_format(format, "%s=%s ", params[i], sym->format().empty() ? "%16X" : sym->format()); - - // validate the parameter - if (!validate_number_parameter(params[i], values[i])) - return; } + // build parameters for printf + auto const format_str = std::move(format).str(); // need this to stay put as long as the string_view exists + std::vector<std::string_view> printf_params; + printf_params.reserve(params.size() + 1); + printf_params.emplace_back(format_str); + std::copy(params.begin(), params.end(), std::back_inserter(printf_params)); + // then do a printf - char buffer[1024]; - if (mini_printf(buffer, format.str().c_str(), params.size(), values)) - m_cpu.get_visible_cpu()->debug()->trace_printf("%s", buffer); + std::ostringstream buffer; + if (mini_printf(buffer, printf_params)) + m_console.get_visible_cpu()->debug()->trace_printf("%s", std::move(buffer).str()); +} + + +/*------------------------------------------------- + execute_cls - execute the cls command +-------------------------------------------------*/ + +void debugger_commands::execute_cls(const std::vector<std::string_view> ¶ms) +{ + text_buffer_clear(m_console.get_console_textbuf()); } @@ -786,7 +765,7 @@ void debugger_commands::execute_tracesym(int ref, const std::vector<std::string> execute_quit - execute the quit command -------------------------------------------------*/ -void debugger_commands::execute_quit(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_quit(const std::vector<std::string_view> ¶ms) { osd_printf_warning("Exited via the debugger\n"); m_machine.schedule_exit(); @@ -797,10 +776,10 @@ void debugger_commands::execute_quit(int ref, const std::vector<std::string> &pa execute_do - execute the do command -------------------------------------------------*/ -void debugger_commands::execute_do(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_do(const std::vector<std::string_view> ¶ms) { u64 dummy; - validate_number_parameter(params[0], dummy); + m_console.validate_number_parameter(params[0], dummy); } @@ -808,14 +787,14 @@ void debugger_commands::execute_do(int ref, const std::vector<std::string> ¶ execute_step - execute the step command -------------------------------------------------*/ -void debugger_commands::execute_step(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_step(const std::vector<std::string_view> ¶ms) { /* if we have a parameter, use it */ u64 steps = 1; - if (params.size() > 0 && !validate_number_parameter(params[0], steps)) + if (params.size() > 0 && !m_console.validate_number_parameter(params[0], steps)) return; - m_cpu.get_visible_cpu()->debug()->single_step(steps); + m_console.get_visible_cpu()->debug()->single_step(steps); } @@ -823,14 +802,14 @@ void debugger_commands::execute_step(int ref, const std::vector<std::string> &pa execute_over - execute the over command -------------------------------------------------*/ -void debugger_commands::execute_over(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_over(const std::vector<std::string_view> ¶ms) { /* if we have a parameter, use it */ u64 steps = 1; - if (params.size() > 0 && !validate_number_parameter(params[0], steps)) + if (params.size() > 0 && !m_console.validate_number_parameter(params[0], steps)) return; - m_cpu.get_visible_cpu()->debug()->single_step_over(steps); + m_console.get_visible_cpu()->debug()->single_step_over(steps); } @@ -838,9 +817,9 @@ void debugger_commands::execute_over(int ref, const std::vector<std::string> &pa execute_out - execute the out command -------------------------------------------------*/ -void debugger_commands::execute_out(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_out(const std::vector<std::string_view> ¶ms) { - m_cpu.get_visible_cpu()->debug()->single_step_out(); + m_console.get_visible_cpu()->debug()->single_step_out(); } @@ -848,15 +827,15 @@ void debugger_commands::execute_out(int ref, const std::vector<std::string> &par execute_go - execute the go command -------------------------------------------------*/ -void debugger_commands::execute_go(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_go(const std::vector<std::string_view> ¶ms) { u64 addr = ~0; /* if we have a parameter, use it instead */ - if (params.size() > 0 && !validate_number_parameter(params[0], addr)) + if (params.size() > 0 && !m_console.validate_number_parameter(params[0], addr)) return; - m_cpu.get_visible_cpu()->debug()->go(addr); + m_console.get_visible_cpu()->debug()->go(addr); } @@ -865,9 +844,9 @@ void debugger_commands::execute_go(int ref, const std::vector<std::string> ¶ command -------------------------------------------------*/ -void debugger_commands::execute_go_vblank(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_go_vblank(const std::vector<std::string_view> ¶ms) { - m_cpu.get_visible_cpu()->debug()->go_vblank(); + m_console.get_visible_cpu()->debug()->go_vblank(); } @@ -875,30 +854,34 @@ void debugger_commands::execute_go_vblank(int ref, const std::vector<std::string execute_go_interrupt - execute the goint command -------------------------------------------------*/ -void debugger_commands::execute_go_interrupt(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_go_interrupt(const std::vector<std::string_view> ¶ms) { u64 irqline = -1; /* if we have a parameter, use it instead */ - if (params.size() > 0 && !validate_number_parameter(params[0], irqline)) + if (params.size() > 0 && !m_console.validate_number_parameter(params[0], irqline)) return; - m_cpu.get_visible_cpu()->debug()->go_interrupt(irqline); + m_console.get_visible_cpu()->debug()->go_interrupt(irqline); } /*------------------------------------------------- execute_go_exception - execute the goex command -------------------------------------------------*/ -void debugger_commands::execute_go_exception(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_go_exception(const std::vector<std::string_view> ¶ms) { u64 exception = -1; /* if we have a parameter, use it instead */ - if (params.size() > 0 && !validate_number_parameter(params[0], exception)) + if (params.size() > 0 && !m_console.validate_number_parameter(params[0], exception)) + return; + + parsed_expression condition(m_console.visible_symtable()); + if (params.size() > 1 && !m_console.validate_expression_parameter(params[1], condition)) return; - m_cpu.get_visible_cpu()->debug()->go_exception(exception); + m_console.get_visible_cpu()->debug()->go_exception(exception, condition.is_empty() ? "1" : condition.original_string()); } @@ -906,15 +889,15 @@ void debugger_commands::execute_go_exception(int ref, const std::vector<std::str execute_go_time - execute the gtime command -------------------------------------------------*/ -void debugger_commands::execute_go_time(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_go_time(const std::vector<std::string_view> ¶ms) { u64 milliseconds = -1; /* if we have a parameter, use it instead */ - if (params.size() > 0 && !validate_number_parameter(params[0], milliseconds)) + if (params.size() > 0 && !m_console.validate_number_parameter(params[0], milliseconds)) return; - m_cpu.get_visible_cpu()->debug()->go_milliseconds(milliseconds); + m_console.get_visible_cpu()->debug()->go_milliseconds(milliseconds); } @@ -922,22 +905,78 @@ void debugger_commands::execute_go_time(int ref, const std::vector<std::string> /*------------------------------------------------- execute_go_privilege - execute the gp command -------------------------------------------------*/ -void debugger_commands::execute_go_privilege(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_go_privilege(const std::vector<std::string_view> ¶ms) +{ + parsed_expression condition(m_console.visible_symtable()); + if (params.size() > 0 && !m_console.validate_expression_parameter(params[0], condition)) + return; + + m_console.get_visible_cpu()->debug()->go_privilege((condition.is_empty()) ? "1" : condition.original_string()); +} + + +/*------------------------------------------------- + execute_go_branch - execute gbt or gbf command +-------------------------------------------------*/ + +void debugger_commands::execute_go_branch(bool sense, const std::vector<std::string_view> ¶ms) +{ + parsed_expression condition(m_console.visible_symtable()); + if (params.size() > 0 && !m_console.validate_expression_parameter(params[0], condition)) + return; + + m_console.get_visible_cpu()->debug()->go_branch(sense, (condition.is_empty()) ? "1" : condition.original_string()); +} + + +/*------------------------------------------------- + execute_go_next_instruction - execute gni command +-------------------------------------------------*/ + +void debugger_commands::execute_go_next_instruction(const std::vector<std::string_view> ¶ms) { - parsed_expression condition(&m_cpu.get_visible_cpu()->debug()->symtable()); - if (params.size() > 0 && !debug_command_parameter_expression(params[0], condition)) + u64 count = 1; + static constexpr u64 MAX_COUNT = 512; + + // if we have a parameter, use it instead */ + if (params.size() > 0 && !m_console.validate_number_parameter(params[0], count)) + return; + if (count == 0) + return; + if (count > MAX_COUNT) + { + m_console.printf("Too many instructions (must be %d or fewer)\n", MAX_COUNT); + return; + } + + device_state_interface *stateintf; + device_t *cpu = m_console.get_visible_cpu(); + if (!cpu->interface(stateintf)) + { + m_console.printf("No state interface available for %s\n", cpu->name()); return; + } + u32 pc = stateintf->pcbase(); + + debug_disasm_buffer buffer(*cpu); + while (count-- != 0) + { + // disassemble the current instruction and get the length + u32 result = buffer.disassemble_info(pc); + pc = buffer.next_pc_wrap(pc, result & util::disasm_interface::LENGTHMASK); + } - m_cpu.get_visible_cpu()->debug()->go_privilege((condition.is_empty()) ? "1" : condition.original_string()); + cpu->debug()->go(pc); } + /*------------------------------------------------- execute_next - execute the next command -------------------------------------------------*/ -void debugger_commands::execute_next(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_next(const std::vector<std::string_view> ¶ms) { - m_cpu.get_visible_cpu()->debug()->go_next_device(); + m_console.get_visible_cpu()->debug()->go_next_device(); } @@ -945,18 +984,18 @@ void debugger_commands::execute_next(int ref, const std::vector<std::string> &pa execute_focus - execute the focus command -------------------------------------------------*/ -void debugger_commands::execute_focus(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_focus(const std::vector<std::string_view> ¶ms) { - /* validate params */ + // validate params device_t *cpu; - if (!validate_cpu_parameter(params[0].c_str(), cpu)) + if (!m_console.validate_cpu_parameter(params[0], cpu)) return; - /* first clear the ignore flag on the focused CPU */ + // first clear the ignore flag on the focused CPU cpu->debug()->ignore(false); - /* then loop over CPUs and set the ignore flags on all other CPUs */ - for (device_execute_interface &exec : execute_interface_iterator(m_machine.root_device())) + // then loop over CPUs and set the ignore flags on all other CPUs + for (device_execute_interface &exec : execute_interface_enumerator(m_machine.root_device())) if (&exec.device() != cpu) exec.device().debug()->ignore(true); m_console.printf("Now focused on CPU '%s'\n", cpu->tag()); @@ -967,17 +1006,17 @@ void debugger_commands::execute_focus(int ref, const std::vector<std::string> &p execute_ignore - execute the ignore command -------------------------------------------------*/ -void debugger_commands::execute_ignore(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_ignore(const std::vector<std::string_view> ¶ms) { - /* if there are no parameters, dump the ignore list */ if (params.empty()) { + // if there are no parameters, dump the ignore list std::string buffer; - /* loop over all executable devices */ - for (device_execute_interface &exec : execute_interface_iterator(m_machine.root_device())) - - /* build up a comma-separated list */ + // loop over all executable devices + for (device_execute_interface &exec : execute_interface_enumerator(m_machine.root_device())) + { + // build up a comma-separated list if (!exec.device().debug()->observing()) { if (buffer.empty()) @@ -985,29 +1024,29 @@ void debugger_commands::execute_ignore(int ref, const std::vector<std::string> & else buffer.append(string_format(", '%s'", exec.device().tag())); } + } - /* special message for none */ + // special message for none if (buffer.empty()) buffer = string_format("Not currently ignoring any devices"); - m_console.printf("%s\n", buffer.c_str()); + m_console.printf("%s\n", buffer); } - - /* otherwise clear the ignore flag on all requested CPUs */ else { + // otherwise clear the ignore flag on all requested CPUs device_t *devicelist[MAX_COMMAND_PARAMS]; - /* validate parameters */ + // validate parameters for (int paramnum = 0; paramnum < params.size(); paramnum++) - if (!validate_cpu_parameter(params[paramnum].c_str(), devicelist[paramnum])) + if (!m_console.validate_cpu_parameter(params[paramnum], devicelist[paramnum])) return; - /* set the ignore flags */ + // set the ignore flags for (int paramnum = 0; paramnum < params.size(); paramnum++) { - /* make sure this isn't the last live CPU */ + // make sure this isn't the last live CPU bool gotone = false; - for (device_execute_interface &exec : execute_interface_iterator(m_machine.root_device())) + for (device_execute_interface &exec : execute_interface_enumerator(m_machine.root_device())) if (&exec.device() != devicelist[paramnum] && exec.device().debug()->observing()) { gotone = true; @@ -1030,17 +1069,17 @@ void debugger_commands::execute_ignore(int ref, const std::vector<std::string> & execute_observe - execute the observe command -------------------------------------------------*/ -void debugger_commands::execute_observe(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_observe(const std::vector<std::string_view> ¶ms) { - /* if there are no parameters, dump the ignore list */ if (params.empty()) { + // if there are no parameters, dump the ignore list std::string buffer; - /* loop over all executable devices */ - for (device_execute_interface &exec : execute_interface_iterator(m_machine.root_device())) - - /* build up a comma-separated list */ + // loop over all executable devices + for (device_execute_interface &exec : execute_interface_enumerator(m_machine.root_device())) + { + // build up a comma-separated list if (exec.device().debug()->observing()) { if (buffer.empty()) @@ -1048,24 +1087,24 @@ void debugger_commands::execute_observe(int ref, const std::vector<std::string> else buffer.append(string_format(", '%s'", exec.device().tag())); } + } - /* special message for none */ + // special message for none if (buffer.empty()) buffer = string_format("Not currently observing any devices"); - m_console.printf("%s\n", buffer.c_str()); + m_console.printf("%s\n", buffer); } - - /* otherwise set the ignore flag on all requested CPUs */ else { + // otherwise set the ignore flag on all requested CPUs device_t *devicelist[MAX_COMMAND_PARAMS]; - /* validate parameters */ + // validate parameters for (int paramnum = 0; paramnum < params.size(); paramnum++) - if (!validate_cpu_parameter(params[paramnum].c_str(), devicelist[paramnum])) + if (!m_console.validate_cpu_parameter(params[paramnum], devicelist[paramnum])) return; - /* clear the ignore flags */ + // clear the ignore flags for (int paramnum = 0; paramnum < params.size(); paramnum++) { devicelist[paramnum]->debug()->ignore(false); @@ -1078,17 +1117,17 @@ void debugger_commands::execute_observe(int ref, const std::vector<std::string> execute_suspend - suspend execution on cpu -------------------------------------------------*/ -void debugger_commands::execute_suspend(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_suspend(const std::vector<std::string_view> ¶ms) { - /* if there are no parameters, dump the ignore list */ + // if there are no parameters, dump the ignore list if (params.empty()) { std::string buffer; - /* loop over all executable devices */ - for (device_execute_interface &exec : execute_interface_iterator(m_machine.root_device())) + // loop over all executable devices + for (device_execute_interface &exec : execute_interface_enumerator(m_machine.root_device())) - /* build up a comma-separated list */ + // build up a comma-separated list if (exec.device().debug()->suspended()) { if (buffer.empty()) @@ -1097,25 +1136,25 @@ void debugger_commands::execute_suspend(int ref, const std::vector<std::string> buffer.append(string_format(", '%s'", exec.device().tag())); } - /* special message for none */ + // special message for none if (buffer.empty()) buffer = string_format("No currently suspended devices"); - m_console.printf("%s\n", buffer.c_str()); + m_console.printf("%s\n", buffer); } else { device_t *devicelist[MAX_COMMAND_PARAMS]; - /* validate parameters */ + // validate parameters for (int paramnum = 0; paramnum < params.size(); paramnum++) - if (!validate_cpu_parameter(params[paramnum].c_str(), devicelist[paramnum])) + if (!m_console.validate_cpu_parameter(params[paramnum], devicelist[paramnum])) return; for (int paramnum = 0; paramnum < params.size(); paramnum++) { - /* make sure this isn't the last live CPU */ + // make sure this isn't the last live CPU bool gotone = false; - for (device_execute_interface &exec : execute_interface_iterator(m_machine.root_device())) + for (device_execute_interface &exec : execute_interface_enumerator(m_machine.root_device())) if (&exec.device() != devicelist[paramnum] && !exec.device().debug()->suspended()) { gotone = true; @@ -1137,17 +1176,17 @@ void debugger_commands::execute_suspend(int ref, const std::vector<std::string> execute_resume - Resume execution on CPU -------------------------------------------------*/ -void debugger_commands::execute_resume(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_resume(const std::vector<std::string_view> ¶ms) { - /* if there are no parameters, dump the ignore list */ + // if there are no parameters, dump the ignore list if (params.empty()) { std::string buffer; - /* loop over all executable devices */ - for (device_execute_interface &exec : execute_interface_iterator(m_machine.root_device())) + // loop over all executable devices + for (device_execute_interface &exec : execute_interface_enumerator(m_machine.root_device())) - /* build up a comma-separated list */ + // build up a comma-separated list if (exec.device().debug()->suspended()) { if (buffer.empty()) @@ -1156,18 +1195,18 @@ void debugger_commands::execute_resume(int ref, const std::vector<std::string> & buffer.append(string_format(", '%s'", exec.device().tag())); } - /* special message for none */ + // special message for none if (buffer.empty()) buffer = string_format("No currently suspended devices"); - m_console.printf("%s\n", buffer.c_str()); + m_console.printf("%s\n", buffer); } else { device_t *devicelist[MAX_COMMAND_PARAMS]; - /* validate parameters */ + // validate parameters for (int paramnum = 0; paramnum < params.size(); paramnum++) - if (!validate_cpu_parameter(params[paramnum].c_str(), devicelist[paramnum])) + if (!m_console.validate_cpu_parameter(params[paramnum], devicelist[paramnum])) return; for (int paramnum = 0; paramnum < params.size(); paramnum++) @@ -1178,32 +1217,56 @@ void debugger_commands::execute_resume(int ref, const std::vector<std::string> & } } +//------------------------------------------------- +// execute_cpulist - list all CPUs +//------------------------------------------------- + +void debugger_commands::execute_cpulist(const std::vector<std::string_view> ¶ms) +{ + int index = 0; + for (device_execute_interface &exec : execute_interface_enumerator(m_machine.root_device())) + { + const device_state_interface *state; + if (exec.device().interface(state) && state->state_find_entry(STATE_GENPCBASE) != nullptr) + m_console.printf("[%s%d] %s\n", &exec.device() == m_console.get_visible_cpu() ? "*" : "", index++, exec.device().tag()); + } +} + +//------------------------------------------------- +// execute_time - execute the time command +//------------------------------------------------- + +void debugger_commands::execute_time(const std::vector<std::string_view> ¶ms) +{ + m_console.printf("%s\n", m_machine.time().as_string()); +} + /*------------------------------------------------- execute_comment - add a comment to a line -------------------------------------------------*/ -void debugger_commands::execute_comment_add(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_comment_add(const std::vector<std::string_view> ¶ms) { - device_t *cpu; + // param 1 is the address for the comment u64 address; - - /* param 1 is the address for the comment */ - if (!validate_number_parameter(params[0], address)) + if (!m_console.validate_number_parameter(params[0], address)) return; - /* CPU parameter is implicit */ - if (!validate_cpu_parameter(nullptr, cpu)) + // CPU parameter is implicit + device_t *cpu; + if (!m_console.validate_cpu_parameter(std::string_view(), cpu)) return; - /* make sure param 2 exists */ + // make sure param 2 exists if (params[1].empty()) { m_console.printf("Error : comment text empty\n"); return; } - /* Now try adding the comment */ - cpu->debug()->comment_add(address, params[1].c_str(), 0x00ff0000); + // Now try adding the comment + std::string const text(params[1]); + cpu->debug()->comment_add(address, text.c_str(), 0x00ff0000); cpu->machine().debug_view().update_all(DVT_DISASSEMBLY); } @@ -1212,57 +1275,56 @@ void debugger_commands::execute_comment_add(int ref, const std::vector<std::stri execute_comment_del - remove a comment from an addr --------------------------------------------------------*/ -void debugger_commands::execute_comment_del(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_comment_del(const std::vector<std::string_view> ¶ms) { - device_t *cpu; + // param 1 can either be a command or the address for the comment u64 address; - - /* param 1 can either be a command or the address for the comment */ - if (!validate_number_parameter(params[0], address)) + if (!m_console.validate_number_parameter(params[0], address)) return; - /* CPU parameter is implicit */ - if (!validate_cpu_parameter(nullptr, cpu)) + // CPU parameter is implicit + device_t *cpu; + if (!m_console.validate_cpu_parameter(std::string_view(), cpu)) return; - /* If it's a number, it must be an address */ - /* The bankoff and cbn will be pulled from what's currently active */ + // If it's a number, it must be an address + // The bankoff and cbn will be pulled from what's currently active cpu->debug()->comment_remove(address); cpu->machine().debug_view().update_all(DVT_DISASSEMBLY); } /** - * @fn void execute_comment_list(running_machine &machine, int ref, int params, const char *param[]) + * @fn void execute_comment_list(const std::vector<std::string_view> ¶ms) * @brief Print current list of comments in debugger * * */ -void debugger_commands::execute_comment_list(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_comment_list(const std::vector<std::string_view> ¶ms) { if (!m_machine.debugger().cpu().comment_load(false)) m_console.printf("Error while parsing XML file\n"); } /** - * @fn void execute_comment_commit(running_machine &machine, int ref, int params, const char *param[]) + * @fn void execute_comment_commit(const std::vector<std::string_view> ¶ms) * @brief Add and Save current list of comments in debugger * */ -void debugger_commands::execute_comment_commit(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_comment_commit(const std::vector<std::string_view> ¶ms) { - execute_comment_add(ref, params); - execute_comment_save(ref, params); + execute_comment_add(params); + execute_comment_save(params); } /*------------------------------------------------- execute_comment - add a comment to a line -------------------------------------------------*/ -void debugger_commands::execute_comment_save(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_comment_save(const std::vector<std::string_view> ¶ms) { - if (m_cpu.comment_save()) + if (m_machine.debugger().cpu().comment_save()) m_console.printf("Comment successfully saved\n"); else m_console.printf("Comment not saved\n"); @@ -1270,7 +1332,7 @@ void debugger_commands::execute_comment_save(int ref, const std::vector<std::str // TODO: add color hex editing capabilities for comments, see below for more info /** - * @fn void execute_comment_color(running_machine &machine, int ref, int params, const char *param[]) + * @fn void execute_comment_color(const std::vector<std::string_view> ¶ms) * @brief Modifies comment given at address $xx with given color * Useful for marking comment with a different color scheme (for example by marking start and end of a given function visually). * @param[in] "address,color" First is the comment address in the current context, color can be hexadecimal or shorthanded to common 1bpp RGB names. @@ -1287,32 +1349,40 @@ void debugger_commands::execute_comment_save(int ref, const std::vector<std::str command -------------------------------------------------*/ -void debugger_commands::execute_bpset(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_bpset(const std::vector<std::string_view> ¶ms) { - device_t *cpu; + // param 1 is the address/CPU u64 address; - int bpnum; - const char *action = nullptr; + address_space *space; + if (!m_console.validate_target_address_parameter(params[0], AS_PROGRAM, space, address)) + return; - /* CPU is implicit */ - if (!validate_cpu_parameter(nullptr, cpu)) + 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(); - /* param 1 is the address */ - if (!validate_number_parameter(params[0], address)) + if (space->spacenum() != AS_PROGRAM) + { + m_console.printf("Only program space breakpoints are supported\n"); return; + } - /* param 2 is the condition */ - parsed_expression condition(&cpu->debug()->symtable()); - if (params.size() > 1 && !debug_command_parameter_expression(params[1], condition)) + // param 2 is the condition + parsed_expression condition(debug->symtable()); + if (params.size() > 1 && !m_console.validate_expression_parameter(params[1], condition)) return; - /* param 3 is the action */ - if (params.size() > 2 && !debug_command_parameter_command(action = params[2].c_str())) + // param 3 is the action + std::string_view action; + if (params.size() > 2 && !m_console.validate_command_parameter(action = params[2])) return; - /* set the breakpoint */ - bpnum = cpu->debug()->breakpoint_set(address, (condition.is_empty()) ? nullptr : condition.original_string(), action); + // set the breakpoint + int const bpnum = debug->breakpoint_set(address, condition.is_empty() ? nullptr : condition.original_string(), action); m_console.printf("Breakpoint %X set\n", bpnum); } @@ -1322,31 +1392,26 @@ void debugger_commands::execute_bpset(int ref, const std::vector<std::string> &p clear command -------------------------------------------------*/ -void debugger_commands::execute_bpclear(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_bpclear(const std::vector<std::string_view> ¶ms) { - u64 bpindex; - - /* if 0 parameters, clear all */ - if (params.empty()) + if (params.empty()) // if no parameters, clear all { - for (device_t &device : device_iterator(m_machine.root_device())) + for (device_t &device : device_enumerator(m_machine.root_device())) device.debug()->breakpoint_clear_all(); m_console.printf("Cleared all breakpoints\n"); } - - /* otherwise, clear the specific one */ - else if (!validate_number_parameter(params[0], bpindex)) - return; - else + else // otherwise, clear the specific ones { - bool found = false; - for (device_t &device : device_iterator(m_machine.root_device())) - if (device.debug()->breakpoint_clear(bpindex)) - found = true; - if (found) - m_console.printf("Breakpoint %X cleared\n", u32(bpindex)); - else - m_console.printf("Invalid breakpoint number %X\n", u32(bpindex)); + execute_index_command( + params, + [this] (device_t &device, u64 param) -> bool + { + if (!device.debug()->breakpoint_clear(param)) + return false; + m_console.printf("Breakpoint %X cleared\n", param); + return true; + }, + "Invalid breakpoint number %X\n"); } } @@ -1356,34 +1421,26 @@ void debugger_commands::execute_bpclear(int ref, const std::vector<std::string> disable/enable commands -------------------------------------------------*/ -void debugger_commands::execute_bpdisenable(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_bpdisenable(bool enable, const std::vector<std::string_view> ¶ms) { - u64 bpindex; - - /* if 0 parameters, clear all */ - if (params.empty()) + if (params.empty()) // if no parameters, disable/enable all { - for (device_t &device : device_iterator(m_machine.root_device())) - device.debug()->breakpoint_enable_all(ref); - if (ref == 0) - m_console.printf("Disabled all breakpoints\n"); - else - m_console.printf("Enabled all breakpoints\n"); + for (device_t &device : device_enumerator(m_machine.root_device())) + device.debug()->breakpoint_enable_all(enable); + m_console.printf(enable ? "Enabled all breakpoints\n" : "Disabled all breakpoints\n"); } - - /* otherwise, clear the specific one */ - else if (!validate_number_parameter(params[0], bpindex)) - return; - else + else // otherwise, disable/enable the specific ones { - bool found = false; - for (device_t &device : device_iterator(m_machine.root_device())) - if (device.debug()->breakpoint_enable(bpindex, ref)) - found = true; - if (found) - m_console.printf("Breakpoint %X %s\n", u32(bpindex), ref ? "enabled" : "disabled"); - else - m_console.printf("Invalid breakpoint number %X\n", u32(bpindex)); + execute_index_command( + params, + [this, enable] (device_t &device, u64 param) -> bool + { + if (!device.debug()->breakpoint_enable(param, enable)) + return false; + m_console.printf(enable ? "Breakpoint %X enabled\n" : "Breakpoint %X disabled\n", param); + return true; + }, + "Invalid breakpoint number %X\n"); } } @@ -1393,32 +1450,49 @@ void debugger_commands::execute_bpdisenable(int ref, const std::vector<std::stri command -------------------------------------------------*/ -void debugger_commands::execute_bplist(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_bplist(const std::vector<std::string_view> ¶ms) { int printed = 0; std::string buffer; - - /* loop over all CPUs */ - for (device_t &device : device_iterator(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 device_debug::breakpoint &bp : device.debug()->breakpoint_list()) + auto const apply = + [this, &printed, &buffer] (device_t &device) { - 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.c_str()); - 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 (!m_console.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"); + } } @@ -1427,50 +1501,57 @@ void debugger_commands::execute_bplist(int ref, const std::vector<std::string> & command -------------------------------------------------*/ -void debugger_commands::execute_wpset(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_wpset(int spacenum, const std::vector<std::string_view> ¶ms) { - address_space *space; - const char *action = nullptr; u64 address, length; - read_or_write type; - int wpnum; + address_space *space; - /* CPU is implicit */ - if (!validate_cpu_space_parameter(nullptr, ref, space)) + // param 1 is the address/CPU + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, address)) return; - /* param 1 is the address */ - if (!validate_number_parameter(params[0], address)) + 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(); - /* param 2 is the length */ - if (!validate_number_parameter(params[1], length)) + // param 2 is the length + if (!m_console.validate_number_parameter(params[1], length)) return; - /* param 3 is the type */ - if (params[2] == "r") - type = read_or_write::READ; - else if (params[2] == "w") - type = read_or_write::WRITE; - else if (params[2] == "rw" || params[2] == "wr") - type = read_or_write::READWRITE; - else + // param 3 is the type + read_or_write type; { - m_console.printf("Invalid watchpoint type: expected r, w, or rw\n"); - return; + using util::streqlower; + using namespace std::literals; + if (streqlower(params[2], "r"sv)) + type = read_or_write::READ; + else if (streqlower(params[2], "w"sv)) + type = read_or_write::WRITE; + else if (streqlower(params[2], "rw"sv) || streqlower(params[2], "wr"sv)) + type = read_or_write::READWRITE; + else + { + m_console.printf("Invalid watchpoint type: expected r, w, or rw\n"); + return; + } } - /* param 4 is the condition */ - parsed_expression condition(&space->device().debug()->symtable()); - if (params.size() > 3 && !debug_command_parameter_expression(params[3], condition)) + // param 4 is the condition + parsed_expression condition(debug->symtable()); + if (params.size() > 3 && !m_console.validate_expression_parameter(params[3], condition)) return; - /* param 5 is the action */ - if (params.size() > 4 && !debug_command_parameter_command(action = params[4].c_str())) + // param 5 is the action + std::string_view action; + if (params.size() > 4 && !m_console.validate_command_parameter(action = params[4])) return; - /* set the watchpoint */ - wpnum = space->device().debug()->watchpoint_set(*space, type, address, length, (condition.is_empty()) ? nullptr : condition.original_string(), action); + // set the watchpoint + int const wpnum = debug->watchpoint_set(*space, type, address, length, (condition.is_empty()) ? nullptr : condition.original_string(), action); m_console.printf("Watchpoint %X set\n", wpnum); } @@ -1480,31 +1561,26 @@ void debugger_commands::execute_wpset(int ref, const std::vector<std::string> &p clear command -------------------------------------------------*/ -void debugger_commands::execute_wpclear(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_wpclear(const std::vector<std::string_view> ¶ms) { - u64 wpindex; - - /* if 0 parameters, clear all */ - if (params.empty()) + if (params.empty()) // if no parameters, clear all { - for (device_t &device : device_iterator(m_machine.root_device())) + for (device_t &device : device_enumerator(m_machine.root_device())) device.debug()->watchpoint_clear_all(); m_console.printf("Cleared all watchpoints\n"); } - - /* otherwise, clear the specific one */ - else if (!validate_number_parameter(params[0], wpindex)) - return; - else + else // otherwise, clear the specific ones { - bool found = false; - for (device_t &device : device_iterator(m_machine.root_device())) - if (device.debug()->watchpoint_clear(wpindex)) - found = true; - if (found) - m_console.printf("Watchpoint %X cleared\n", u32(wpindex)); - else - m_console.printf("Invalid watchpoint number %X\n", u32(wpindex)); + execute_index_command( + params, + [this] (device_t &device, u64 param) -> bool + { + if (!device.debug()->watchpoint_clear(param)) + return false; + m_console.printf("Watchpoint %X cleared\n", param); + return true; + }, + "Invalid watchpoint number %X\n"); } } @@ -1514,34 +1590,26 @@ void debugger_commands::execute_wpclear(int ref, const std::vector<std::string> disable/enable commands -------------------------------------------------*/ -void debugger_commands::execute_wpdisenable(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_wpdisenable(bool enable, const std::vector<std::string_view> ¶ms) { - u64 wpindex; - - /* if 0 parameters, clear all */ - if (params.empty()) + if (params.empty()) // if no parameters, disable/enable all { - for (device_t &device : device_iterator(m_machine.root_device())) - device.debug()->watchpoint_enable_all(ref); - if (ref == 0) - m_console.printf("Disabled all watchpoints\n"); - else - m_console.printf("Enabled all watchpoints\n"); + for (device_t &device : device_enumerator(m_machine.root_device())) + device.debug()->watchpoint_enable_all(enable); + m_console.printf(enable ? "Enabled all watchpoints\n" : "Disabled all watchpoints\n"); } - - /* otherwise, clear the specific one */ - else if (!validate_number_parameter(params[0], wpindex)) - return; - else + else // otherwise, disable/enable the specific ones { - bool found = false; - for (device_t &device : device_iterator(m_machine.root_device())) - if (device.debug()->watchpoint_enable(wpindex, ref)) - found = true; - if (found) - m_console.printf("Watchpoint %X %s\n", u32(wpindex), ref ? "enabled" : "disabled"); - else - m_console.printf("Invalid watchpoint number %X\n", u32(wpindex)); + execute_index_command( + params, + [this, enable] (device_t &device, u64 param) -> bool + { + if (!device.debug()->watchpoint_enable(param, enable)) + return false; + m_console.printf(enable ? "Watchpoint %X enabled\n" : "Watchpoint %X disabled\n", param); + return true; + }, + "Invalid watchpoint number %X\n"); } } @@ -1551,39 +1619,61 @@ void debugger_commands::execute_wpdisenable(int ref, const std::vector<std::stri command -------------------------------------------------*/ -void debugger_commands::execute_wplist(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_wplist(const std::vector<std::string_view> ¶ms) { int printed = 0; std::string buffer; - - /* loop over all CPUs */ - for (device_t &device : device_iterator(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.c_str()); - 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 (!m_console.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"); + } } @@ -1592,28 +1682,26 @@ void debugger_commands::execute_wplist(int ref, const std::vector<std::string> & command -------------------------------------------------*/ -void debugger_commands::execute_rpset(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_rpset(const std::vector<std::string_view> ¶ms) { + // CPU is implicit device_t *cpu; - const char *action = nullptr; - int bpnum; - - /* CPU is implicit */ - if (!validate_cpu_parameter(nullptr, cpu)) + if (!m_console.validate_cpu_parameter(std::string_view(), cpu)) return; - /* param 1 is the condition */ - parsed_expression condition(&cpu->debug()->symtable()); - if (params.size() > 0 && !debug_command_parameter_expression(params[0], condition)) + // param 1 is the condition + parsed_expression condition(cpu->debug()->symtable()); + if (params.size() > 0 && !m_console.validate_expression_parameter(params[0], condition)) return; - /* param 2 is the action */ - if (params.size() > 1 && !debug_command_parameter_command(action = params[1].c_str())) + // param 2 is the action + std::string_view action; + if (params.size() > 1 && !m_console.validate_command_parameter(action = params[1])) return; - /* set the breakpoint */ - bpnum = cpu->debug()->registerpoint_set(condition.original_string(), action); - m_console.printf("Registerpoint %X set\n", bpnum); + // set the registerpoint + int const rpnum = cpu->debug()->registerpoint_set(condition.original_string(), action); + m_console.printf("Registerpoint %X set\n", rpnum); } @@ -1622,31 +1710,26 @@ void debugger_commands::execute_rpset(int ref, const std::vector<std::string> &p clear command -------------------------------------------------*/ -void debugger_commands::execute_rpclear(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_rpclear(const std::vector<std::string_view> ¶ms) { - u64 rpindex; - - /* if 0 parameters, clear all */ - if (params.empty()) + if (params.empty()) // if no parameters, clear all { - for (device_t &device : device_iterator(m_machine.root_device())) + for (device_t &device : device_enumerator(m_machine.root_device())) device.debug()->registerpoint_clear_all(); m_console.printf("Cleared all registerpoints\n"); } - - /* otherwise, clear the specific one */ - else if (!validate_number_parameter(params[0], rpindex)) - return; - else + else // otherwise, clear the specific ones { - bool found = false; - for (device_t &device : device_iterator(m_machine.root_device())) - if (device.debug()->registerpoint_clear(rpindex)) - found = true; - if (found) - m_console.printf("Registerpoint %X cleared\n", u32(rpindex)); - else - m_console.printf("Invalid registerpoint number %X\n", u32(rpindex)); + execute_index_command( + params, + [this] (device_t &device, u64 param) -> bool + { + if (!device.debug()->registerpoint_clear(param)) + return false; + m_console.printf("Registerpoint %X cleared\n", param); + return true; + }, + "Invalid registerpoint number %X\n"); } } @@ -1656,110 +1739,217 @@ void debugger_commands::execute_rpclear(int ref, const std::vector<std::string> disable/enable commands -------------------------------------------------*/ -void debugger_commands::execute_rpdisenable(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_rpdisenable(bool enable, const std::vector<std::string_view> ¶ms) { - u64 rpindex; - - /* if 0 parameters, clear all */ - if (params.empty()) + if (params.empty()) // if no parameters, disable/enable all { - for (device_t &device : device_iterator(m_machine.root_device())) - device.debug()->registerpoint_enable_all(ref); - if (ref == 0) - m_console.printf("Disabled all registerpoints\n"); - else - m_console.printf("Enabled all registeroints\n"); + for (device_t &device : device_enumerator(m_machine.root_device())) + device.debug()->registerpoint_enable_all(enable); + m_console.printf(enable ? "Enabled all registerpoints\n" : "Disabled all registerpoints\n"); + } + else // otherwise, disable/enable the specific ones + { + execute_index_command( + params, + [this, enable] (device_t &device, u64 param) -> bool + { + if (!device.debug()->registerpoint_enable(param, enable)) + return false; + m_console.printf(enable ? "Registerpoint %X enabled\n" : "Breakpoint %X disabled\n", param); + return true; + }, + "Invalid registerpoint number %X\n"); } +} + - /* otherwise, clear the specific one */ - else if (!validate_number_parameter(params[0], rpindex)) +//------------------------------------------------- +// execute_epset - execute the exception point +// set command +//------------------------------------------------- + +void debugger_commands::execute_epset(const std::vector<std::string_view> ¶ms) +{ + // CPU is implicit + device_t *cpu; + if (!m_console.validate_cpu_parameter(std::string_view(), cpu)) return; - else + + // param 1 is the exception type + u64 type; + if (!m_console.validate_number_parameter(params[0], type)) + return; + + // param 2 is the condition + parsed_expression condition(cpu->debug()->symtable()); + if (params.size() > 1 && !m_console.validate_expression_parameter(params[1], condition)) + return; + + // param 3 is the action + std::string_view action; + if (params.size() > 2 && !m_console.validate_command_parameter(action = params[2])) + return; + + // set the exception point + int epnum = cpu->debug()->exceptionpoint_set(type, (condition.is_empty()) ? nullptr : condition.original_string(), action); + m_console.printf("Exception point %X set\n", epnum); +} + + +//------------------------------------------------- +// execute_epclear - execute the exception point +// clear command +//------------------------------------------------- + +void debugger_commands::execute_epclear(const std::vector<std::string_view> ¶ms) +{ + if (params.empty()) // if no parameters, clear all { - bool found = false; - for (device_t &device : device_iterator(m_machine.root_device())) - if (device.debug()->registerpoint_enable(rpindex, ref)) - found = true; - if (found) - m_console.printf("Registerpoint %X %s\n", u32(rpindex), ref ? "enabled" : "disabled"); - else - m_console.printf("Invalid registerpoint number %X\n", u32(rpindex)); + for (device_t &device : device_enumerator(m_machine.root_device())) + device.debug()->exceptionpoint_clear_all(); + m_console.printf("Cleared all exception points\n"); + } + else // otherwise, clear the specific ones + { + execute_index_command( + params, + [this] (device_t &device, u64 param) -> bool + { + if (!device.debug()->exceptionpoint_clear(param)) + return false; + m_console.printf("Exception point %X cleared\n", param); + return true; + }, + "Invalid exception point number %X\n"); } } -/*------------------------------------------------- - execute_rplist - execute the registerpoint list - command --------------------------------------------------*/ +//------------------------------------------------- +// execute_epdisenable - execute the exception +// point disable/enable commands +//------------------------------------------------- -void debugger_commands::execute_rplist(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_epdisenable(bool enable, const std::vector<std::string_view> ¶ms) { - int printed = 0; - std::string buffer; + if (params.empty()) // if no parameters, disable/enable all + { + for (device_t &device : device_enumerator(m_machine.root_device())) + device.debug()->exceptionpoint_enable_all(enable); + m_console.printf(enable ? "Enabled all exception points\n" : "Disabled all exception points\n"); + } + else // otherwise, disable/enable the specific ones + { + execute_index_command( + params, + [this, enable] (device_t &device, u64 param) -> bool + { + if (!device.debug()->exceptionpoint_enable(param, enable)) + return false; + m_console.printf(enable ? "Exception point %X enabled\n" : "Exception point %X disabled\n", param); + return true; + }, + "Invalid exception point number %X\n"); + } +} - /* loop over all CPUs */ - for (device_t &device : device_iterator(m_machine.root_device())) - if (!device.debug()->registerpoint_list().empty()) - { - m_console.printf("Device '%s' registerpoints:\n", device.tag()); - /* loop over the breakpoints */ - for (const device_debug::registerpoint &rp : device.debug()->registerpoint_list()) +//------------------------------------------------- +// execute_eplist - execute the exception point +// list command +//------------------------------------------------- + +void debugger_commands::execute_eplist(const std::vector<std::string_view> ¶ms) +{ + int printed = 0; + std::string buffer; + auto const apply = + [this, &printed, &buffer] (device_t &device) { - buffer = string_format("%c%4X if %s", rp.enabled() ? ' ' : 'D', rp.index(), rp.condition()); - if (rp.action() != nullptr) - buffer.append(string_format(" do %s", rp.action())); - m_console.printf("%s\n", buffer.c_str()); - printed++; - } - } + if (!device.debug()->exceptionpoint_list().empty()) + { + m_console.printf("Device '%s' exception points:\n", device.tag()); + + // loop over the exception points + for (const auto &epp : device.debug()->exceptionpoint_list()) + { + debug_exceptionpoint &ep = *epp.second; + buffer = string_format("%c%4X : %X", ep.enabled() ? ' ' : 'D', ep.index(), ep.type()); + if (std::string(ep.condition()).compare("1") != 0) + buffer.append(string_format(" if %s", ep.condition())); + if (!ep.action().empty()) + buffer.append(string_format(" do %s", ep.action())); + m_console.printf("%s\n", buffer); + printed++; + } + } + }; - if (printed == 0) - m_console.printf("No registerpoints currently installed\n"); + if (!params.empty()) + { + device_t *cpu; + if (!m_console.validate_cpu_parameter(params[0], cpu)) + return; + apply(*cpu); + if (!printed) + m_console.printf("No exception points 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 exception points currently installed\n"); + } } /*------------------------------------------------- - execute_hotspot - execute the hotspot + execute_rplist - execute the registerpoint list command -------------------------------------------------*/ -void debugger_commands::execute_hotspot(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_rplist(const std::vector<std::string_view> ¶ms) { - /* if no params, and there are live hotspots, clear them */ - if (params.empty()) - { - bool cleared = false; - - /* loop over CPUs and find live spots */ - for (device_t &device : device_iterator(m_machine.root_device())) - if (device.debug()->hotspot_tracking_enabled()) + int printed = 0; + std::string buffer; + auto const apply = + [this, &printed, &buffer] (device_t &device) { - device.debug()->hotspot_track(0, 0); - m_console.printf("Cleared hotspot tracking on CPU '%s'\n", device.tag()); - cleared = true; - } + if (!device.debug()->registerpoint_list().empty()) + { + m_console.printf("Device '%s' registerpoints:\n", device.tag()); - /* if we cleared, we're done */ - if (cleared) + // loop over the registerpoints + for (const auto &rp : device.debug()->registerpoint_list()) + { + buffer = string_format("%c%4X if %s", rp.enabled() ? ' ' : 'D', rp.index(), rp.condition()); + if (!rp.action().empty()) + buffer.append(string_format(" do %s", rp.action())); + m_console.printf("%s\n", buffer); + printed++; + } + } + }; + + if (!params.empty()) + { + device_t *cpu; + if (!m_console.validate_cpu_parameter(params[0], cpu)) return; + apply(*cpu); + if (!printed) + m_console.printf("No registerpoints currently installed for CPU %s\n", cpu->tag()); + } + else + { + // loop over all CPUs + for (device_t &device : device_enumerator(m_machine.root_device())) + apply(device); + if (!printed) + m_console.printf("No registerpoints currently installed\n"); } - - /* extract parameters */ - device_t *device = nullptr; - if (!validate_cpu_parameter(!params.empty() ? params[0].c_str() : nullptr, device)) - return; - u64 count = 64; - if (params.size() > 1 && !validate_number_parameter(params[1], count)) - return; - u64 threshhold = 250; - if (params.size() > 2 && !validate_number_parameter(params[2], threshhold)) - return; - - /* attempt to install */ - device->debug()->hotspot_track(count, threshhold); - m_console.printf("Now tracking hotspots on CPU '%s' using %d slots with a threshold of %d\n", device->tag(), (int)count, (int)threshhold); } @@ -1767,10 +1957,9 @@ void debugger_commands::execute_hotspot(int ref, const std::vector<std::string> execute_statesave - execute the statesave command -------------------------------------------------*/ -void debugger_commands::execute_statesave(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_statesave(const std::vector<std::string_view> ¶ms) { - const std::string &filename(params[0]); - m_machine.immediate_save(filename.c_str()); + m_machine.immediate_save(params[0]); m_console.printf("State save attempted. Please refer to window message popup for results.\n"); } @@ -1779,13 +1968,12 @@ void debugger_commands::execute_statesave(int ref, const std::vector<std::string execute_stateload - execute the stateload command -------------------------------------------------*/ -void debugger_commands::execute_stateload(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_stateload(const std::vector<std::string_view> ¶ms) { - const std::string &filename(params[0]); - m_machine.immediate_load(filename.c_str()); + m_machine.immediate_load(params[0]); // clear all PC & memory tracks - for (device_t &device : device_iterator(m_machine.root_device())) + for (device_t &device : device_enumerator(m_machine.root_device())) { device.debug()->track_pc_data_clear(); device.debug()->track_mem_data_clear(); @@ -1798,12 +1986,12 @@ void debugger_commands::execute_stateload(int ref, const std::vector<std::string execute_rewind - execute the rewind command -------------------------------------------------*/ -void debugger_commands::execute_rewind(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_rewind(const std::vector<std::string_view> ¶ms) { bool success = m_machine.rewind_step(); if (success) // clear all PC & memory tracks - for (device_t &device : device_iterator(m_machine.root_device())) + for (device_t &device : device_enumerator(m_machine.root_device())) { device.debug()->track_pc_data_clear(); device.debug()->track_mem_data_clear(); @@ -1817,34 +2005,32 @@ void debugger_commands::execute_rewind(int ref, const std::vector<std::string> & execute_save - execute the save command -------------------------------------------------*/ -void debugger_commands::execute_save(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_save(int spacenum, const std::vector<std::string_view> ¶ms) { u64 offset, endoffset, length; address_space *space; - FILE *f; - /* validate parameters */ - if (!validate_number_parameter(params[1], offset)) - return; - if (!validate_number_parameter(params[2], length)) + // validate parameters + if (!m_console.validate_target_address_parameter(params[1], spacenum, space, offset)) return; - if (!validate_cpu_space_parameter(params.size() > 3 ? params[3].c_str() : nullptr, ref, space)) + if (!m_console.validate_number_parameter(params[2], length)) return; - /* determine the addresses to write */ + // determine the addresses to write endoffset = (offset + length - 1) & space->addrmask(); offset = offset & space->addrmask(); - endoffset ++; + endoffset++; - /* open the file */ - f = fopen(params[0].c_str(), "wb"); + // open the file + std::string const filename(params[0]); + FILE *const f = fopen(filename.c_str(), "wb"); if (!f) { - m_console.printf("Error opening file '%s'\n", params[0].c_str()); + m_console.printf("Error opening file '%s'\n", params[0]); return; } - /* now write the data out */ + // now write the data out auto dis = space->device().machine().disable_side_effects(); switch (space->addr_shift()) { @@ -1852,8 +2038,9 @@ void debugger_commands::execute_save(int ref, const std::vector<std::string> &pa for (u64 i = offset; i != endoffset; i++) { offs_t curaddr = i; - u64 data = space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr) ? - space->read_qword(curaddr) : space->unmap(); + address_space *tspace; + u64 data = space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace) ? + tspace->read_qword(curaddr) : space->unmap(); fwrite(&data, 8, 1, f); } break; @@ -1861,8 +2048,9 @@ void debugger_commands::execute_save(int ref, const std::vector<std::string> &pa for (u64 i = offset; i != endoffset; i++) { offs_t curaddr = i; - u32 data = space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr) ? - space->read_dword(curaddr) : space->unmap(); + address_space *tspace; + u32 data = space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace) ? + tspace->read_dword(curaddr) : space->unmap(); fwrite(&data, 4, 1, f); } break; @@ -1870,8 +2058,9 @@ void debugger_commands::execute_save(int ref, const std::vector<std::string> &pa for (u64 i = offset; i != endoffset; i++) { offs_t curaddr = i; - u16 data = space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr) ? - space->read_word(curaddr) : space->unmap(); + address_space *tspace; + u16 data = space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace) ? + tspace->read_word(curaddr) : space->unmap(); fwrite(&data, 2, 1, f); } break; @@ -1879,8 +2068,9 @@ void debugger_commands::execute_save(int ref, const std::vector<std::string> &pa for (u64 i = offset; i != endoffset; i++) { offs_t curaddr = i; - u8 data = space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr) ? - space->read_byte(curaddr) : space->unmap(); + address_space *tspace; + u8 data = space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace) ? + tspace->read_byte(curaddr) : space->unmap(); fwrite(&data, 1, 1, f); } break; @@ -1890,14 +2080,55 @@ void debugger_commands::execute_save(int ref, const std::vector<std::string> &pa for (u64 i = offset; i != endoffset; i+=16) { offs_t curaddr = i; - u16 data = space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr) ? - space->read_word(curaddr) : space->unmap(); + address_space *tspace; + u16 data = space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace) ? + tspace->read_word(curaddr) : space->unmap(); fwrite(&data, 2, 1, f); } break; } - /* close the file */ + // close the file + fclose(f); + m_console.printf("Data saved successfully\n"); +} + + +/*------------------------------------------------- + execute_saveregion - execute the save command on region memory +-------------------------------------------------*/ + +void debugger_commands::execute_saveregion(const std::vector<std::string_view> ¶ms) +{ + u64 offset, length; + memory_region *region; + + // validate parameters + if (!m_console.validate_number_parameter(params[1], offset)) + return; + if (!m_console.validate_number_parameter(params[2], length)) + return; + if (!m_console.validate_memory_region_parameter(params[3], region)) + return; + + if (offset >= region->bytes()) + { + m_console.printf("Invalid offset\n"); + return; + } + if ((length <= 0) || ((length + offset) >= region->bytes())) + length = region->bytes() - offset; + + /* open the file */ + std::string const filename(params[0]); + FILE *f = fopen(filename.c_str(), "wb"); + if (!f) + { + m_console.printf("Error opening file '%s'\n", params[0]); + return; + } + fwrite(region->base() + offset, 1, length, f); + fclose(f); m_console.printf("Data saved successfully\n"); } @@ -1907,25 +2138,24 @@ void debugger_commands::execute_save(int ref, const std::vector<std::string> &pa execute_load - execute the load command -------------------------------------------------*/ -void debugger_commands::execute_load(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_load(int spacenum, const std::vector<std::string_view> ¶ms) { u64 offset, endoffset, length = 0; address_space *space; // validate parameters - if (!validate_number_parameter(params[1], offset)) - return; - if (params.size() > 2 && !validate_number_parameter(params[2], length)) + if (!m_console.validate_target_address_parameter(params[1], spacenum, space, offset)) return; - if (!validate_cpu_space_parameter((params.size() > 3) ? params[3].c_str() : nullptr, ref, space)) + if (params.size() > 2 && !m_console.validate_number_parameter(params[2], length)) return; // open the file std::ifstream f; - f.open(params[0], std::ifstream::in | std::ifstream::binary); + std::string const fname(params[0]); + f.open(fname, std::ifstream::in | std::ifstream::binary); if (f.fail()) { - m_console.printf("Error opening file '%s'\n", params[0].c_str()); + m_console.printf("Error opening file '%s'\n", params[0]); return; } @@ -1945,7 +2175,9 @@ void debugger_commands::execute_load(int ref, const std::vector<std::string> &pa endoffset = (offset + length - 1) & space->addrmask(); offset = offset & space->addrmask(); 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: @@ -1954,8 +2186,9 @@ void debugger_commands::execute_load(int ref, const std::vector<std::string> &pa offs_t curaddr = i; u64 data; f.read((char *)&data, 8); - if (f && space->device().memory().translate(space->spacenum(), TRANSLATE_WRITE_DEBUG, curaddr)) - space->write_qword(curaddr, data); + address_space *tspace; + if (f && space->device().memory().translate(space->spacenum(), device_memory_interface::TR_WRITE, curaddr, tspace)) + tspace->write_qword(curaddr, data); } break; case -2: @@ -1964,8 +2197,9 @@ void debugger_commands::execute_load(int ref, const std::vector<std::string> &pa offs_t curaddr = i; u32 data; f.read((char *)&data, 4); - if (f && space->device().memory().translate(space->spacenum(), TRANSLATE_WRITE_DEBUG, curaddr)) - space->write_dword(curaddr, data); + address_space *tspace; + if (f && space->device().memory().translate(space->spacenum(), device_memory_interface::TR_WRITE, curaddr, tspace)) + tspace->write_dword(curaddr, data); } break; case -1: @@ -1974,8 +2208,9 @@ void debugger_commands::execute_load(int ref, const std::vector<std::string> &pa offs_t curaddr = i; u16 data; f.read((char *)&data, 2); - if (f && space->device().memory().translate(space->spacenum(), TRANSLATE_WRITE_DEBUG, curaddr)) - space->write_word(curaddr, data); + address_space *tspace; + if (f && space->device().memory().translate(space->spacenum(), device_memory_interface::TR_WRITE, curaddr, tspace)) + tspace->write_word(curaddr, data); } break; case 0: @@ -1984,8 +2219,9 @@ void debugger_commands::execute_load(int ref, const std::vector<std::string> &pa offs_t curaddr = i; u8 data; f.read((char *)&data, 1); - if (f && space->device().memory().translate(space->spacenum(), TRANSLATE_WRITE_DEBUG, curaddr)) - space->write_byte(curaddr, data); + address_space *tspace; + if (f && space->device().memory().translate(space->spacenum(), device_memory_interface::TR_WRITE, curaddr, tspace)) + tspace->write_byte(curaddr, data); } break; case 3: @@ -1996,8 +2232,9 @@ void debugger_commands::execute_load(int ref, const std::vector<std::string> &pa offs_t curaddr = i; u16 data; f.read((char *)&data, 2); - if (f && space->device().memory().translate(space->spacenum(), TRANSLATE_WRITE_DEBUG, curaddr)) - space->write_word(curaddr, data); + address_space *tspace; + if (f && space->device().memory().translate(space->spacenum(), device_memory_interface::TR_WRITE, curaddr, tspace)) + tspace->write_word(curaddr, data); } break; } @@ -2012,40 +2249,86 @@ void debugger_commands::execute_load(int ref, const std::vector<std::string> &pa /*------------------------------------------------- + execute_loadregion - execute the load command on region memory +-------------------------------------------------*/ + +void debugger_commands::execute_loadregion(const std::vector<std::string_view> ¶ms) +{ + u64 offset, length; + memory_region *region; + + // validate parameters + if (!m_console.validate_number_parameter(params[1], offset)) + return; + if (!m_console.validate_number_parameter(params[2], length)) + return; + if (!m_console.validate_memory_region_parameter(params[3], region)) + return; + + if (offset >= region->bytes()) + { + m_console.printf("Invalid offset\n"); + return; + } + if ((length <= 0) || ((length + offset) >= region->bytes())) + length = region->bytes() - offset; + + // open the file + std::string filename(params[0]); + FILE *const f = fopen(filename.c_str(), "rb"); + if (!f) + { + m_console.printf("Error opening file '%s'\n", params[0]); + return; + } + + fseek(f, 0L, SEEK_END); + u64 size = ftell(f); + rewind(f); + + // check file size + if (length >= size) + length = size; + + fread(region->base() + offset, 1, length, f); + + fclose(f); + m_console.printf("Data loaded successfully to memory : 0x%X to 0x%X\n", offset, offset + length - 1); +} + + +/*------------------------------------------------- execute_dump - execute the dump command -------------------------------------------------*/ -void debugger_commands::execute_dump(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_dump(int spacenum, const std::vector<std::string_view> ¶ms) { - /* validate parameters */ + // validate parameters + address_space *space; u64 offset; - if (!validate_number_parameter(params[1], offset)) + if (!m_console.validate_target_address_parameter(params[1], spacenum, space, offset)) return; u64 length; - if (!validate_number_parameter(params[2], length)) + if (!m_console.validate_number_parameter(params[2], length)) return; u64 width = 0; - if (params.size() > 3 && !validate_number_parameter(params[3], width)) - return; - - u64 ascii = 1; - if (params.size() > 4 && !validate_number_parameter(params[4], ascii)) + if (params.size() > 3 && !m_console.validate_number_parameter(params[3], width)) return; - address_space *space; - if (!validate_cpu_space_parameter((params.size() > 6) ? params[6].c_str() : nullptr, ref, space)) + bool ascii = true; + if (params.size() > 4 && !m_console.validate_boolean_parameter(params[4], ascii)) return; u64 rowsize = space->byte_to_address(16); - if (params.size() > 5 && !validate_number_parameter(params[5], rowsize)) + if (params.size() > 5 && !m_console.validate_number_parameter(params[5], rowsize)) return; int shift = space->addr_shift(); - u64 granularity = shift > 0 ? 2 : 1 << -shift; + u64 granularity = shift >= 0 ? 1 : 1 << -shift; - /* further validation */ + // further validation if (width == 0) width = space->data_width() / 8; if (width < space->address_to_byte(1)) @@ -2069,15 +2352,16 @@ void debugger_commands::execute_dump(int ref, const std::vector<std::string> &pa u64 endoffset = (offset + length - 1) & space->addrmask(); offset = offset & space->addrmask(); - /* open the file */ - FILE* f = fopen(params[0].c_str(), "w"); + // open the file + std::string filename(params[0]); + FILE *const f = fopen(filename.c_str(), "w"); if (!f) { - m_console.printf("Error opening file '%s'\n", params[0].c_str()); + m_console.printf("Error opening file '%s'\n", params[0]); return; } - /* now write the data out */ + // now write the data out util::ovectorstream output; output.reserve(200); @@ -2091,30 +2375,31 @@ void debugger_commands::execute_dump(int ref, const std::vector<std::string> &pa output.clear(); output.rdbuf()->clear(); - /* print the address */ + // print the address util::stream_format(output, "%0*X: ", space->logaddrchars(), i); - /* print the bytes */ + // print the bytes for (u64 j = 0; j < rowsize; j += delta) { if (i + j <= endoffset) { offs_t curaddr = i + j; - if (space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr)) + address_space *tspace; + if (space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace)) { switch (width) { case 8: - util::stream_format(output, " %016X", space->read_qword_unaligned(i+j)); + util::stream_format(output, " %016X", tspace->read_qword_unaligned(i+j)); break; case 4: - util::stream_format(output, " %08X", space->read_dword_unaligned(i+j)); + util::stream_format(output, " %08X", tspace->read_dword_unaligned(i+j)); break; case 2: - util::stream_format(output, " %04X", space->read_word_unaligned(i+j)); + util::stream_format(output, " %04X", tspace->read_word_unaligned(i+j)); break; case 1: - util::stream_format(output, " %02X", space->read_byte(i+j)); + util::stream_format(output, " %02X", tspace->read_byte(i+j)); break; } } @@ -2127,29 +2412,30 @@ void debugger_commands::execute_dump(int ref, const std::vector<std::string> &pa util::stream_format(output, " %*s", width * 2, ""); } - /* print the ASCII */ + // print the ASCII if (ascii) { util::stream_format(output, " "); for (u64 j = 0; j < rowsize && (i + j) <= endoffset; j += delta) { offs_t curaddr = i + j; - if (space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, curaddr)) + address_space *tspace; + if (space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace)) { u64 data = 0; switch (width) { case 8: - data = space->read_qword_unaligned(i+j); + data = tspace->read_qword_unaligned(i+j); break; case 4: - data = space->read_dword_unaligned(i+j); + data = tspace->read_dword_unaligned(i+j); break; case 2: - data = space->read_word_unaligned(i+j); + data = tspace->read_word_unaligned(i+j); break; case 1: - data = space->read_byte(i+j); + data = tspace->read_byte(i+j); break; } for (unsigned int b = 0; b != width; b++) { @@ -2164,167 +2450,361 @@ void debugger_commands::execute_dump(int ref, const std::vector<std::string> &pa } } - /* output the result */ + // output the result auto const &text = output.vec(); fprintf(f, "%.*s\n", int(unsigned(text.size())), &text[0]); } - /* close the file */ + // close the file fclose(f); m_console.printf("Data dumped successfully\n"); } -/*------------------------------------------------- - execute_cheatinit - initialize the cheat system --------------------------------------------------*/ +//------------------------------------------------- +// execute_strdump - execute the strdump command +//------------------------------------------------- -void debugger_commands::execute_cheatinit(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_strdump(int spacenum, const std::vector<std::string_view> ¶ms) { - u64 offset, length = 0, real_length = 0; - address_space *space; - u32 active_cheat = 0; - u64 curaddr; - u8 i, region_count = 0; + // validate parameters + u64 offset; + if (!m_console.validate_number_parameter(params[1], offset)) + return; - cheat_region_map cheat_region[100]; + u64 length; + if (!m_console.validate_number_parameter(params[2], length)) + return; - memset(cheat_region, 0, sizeof(cheat_region)); + u64 term = 0; + if (params.size() > 3 && !m_console.validate_number_parameter(params[3], term)) + return; - /* validate parameters */ - if (!validate_cpu_space_parameter((params.size() > 3) ? params[3].c_str() : nullptr, AS_PROGRAM, space)) + address_space *space; + if (!m_console.validate_device_space_parameter((params.size() > 4) ? params[4] : std::string_view(), spacenum, space)) return; - if (ref == 0) + // further validation + if (term >= 0x100 && term != u64(-0x80)) { - m_cheat.width = 1; - m_cheat.signed_cheat = false; - m_cheat.swapped_cheat = false; - if (!params.empty()) + m_console.printf("Invalid termination character\n"); + return; + } + + // open the file + std::string filename(params[0]); + FILE *f = fopen(filename.c_str(), "w"); + if (!f) + { + m_console.printf("Error opening file '%s'\n", params[0]); + return; + } + + const int shift = space->addr_shift(); + const unsigned delta = (shift >= 0) ? (1 << shift) : 1; + const unsigned width = (shift >= 0) ? 1 : (1 << -shift); + const bool be = space->endianness() == ENDIANNESS_BIG; + + offset = offset & space->addrmask(); + if (shift > 0) + length >>= shift; + + // now write the data out + util::ovectorstream output; + output.reserve(200); + + auto dis = space->device().machine().disable_side_effects(); + + bool terminated = true; + while (length-- != 0) + { + if (terminated) { - char *srtpnt = (char*)params[0].c_str(); + terminated = false; + output.clear(); + output.rdbuf()->clear(); - if (*srtpnt == 's') - m_cheat.signed_cheat = true; - else if (*srtpnt == 'u') - m_cheat.signed_cheat = false; - else + // print the address + util::stream_format(output, "%0*X: \"", space->logaddrchars(), offset); + } + + // get the character data + u64 data = 0; + offs_t curaddr = offset; + address_space *tspace; + if (space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, curaddr, tspace)) + { + switch (width) { - m_console.printf("Invalid sign: expected s or u\n"); - return; + case 1: + data = tspace->read_byte(curaddr); + break; + + case 2: + data = tspace->read_word(curaddr); + if (be) + data = swapendian_int16(data); + break; + + case 4: + data = tspace->read_dword(curaddr); + if (be) + data = swapendian_int32(data); + break; + + case 8: + data = tspace->read_qword(curaddr); + if (be) + data = swapendian_int64(data); + break; } + } - if (*(++srtpnt) == 'b') - m_cheat.width = 1; - else if (*srtpnt == 'w') - m_cheat.width = 2; - else if (*srtpnt == 'd') - m_cheat.width = 4; - else if (*srtpnt == 'q') - m_cheat.width = 8; - else + // print the characters + for (int n = 0; n < width; n++) + { + // check for termination within word + if (terminated) { - m_console.printf("Invalid width: expected b, w, d or q\n"); - return; + terminated = false; + + // output the result + auto const &text = output.vec(); + fprintf(f, "%.*s\"\n", int(unsigned(text.size())), &text[0]); + output.clear(); + output.rdbuf()->clear(); + + // print the address + util::stream_format(output, "%0*X.%d: \"", space->logaddrchars(), offset, n); + } + + u8 ch = data & 0xff; + data >>= 8; + + // check for termination + if (term == u64(-0x80)) + { + if (BIT(ch, 7)) + { + terminated = true; + ch &= 0x7f; + } + } + else if (ch == term) + { + terminated = true; + continue; } - if (*(++srtpnt) == 's') - m_cheat.swapped_cheat = true; + // check for non-ASCII characters + if (ch < 0x20 || ch >= 0x7f) + { + // use special or octal escape + if (ch >= 0x07 && ch <= 0x0d) + util::stream_format(output, "\\%c", "abtnvfr"[ch - 0x07]); + else + util::stream_format(output, "\\%03o", ch); + } else - m_cheat.swapped_cheat = false; + { + if (ch == '"' || ch == '\\') + output << '\\'; + output << char(ch); + } } + + if (terminated) + { + // output the result + auto const &text = output.vec(); + fprintf(f, "%.*s\"\n", int(unsigned(text.size())), &text[0]); + output.clear(); + output.rdbuf()->clear(); + } + + offset += delta; } - /* initialize entire memory by default */ - if (params.size() <= 1) + if (!terminated) { - for (address_map_entry &entry : space->map()->m_entrylist) + // output the result + auto const &text = output.vec(); + fprintf(f, "%.*s\"\\\n", int(unsigned(text.size())), &text[0]); + } + + // close the file + fclose(f); + m_console.printf("Data dumped successfully\n"); +} + + +/*------------------------------------------------- + execute_cheatrange - add a range to search for + cheats +-------------------------------------------------*/ + +void debugger_commands::execute_cheatrange(bool init, const std::vector<std::string_view> ¶ms) +{ + address_space *space = m_cheat.space; + if (!space && !init) + { + m_console.printf("Use cheatinit before cheatrange\n"); + return; + } + + u8 width = (space || !init) ? m_cheat.width : 1; + bool signed_cheat = (space || !init) ? m_cheat.signed_cheat : false; + bool swapped_cheat = (space || !init) ? m_cheat.swapped_cheat : false; + if (init) + { + // first argument is sign/size/swap flags + if (!params.empty()) { - cheat_region[region_count].offset = entry.m_addrstart & space->addrmask(); - cheat_region[region_count].endoffset = entry.m_addrend & space->addrmask(); - cheat_region[region_count].share = entry.m_share; - cheat_region[region_count].disabled = (entry.m_write.m_type == AMH_RAM) ? false : true; + std::string_view const &srtpnt = params[0]; + if (!srtpnt.empty()) + { + width = 1; + signed_cheat = false; + swapped_cheat = false; + } + + if (srtpnt.length() >= 1) + { + char const sspec = std::tolower((unsigned char)srtpnt[0]); + if (sspec == 's') + signed_cheat = true; + else if (sspec == 'u') + signed_cheat = false; + else + { + m_console.printf("Invalid sign: expected s or u\n"); + return; + } + } - /* disable double share regions */ - if (entry.m_share != nullptr) - for (i = 0; i < region_count; i++) - if (cheat_region[i].share != nullptr) - if (strcmp(cheat_region[i].share, entry.m_share) == 0) - cheat_region[region_count].disabled = true; + if (srtpnt.length() >= 2) + { + char const wspec = std::tolower((unsigned char)srtpnt[1]); + if (wspec == 'b') + width = 1; + else if (wspec == 'w') + width = 2; + else if (wspec == 'd') + width = 4; + else if (wspec == 'q') + width = 8; + else + { + m_console.printf("Invalid width: expected b, w, d or q\n"); + return; + } + } - region_count++; + if (srtpnt.length() >= 3) + { + if (std::tolower((unsigned char)srtpnt[2]) == 's') + swapped_cheat = true; + else + { + m_console.printf("Invalid swap: expected s\n"); + return; + } + } } + + // fourth argument is device/space + if (!m_console.validate_device_space_parameter((params.size() > 3) ? params[3] : std::string_view(), -1, space)) + return; } - else + + cheat_region_map cheat_region[100]; // FIXME: magic number + unsigned region_count = 0; + if (params.size() >= (init ? 3 : 2)) { - /* validate parameters */ - if (!validate_number_parameter(params[(ref == 0) ? 1 : 0], offset)) + // validate parameters + u64 offset, length; + if (!m_console.validate_number_parameter(params[init ? 1 : 0], offset)) return; - if (!validate_number_parameter(params[(ref == 0) ? 2 : 1], length)) + if (!m_console.validate_number_parameter(params[init ? 2 : 1], length)) return; - /* force region to the specified range */ + // force region to the specified range cheat_region[region_count].offset = offset & space->addrmask(); cheat_region[region_count].endoffset = (offset + length - 1) & space->addrmask(); cheat_region[region_count].share = nullptr; cheat_region[region_count].disabled = false; region_count++; } + else + { + // initialize to entire memory by default + for (address_map_entry &entry : space->map()->m_entrylist) + { + cheat_region[region_count].offset = entry.m_addrstart & space->addrmask(); + cheat_region[region_count].endoffset = entry.m_addrend & space->addrmask(); + cheat_region[region_count].share = entry.m_share; + cheat_region[region_count].disabled = entry.m_write.m_type != AMH_RAM; + + // disable duplicate share regions + if (entry.m_share) + for (unsigned i = 0; i < region_count; i++) + if (cheat_region[i].share && !strcmp(cheat_region[i].share, entry.m_share)) + cheat_region[region_count].disabled = true; + + if (!cheat_region[region_count].disabled) + region_count++; + } + } - /* determine the writable extent of each region in total */ - for (i = 0; i < region_count; i++) - if (!cheat_region[i].disabled) - for (curaddr = cheat_region[i].offset; curaddr <= cheat_region[i].endoffset; curaddr += m_cheat.width) - if (cheat_address_is_valid(*space, curaddr)) - real_length++; + // determine the writable extent of each region in total + u64 real_length = 0; + for (unsigned i = 0; i < region_count; i++) + for (u64 curaddr = cheat_region[i].offset; curaddr <= cheat_region[i].endoffset; curaddr += width) + if (cheat_address_is_valid(*space, curaddr)) + real_length++; - if (real_length == 0) + if (!real_length) { m_console.printf("No writable bytes found in this area\n"); return; } - if (ref == 0) + size_t active_cheat = 0; + if (init) { - /* initialize new cheat system */ - m_cheat.cheatmap.resize(real_length); + // initialize new cheat system + m_cheat.space = space; + m_cheat.width = width; m_cheat.undo = 0; - m_cheat.cpu[0] = params.size() > 3 ? params[3][0] : '0'; + m_cheat.signed_cheat = signed_cheat; + m_cheat.swapped_cheat = swapped_cheat; } else { - /* add range to cheat system */ - if (m_cheat.cpu[0] == 0) - { - m_console.printf("Use cheatinit before cheatrange\n"); - return; - } - - if (!validate_cpu_space_parameter(m_cheat.cpu, AS_PROGRAM, space)) - return; - active_cheat = m_cheat.cheatmap.size(); - m_cheat.cheatmap.resize(m_cheat.cheatmap.size() + real_length); } + m_cheat.cheatmap.resize(active_cheat + real_length); - /* initialize cheatmap in the selected space */ - for (i = 0; i < region_count; i++) - if (!cheat_region[i].disabled) - for (curaddr = cheat_region[i].offset; curaddr <= cheat_region[i].endoffset; curaddr += m_cheat.width) - if (cheat_address_is_valid(*space, curaddr)) - { - m_cheat.cheatmap[active_cheat].previous_value = cheat_read_extended(&m_cheat, *space, curaddr); - m_cheat.cheatmap[active_cheat].first_value = m_cheat.cheatmap[active_cheat].previous_value; - m_cheat.cheatmap[active_cheat].offset = curaddr; - m_cheat.cheatmap[active_cheat].state = 1; - m_cheat.cheatmap[active_cheat].undo = 0; - active_cheat++; - } + // initialize cheatmap in the selected space + for (unsigned i = 0; i < region_count; i++) + for (u64 curaddr = cheat_region[i].offset; curaddr <= cheat_region[i].endoffset; curaddr += width) + if (cheat_address_is_valid(*space, curaddr)) + { + m_cheat.cheatmap[active_cheat].previous_value = m_cheat.read_extended(curaddr); + m_cheat.cheatmap[active_cheat].first_value = m_cheat.cheatmap[active_cheat].previous_value; + m_cheat.cheatmap[active_cheat].offset = curaddr; + m_cheat.cheatmap[active_cheat].state = 1; + m_cheat.cheatmap[active_cheat].undo = 0; + active_cheat++; + } - /* give a detailed init message to avoid searches being mistakingly carried out on the wrong CPU */ - device_t *cpu = nullptr; - validate_cpu_parameter(m_cheat.cpu, cpu); - m_console.printf("%u cheat initialized for CPU index %s ( aka %s )\n", active_cheat, m_cheat.cpu, cpu->tag()); + // give a detailed init message to avoid searches being mistakenly carried out on the wrong CPU + m_console.printf( + "%u cheat locations initialized for %s '%s' %s space\n", + active_cheat, + space->device().type().fullname(), + space->device().tag(), + space->name()); } @@ -2332,14 +2812,8 @@ void debugger_commands::execute_cheatinit(int ref, const std::vector<std::string execute_cheatnext - execute the search -------------------------------------------------*/ -void debugger_commands::execute_cheatnext(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_cheatnext(bool initial, const std::vector<std::string_view> ¶ms) { - address_space *space; - u64 cheatindex; - u32 active_cheat = 0; - u8 condition; - u64 comp_value = 0; - enum { CHEAT_ALL = 0, @@ -2358,54 +2832,61 @@ void debugger_commands::execute_cheatnext(int ref, const std::vector<std::string CHEAT_CHANGEDBY }; - if (m_cheat.cpu[0] == 0) + address_space *const space = m_cheat.space; + if (!space) { m_console.printf("Use cheatinit before cheatnext\n"); return; } - if (!validate_cpu_space_parameter(m_cheat.cpu, AS_PROGRAM, space)) - return; - - if (params.size() > 1 && !validate_number_parameter(params[1], comp_value)) + u64 comp_value = 0; + if (params.size() > 1 && !m_console.validate_number_parameter(params[1], comp_value)) return; - comp_value = cheat_sign_extend(&m_cheat, comp_value); + comp_value = m_cheat.sign_extend(comp_value); - /* decode condition */ - if (params[0] == "all") - condition = CHEAT_ALL; - else if (params[0] == "equal" || params[0] == "eq") - condition = (params.size() > 1) ? CHEAT_EQUALTO : CHEAT_EQUAL; - else if (params[0] == "notequal" || params[0] == "ne") - condition = (params.size() > 1) ? CHEAT_NOTEQUALTO : CHEAT_NOTEQUAL; - else if (params[0] == "decrease" || params[0] == "de" || params[0] == "-") - condition = (params.size() > 1) ? CHEAT_DECREASEOF : CHEAT_DECREASE; - else if (params[0] == "increase" || params[0] == "in" || params[0] == "+") - condition = (params.size() > 1) ? CHEAT_INCREASEOF : CHEAT_INCREASE; - else if (params[0] == "decreaseorequal" || params[0] == "deeq") - condition = CHEAT_DECREASE_OR_EQUAL; - else if (params[0] == "increaseorequal" || params[0] == "ineq") - condition = CHEAT_INCREASE_OR_EQUAL; - else if (params[0] == "smallerof" || params[0] == "lt" || params[0] == "<") - condition = CHEAT_SMALLEROF; - else if (params[0] == "greaterof" || params[0] == "gt" || params[0] == ">") - condition = CHEAT_GREATEROF; - else if (params[0] == "changedby" || params[0] == "ch" || params[0] == "~") - condition = CHEAT_CHANGEDBY; - else + // decode condition + u8 condition; { - m_console.printf("Invalid condition type\n"); - return; + using util::streqlower; + using namespace std::literals; + if (streqlower(params[0], "all"sv)) + condition = CHEAT_ALL; + else if (streqlower(params[0], "equal"sv) || streqlower(params[0], "eq"sv)) + condition = (params.size() > 1) ? CHEAT_EQUALTO : CHEAT_EQUAL; + else if (streqlower(params[0], "notequal"sv) || streqlower(params[0], "ne"sv)) + condition = (params.size() > 1) ? CHEAT_NOTEQUALTO : CHEAT_NOTEQUAL; + else if (streqlower(params[0], "decrease"sv) || streqlower(params[0], "de"sv) || params[0] == "-"sv) + condition = (params.size() > 1) ? CHEAT_DECREASEOF : CHEAT_DECREASE; + else if (streqlower(params[0], "increase"sv) || streqlower(params[0], "in"sv) || params[0] == "+"sv) + condition = (params.size() > 1) ? CHEAT_INCREASEOF : CHEAT_INCREASE; + else if (streqlower(params[0], "decreaseorequal"sv) || streqlower(params[0], "deeq"sv)) + condition = CHEAT_DECREASE_OR_EQUAL; + else if (streqlower(params[0], "increaseorequal"sv) || streqlower(params[0], "ineq"sv)) + condition = CHEAT_INCREASE_OR_EQUAL; + else if (streqlower(params[0], "smallerof"sv) || streqlower(params[0], "lt"sv) || params[0] == "<"sv) + condition = CHEAT_SMALLEROF; + else if (streqlower(params[0], "greaterof"sv) || streqlower(params[0], "gt"sv) || params[0] == ">"sv) + condition = CHEAT_GREATEROF; + else if (streqlower(params[0], "changedby"sv) || streqlower(params[0], "ch"sv) || params[0] == "~"sv) + condition = CHEAT_CHANGEDBY; + else + { + m_console.printf("Invalid condition type\n"); + return; + } } m_cheat.undo++; - /* execute the search */ - for (cheatindex = 0; cheatindex < m_cheat.cheatmap.size(); cheatindex += 1) + // execute the search + u32 active_cheat = 0; + for (u64 cheatindex = 0; cheatindex < m_cheat.cheatmap.size(); cheatindex += 1) if (m_cheat.cheatmap[cheatindex].state == 1) { - u64 cheat_value = cheat_read_extended(&m_cheat, *space, m_cheat.cheatmap[cheatindex].offset); - u64 comp_byte = (ref == 0) ? m_cheat.cheatmap[cheatindex].previous_value : m_cheat.cheatmap[cheatindex].first_value; + u64 cheat_value = m_cheat.read_extended(m_cheat.cheatmap[cheatindex].offset); + u64 comp_byte = initial + ? m_cheat.cheatmap[cheatindex].first_value + : m_cheat.cheatmap[cheatindex].previous_value; u8 disable_byte = false; switch (condition) @@ -2494,12 +2975,12 @@ void debugger_commands::execute_cheatnext(int ref, const std::vector<std::string else active_cheat++; - /* update previous value */ + // update previous value m_cheat.cheatmap[cheatindex].previous_value = cheat_value; } if (active_cheat <= 5) - execute_cheatlist(0, std::vector<std::string>()); + execute_cheatlist(std::vector<std::string_view>()); m_console.printf("%u cheats found\n", active_cheat); } @@ -2509,51 +2990,79 @@ void debugger_commands::execute_cheatnext(int ref, const std::vector<std::string execute_cheatlist - show a list of active cheat -------------------------------------------------*/ -void debugger_commands::execute_cheatlist(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_cheatlist(const std::vector<std::string_view> ¶ms) { - char spaceletter, sizeletter; - address_space *space; - device_t *cpu; - u32 active_cheat = 0; - u64 cheatindex; - u64 sizemask; - FILE *f = nullptr; - - if (!validate_cpu_space_parameter(m_cheat.cpu, AS_PROGRAM, space)) - return; - - if (!validate_cpu_parameter(m_cheat.cpu, cpu)) + address_space *const space = m_cheat.space; + if (!space) + { + m_console.printf("Use cheatinit before cheatlist\n"); return; + } + FILE *f = nullptr; if (params.size() > 0) - f = fopen(params[0].c_str(), "w"); + { + std::string filename(params[0]); + f = fopen(filename.c_str(), "w"); + if (!f) + { + m_console.printf("Error opening file '%s'\n", params[0]); + return; + } + } + // get device/space syntax for memory access + std::string tag(space->device().tag()); + std::string spaceletter; switch (space->spacenum()) { - default: - case AS_PROGRAM: spaceletter = 'p'; break; - case AS_DATA: spaceletter = 'd'; break; - case AS_IO: spaceletter = 'i'; break; - case AS_OPCODES: spaceletter = 'o'; break; + default: + tag.append(1, ':'); + tag.append(space->name()); + break; + case AS_PROGRAM: + spaceletter = "p"; + break; + case AS_DATA: + spaceletter = "d"; + break; + case AS_IO: + spaceletter = "i"; + break; + case AS_OPCODES: + spaceletter = "3"; + break; } + // get size syntax for memory access and formatting values + bool const octal = space->is_octal(); + int const addrchars = octal + ? ((2 + space->logaddr_width()) / 3) + : ((3 + space->logaddr_width()) / 4); + int const datachars = octal + ? ((2 + (m_cheat.width * 8)) / 3) + : ((3 + (m_cheat.width * 8)) / 4); + u64 const sizemask = util::make_bitmask<u64>(m_cheat.width * 8); + char sizeletter; switch (m_cheat.width) { - default: - case 1: sizeletter = 'b'; sizemask = 0xffU; break; - case 2: sizeletter = 'w'; sizemask = 0xffffU; break; - case 4: sizeletter = 'd'; sizemask = 0xffffffffU; break; - case 8: sizeletter = 'q'; sizemask = 0xffffffffffffffffU; break; + default: + case 1: sizeletter = 'b'; break; + case 2: sizeletter = 'w'; break; + case 4: sizeletter = 'd'; break; + case 8: sizeletter = 'q'; break; } - /* write the cheat list */ + // write the cheat list + u32 active_cheat = 0; util::ovectorstream output; - for (cheatindex = 0; cheatindex < m_cheat.cheatmap.size(); cheatindex += 1) + for (u64 cheatindex = 0; cheatindex < m_cheat.cheatmap.size(); cheatindex += 1) { if (m_cheat.cheatmap[cheatindex].state == 1) { - u64 value = cheat_byte_swap(&m_cheat, cheat_read_extended(&m_cheat, *space, m_cheat.cheatmap[cheatindex].offset)) & sizemask; - offs_t address = space->byte_to_address(m_cheat.cheatmap[cheatindex].offset); + u64 const value = m_cheat.byte_swap(m_cheat.read_extended(m_cheat.cheatmap[cheatindex].offset)) & sizemask; + u64 const first_value = m_cheat.byte_swap(m_cheat.cheatmap[cheatindex].first_value) & sizemask; + offs_t const address = space->byte_to_address(m_cheat.cheatmap[cheatindex].offset); if (!params.empty()) { @@ -2562,23 +3071,31 @@ void debugger_commands::execute_cheatlist(int ref, const std::vector<std::string output.rdbuf()->clear(); stream_format( output, - " <cheat desc=\"Possibility %d : %0*X (%0*X)\">\n" - " <script state=\"run\">\n" - " <action>%s.p%c%c@%0*X=%0*X</action>\n" - " </script>\n" - " </cheat>\n\n", - active_cheat, space->logaddrchars(), address, m_cheat.width * 2, value, - cpu->tag(), spaceletter, sizeletter, space->logaddrchars(), address, m_cheat.width * 2, cheat_byte_swap(&m_cheat, m_cheat.cheatmap[cheatindex].first_value) & sizemask); + octal ? + " <cheat desc=\"Possibility %d: 0%0*o (0%0*o)\">\n" + " <script state=\"run\">\n" + " <action>%s.%s%c@0o%0*o=0o%0*o</action>\n" + " </script>\n" + " </cheat>\n\n" : + " <cheat desc=\"Possibility %d: %0*X (%0*X)\">\n" + " <script state=\"run\">\n" + " <action>%s.%s%c@0x%0*X=0x%0*X</action>\n" + " </script>\n" + " </cheat>\n\n", + active_cheat, addrchars, address, datachars, value, + tag, spaceletter, sizeletter, addrchars, address, datachars, first_value); auto const &text(output.vec()); fprintf(f, "%.*s", int(unsigned(text.size())), &text[0]); } else { m_console.printf( - "Address=%0*X Start=%0*X Current=%0*X\n", - space->logaddrchars(), address, - m_cheat.width * 2, cheat_byte_swap(&m_cheat, m_cheat.cheatmap[cheatindex].first_value) & sizemask, - m_cheat.width * 2, value); + octal + ? "Address=0%0*o Start=0%0*o Current=0%0*o\n" + : "Address=%0*X Start=%0*X Current=%0*X\n", + addrchars, address, + datachars, first_value, + datachars, value); } } } @@ -2591,14 +3108,12 @@ void debugger_commands::execute_cheatlist(int ref, const std::vector<std::string execute_cheatundo - undo the last search -------------------------------------------------*/ -void debugger_commands::execute_cheatundo(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_cheatundo(const std::vector<std::string_view> ¶ms) { - u64 cheatindex; - u32 undo_count = 0; - if (m_cheat.undo > 0) { - for (cheatindex = 0; cheatindex < m_cheat.cheatmap.size(); cheatindex += 1) + u64 undo_count = 0; + for (u64 cheatindex = 0; cheatindex < m_cheat.cheatmap.size(); cheatindex += 1) { if (m_cheat.cheatmap[cheatindex].undo == m_cheat.undo) { @@ -2612,7 +3127,9 @@ void debugger_commands::execute_cheatundo(int ref, const std::vector<std::string m_console.printf("%u cheat reactivated\n", undo_count); } else + { m_console.printf("Maximum undo reached\n"); + } } @@ -2620,89 +3137,119 @@ void debugger_commands::execute_cheatundo(int ref, const std::vector<std::string execute_find - execute the find command -------------------------------------------------*/ -void debugger_commands::execute_find(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_find(int spacenum, const std::vector<std::string_view> ¶ms) { - u64 offset, endoffset, length; + u64 offset, length; address_space *space; - u64 data_to_find[256]; - u8 data_size[256]; - int cur_data_size; - int data_count = 0; - int found = 0; - int j; - /* validate parameters */ - if (!validate_number_parameter(params[0], offset)) - return; - if (!validate_number_parameter(params[1], length)) + // validate parameters + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, offset)) return; - if (!validate_cpu_space_parameter(nullptr, ref, space)) + if (!m_console.validate_number_parameter(params[1], length)) return; - /* further validation */ - endoffset = space->address_to_byte_end((offset + length - 1) & space->addrmask()); + // further validation + u64 const endoffset = space->address_to_byte_end((offset + length - 1) & space->addrmask()); offset = space->address_to_byte(offset & space->addrmask()); - cur_data_size = space->addr_shift() > 0 ? 2 : 1 << -space->addr_shift(); + int cur_data_size = (space->addr_shift() > 0) ? 2 : (1 << -space->addr_shift()); if (cur_data_size == 0) cur_data_size = 1; - /* parse the data parameters */ + // parse the data parameters + u64 data_to_find[256]; + u8 data_size[256]; + int data_count = 0; for (int i = 2; i < params.size(); i++) { - const char *pdata = params[i].c_str(); - size_t pdatalen = strlen(pdata) - 1; + std::string_view pdata = params[i]; - /* check for a string */ - if (pdata[0] == '"' && pdata[pdatalen] == '"') + if (!pdata.empty() && pdata.front() == '"' && pdata.back() == '"') // check for a string { - for (j = 1; j < pdatalen; j++) + auto const pdatalen = params[i].length() - 1; + for (int j = 1; j < pdatalen; j++) { data_to_find[data_count] = pdata[j]; data_size[data_count++] = 1; } } - - /* otherwise, validate as a number */ - else + else // otherwise, validate as a number { - /* check for a 'b','w','d',or 'q' prefix */ + // check for a 'b','w','d',or 'q' prefix data_size[data_count] = cur_data_size; - if (tolower(u8(pdata[0])) == 'b' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 1; pdata += 2; } - if (tolower(u8(pdata[0])) == 'w' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 2; pdata += 2; } - if (tolower(u8(pdata[0])) == 'd' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 4; pdata += 2; } - if (tolower(u8(pdata[0])) == 'q' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 8; pdata += 2; } + if (pdata.length() >= 2) + { + if (tolower(u8(pdata[0])) == 'b' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 1; pdata.remove_prefix(2); } + if (tolower(u8(pdata[0])) == 'w' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 2; pdata.remove_prefix(2); } + if (tolower(u8(pdata[0])) == 'd' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 4; pdata.remove_prefix(2); } + if (tolower(u8(pdata[0])) == 'q' && pdata[1] == '.') { data_size[data_count] = cur_data_size = 8; pdata.remove_prefix(2); } + } - /* look for a wildcard */ - if (!strcmp(pdata, "?")) + // look for a wildcard + if (pdata == "?") data_size[data_count++] |= 0x10; - /* otherwise, validate as a number */ - else if (!validate_number_parameter(pdata, data_to_find[data_count++])) + // otherwise, validate as a number + else if (!m_console.validate_number_parameter(pdata, data_to_find[data_count++])) return; } } - /* now search */ + // now search + device_memory_interface &memory = space->device().memory(); + auto dis = space->device().machine().disable_side_effects(); + int found = 0; for (u64 i = offset; i <= endoffset; i += data_size[0]) { int suboffset = 0; - int match = 1; + bool match = true; - /* find the entire string */ - for (j = 0; j < data_count && match; j++) + // find the entire string + for (int j = 0; j < data_count && match; j++) { + offs_t address = space->byte_to_address(i + suboffset); + address_space *tspace; switch (data_size[j]) { - case 1: match = (u8(m_cpu.read_byte(*space, space->byte_to_address(i + suboffset), true)) == u8(data_to_find[j])); break; - case 2: match = (u16(m_cpu.read_word(*space, space->byte_to_address(i + suboffset), true)) == u16(data_to_find[j])); break; - case 4: match = (u32(m_cpu.read_dword(*space, space->byte_to_address(i + suboffset), true)) == u32(data_to_find[j])); break; - case 8: match = (u64(m_cpu.read_qword(*space, space->byte_to_address(i + suboffset), true)) == u64(data_to_find[j])); break; - default: /* all other cases are wildcards */ break; + case 1: + address &= space->logaddrmask(); + if (memory.translate(space->spacenum(), device_memory_interface::TR_READ, address, tspace)) + match = tspace->read_byte(address) == u8(data_to_find[j]); + else + match = false; + break; + + case 2: + address &= space->logaddrmask(); + if (memory.translate(space->spacenum(), device_memory_interface::TR_READ, address, tspace)) + match = tspace->read_word_unaligned(address) == u16(data_to_find[j]); + else + match = false; + break; + + case 4: + address &= space->logaddrmask(); + if (memory.translate(space->spacenum(), device_memory_interface::TR_READ, address, tspace)) + match = tspace->read_dword_unaligned(address) == u32(data_to_find[j]); + else + match = false; + break; + + case 8: + address &= space->logaddrmask(); + if (memory.translate(space->spacenum(), device_memory_interface::TR_READ, address, tspace)) + match = tspace->read_qword_unaligned(address) == u64(data_to_find[j]); + else + match = false; + break; + + default: + // all other cases are wildcards + break; } suboffset += data_size[j] & 0x0f; } - /* did we find it? */ + // did we find it? if (match) { found++; @@ -2710,32 +3257,142 @@ void debugger_commands::execute_find(int ref, const std::vector<std::string> &pa } } - /* print something if not found */ + // print something if not found if (found == 0) m_console.printf("Not found\n"); } +//------------------------------------------------- +// execute_fill - execute the fill command +//------------------------------------------------- + +void debugger_commands::execute_fill(int spacenum, const std::vector<std::string_view> ¶ms) +{ + u64 offset, length; + address_space *space; + + // validate parameters + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, offset)) + return; + if (!m_console.validate_number_parameter(params[1], length)) + return; + + // further validation + offset = space->address_to_byte(offset & space->addrmask()); + int cur_data_size = (space->addr_shift() > 0) ? 2 : (1 << -space->addr_shift()); + if (cur_data_size == 0) + cur_data_size = 1; + + // parse the data parameters + u64 fill_data[256]; + u8 fill_data_size[256]; + int data_count = 0; + for (int i = 2; i < params.size(); i++) + { + std::string_view pdata = params[i]; + + // check for a string + if (!pdata.empty() && pdata.front() == '"' && pdata.back() == '"') + { + auto const pdatalen = pdata.length() - 1; + for (int j = 1; j < pdatalen; j++) + { + fill_data[data_count] = pdata[j]; + fill_data_size[data_count++] = 1; + } + } + + // otherwise, validate as a number + else + { + // check for a 'b','w','d',or 'q' prefix + fill_data_size[data_count] = cur_data_size; + if (pdata.length() >= 2) + { + if (tolower(u8(pdata[0])) == 'b' && pdata[1] == '.') { fill_data_size[data_count] = cur_data_size = 1; pdata.remove_prefix(2); } + if (tolower(u8(pdata[0])) == 'w' && pdata[1] == '.') { fill_data_size[data_count] = cur_data_size = 2; pdata.remove_prefix(2); } + if (tolower(u8(pdata[0])) == 'd' && pdata[1] == '.') { fill_data_size[data_count] = cur_data_size = 4; pdata.remove_prefix(2); } + if (tolower(u8(pdata[0])) == 'q' && pdata[1] == '.') { fill_data_size[data_count] = cur_data_size = 8; pdata.remove_prefix(2); } + } + + // validate as a number + if (!m_console.validate_number_parameter(pdata, fill_data[data_count++])) + return; + } + } + if (data_count == 0) + return; + + // now fill memory + device_memory_interface &memory = space->device().memory(); + auto dis = space->device().machine().disable_side_effects(); + u64 count = space->address_to_byte(length); + while (count != 0) + { + // write the entire string + for (int j = 0; j < data_count; j++) + { + offs_t address = space->byte_to_address(offset) & space->logaddrmask(); + address_space *tspace; + if (!memory.translate(space->spacenum(), device_memory_interface::TR_WRITE, address, tspace)) + { + m_console.printf("Fill aborted due to page fault at %0*X\n", space->logaddrchars(), space->byte_to_address(offset) & space->logaddrmask()); + length = 0; + break; + } + switch (fill_data_size[j]) + { + case 1: + tspace->write_byte(address, fill_data[j]); + break; + + case 2: + tspace->write_word_unaligned(address, fill_data[j]); + break; + + case 4: + tspace->write_dword_unaligned(address, fill_data[j]); + break; + + case 8: + tspace->read_qword_unaligned(address, fill_data[j]); + break; + } + offset += fill_data_size[j]; + if (count <= fill_data_size[j]) + { + count = 0; + break; + } + else + count -= fill_data_size[j]; + } + } +} + + /*------------------------------------------------- execute_dasm - execute the dasm command -------------------------------------------------*/ -void debugger_commands::execute_dasm(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_dasm(const std::vector<std::string_view> ¶ms) { - u64 offset, length, bytes = 1; + u64 offset, length; + bool bytes = true; address_space *space; - /* validate parameters */ - if (!validate_number_parameter(params[1], offset)) + // validate parameters + if (!m_console.validate_number_parameter(params[1], offset)) return; - if (!validate_number_parameter(params[2], length)) + if (!m_console.validate_number_parameter(params[2], length)) return; - if (params.size() > 3 && !validate_number_parameter(params[3], bytes)) + if (params.size() > 3 && !m_console.validate_boolean_parameter(params[3], bytes)) return; - if (!validate_cpu_space_parameter(params.size() > 4 ? params[4].c_str() : nullptr, AS_PROGRAM, space)) + if (!m_console.validate_device_space_parameter(params.size() > 4 ? params[4] : std::string_view(), AS_PROGRAM, space)) return; - /* determine the width of the bytes */ + // determine the width of the bytes device_disasm_interface *dasmintf; if (!space->device().interface(dasmintf)) { @@ -2743,7 +3400,7 @@ void debugger_commands::execute_dasm(int ref, const std::vector<std::string> &pa return; } - /* build the data, check the maximum size of the opcodes and disasm */ + // build the data, check the maximum size of the opcodes and disasm std::vector<offs_t> pcs; std::vector<std::string> instructions; std::vector<std::string> tpc; @@ -2766,11 +3423,11 @@ void debugger_commands::execute_dasm(int ref, const std::vector<std::string> &pa 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; @@ -2778,7 +3435,8 @@ void debugger_commands::execute_dasm(int ref, const std::vector<std::string> &pa } /* write the data */ - std::ofstream f(params[0]); + std::string fname(params[0]); + std::ofstream f(fname); if (!f.good()) { m_console.printf("Error opening file '%s'\n", params[0]); @@ -2787,7 +3445,7 @@ void debugger_commands::execute_dasm(int ref, const std::vector<std::string> &pa 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) @@ -2798,7 +3456,7 @@ void debugger_commands::execute_dasm(int ref, const std::vector<std::string> &pa } 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) @@ -2813,104 +3471,88 @@ void debugger_commands::execute_dasm(int ref, const std::vector<std::string> &pa /*------------------------------------------------- - execute_trace_internal - functionality for + execute_trace - functionality for trace over and trace info -------------------------------------------------*/ -void debugger_commands::execute_trace_internal(int ref, const std::vector<std::string> ¶ms, bool trace_over) +void debugger_commands::execute_trace(const std::vector<std::string_view> ¶ms, bool trace_over) { - const char *action = nullptr; + std::string_view action; bool detect_loops = true; bool logerror = false; - device_t *cpu; - FILE *f = nullptr; - const char *mode; - std::string filename = params[0]; + std::string filename(params[0]); - /* replace macros */ + // replace macros strreplace(filename, "{game}", m_machine.basename()); - /* validate parameters */ - if (!validate_cpu_parameter(params.size() > 1 ? params[1].c_str() : nullptr, cpu)) + // validate parameters + device_t *cpu; + if (!m_console.validate_cpu_parameter(params.size() > 1 ? params[1] : std::string_view(), cpu)) return; if (params.size() > 2) { std::stringstream stream; - stream.str(params[2]); + stream.str(std::string(params[2])); std::string flag; while (std::getline(stream, flag, '|')) { - if (!core_stricmp(flag.c_str(), "noloop")) + using namespace std::literals; + if (util::streqlower(flag, "noloop"sv)) detect_loops = false; - else if (!core_stricmp(flag.c_str(), "logerror")) + else if (util::streqlower(flag, "logerror"sv)) logerror = true; else { - m_console.printf("Invalid flag '%s'\n", flag.c_str()); + m_console.printf("Invalid flag '%s'\n", flag); return; } } } - if (!debug_command_parameter_command(action = (params.size() > 3) ? params[3].c_str() : nullptr)) + if (params.size() > 3 && !m_console.validate_command_parameter(action = params[3])) return; - /* open the file */ - if (core_stricmp(filename.c_str(), "off") != 0) + // open the file + std::unique_ptr<std::ofstream> f; + using namespace std::literals; + if (!util::streqlower(filename, "off"sv)) { - mode = "w"; + std::ios_base::openmode mode; - /* opening for append? */ + // opening for append? if ((filename[0] == '>') && (filename[1] == '>')) { - mode = "a"; + mode = std::ios_base::in | std::ios_base::out | std::ios_base::ate; filename = filename.substr(2); } + else + mode = std::ios_base::out | std::ios_base::trunc; - f = fopen(filename.c_str(), mode); - if (!f) + f = std::make_unique<std::ofstream>(filename.c_str(), mode); + if (f->fail()) { - m_console.printf("Error opening file '%s'\n", params[0].c_str()); + m_console.printf("Error opening file '%s'\n", params[0]); return; } } - /* do it */ - cpu->debug()->trace(f, trace_over, detect_loops, logerror, action); - if (f) - m_console.printf("Tracing CPU '%s' to file %s\n", cpu->tag(), filename.c_str()); + // do it + bool const on(f); + cpu->debug()->trace(std::move(f), trace_over, detect_loops, logerror, action); + if (on) + m_console.printf("Tracing CPU '%s' to file %s\n", cpu->tag(), filename); else m_console.printf("Stopped tracing on CPU '%s'\n", cpu->tag()); } /*------------------------------------------------- - execute_trace - execute the trace command --------------------------------------------------*/ - -void debugger_commands::execute_trace(int ref, const std::vector<std::string> ¶ms) -{ - execute_trace_internal(ref, params, false); -} - - -/*------------------------------------------------- - execute_traceover - execute the trace over command --------------------------------------------------*/ - -void debugger_commands::execute_traceover(int ref, const std::vector<std::string> ¶ms) -{ - execute_trace_internal(ref, params, true); -} - - -/*------------------------------------------------- execute_traceflush - execute the trace flush command -------------------------------------------------*/ -void debugger_commands::execute_traceflush(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_traceflush(const std::vector<std::string_view> ¶ms) { - m_cpu.flush_traces(); + m_machine.debugger().cpu().flush_traces(); } @@ -2918,43 +3560,46 @@ void debugger_commands::execute_traceflush(int ref, const std::vector<std::strin execute_history - execute the history command -------------------------------------------------*/ -void debugger_commands::execute_history(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_history(const std::vector<std::string_view> ¶ms) { - /* validate parameters */ - address_space *space; - if (!validate_cpu_space_parameter(!params.empty() ? params[0].c_str() : nullptr, AS_PROGRAM, space)) + // validate parameters + device_t *device; + if (!m_console.validate_cpu_parameter(!params.empty() ? params[0] : std::string_view(), device)) return; u64 count = device_debug::HISTORY_SIZE; - if (params.size() > 1 && !validate_number_parameter(params[1], count)) + if (params.size() > 1 && !m_console.validate_number_parameter(params[1], count)) return; - /* further validation */ + // further validation if (count > device_debug::HISTORY_SIZE) count = device_debug::HISTORY_SIZE; - device_debug *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 %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 + std::string instruction; + for (int index = int(unsigned(count)); index > 0; index--) { - offs_t 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); - - m_console.printf("%s: %s\n", buffer.pc_to_string(pc), instruction); + auto const pc = debug->history_pc(1 - index); + if (pc.second) + { + debug_disasm_buffer buffer(*device); + 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.first), instruction); + } } } @@ -2963,30 +3608,37 @@ void debugger_commands::execute_history(int ref, const std::vector<std::string> execute_trackpc - execute the trackpc command -------------------------------------------------*/ -void debugger_commands::execute_trackpc(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_trackpc(const std::vector<std::string_view> ¶ms) { // Gather the on/off switch (if present) bool turnOn = true; - if (params.size() > 0 && !validate_boolean_parameter(params[0], turnOn)) + if (params.size() > 0 && !m_console.validate_boolean_parameter(params[0], turnOn)) return; // Gather the cpu id (if present) device_t *cpu = nullptr; - if (!validate_cpu_parameter((params.size() > 1) ? params[1].c_str() : nullptr, cpu)) + if (!m_console.validate_cpu_parameter((params.size() > 1) ? params[1] : std::string_view(), cpu)) return; + const device_state_interface *state; + if (!cpu->interface(state)) + { + m_console.printf("Device has no PC to be tracked\n"); + return; + } + // Should we clear the existing data? bool clear = false; - if (params.size() > 2 && !validate_boolean_parameter(params[2], clear)) + if (params.size() > 2 && !m_console.validate_boolean_parameter(params[2], clear)) return; cpu->debug()->set_track_pc((bool)turnOn); if (turnOn) { // Insert current pc - if (m_cpu.get_visible_cpu() == cpu) + if (m_console.get_visible_cpu() == cpu) { - const offs_t pc = cpu->state().pcbase(); + const offs_t pc = state->pcbase(); cpu->debug()->set_track_pc_visited(pc); } m_console.printf("PC tracking enabled\n"); @@ -3005,26 +3657,29 @@ void debugger_commands::execute_trackpc(int ref, const std::vector<std::string> execute_trackmem - execute the trackmem command -------------------------------------------------*/ -void debugger_commands::execute_trackmem(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_trackmem(const std::vector<std::string_view> ¶ms) { // Gather the on/off switch (if present) bool turnOn = true; - if (params.size() > 0 && !validate_boolean_parameter(params[0], turnOn)) + if (params.size() > 0 && !m_console.validate_boolean_parameter(params[0], turnOn)) return; // Gather the cpu id (if present) + std::string_view cpuparam; + if (params.size() > 1) + cpuparam = params[1]; device_t *cpu = nullptr; - if (!validate_cpu_parameter((params.size() > 1) ? params[1].c_str() : nullptr, cpu)) + if (!m_console.validate_cpu_parameter(cpuparam, cpu)) return; // Should we clear the existing data? bool clear = false; - if (params.size() > 2 && !validate_boolean_parameter(params[2], clear)) + if (params.size() > 2 && !m_console.validate_boolean_parameter(params[2], clear)) return; // Get the address space for the given cpu address_space *space; - if (!validate_cpu_space_parameter((params.size() > 1) ? params[1].c_str() : nullptr, AS_PROGRAM, space)) + if (!m_console.validate_device_space_parameter(cpuparam, AS_PROGRAM, space)) return; // Inform the CPU it's time to start tracking memory writes @@ -3040,30 +3695,47 @@ void debugger_commands::execute_trackmem(int ref, const std::vector<std::string> execute_pcatmem - execute the pcatmem command -------------------------------------------------*/ -void debugger_commands::execute_pcatmem(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_pcatmem(int spacenum, const std::vector<std::string_view> ¶ms) { - // Gather the required address parameter + // Gather the required target address/space parameter u64 address; - if (!validate_number_parameter(params[0], address)) - return; - - // Gather the cpu id (if present) - device_t *cpu = nullptr; - if (!validate_cpu_parameter((params.size() > 1) ? params[1].c_str() : nullptr, cpu)) + address_space *space; + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, address)) return; - // Get the address space for the given cpu - address_space *space; - if (!validate_cpu_space_parameter((params.size() > 1) ? params[1].c_str() : nullptr, ref, space)) + // Translate the address + offs_t a = address & space->logaddrmask(); + address_space *tspace; + if (!space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, a, tspace)) + { + m_console.printf("Address translation failed\n"); return; + } // Get the value of memory at the address - const int native_data_width = space->data_width() / 8; - const u64 data = m_cpu.read_memory(*space, space->address_to_byte(address), native_data_width, true); + u64 data = space->unmap(); + auto dis = space->device().machine().disable_side_effects(); + switch (space->data_width()) + { + case 8: + data = tspace->read_byte(a); + break; + + case 16: + data = tspace->read_word_unaligned(a); + break; + + case 32: + data = tspace->read_dword_unaligned(a); + break; + + case 64: + data = tspace->read_qword_unaligned(a); + break; + } // Recover the pc & print - const int space_num = (int)ref; - const offs_t result = space->device().debug()->track_mem_pc_from_space_address_data(space_num, address, data); + const offs_t result = space->device().debug()->track_mem_pc_from_space_address_data(space->spacenum(), address, data); if (result != (offs_t)(-1)) m_console.printf("%02x\n", result); else @@ -3075,7 +3747,7 @@ void debugger_commands::execute_pcatmem(int ref, const std::vector<std::string> execute_snap - execute the snapshot command -------------------------------------------------*/ -void debugger_commands::execute_snap(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_snap(const std::vector<std::string_view> ¶ms) { /* if no params, use the default behavior */ if (params.empty()) @@ -3087,10 +3759,11 @@ void debugger_commands::execute_snap(int ref, const std::vector<std::string> &pa /* otherwise, we have to open the file ourselves */ else { - const char *filename = params[0].c_str(); - int scrnum = (params.size() > 1) ? atoi(params[1].c_str()) : 0; + u64 scrnum = 0; + if (params.size() > 1 && !m_console.validate_number_parameter(params[1], scrnum)) + return; - screen_device_iterator iter(m_machine.root_device()); + screen_device_enumerator iter(m_machine.root_device()); screen_device *screen = iter.byindex(scrnum); if ((screen == nullptr) || !m_machine.render().is_live(*screen)) @@ -3099,20 +3772,20 @@ void debugger_commands::execute_snap(int ref, const std::vector<std::string> &pa return; } - std::string fname(filename); + std::string fname(params[0]); if (fname.find(".png") == -1) fname.append(".png"); emu_file file(m_machine.options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - osd_file::error filerr = file.open(fname.c_str()); + std::error_condition filerr = file.open(std::move(fname)); - if (filerr != osd_file::error::NONE) + if (filerr) { - m_console.printf("Error creating file '%s'\n", filename); + m_console.printf("Error creating file '%s' (%s:%d %s)\n", params[0], filerr.category().name(), filerr.value(), filerr.message()); return; } screen->machine().video().save_snapshot(screen, file); - m_console.printf("Saved screen #%d snapshot as '%s'\n", scrnum, filename); + m_console.printf("Saved screen #%d snapshot as '%s'\n", scrnum, params[0]); } } @@ -3121,9 +3794,10 @@ void debugger_commands::execute_snap(int ref, const std::vector<std::string> &pa execute_source - execute the source command -------------------------------------------------*/ -void debugger_commands::execute_source(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_source(const std::vector<std::string_view> ¶ms) { - m_console.source_script(params[0].c_str()); + std::string filename(params[0]); + m_console.source_script(filename.c_str()); } @@ -3131,34 +3805,29 @@ void debugger_commands::execute_source(int ref, const std::vector<std::string> & execute_map - execute the map command -------------------------------------------------*/ -void debugger_commands::execute_map(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_map(int spacenum, const std::vector<std::string_view> ¶ms) { - address_space *space; - offs_t taddress; + // validate parameters u64 address; - int intention; - - /* validate parameters */ - if (!validate_number_parameter(params[0], address)) - return; - - /* CPU is implicit */ - if (!validate_cpu_space_parameter(nullptr, ref, space)) + address_space *space; + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, address)) return; + address &= space->logaddrmask(); - /* do the translation first */ - for (intention = TRANSLATE_READ_DEBUG; intention <= TRANSLATE_FETCH_DEBUG; intention++) + // do the translation first + for (int intention = device_memory_interface::TR_READ; intention <= device_memory_interface::TR_FETCH; intention++) { static const char *const intnames[] = { "Read", "Write", "Fetch" }; - taddress = address & space->addrmask(); - if (space->device().memory().translate(space->spacenum(), intention, taddress)) + offs_t taddress = address; + address_space *tspace; + if (space->device().memory().translate(space->spacenum(), intention, taddress, tspace)) { - std::string mapname = space->get_handler_string((intention == TRANSLATE_WRITE_DEBUG) ? read_or_write::WRITE : read_or_write::READ, taddress); + std::string mapname = tspace->get_handler_string((intention == device_memory_interface::TR_WRITE) ? read_or_write::WRITE : read_or_write::READ, taddress); m_console.printf( - "%7s: %0*X logical == %0*X physical -> %s\n", + "%7s: %0*X logical %s == %0*X physical %s -> %s\n", intnames[intention & 3], - space->logaddrchars(), address, - space->addrchars(), taddress, + space->logaddrchars(), address, space->name(), + tspace->addrchars(), taddress, tspace->name(), mapname); } else @@ -3171,20 +3840,29 @@ void debugger_commands::execute_map(int ref, const std::vector<std::string> &par execute_memdump - execute the memdump command -------------------------------------------------*/ -void debugger_commands::execute_memdump(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_memdump(const std::vector<std::string_view> ¶ms) { - FILE *file; - const char *filename; + device_t *root = &m_machine.root_device(); + if ((params.size() >= 2) && !m_console.validate_device_parameter(params[1], root)) + return; - filename = params.empty() ? "memdump.log" : params[0].c_str(); + using namespace std::literals; + std::string filename = params.empty() ? "memdump.log"s : std::string(params[0]); + FILE *const file = fopen(filename.c_str(), "w"); + if (!file) + { + m_console.printf("Error opening file %s\n", filename); + return; + } - m_console.printf("Dumping memory to %s\n", filename); + m_console.printf("Dumping memory maps to %s\n", filename); - file = fopen(filename, "w"); - if (file) + try { - memory_interface_iterator iter(m_machine.root_device()); - for (device_memory_interface &memory : iter) { + memory_interface_enumerator iter(*root); + std::vector<memory_entry> entries[2]; + for (device_memory_interface &memory : iter) + { for (int space = 0; space != memory.max_space_count(); space++) if (memory.has_space(space)) { @@ -3192,25 +3870,36 @@ void debugger_commands::execute_memdump(int ref, const std::vector<std::string> bool octal = sp.is_octal(); int nc = octal ? (sp.addr_width() + 2) / 3 : (sp.addr_width() + 3) / 4; - std::vector<memory_entry> entries[2]; sp.dump_maps(entries[0], entries[1]); for (int mode = 0; mode < 2; mode ++) { - fprintf(file, " device %s space %s %s:\n", memory.device().tag(), sp.name(), mode ? "write" : "read"); + fprintf(file, " %s '%s' space %s %s:\n", memory.device().type().fullname(), memory.device().tag(), sp.name(), mode ? "write" : "read"); for (memory_entry &entry : entries[mode]) { if (octal) - fprintf(file, "%0*o - %0*o", nc, entry.start, nc, entry.end); + fprintf(file, "%0*o - %0*o:", nc, entry.start, nc, entry.end); else - fprintf(file, "%0*x - %0*x", nc, entry.start, nc, entry.end); - fprintf(file, ": %s\n", entry.entry->name().c_str()); + fprintf(file, "%0*x - %0*x:", nc, entry.start, nc, entry.end); + for (const auto &c : entry.context) + if (c.disabled) + fprintf(file, " %s[off]", c.view->name().c_str()); + else + fprintf(file, " %s[%d]", c.view->name().c_str(), c.slot); + fprintf(file, " %s\n", entry.entry->name().c_str()); } fprintf(file, "\n"); } + entries[0].clear(); + entries[1].clear(); } } fclose(file); } + catch (...) + { + fclose(file); + throw; + } } @@ -3218,53 +3907,56 @@ void debugger_commands::execute_memdump(int ref, const std::vector<std::string> execute_symlist - execute the symlist command -------------------------------------------------*/ -void debugger_commands::execute_symlist(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_symlist(const std::vector<std::string_view> ¶ms) { - device_t *cpu = nullptr; const char *namelist[1000]; symbol_table *symtable; - int symnum, count = 0; + int count = 0; if (!params.empty()) { - /* validate parameters */ - if (!validate_cpu_parameter(params[0].c_str(), cpu)) + // validate parameters + device_t *cpu; + if (!m_console.validate_cpu_parameter(params[0], cpu)) return; symtable = &cpu->debug()->symtable(); m_console.printf("CPU '%s' symbols:\n", cpu->tag()); } else { - symtable = m_cpu.get_global_symtable(); + symtable = &m_machine.debugger().cpu().global_symtable(); m_console.printf("Global symbols:\n"); } - /* gather names for all symbols */ + // gather names for all symbols for (auto &entry : symtable->entries()) { - /* only display "register" type symbols */ + // only display "register" type symbols if (!entry.second->is_function()) { namelist[count++] = entry.second->name(); - if (count >= ARRAY_LENGTH(namelist)) + if (count >= std::size(namelist)) break; } } - /* sort the symbols */ + // sort the symbols if (count > 1) - std::sort(&namelist[0], &namelist[count], [](const char *item1, const char *item2) { - return strcmp(item1, item2) < 0; - }); + { + std::sort( + &namelist[0], + &namelist[count], + [] (const char *item1, const char *item2) { return strcmp(item1, item2) < 0; }); + } - /* iterate over symbols and print out relevant ones */ - for (symnum = 0; symnum < count; symnum++) + // iterate over symbols and print out relevant ones + for (int symnum = 0; symnum < count; symnum++) { - const symbol_entry *entry = symtable->find(namelist[symnum]); + symbol_entry const *const entry = symtable->find(namelist[symnum]); assert(entry != nullptr); u64 value = entry->value(); - /* only display "register" type symbols */ + // only display "register" type symbols m_console.printf("%s = %X", namelist[symnum], value); if (!entry->is_lval()) m_console.printf(" (read-only)"); @@ -3277,7 +3969,7 @@ void debugger_commands::execute_symlist(int ref, const std::vector<std::string> execute_softreset - execute the softreset command -------------------------------------------------*/ -void debugger_commands::execute_softreset(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_softreset(const std::vector<std::string_view> ¶ms) { m_machine.schedule_soft_reset(); } @@ -3287,7 +3979,7 @@ void debugger_commands::execute_softreset(int ref, const std::vector<std::string execute_hardreset - execute the hardreset command -------------------------------------------------*/ -void debugger_commands::execute_hardreset(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_hardreset(const std::vector<std::string_view> ¶ms) { m_machine.schedule_hard_reset(); } @@ -3297,57 +3989,84 @@ void debugger_commands::execute_hardreset(int ref, const std::vector<std::string mounted files -------------------------------------------------*/ -void debugger_commands::execute_images(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_images(const std::vector<std::string_view> ¶ms) { - image_interface_iterator iter(m_machine.root_device()); + image_interface_enumerator iter(m_machine.root_device()); for (device_image_interface &img : iter) - m_console.printf("%s: %s\n", img.brief_instance_name(), img.exists() ? img.filename() : "[empty slot]"); - if (iter.first() == nullptr) - m_console.printf("No image devices in this driver\n"); + { + if (!img.exists()) + { + m_console.printf("%s: [no media]\n", img.brief_instance_name()); + } + else if (img.loaded_through_softlist()) + { + m_console.printf("%s: %s:%s:%s\n", + img.brief_instance_name(), + img.software_list_name(), + img.software_entry()->shortname(), + img.part_entry()->name()); + } + else + { + m_console.printf("%s: %s\n", img.brief_instance_name(), img.filename()); + } + } + if (!iter.first()) + m_console.printf("No image devices present\n"); } /*------------------------------------------------- execute_mount - execute the image mount command -------------------------------------------------*/ -void debugger_commands::execute_mount(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_mount(const std::vector<std::string_view> ¶ms) { - bool done = false; - for (device_image_interface &img : image_interface_iterator(m_machine.root_device())) + for (device_image_interface &img : image_interface_enumerator(m_machine.root_device())) { - if (img.brief_instance_name() == params[0]) + if ((img.instance_name() == params[0]) || (img.brief_instance_name() == params[0])) { - if (img.load(params[1]) != image_init_result::PASS) - m_console.printf("Unable to mount file %s on %s\n", params[1], params[0]); - else + auto [err, msg] = img.load(params[1]); + if (!err) + { m_console.printf("File %s mounted on %s\n", params[1], params[0]); - done = true; - break; + } + else + { + m_console.printf( + "Unable to mount file %s on %s: %s\n", + params[1], + params[0], + !msg.empty() ? msg : err.message()); + } + return; } } - if (!done) - m_console.printf("There is no image device :%s\n", params[0].c_str()); + m_console.printf("No image instance %s\n", params[0]); } /*------------------------------------------------- execute_unmount - execute the image unmount command -------------------------------------------------*/ -void debugger_commands::execute_unmount(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_unmount(const std::vector<std::string_view> ¶ms) { - bool done = false; - for (device_image_interface &img : image_interface_iterator(m_machine.root_device())) + for (device_image_interface &img : image_interface_enumerator(m_machine.root_device())) { - if (img.brief_instance_name() == params[0]) + if ((img.instance_name() == params[0]) || (img.brief_instance_name() == params[0])) { - img.unload(); - m_console.printf("Unmounted file from : %s\n", params[0]); - done = true; - break; + if (img.exists()) + { + img.unload(); + m_console.printf("Unmounted media from %s\n", params[0]); + } + else + { + m_console.printf("No media mounted on %s\n", params[0]); + } + return; } } - if (!done) - m_console.printf("There is no image device :%s\n", params[0]); + m_console.printf("No image instance %s\n", params[0]); } @@ -3356,9 +4075,9 @@ void debugger_commands::execute_unmount(int ref, const std::vector<std::string> natural keyboard input -------------------------------------------------*/ -void debugger_commands::execute_input(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_input(const std::vector<std::string_view> ¶ms) { - m_machine.ioport().natkeyboard().post_coded(params[0].c_str()); + m_machine.natkeyboard().post_coded(params[0]); } @@ -3367,15 +4086,15 @@ void debugger_commands::execute_input(int ref, const std::vector<std::string> &p keyboard codes -------------------------------------------------*/ -void debugger_commands::execute_dumpkbd(int ref, const std::vector<std::string> ¶ms) +void debugger_commands::execute_dumpkbd(const std::vector<std::string_view> ¶ms) { // was there a file specified? - const char *filename = !params.empty() ? params[0].c_str() : nullptr; + std::string filename = !params.empty() ? std::string(params[0]) : std::string(); FILE *file = nullptr; - if (filename != nullptr) + if (!filename.empty()) { // if so, open it - file = fopen(filename, "w"); + file = fopen(filename.c_str(), "w"); if (file == nullptr) { m_console.printf("Cannot open \"%s\"\n", filename); @@ -3384,13 +4103,13 @@ void debugger_commands::execute_dumpkbd(int ref, const std::vector<std::string> } // loop through all codes - std::string buffer = m_machine.ioport().natkeyboard().dump(); + std::string buffer = m_machine.natkeyboard().dump(); // and output it as appropriate if (file != nullptr) fprintf(file, "%s\n", buffer.c_str()); else - m_console.printf("%s\n", buffer.c_str()); + m_console.printf("%s\n", buffer); // cleanup if (file != nullptr) |