diff options
Diffstat (limited to 'src/emu/debug/debugcmd.cpp')
-rw-r--r-- | src/emu/debug/debugcmd.cpp | 1649 |
1 files changed, 732 insertions, 917 deletions
diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index b8de0298432..ad463ace500 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -21,6 +21,7 @@ #include "debugger.h" #include "emuopts.h" +#include "fileio.h" #include "natkeyboard.h" #include "render.h" #include "screen.h" @@ -31,35 +32,7 @@ #include <algorithm> #include <cctype> #include <fstream> - - - -namespace { - -template <typename T> -inline std::string_view::size_type find_delimiter(std::string_view str, T &&is_delim) -{ - unsigned parens = 0; - for (std::string_view::size_type i = 0; str.length() > i; ++i) - { - if (str[i] == '(') - { - ++parens; - } - else if (parens) - { - if (str[i] == ')') - --parens; - } - else if (is_delim(str[i])) - { - return i; - } - } - return std::string_view::npos; -} - -} // anonymous namespace +#include <sstream> @@ -80,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); } @@ -131,14 +105,15 @@ u64 debugger_commands::cheat_system::read_extended(offs_t address) const { address &= space->logaddrmask(); u64 value = space->unmap(); - if (space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, address)) + address_space *tspace; + if (space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, address, tspace)) { switch (width) { - case 1: value = space->read_byte(address); break; - case 2: value = space->read_word_unaligned(address); break; - case 4: value = space->read_dword_unaligned(address); break; - case 8: value = space->read_qword_unaligned(address); break; + 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)); @@ -195,7 +170,7 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu 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( @@ -232,6 +207,9 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu 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)); @@ -240,6 +218,7 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu 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)); @@ -276,6 +255,13 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu 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)); @@ -443,475 +429,15 @@ void debugger_commands::global_set(global_entry *global, u64 value) -/*************************************************************************** - PARAMETER VALIDATION HELPERS -***************************************************************************/ - -/// \brief Validate parameter as a Boolean value -/// -/// Validates a parameter as a Boolean value. Fixed strings and -/// expressions evaluating to numeric values are recognised. The result -/// is unchanged for an empty string. -/// \param [in] param The parameter string. -/// \param [in,out] result The default value on entry, and the value of -/// the parameter interpreted as a Boolean on success. Unchanged if -/// the parameter is an empty string. -/// \return true if the parameter is a valid Boolean value or an empty -/// string, or false otherwise. -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 const is_true = !core_stricmp(param.c_str(), "true"); - bool const is_false = !core_stricmp(param.c_str(), "false"); - - if (is_true || is_false) - { - result = is_true; - return true; - } - - // try to evaluate as a number - u64 val; - if (!validate_number_parameter(param, val)) - return false; - - result = val != 0; - return true; -} - - -/// \brief Validate parameter as a numeric value -/// -/// Parses the parameter as an expression and evaluates it as a number. -/// \param [in] param The parameter string. -/// \param [out] result The numeric value of the expression on success. -/// Unchanged on failure. -/// \return true if the parameter is a valid expression that evaluates -/// to a numeric value, or false otherwise. -bool debugger_commands::validate_number_parameter(std::string_view param, u64 &result) -{ - // evaluate the expression; success if no error - try - { - result = parsed_expression(m_console.visible_symtable(), param).execute(); - return true; - } - catch (expression_error const &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; - } -} - - -/// \brief Validate parameter as a device -/// -/// Validates a parameter as a device identifier and retrieves the -/// device on success. A string corresponding to the tag of a device -/// refers to that device; an empty string refers to the current CPU -/// with debugger focus; any other string is parsed as an expression -/// and treated as an index of a device implementing -/// #device_execute_interface and #device_state_interface, and exposing -/// a generic PC base value. -/// \param [in] param The parameter string. -/// \param [out] result A pointer to the device on success, or unchanged -/// on failure. -/// \return true if the parameter refers to a device in the current -/// system, or false otherwise. -bool debugger_commands::validate_device_parameter(std::string_view param, device_t *&result) -{ - // if no parameter, use the visible CPU - if (param.empty()) - { - device_t *const current = m_console.get_visible_cpu(); - if (current) - { - result = current; - return true; - } - else - { - m_console.printf("No valid CPU is currently selected\n"); - return false; - } - } - - // next look for a tag match - std::string_view relative = param; - device_t &base = get_device_search_base(relative); - device_t *device = base.subdevice(strmakelower(relative)); - if (device) - { - result = device; - return true; - } - - // then evaluate as an expression; on an error assume it was a tag - u64 cpunum; - try - { - cpunum = parsed_expression(m_console.visible_symtable(), param).execute(); - } - catch (expression_error &) - { - m_console.printf("Unable to find device '%s'\n", param); - return false; - } - - // attempt to find by numerical index - device = get_cpu_by_index(cpunum); - if (device) - { - result = device; - return true; - } - else - { - // if out of range, complain - m_console.printf("Invalid CPU index %u\n", cpunum); - return false; - } -} - - -/// \brief Validate a parameter as a CPU -/// -/// Validates a parameter as a CPU identifier. Uses the same rules as -/// #validate_device_parameter to identify devices, but additionally -/// checks that the device is a "CPU" for the debugger's purposes. -/// \param [in] The parameter string. -/// \param [out] result The device on success, or unchanged on failure. -/// \return true if the parameter refers to a CPU-like device in the -/// current system, or false otherwise. -bool debugger_commands::validate_cpu_parameter(std::string_view param, device_t *&result) -{ - // first do the standard device thing - device_t *device; - if (!validate_device_parameter(param, device)) - return false; - - // check that it's a "CPU" for the debugger's purposes - device_execute_interface const *execute; - if (device->interface(execute)) - { - result = device; - return true; - } - - m_console.printf("Device %s is not a CPU\n", device->name()); - return false; -} - - -/// \brief Validate a parameter as an address space identifier -/// -/// Validates a parameter as an address space identifier. Uses the same -/// rules as #validate_device_parameter to identify devices. If the -/// default address space number is negative, the first address space -/// exposed by the device will be used as the default. -/// \param [in] The parameter string. -/// \param [in] spacenum The default address space index. If negative, -/// the first address space exposed by the device (i.e. the address -/// space with the lowest index) will be used as the default. -/// \param [out] result The address space on success, or unchanged on -/// failure. -/// \return true if the parameter refers to an address space in the -/// current system, or false otherwise. -bool debugger_commands::validate_device_space_parameter(std::string_view param, int spacenum, address_space *&result) -{ - device_t *device; - std::string spacename; - if (param.empty()) - { - // if no parameter, use the visible CPU - device = m_console.get_visible_cpu(); - if (!device) - { - m_console.printf("No valid CPU is currently selected\n"); - return false; - } - } - else - { - // look for a tag match on the whole parameter value - std::string_view relative = param; - device_t &base = get_device_search_base(relative); - device = base.subdevice(strmakelower(relative)); - - // if that failed, treat the last component as an address space - if (!device) - { - auto const delimiter = relative.find_last_of(":^"); - bool const found = std::string_view::npos != delimiter; - if (!found || (':' == relative[delimiter])) - { - spacename = strmakelower(relative.substr(found ? (delimiter + 1) : 0)); - relative = relative.substr(0, !found ? 0 : !delimiter ? 1 : delimiter); - if (!relative.empty()) - device = base.subdevice(strmakelower(relative)); - else if (m_console.get_visible_cpu()) - device = m_console.get_visible_cpu(); - else - device = &m_machine.root_device(); - } - } - } - - // if still no device found, evaluate as an expression - if (!device) - { - u64 cpunum; - try - { - cpunum = parsed_expression(m_console.visible_symtable(), param).execute(); - } - catch (expression_error const &) - { - // parsing failed - assume it was a tag - m_console.printf("Unable to find device '%s'\n", param); - return false; - } - - // attempt to find by numerical index - device = get_cpu_by_index(cpunum); - if (!device) - { - // if out of range, complain - m_console.printf("Invalid CPU index %u\n", cpunum); - return false; - } - } - - // ensure the device implements the memory interface - device_memory_interface *memory; - if (!device->interface(memory)) - { - m_console.printf("No memory interface found for device %s\n", device->name()); - return false; - } - - // fall back to supplied default space if appropriate - if (spacename.empty() && (0 <= spacenum)) - { - if (memory->has_space(spacenum)) - { - result = &memory->space(spacenum); - return true; - } - else - { - m_console.printf("No matching memory space found for device '%s'\n", device->tag()); - return false; - } - } - - // otherwise find the specified space or fall back to the first populated space - for (int i = 0; memory->max_space_count() > i; ++i) - { - if (memory->has_space(i) && (spacename.empty() || (memory->space(i).name() == spacename))) - { - result = &memory->space(i); - return true; - } - } - - // report appropriate error message - if (spacename.empty()) - m_console.printf("No memory spaces found for device '%s'\n", device->tag()); - else - m_console.printf("Memory space '%s' not found found for device '%s'\n", spacename, device->tag()); - return false; -} - - -/// \brief Validate a parameter as a target address -/// -/// Validates a parameter as an numeric expression to use as an address -/// optionally followed by a colon and a device identifier. If the -/// device identifier is not presnt, the current CPU with debugger focus -/// is assumed. See #validate_device_parameter for information on how -/// device parametersare interpreted. -/// \param [in] The parameter string. -/// \param [in] spacenum The default address space index. If negative, -/// the first address space exposed by the device (i.e. the address -/// space with the lowest index) will be used as the default. -/// \param [out] space The address space on success, or unchanged on -/// failure. -/// \param [out] addr The address on success, or unchanged on failure. -/// \return true if the address is a valid expression evaluating to a -/// number and the address space is found, or false otherwise. -bool debugger_commands::validate_target_address_parameter(std::string_view param, int spacenum, address_space *&space, u64 &addr) -{ - // check for the device delimiter - std::string_view::size_type const devdelim = find_delimiter(param, [] (char ch) { return ':' == ch; }); - std::string_view device; - if (devdelim != std::string::npos) - device = param.substr(devdelim + 1); - - // parse the address first - u64 addrval; - if (!validate_number_parameter(param.substr(0, devdelim), addrval)) - return false; - - // find the address space - if (!validate_device_space_parameter(device, spacenum, space)) - return false; - - // set the address now that we have the space - addr = addrval; - return true; -} - - -/// \brief Validate a parameter as a memory region -/// -/// Validates a parameter as a memory region tag and retrieves the -/// specified memory region. -/// \param [in] The parameter string. -/// \param [out] result The memory region on success, or unchanged on -/// failure. -/// \return true if the parameter refers to a memory region in the -/// current system, or false otherwise. -bool debugger_commands::validate_memory_region_parameter(std::string_view param, memory_region *&result) -{ - auto const ®ions = m_machine.memory().regions(); - std::string_view relative = param; - device_t &base = get_device_search_base(relative); - auto const iter = regions.find(base.subtag(strmakelower(relative))); - if (regions.end() != iter) - { - result = iter->second.get(); - return true; - } - else - { - m_console.printf("No matching memory region found for '%s'\n", param); - return false; - } -} - - -/// \brief Get search base for device or address space parameter -/// -/// Handles prefix prefixes used to indicate that a device tag should be -/// interpreted relative to the selected CPU. Removes the recognised -/// prefixes from the parameter value. -/// \param [in,out] param The parameter string. Recognised prefixes -/// affecting the search base are removed, leaving a tag relative to -/// the base device. -/// \return A reference to the base device that the tag should be -/// interpreted relative to. -device_t &debugger_commands::get_device_search_base(std::string_view ¶m) -{ - if (!param.empty()) - { - // handle ".:" or ".^" prefix for tag relative to current CPU if any - if (('.' == param[0]) && ((param.size() == 1) || (':' == param[1]) || ('^' == param[1]))) - { - param.remove_prefix(((param.size() > 1) && (':' == param[1])) ? 2 : 1); - device_t *const current = m_console.get_visible_cpu(); - return current ? *current : m_machine.root_device(); - } - - // a sibling path makes most sense relative to current CPU - if ('^' == param[0]) - { - device_t *const current = m_console.get_visible_cpu(); - return current ? *current : m_machine.root_device(); - } - } - - - // default to root device - return m_machine.root_device(); -} - - -/// \brief Get CPU by index -/// -/// Looks up a CPU by the number the debugger assigns it based on its -/// position in the device tree relative to other CPUs. -/// \param [in] cpunum Zero-based index of the CPU to find. -/// \return A pointer to the CPU if found, or \c nullptr if no CPU has -/// the specified index. -device_t *debugger_commands::get_cpu_by_index(u64 cpunum) -{ - unsigned index = 0; - for (device_execute_interface &exec : execute_interface_enumerator(m_machine.root_device())) - { - // real CPUs should have pcbase - device_state_interface const *state; - if (exec.device().interface(state) && state->state_find_entry(STATE_GENPCBASE)) - { - if (index++ == cpunum) - { - return &exec.device(); - } - } - } - return nullptr; -} - - -/*------------------------------------------------- - debug_command_parameter_expression - validates - an expression parameter --------------------------------------------------*/ - -bool debugger_commands::debug_command_parameter_expression(std::string_view param, parsed_expression &result) -{ - try - { - // parse the expression; success if no error - result.parse(param); - return true; - } - catch (expression_error const &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.error_class() == CMDERR::NONE) - return true; - - /* output an error */ - m_console.printf("Error in command: %s\n", param); - m_console.printf(" %*s^", err.error_offset(), ""); - 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(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(std::string_view())); @@ -924,12 +450,12 @@ void debugger_commands::execute_help(const std::vector<std::string> ¶ms) execute_print - execute the print command -------------------------------------------------*/ -void debugger_commands::execute_print(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 */ @@ -943,131 +469,177 @@ void debugger_commands::execute_print(const std::vector<std::string> ¶ms) 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(); + + int param = 1; + u64 number; - /* parse the string looking for % signs */ - for (;;) + // 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 out the width */ - for (;;) + // parse optional left justification flag + if (f != format.end() && *f == '-') { - c = *f++; - if (!c || c < '0' || c > '9') break; - if (c == '0' && width == 0) - zerofill = 1; - width = width * 10 + (c - '0'); + left_justify = true; + f++; + } + + // parse optional zero fill flag + if (f != format.end() && *f == '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; } - 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 'O': case 'o': - if (params == 0) - { - m_console.printf("Not enough parameters for format!\n"); - return 0; - } - if (u32(*param >> 60) != 0) - { - p += sprintf(p, zerofill ? "%0*o" : "%*o", (width <= 20) ? 1 : width - 20, u32(*param >> 60)); - p += sprintf(p, "%0*o", 10, u32(BIT(*param, 30, 30))); - } + if (param < params.size() && m_console.validate_number_parameter(params[param++], number)) + util::stream_format(stream, zero_fill ? "%0*o" : "%*o", width, number); else { - if (width > 20) - p += sprintf(p, zerofill ? "%0*o" : "%*o", width - 20, 0); - if (u32(BIT(*param, 30, 30)) != 0) - p += sprintf(p, zerofill ? "%0*o" : "%*o", (width <= 10) ? 1 : width - 10, u32(BIT(*param, 30, 30))); - else if (width > 10) - p += sprintf(p, zerofill ? "%0*o" : "%*o", width - 10, 0); + m_console.printf("Not enough parameters for format!\n"); + return false; } - p += sprintf(p, zerofill ? "%0*o" : "%*o", (width < 10) ? width : 10, u32(BIT(*param, 0, 30))); - 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; } @@ -1077,12 +649,12 @@ int debugger_commands::mini_printf(char *buffer, const char *format, int params, -------------------------------------------------*/ template <typename T> -void debugger_commands::execute_index_command(std::vector<std::string> const ¶ms, T &&apply, char const *unused_message) +void debugger_commands::execute_index_command(std::vector<std::string_view> const ¶ms, T &&apply, char const *unused_message) { std::vector<u64> index(params.size()); for (int paramnum = 0; paramnum < params.size(); paramnum++) { - if (!validate_number_parameter(params[paramnum], index[paramnum])) + if (!m_console.validate_number_parameter(params[paramnum], index[paramnum])) return; } @@ -1106,18 +678,12 @@ void debugger_commands::execute_index_command(std::vector<std::string> const &pa execute_printf - execute the printf command -------------------------------------------------*/ -void debugger_commands::execute_printf(const std::vector<std::string> ¶ms) +void debugger_commands::execute_printf(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_console.printf("%s\n", buffer); + std::ostringstream buffer; + if (mini_printf(buffer, params)) + m_console.printf("%s\n", std::move(buffer).str()); } @@ -1125,18 +691,12 @@ void debugger_commands::execute_printf(const std::vector<std::string> ¶ms) execute_logerror - execute the logerror command -------------------------------------------------*/ -void debugger_commands::execute_logerror(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()); } @@ -1144,18 +704,12 @@ void debugger_commands::execute_logerror(const std::vector<std::string> ¶ms) execute_tracelog - execute the tracelog command -------------------------------------------------*/ -void debugger_commands::execute_tracelog(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_console.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()); } @@ -1163,11 +717,10 @@ void debugger_commands::execute_tracelog(const std::vector<std::string> ¶ms) execute_tracesym - execute the tracesym command -------------------------------------------------*/ -void debugger_commands::execute_tracesym(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]; for (int i = 0; i < params.size(); i++) { // find this symbol @@ -1182,16 +735,16 @@ void debugger_commands::execute_tracesym(const std::vector<std::string> ¶ms) 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 + std::vector<std::string_view> printf_params(params); + printf_params.insert(printf_params.begin(), format.str()); + // then do a printf - char buffer[1024]; - if (mini_printf(buffer, format.str().c_str(), params.size(), values)) - m_console.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()); } @@ -1199,7 +752,7 @@ void debugger_commands::execute_tracesym(const std::vector<std::string> ¶ms) execute_cls - execute the cls command -------------------------------------------------*/ -void debugger_commands::execute_cls(const std::vector<std::string> ¶ms) +void debugger_commands::execute_cls(const std::vector<std::string_view> ¶ms) { text_buffer_clear(m_console.get_console_textbuf()); } @@ -1209,7 +762,7 @@ void debugger_commands::execute_cls(const std::vector<std::string> ¶ms) execute_quit - execute the quit command -------------------------------------------------*/ -void debugger_commands::execute_quit(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(); @@ -1220,10 +773,10 @@ void debugger_commands::execute_quit(const std::vector<std::string> ¶ms) execute_do - execute the do command -------------------------------------------------*/ -void debugger_commands::execute_do(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); } @@ -1231,11 +784,11 @@ void debugger_commands::execute_do(const std::vector<std::string> ¶ms) execute_step - execute the step command -------------------------------------------------*/ -void debugger_commands::execute_step(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_console.get_visible_cpu()->debug()->single_step(steps); @@ -1246,11 +799,11 @@ void debugger_commands::execute_step(const std::vector<std::string> ¶ms) execute_over - execute the over command -------------------------------------------------*/ -void debugger_commands::execute_over(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_console.get_visible_cpu()->debug()->single_step_over(steps); @@ -1261,7 +814,7 @@ void debugger_commands::execute_over(const std::vector<std::string> ¶ms) execute_out - execute the out command -------------------------------------------------*/ -void debugger_commands::execute_out(const std::vector<std::string> ¶ms) +void debugger_commands::execute_out(const std::vector<std::string_view> ¶ms) { m_console.get_visible_cpu()->debug()->single_step_out(); } @@ -1271,12 +824,12 @@ void debugger_commands::execute_out(const std::vector<std::string> ¶ms) execute_go - execute the go command -------------------------------------------------*/ -void debugger_commands::execute_go(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_console.get_visible_cpu()->debug()->go(addr); @@ -1288,7 +841,7 @@ void debugger_commands::execute_go(const std::vector<std::string> ¶ms) command -------------------------------------------------*/ -void debugger_commands::execute_go_vblank(const std::vector<std::string> ¶ms) +void debugger_commands::execute_go_vblank(const std::vector<std::string_view> ¶ms) { m_console.get_visible_cpu()->debug()->go_vblank(); } @@ -1298,12 +851,12 @@ void debugger_commands::execute_go_vblank(const std::vector<std::string> ¶ms execute_go_interrupt - execute the goint command -------------------------------------------------*/ -void debugger_commands::execute_go_interrupt(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_console.get_visible_cpu()->debug()->go_interrupt(irqline); @@ -1313,16 +866,16 @@ void debugger_commands::execute_go_interrupt(const std::vector<std::string> &par execute_go_exception - execute the goex command -------------------------------------------------*/ -void debugger_commands::execute_go_exception(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 && !debug_command_parameter_expression(params[1], condition)) + if (params.size() > 1 && !m_console.validate_expression_parameter(params[1], condition)) return; m_console.get_visible_cpu()->debug()->go_exception(exception, condition.is_empty() ? "1" : condition.original_string()); @@ -1333,12 +886,12 @@ void debugger_commands::execute_go_exception(const std::vector<std::string> &par execute_go_time - execute the gtime command -------------------------------------------------*/ -void debugger_commands::execute_go_time(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_console.get_visible_cpu()->debug()->go_milliseconds(milliseconds); @@ -1349,20 +902,76 @@ void debugger_commands::execute_go_time(const std::vector<std::string> ¶ms) /*------------------------------------------------- execute_go_privilege - execute the gp command -------------------------------------------------*/ -void debugger_commands::execute_go_privilege(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 && !debug_command_parameter_expression(params[0], condition)) + 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) +{ + 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); + } + + cpu->debug()->go(pc); +} + + /*------------------------------------------------- execute_next - execute the next command -------------------------------------------------*/ -void debugger_commands::execute_next(const std::vector<std::string> ¶ms) +void debugger_commands::execute_next(const std::vector<std::string_view> ¶ms) { m_console.get_visible_cpu()->debug()->go_next_device(); } @@ -1372,11 +981,11 @@ void debugger_commands::execute_next(const std::vector<std::string> ¶ms) execute_focus - execute the focus command -------------------------------------------------*/ -void debugger_commands::execute_focus(const std::vector<std::string> ¶ms) +void debugger_commands::execute_focus(const std::vector<std::string_view> ¶ms) { // validate params device_t *cpu; - if (!validate_cpu_parameter(params[0], cpu)) + if (!m_console.validate_cpu_parameter(params[0], cpu)) return; // first clear the ignore flag on the focused CPU @@ -1394,7 +1003,7 @@ void debugger_commands::execute_focus(const std::vector<std::string> ¶ms) execute_ignore - execute the ignore command -------------------------------------------------*/ -void debugger_commands::execute_ignore(const std::vector<std::string> ¶ms) +void debugger_commands::execute_ignore(const std::vector<std::string_view> ¶ms) { if (params.empty()) { @@ -1426,7 +1035,7 @@ void debugger_commands::execute_ignore(const std::vector<std::string> ¶ms) // validate parameters for (int paramnum = 0; paramnum < params.size(); paramnum++) - if (!validate_cpu_parameter(params[paramnum], devicelist[paramnum])) + if (!m_console.validate_cpu_parameter(params[paramnum], devicelist[paramnum])) return; // set the ignore flags @@ -1457,7 +1066,7 @@ void debugger_commands::execute_ignore(const std::vector<std::string> ¶ms) execute_observe - execute the observe command -------------------------------------------------*/ -void debugger_commands::execute_observe(const std::vector<std::string> ¶ms) +void debugger_commands::execute_observe(const std::vector<std::string_view> ¶ms) { if (params.empty()) { @@ -1489,7 +1098,7 @@ void debugger_commands::execute_observe(const std::vector<std::string> ¶ms) // validate parameters for (int paramnum = 0; paramnum < params.size(); paramnum++) - if (!validate_cpu_parameter(params[paramnum], devicelist[paramnum])) + if (!m_console.validate_cpu_parameter(params[paramnum], devicelist[paramnum])) return; // clear the ignore flags @@ -1505,7 +1114,7 @@ void debugger_commands::execute_observe(const std::vector<std::string> ¶ms) execute_suspend - suspend execution on cpu -------------------------------------------------*/ -void debugger_commands::execute_suspend(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 (params.empty()) @@ -1535,7 +1144,7 @@ void debugger_commands::execute_suspend(const std::vector<std::string> ¶ms) // validate parameters for (int paramnum = 0; paramnum < params.size(); paramnum++) - if (!validate_cpu_parameter(params[paramnum], devicelist[paramnum])) + if (!m_console.validate_cpu_parameter(params[paramnum], devicelist[paramnum])) return; for (int paramnum = 0; paramnum < params.size(); paramnum++) @@ -1564,7 +1173,7 @@ void debugger_commands::execute_suspend(const std::vector<std::string> ¶ms) execute_resume - Resume execution on CPU -------------------------------------------------*/ -void debugger_commands::execute_resume(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 (params.empty()) @@ -1594,7 +1203,7 @@ void debugger_commands::execute_resume(const std::vector<std::string> ¶ms) // validate parameters for (int paramnum = 0; paramnum < params.size(); paramnum++) - if (!validate_cpu_parameter(params[paramnum], devicelist[paramnum])) + if (!m_console.validate_cpu_parameter(params[paramnum], devicelist[paramnum])) return; for (int paramnum = 0; paramnum < params.size(); paramnum++) @@ -1609,7 +1218,7 @@ void debugger_commands::execute_resume(const std::vector<std::string> ¶ms) // execute_cpulist - list all CPUs //------------------------------------------------- -void debugger_commands::execute_cpulist(const std::vector<std::string> ¶ms) +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())) @@ -1620,20 +1229,29 @@ void debugger_commands::execute_cpulist(const std::vector<std::string> ¶ms) } } +//------------------------------------------------- +// 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(const std::vector<std::string> ¶ms) +void debugger_commands::execute_comment_add(const std::vector<std::string_view> ¶ms) { // param 1 is the address for the comment u64 address; - if (!validate_number_parameter(params[0], address)) + if (!m_console.validate_number_parameter(params[0], address)) return; // CPU parameter is implicit device_t *cpu; - if (!validate_cpu_parameter(std::string_view(), cpu)) + if (!m_console.validate_cpu_parameter(std::string_view(), cpu)) return; // make sure param 2 exists @@ -1644,7 +1262,8 @@ void debugger_commands::execute_comment_add(const std::vector<std::string> ¶ } // Now try adding the comment - cpu->debug()->comment_add(address, params[1].c_str(), 0x00ff0000); + std::string const text(params[1]); + cpu->debug()->comment_add(address, text.c_str(), 0x00ff0000); cpu->machine().debug_view().update_all(DVT_DISASSEMBLY); } @@ -1653,16 +1272,16 @@ void debugger_commands::execute_comment_add(const std::vector<std::string> ¶ execute_comment_del - remove a comment from an addr --------------------------------------------------------*/ -void debugger_commands::execute_comment_del(const std::vector<std::string> ¶ms) +void debugger_commands::execute_comment_del(const std::vector<std::string_view> ¶ms) { // param 1 can either be a command or the address for the comment u64 address; - if (!validate_number_parameter(params[0], address)) + if (!m_console.validate_number_parameter(params[0], address)) return; // CPU parameter is implicit device_t *cpu; - if (!validate_cpu_parameter(std::string_view(), cpu)) + if (!m_console.validate_cpu_parameter(std::string_view(), cpu)) return; // If it's a number, it must be an address @@ -1672,25 +1291,25 @@ void debugger_commands::execute_comment_del(const std::vector<std::string> ¶ } /** - * @fn void execute_comment_list(const std::vector<std::string> ¶ms) + * @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(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(const std::vector<std::string> ¶ms) + * @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(const std::vector<std::string> ¶ms) +void debugger_commands::execute_comment_commit(const std::vector<std::string_view> ¶ms) { execute_comment_add(params); execute_comment_save(params); @@ -1700,7 +1319,7 @@ void debugger_commands::execute_comment_commit(const std::vector<std::string> &p execute_comment - add a comment to a line -------------------------------------------------*/ -void debugger_commands::execute_comment_save(const std::vector<std::string> ¶ms) +void debugger_commands::execute_comment_save(const std::vector<std::string_view> ¶ms) { if (m_machine.debugger().cpu().comment_save()) m_console.printf("Comment successfully saved\n"); @@ -1710,7 +1329,7 @@ void debugger_commands::execute_comment_save(const std::vector<std::string> &par // TODO: add color hex editing capabilities for comments, see below for more info /** - * @fn void execute_comment_color(const std::vector<std::string> ¶ms) + * @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. @@ -1727,12 +1346,12 @@ void debugger_commands::execute_comment_save(const std::vector<std::string> &par command -------------------------------------------------*/ -void debugger_commands::execute_bpset(const std::vector<std::string> ¶ms) +void debugger_commands::execute_bpset(const std::vector<std::string_view> ¶ms) { // param 1 is the address/CPU u64 address; address_space *space; - if (!validate_target_address_parameter(params[0], AS_PROGRAM, space, address)) + if (!m_console.validate_target_address_parameter(params[0], AS_PROGRAM, space, address)) return; device_execute_interface const *execute; @@ -1751,12 +1370,12 @@ void debugger_commands::execute_bpset(const std::vector<std::string> ¶ms) // param 2 is the condition parsed_expression condition(debug->symtable()); - if (params.size() > 1 && !debug_command_parameter_expression(params[1], condition)) + if (params.size() > 1 && !m_console.validate_expression_parameter(params[1], condition)) return; // param 3 is the action - const char *action = nullptr; - if (params.size() > 2 && !debug_command_parameter_command(action = params[2].c_str())) + std::string_view action; + if (params.size() > 2 && !m_console.validate_command_parameter(action = params[2])) return; // set the breakpoint @@ -1770,7 +1389,7 @@ void debugger_commands::execute_bpset(const std::vector<std::string> ¶ms) clear command -------------------------------------------------*/ -void debugger_commands::execute_bpclear(const std::vector<std::string> ¶ms) +void debugger_commands::execute_bpclear(const std::vector<std::string_view> ¶ms) { if (params.empty()) // if no parameters, clear all { @@ -1799,7 +1418,7 @@ void debugger_commands::execute_bpclear(const std::vector<std::string> ¶ms) disable/enable commands -------------------------------------------------*/ -void debugger_commands::execute_bpdisenable(bool enable, const std::vector<std::string> ¶ms) +void debugger_commands::execute_bpdisenable(bool enable, const std::vector<std::string_view> ¶ms) { if (params.empty()) // if no parameters, disable/enable all { @@ -1828,7 +1447,7 @@ void debugger_commands::execute_bpdisenable(bool enable, const std::vector<std:: command -------------------------------------------------*/ -void debugger_commands::execute_bplist(const std::vector<std::string> ¶ms) +void debugger_commands::execute_bplist(const std::vector<std::string_view> ¶ms) { int printed = 0; std::string buffer; @@ -1857,7 +1476,7 @@ void debugger_commands::execute_bplist(const std::vector<std::string> ¶ms) if (!params.empty()) { device_t *cpu; - if (!validate_cpu_parameter(params[0], cpu)) + if (!m_console.validate_cpu_parameter(params[0], cpu)) return; apply(*cpu); if (!printed) @@ -1879,13 +1498,13 @@ void debugger_commands::execute_bplist(const std::vector<std::string> ¶ms) command -------------------------------------------------*/ -void debugger_commands::execute_wpset(int spacenum, const std::vector<std::string> ¶ms) +void debugger_commands::execute_wpset(int spacenum, const std::vector<std::string_view> ¶ms) { u64 address, length; address_space *space; // param 1 is the address/CPU - if (!validate_target_address_parameter(params[0], spacenum, space, address)) + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, address)) return; device_execute_interface const *execute; @@ -1897,31 +1516,35 @@ void debugger_commands::execute_wpset(int spacenum, const std::vector<std::strin device_debug *const debug = space->device().debug(); // param 2 is the length - if (!validate_number_parameter(params[1], length)) + if (!m_console.validate_number_parameter(params[1], length)) return; // param 3 is the type read_or_write type; - if (!core_stricmp(params[2].c_str(), "r")) - type = read_or_write::READ; - else if (!core_stricmp(params[2].c_str(), "w")) - type = read_or_write::WRITE; - else if (!core_stricmp(params[2].c_str(), "rw") || !core_stricmp(params[2].c_str(), "wr")) - type = read_or_write::READWRITE; - else { - 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(debug->symtable()); - if (params.size() > 3 && !debug_command_parameter_expression(params[3], condition)) + if (params.size() > 3 && !m_console.validate_expression_parameter(params[3], condition)) return; // param 5 is the action - const char *action = nullptr; - if (params.size() > 4 && !debug_command_parameter_command(action = params[4].c_str())) + std::string_view action; + if (params.size() > 4 && !m_console.validate_command_parameter(action = params[4])) return; // set the watchpoint @@ -1935,7 +1558,7 @@ void debugger_commands::execute_wpset(int spacenum, const std::vector<std::strin clear command -------------------------------------------------*/ -void debugger_commands::execute_wpclear(const std::vector<std::string> ¶ms) +void debugger_commands::execute_wpclear(const std::vector<std::string_view> ¶ms) { if (params.empty()) // if no parameters, clear all { @@ -1964,7 +1587,7 @@ void debugger_commands::execute_wpclear(const std::vector<std::string> ¶ms) disable/enable commands -------------------------------------------------*/ -void debugger_commands::execute_wpdisenable(bool enable, const std::vector<std::string> ¶ms) +void debugger_commands::execute_wpdisenable(bool enable, const std::vector<std::string_view> ¶ms) { if (params.empty()) // if no parameters, disable/enable all { @@ -1993,7 +1616,7 @@ void debugger_commands::execute_wpdisenable(bool enable, const std::vector<std:: command -------------------------------------------------*/ -void debugger_commands::execute_wplist(const std::vector<std::string> ¶ms) +void debugger_commands::execute_wplist(const std::vector<std::string_view> ¶ms) { int printed = 0; std::string buffer; @@ -2034,7 +1657,7 @@ void debugger_commands::execute_wplist(const std::vector<std::string> ¶ms) if (!params.empty()) { device_t *cpu; - if (!validate_cpu_parameter(params[0], cpu)) + if (!m_console.validate_cpu_parameter(params[0], cpu)) return; apply(*cpu); if (!printed) @@ -2056,21 +1679,21 @@ void debugger_commands::execute_wplist(const std::vector<std::string> ¶ms) command -------------------------------------------------*/ -void debugger_commands::execute_rpset(const std::vector<std::string> ¶ms) +void debugger_commands::execute_rpset(const std::vector<std::string_view> ¶ms) { // CPU is implicit device_t *cpu; - if (!validate_cpu_parameter(std::string_view(), 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)) + if (params.size() > 0 && !m_console.validate_expression_parameter(params[0], condition)) return; // param 2 is the action - const char *action = nullptr; - if (params.size() > 1 && !debug_command_parameter_command(action = params[1].c_str())) + std::string_view action; + if (params.size() > 1 && !m_console.validate_command_parameter(action = params[1])) return; // set the registerpoint @@ -2084,7 +1707,7 @@ void debugger_commands::execute_rpset(const std::vector<std::string> ¶ms) clear command -------------------------------------------------*/ -void debugger_commands::execute_rpclear(const std::vector<std::string> ¶ms) +void debugger_commands::execute_rpclear(const std::vector<std::string_view> ¶ms) { if (params.empty()) // if no parameters, clear all { @@ -2113,7 +1736,7 @@ void debugger_commands::execute_rpclear(const std::vector<std::string> ¶ms) disable/enable commands -------------------------------------------------*/ -void debugger_commands::execute_rpdisenable(bool enable, const std::vector<std::string> ¶ms) +void debugger_commands::execute_rpdisenable(bool enable, const std::vector<std::string_view> ¶ms) { if (params.empty()) // if no parameters, disable/enable all { @@ -2137,12 +1760,154 @@ void debugger_commands::execute_rpdisenable(bool enable, const std::vector<std:: } +//------------------------------------------------- +// 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; + + // 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 + { + 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_epdisenable - execute the exception +// point disable/enable commands +//------------------------------------------------- + +void debugger_commands::execute_epdisenable(bool enable, const std::vector<std::string_view> ¶ms) +{ + 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"); + } +} + + +//------------------------------------------------- +// 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) + { + 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 (!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_rplist - execute the registerpoint list command -------------------------------------------------*/ -void debugger_commands::execute_rplist(const std::vector<std::string> ¶ms) +void debugger_commands::execute_rplist(const std::vector<std::string_view> ¶ms) { int printed = 0; std::string buffer; @@ -2157,7 +1922,7 @@ void debugger_commands::execute_rplist(const std::vector<std::string> ¶ms) for (const auto &rp : device.debug()->registerpoint_list()) { buffer = string_format("%c%4X if %s", rp.enabled() ? ' ' : 'D', rp.index(), rp.condition()); - if (rp.action() && *rp.action()) + if (!rp.action().empty()) buffer.append(string_format(" do %s", rp.action())); m_console.printf("%s\n", buffer); printed++; @@ -2168,7 +1933,7 @@ void debugger_commands::execute_rplist(const std::vector<std::string> ¶ms) if (!params.empty()) { device_t *cpu; - if (!validate_cpu_parameter(params[0], cpu)) + if (!m_console.validate_cpu_parameter(params[0], cpu)) return; apply(*cpu); if (!printed) @@ -2189,10 +1954,9 @@ void debugger_commands::execute_rplist(const std::vector<std::string> ¶ms) execute_statesave - execute the statesave command -------------------------------------------------*/ -void debugger_commands::execute_statesave(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"); } @@ -2201,10 +1965,9 @@ void debugger_commands::execute_statesave(const std::vector<std::string> ¶ms execute_stateload - execute the stateload command -------------------------------------------------*/ -void debugger_commands::execute_stateload(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_enumerator(m_machine.root_device())) @@ -2220,7 +1983,7 @@ void debugger_commands::execute_stateload(const std::vector<std::string> ¶ms execute_rewind - execute the rewind command -------------------------------------------------*/ -void debugger_commands::execute_rewind(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) @@ -2239,15 +2002,15 @@ void debugger_commands::execute_rewind(const std::vector<std::string> ¶ms) execute_save - execute the save command -------------------------------------------------*/ -void debugger_commands::execute_save(int spacenum, 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; // validate parameters - if (!validate_target_address_parameter(params[1], spacenum, space, offset)) + if (!m_console.validate_target_address_parameter(params[1], spacenum, space, offset)) return; - if (!validate_number_parameter(params[2], length)) + if (!m_console.validate_number_parameter(params[2], length)) return; // determine the addresses to write @@ -2256,7 +2019,8 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string endoffset++; // open the file - FILE *const f = fopen(params[0].c_str(), "wb"); + 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]); @@ -2271,8 +2035,9 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string 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; @@ -2280,8 +2045,9 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string 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; @@ -2289,8 +2055,9 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string 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; @@ -2298,8 +2065,9 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string 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; @@ -2309,8 +2077,9 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string 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; @@ -2326,17 +2095,17 @@ void debugger_commands::execute_save(int spacenum, const std::vector<std::string execute_saveregion - execute the save command on region memory -------------------------------------------------*/ -void debugger_commands::execute_saveregion(const std::vector<std::string> ¶ms) +void debugger_commands::execute_saveregion(const std::vector<std::string_view> ¶ms) { u64 offset, length; memory_region *region; // validate parameters - if (!validate_number_parameter(params[1], offset)) + 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 (!validate_memory_region_parameter(params[3], region)) + if (!m_console.validate_memory_region_parameter(params[3], region)) return; if (offset >= region->bytes()) @@ -2348,7 +2117,8 @@ void debugger_commands::execute_saveregion(const std::vector<std::string> ¶m length = region->bytes() - offset; /* open the file */ - FILE *f = fopen(params[0].c_str(), "wb"); + 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]); @@ -2365,20 +2135,21 @@ void debugger_commands::execute_saveregion(const std::vector<std::string> ¶m execute_load - execute the load command -------------------------------------------------*/ -void debugger_commands::execute_load(int spacenum, 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_target_address_parameter(params[1], spacenum, space, offset)) + if (!m_console.validate_target_address_parameter(params[1], spacenum, space, offset)) return; - if (params.size() > 2 && !validate_number_parameter(params[2], length)) + 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]); @@ -2412,8 +2183,9 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string 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: @@ -2422,8 +2194,9 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string 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: @@ -2432,8 +2205,9 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string 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: @@ -2442,8 +2216,9 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string 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: @@ -2454,8 +2229,9 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string 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; } @@ -2473,17 +2249,17 @@ void debugger_commands::execute_load(int spacenum, const std::vector<std::string execute_loadregion - execute the load command on region memory -------------------------------------------------*/ -void debugger_commands::execute_loadregion(const std::vector<std::string> ¶ms) +void debugger_commands::execute_loadregion(const std::vector<std::string_view> ¶ms) { u64 offset, length; memory_region *region; // validate parameters - if (!validate_number_parameter(params[1], offset)) + 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 (!validate_memory_region_parameter(params[3], region)) + if (!m_console.validate_memory_region_parameter(params[3], region)) return; if (offset >= region->bytes()) @@ -2495,7 +2271,8 @@ void debugger_commands::execute_loadregion(const std::vector<std::string> ¶m length = region->bytes() - offset; // open the file - FILE *const f = fopen(params[0].c_str(), "rb"); + 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]); @@ -2521,28 +2298,28 @@ void debugger_commands::execute_loadregion(const std::vector<std::string> ¶m execute_dump - execute the dump command -------------------------------------------------*/ -void debugger_commands::execute_dump(int spacenum, const std::vector<std::string> ¶ms) +void debugger_commands::execute_dump(int spacenum, const std::vector<std::string_view> ¶ms) { // validate parameters address_space *space; u64 offset; - if (!validate_target_address_parameter(params[1], spacenum, space, 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)) + if (params.size() > 3 && !m_console.validate_number_parameter(params[3], width)) return; bool ascii = true; - if (params.size() > 4 && !validate_boolean_parameter(params[4], ascii)) + 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(); @@ -2573,7 +2350,8 @@ void debugger_commands::execute_dump(int spacenum, const std::vector<std::string offset = offset & space->addrmask(); // open the file - FILE *const f = fopen(params[0].c_str(), "w"); + 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]); @@ -2603,21 +2381,22 @@ void debugger_commands::execute_dump(int spacenum, const std::vector<std::string 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; } } @@ -2637,22 +2416,23 @@ void debugger_commands::execute_dump(int spacenum, const std::vector<std::string 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++) { @@ -2682,23 +2462,23 @@ void debugger_commands::execute_dump(int spacenum, const std::vector<std::string // execute_strdump - execute the strdump command //------------------------------------------------- -void debugger_commands::execute_strdump(int spacenum, const std::vector<std::string> ¶ms) +void debugger_commands::execute_strdump(int spacenum, const std::vector<std::string_view> ¶ms) { // validate parameters u64 offset; - if (!validate_number_parameter(params[1], offset)) + if (!m_console.validate_number_parameter(params[1], offset)) return; u64 length; - if (!validate_number_parameter(params[2], length)) + if (!m_console.validate_number_parameter(params[2], length)) return; u64 term = 0; - if (params.size() > 3 && !validate_number_parameter(params[3], term)) + if (params.size() > 3 && !m_console.validate_number_parameter(params[3], term)) return; address_space *space; - if (!validate_device_space_parameter((params.size() > 4) ? params[4] : std::string_view(), spacenum, space)) + if (!m_console.validate_device_space_parameter((params.size() > 4) ? params[4] : std::string_view(), spacenum, space)) return; // further validation @@ -2709,7 +2489,8 @@ void debugger_commands::execute_strdump(int spacenum, const std::vector<std::str } // open the file - FILE *f = fopen(params[0].c_str(), "w"); + std::string filename(params[0]); + FILE *f = fopen(filename.c_str(), "w"); if (!f) { m_console.printf("Error opening file '%s'\n", params[0]); @@ -2747,28 +2528,29 @@ void debugger_commands::execute_strdump(int spacenum, const std::vector<std::str // get the character data u64 data = 0; offs_t curaddr = offset; - 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 1: - data = space->read_byte(curaddr); + data = tspace->read_byte(curaddr); break; case 2: - data = space->read_word(curaddr); + data = tspace->read_word(curaddr); if (be) data = swapendian_int16(data); break; case 4: - data = space->read_dword(curaddr); + data = tspace->read_dword(curaddr); if (be) data = swapendian_int32(data); break; case 8: - data = space->read_qword(curaddr); + data = tspace->read_qword(curaddr); if (be) data = swapendian_int64(data); break; @@ -2858,7 +2640,7 @@ void debugger_commands::execute_strdump(int spacenum, const std::vector<std::str cheats -------------------------------------------------*/ -void debugger_commands::execute_cheatrange(bool init, const std::vector<std::string> ¶ms) +void debugger_commands::execute_cheatrange(bool init, const std::vector<std::string_view> ¶ms) { address_space *space = m_cheat.space; if (!space && !init) @@ -2875,7 +2657,7 @@ void debugger_commands::execute_cheatrange(bool init, const std::vector<std::str // first argument is sign/size/swap flags if (!params.empty()) { - std::string const &srtpnt = params[0]; + std::string_view const &srtpnt = params[0]; if (!srtpnt.empty()) { width = 1; @@ -2928,7 +2710,7 @@ void debugger_commands::execute_cheatrange(bool init, const std::vector<std::str } // fourth argument is device/space - if (!validate_device_space_parameter((params.size() > 3) ? params[3] : std::string_view(), -1, space)) + if (!m_console.validate_device_space_parameter((params.size() > 3) ? params[3] : std::string_view(), -1, space)) return; } @@ -2938,9 +2720,9 @@ void debugger_commands::execute_cheatrange(bool init, const std::vector<std::str { // validate parameters u64 offset, length; - if (!validate_number_parameter(params[init ? 1 : 0], offset)) + if (!m_console.validate_number_parameter(params[init ? 1 : 0], offset)) return; - if (!validate_number_parameter(params[init ? 2 : 1], length)) + if (!m_console.validate_number_parameter(params[init ? 2 : 1], length)) return; // force region to the specified range @@ -3027,7 +2809,7 @@ void debugger_commands::execute_cheatrange(bool init, const std::vector<std::str execute_cheatnext - execute the search -------------------------------------------------*/ -void debugger_commands::execute_cheatnext(bool initial, const std::vector<std::string> ¶ms) +void debugger_commands::execute_cheatnext(bool initial, const std::vector<std::string_view> ¶ms) { enum { @@ -3055,36 +2837,40 @@ void debugger_commands::execute_cheatnext(bool initial, const std::vector<std::s } u64 comp_value = 0; - if (params.size() > 1 && !validate_number_parameter(params[1], comp_value)) + if (params.size() > 1 && !m_console.validate_number_parameter(params[1], comp_value)) return; comp_value = m_cheat.sign_extend(comp_value); // decode condition u8 condition; - if (!core_stricmp(params[0].c_str(), "all")) - condition = CHEAT_ALL; - else if (!core_stricmp(params[0].c_str(), "equal") || !core_stricmp(params[0].c_str(), "eq")) - condition = (params.size() > 1) ? CHEAT_EQUALTO : CHEAT_EQUAL; - else if (!core_stricmp(params[0].c_str(), "notequal") || !core_stricmp(params[0].c_str(), "ne")) - condition = (params.size() > 1) ? CHEAT_NOTEQUALTO : CHEAT_NOTEQUAL; - else if (!core_stricmp(params[0].c_str(), "decrease") || !core_stricmp(params[0].c_str(), "de") || params[0] == "-") - condition = (params.size() > 1) ? CHEAT_DECREASEOF : CHEAT_DECREASE; - else if (!core_stricmp(params[0].c_str(), "increase") || !core_stricmp(params[0].c_str(), "in") || params[0] == "+") - condition = (params.size() > 1) ? CHEAT_INCREASEOF : CHEAT_INCREASE; - else if (!core_stricmp(params[0].c_str(), "decreaseorequal") || !core_stricmp(params[0].c_str(), "deeq")) - condition = CHEAT_DECREASE_OR_EQUAL; - else if (!core_stricmp(params[0].c_str(), "increaseorequal") || !core_stricmp(params[0].c_str(), "ineq")) - condition = CHEAT_INCREASE_OR_EQUAL; - else if (!core_stricmp(params[0].c_str(), "smallerof") || !core_stricmp(params[0].c_str(), "lt") || params[0] == "<") - condition = CHEAT_SMALLEROF; - else if (!core_stricmp(params[0].c_str(), "greaterof") || !core_stricmp(params[0].c_str(), "gt") || params[0] == ">") - condition = CHEAT_GREATEROF; - else if (!core_stricmp(params[0].c_str(), "changedby") || !core_stricmp(params[0].c_str(), "ch") || params[0] == "~") - condition = CHEAT_CHANGEDBY; - else { - 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++; @@ -3191,7 +2977,7 @@ void debugger_commands::execute_cheatnext(bool initial, const std::vector<std::s } if (active_cheat <= 5) - execute_cheatlist(std::vector<std::string>()); + execute_cheatlist(std::vector<std::string_view>()); m_console.printf("%u cheats found\n", active_cheat); } @@ -3201,7 +2987,7 @@ void debugger_commands::execute_cheatnext(bool initial, const std::vector<std::s execute_cheatlist - show a list of active cheat -------------------------------------------------*/ -void debugger_commands::execute_cheatlist(const std::vector<std::string> ¶ms) +void debugger_commands::execute_cheatlist(const std::vector<std::string_view> ¶ms) { address_space *const space = m_cheat.space; if (!space) @@ -3213,7 +2999,8 @@ void debugger_commands::execute_cheatlist(const std::vector<std::string> ¶ms 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]); @@ -3318,7 +3105,7 @@ void debugger_commands::execute_cheatlist(const std::vector<std::string> ¶ms execute_cheatundo - undo the last search -------------------------------------------------*/ -void debugger_commands::execute_cheatundo(const std::vector<std::string> ¶ms) +void debugger_commands::execute_cheatundo(const std::vector<std::string_view> ¶ms) { if (m_cheat.undo > 0) { @@ -3347,15 +3134,15 @@ void debugger_commands::execute_cheatundo(const std::vector<std::string> ¶ms execute_find - execute the find command -------------------------------------------------*/ -void debugger_commands::execute_find(int spacenum, const std::vector<std::string> ¶ms) +void debugger_commands::execute_find(int spacenum, const std::vector<std::string_view> ¶ms) { u64 offset, length; address_space *space; // validate parameters - if (!validate_target_address_parameter(params[0], spacenum, space, offset)) + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, offset)) return; - if (!validate_number_parameter(params[1], length)) + if (!m_console.validate_number_parameter(params[1], length)) return; // further validation @@ -3371,11 +3158,11 @@ void debugger_commands::execute_find(int spacenum, const std::vector<std::string int data_count = 0; for (int i = 2; i < params.size(); i++) { - char const *pdata = params[i].c_str(); - auto const pdatalen = params[i].length() - 1; + std::string_view pdata = params[i]; - if (pdata[0] == '"' && pdata[pdatalen] == '"') // check for a string + if (!pdata.empty() && pdata.front() == '"' && pdata.back() == '"') // check for a string { + auto const pdatalen = params[i].length() - 1; for (int j = 1; j < pdatalen; j++) { data_to_find[data_count] = pdata[j]; @@ -3386,17 +3173,20 @@ void debugger_commands::execute_find(int spacenum, const std::vector<std::string { // 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, "?")) + if (pdata == "?") data_size[data_count++] |= 0x10; // otherwise, validate as a number - else if (!validate_number_parameter(pdata, data_to_find[data_count++])) + else if (!m_console.validate_number_parameter(pdata, data_to_find[data_count++])) return; } } @@ -3414,36 +3204,37 @@ void debugger_commands::execute_find(int spacenum, const std::vector<std::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: address &= space->logaddrmask(); - if (memory.translate(space->spacenum(), TRANSLATE_READ_DEBUG, address)) - match = space->read_byte(address) == u8(data_to_find[j]); + 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(), TRANSLATE_READ_DEBUG, address)) - match = space->read_word_unaligned(address) == u16(data_to_find[j]); + 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(), TRANSLATE_READ_DEBUG, address)) - match = space->read_dword_unaligned(address) == u32(data_to_find[j]); + 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(), TRANSLATE_READ_DEBUG, address)) - match = space->read_qword_unaligned(address) == u64(data_to_find[j]); + 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; @@ -3473,15 +3264,15 @@ void debugger_commands::execute_find(int spacenum, const std::vector<std::string // execute_fill - execute the fill command //------------------------------------------------- -void debugger_commands::execute_fill(int spacenum, const std::vector<std::string> ¶ms) +void debugger_commands::execute_fill(int spacenum, const std::vector<std::string_view> ¶ms) { u64 offset, length; address_space *space; // validate parameters - if (!validate_target_address_parameter(params[0], spacenum, space, offset)) + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, offset)) return; - if (!validate_number_parameter(params[1], length)) + if (!m_console.validate_number_parameter(params[1], length)) return; // further validation @@ -3496,12 +3287,12 @@ void debugger_commands::execute_fill(int spacenum, const std::vector<std::string 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() == '"') { + auto const pdatalen = pdata.length() - 1; for (int j = 1; j < pdatalen; j++) { fill_data[data_count] = pdata[j]; @@ -3514,13 +3305,16 @@ void debugger_commands::execute_fill(int spacenum, const std::vector<std::string { // check for a 'b','w','d',or 'q' prefix fill_data_size[data_count] = cur_data_size; - if (tolower(u8(pdata[0])) == 'b' && pdata[1] == '.') { fill_data_size[data_count] = cur_data_size = 1; pdata += 2; } - if (tolower(u8(pdata[0])) == 'w' && pdata[1] == '.') { fill_data_size[data_count] = cur_data_size = 2; pdata += 2; } - if (tolower(u8(pdata[0])) == 'd' && pdata[1] == '.') { fill_data_size[data_count] = cur_data_size = 4; pdata += 2; } - if (tolower(u8(pdata[0])) == 'q' && pdata[1] == '.') { fill_data_size[data_count] = cur_data_size = 8; pdata += 2; } + 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 (!validate_number_parameter(pdata, fill_data[data_count++])) + if (!m_console.validate_number_parameter(pdata, fill_data[data_count++])) return; } } @@ -3537,7 +3331,8 @@ void debugger_commands::execute_fill(int spacenum, const std::vector<std::string for (int j = 0; j < data_count; j++) { offs_t address = space->byte_to_address(offset) & space->logaddrmask(); - if (!memory.translate(space->spacenum(), TRANSLATE_WRITE_DEBUG, address)) + 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; @@ -3546,19 +3341,19 @@ void debugger_commands::execute_fill(int spacenum, const std::vector<std::string switch (fill_data_size[j]) { case 1: - space->write_byte(address, fill_data[j]); + tspace->write_byte(address, fill_data[j]); break; case 2: - space->write_word_unaligned(address, fill_data[j]); + tspace->write_word_unaligned(address, fill_data[j]); break; case 4: - space->write_dword_unaligned(address, fill_data[j]); + tspace->write_dword_unaligned(address, fill_data[j]); break; case 8: - space->read_qword_unaligned(address, fill_data[j]); + tspace->read_qword_unaligned(address, fill_data[j]); break; } offset += fill_data_size[j]; @@ -3578,20 +3373,20 @@ void debugger_commands::execute_fill(int spacenum, const std::vector<std::string execute_dasm - execute the dasm command -------------------------------------------------*/ -void debugger_commands::execute_dasm(const std::vector<std::string> ¶ms) +void debugger_commands::execute_dasm(const std::vector<std::string_view> ¶ms) { u64 offset, length; bool bytes = true; address_space *space; // validate parameters - if (!validate_number_parameter(params[1], offset)) + 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_boolean_parameter(params[3], bytes)) + if (params.size() > 3 && !m_console.validate_boolean_parameter(params[3], bytes)) return; - if (!validate_device_space_parameter(params.size() > 4 ? params[4] : std::string_view(), 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 @@ -3637,7 +3432,8 @@ void debugger_commands::execute_dasm(const std::vector<std::string> ¶ms) } /* 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]); @@ -3676,32 +3472,32 @@ void debugger_commands::execute_dasm(const std::vector<std::string> ¶ms) trace over and trace info -------------------------------------------------*/ -void debugger_commands::execute_trace(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; - const char *mode; - std::string filename = params[0]; + std::string filename(params[0]); // replace macros strreplace(filename, "{game}", m_machine.basename()); // validate parameters - if (!validate_cpu_parameter(params.size() > 1 ? params[1] : std::string_view(), cpu)) + 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 { @@ -3710,24 +3506,27 @@ void debugger_commands::execute_trace(const std::vector<std::string> ¶ms, bo } } } - 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 - FILE *f = nullptr; - if (core_stricmp(filename.c_str(), "off") != 0) + std::unique_ptr<std::ofstream> f; + using namespace std::literals; + if (!util::streqlower(filename, "off"sv)) { - mode = "w"; + std::ios_base::openmode mode = std::ios_base::out; // opening for append? if ((filename[0] == '>') && (filename[1] == '>')) { - mode = "a"; + mode |= std::ios_base::ate; filename = filename.substr(2); } + else + mode |= 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]); return; @@ -3735,8 +3534,9 @@ void debugger_commands::execute_trace(const std::vector<std::string> ¶ms, bo } // do it - cpu->debug()->trace(f, trace_over, detect_loops, logerror, action); - if (f) + 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()); @@ -3747,7 +3547,7 @@ void debugger_commands::execute_trace(const std::vector<std::string> ¶ms, bo execute_traceflush - execute the trace flush command -------------------------------------------------*/ -void debugger_commands::execute_traceflush(const std::vector<std::string> ¶ms) +void debugger_commands::execute_traceflush(const std::vector<std::string_view> ¶ms) { m_machine.debugger().cpu().flush_traces(); } @@ -3757,15 +3557,15 @@ void debugger_commands::execute_traceflush(const std::vector<std::string> ¶m execute_history - execute the history command -------------------------------------------------*/ -void debugger_commands::execute_history(const std::vector<std::string> ¶ms) +void debugger_commands::execute_history(const std::vector<std::string_view> ¶ms) { // validate parameters device_t *device; - if (!validate_cpu_parameter(!params.empty() ? params[0] : std::string_view(), 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 @@ -3782,13 +3582,13 @@ void debugger_commands::execute_history(const std::vector<std::string> ¶ms) } // loop over lines - debug_disasm_buffer buffer(*device); std::string instruction; for (int index = int(unsigned(count)); index > 0; index--) { 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; @@ -3805,16 +3605,16 @@ void debugger_commands::execute_history(const std::vector<std::string> ¶ms) execute_trackpc - execute the trackpc command -------------------------------------------------*/ -void debugger_commands::execute_trackpc(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] : std::string_view(), cpu)) + if (!m_console.validate_cpu_parameter((params.size() > 1) ? params[1] : std::string_view(), cpu)) return; const device_state_interface *state; @@ -3826,7 +3626,7 @@ void debugger_commands::execute_trackpc(const std::vector<std::string> ¶ms) // 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); @@ -3854,11 +3654,11 @@ void debugger_commands::execute_trackpc(const std::vector<std::string> ¶ms) execute_trackmem - execute the trackmem command -------------------------------------------------*/ -void debugger_commands::execute_trackmem(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) @@ -3866,17 +3666,17 @@ void debugger_commands::execute_trackmem(const std::vector<std::string> ¶ms) if (params.size() > 1) cpuparam = params[1]; device_t *cpu = nullptr; - if (!validate_cpu_parameter(cpuparam, 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_device_space_parameter(cpuparam, 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 @@ -3892,17 +3692,18 @@ void debugger_commands::execute_trackmem(const std::vector<std::string> ¶ms) execute_pcatmem - execute the pcatmem command -------------------------------------------------*/ -void debugger_commands::execute_pcatmem(int spacenum, const std::vector<std::string> ¶ms) +void debugger_commands::execute_pcatmem(int spacenum, const std::vector<std::string_view> ¶ms) { // Gather the required target address/space parameter u64 address; address_space *space; - if (!validate_target_address_parameter(params[0], spacenum, space, address)) + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, address)) return; // Translate the address offs_t a = address & space->logaddrmask(); - if (!space->device().memory().translate(space->spacenum(), TRANSLATE_READ_DEBUG, a)) + 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; @@ -3914,19 +3715,19 @@ void debugger_commands::execute_pcatmem(int spacenum, const std::vector<std::str switch (space->data_width()) { case 8: - data = space->read_byte(a); + data = tspace->read_byte(a); break; case 16: - data = space->read_word_unaligned(a); + data = tspace->read_word_unaligned(a); break; case 32: - data = space->read_dword_unaligned(a); + data = tspace->read_dword_unaligned(a); break; case 64: - data = space->read_qword_unaligned(a); + data = tspace->read_qword_unaligned(a); break; } @@ -3943,7 +3744,7 @@ void debugger_commands::execute_pcatmem(int spacenum, const std::vector<std::str execute_snap - execute the snapshot command -------------------------------------------------*/ -void debugger_commands::execute_snap(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()) @@ -3955,8 +3756,9 @@ void debugger_commands::execute_snap(const std::vector<std::string> ¶ms) /* 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_enumerator iter(m_machine.root_device()); screen_device *screen = iter.byindex(scrnum); @@ -3967,7 +3769,7 @@ void debugger_commands::execute_snap(const std::vector<std::string> ¶ms) 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); @@ -3975,12 +3777,12 @@ void debugger_commands::execute_snap(const std::vector<std::string> ¶ms) if (filerr) { - m_console.printf("Error creating file '%s' (%s:%d %s)\n", filename, filerr.category().name(), filerr.value(), filerr.message()); + 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]); } } @@ -3989,9 +3791,10 @@ void debugger_commands::execute_snap(const std::vector<std::string> ¶ms) execute_source - execute the source command -------------------------------------------------*/ -void debugger_commands::execute_source(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()); } @@ -3999,27 +3802,29 @@ void debugger_commands::execute_source(const std::vector<std::string> ¶ms) execute_map - execute the map command -------------------------------------------------*/ -void debugger_commands::execute_map(int spacenum, const std::vector<std::string> ¶ms) +void debugger_commands::execute_map(int spacenum, const std::vector<std::string_view> ¶ms) { // validate parameters u64 address; address_space *space; - if (!validate_target_address_parameter(params[0], spacenum, space, address)) + if (!m_console.validate_target_address_parameter(params[0], spacenum, space, address)) return; + address &= space->logaddrmask(); // do the translation first - for (int intention = TRANSLATE_READ_DEBUG; intention <= TRANSLATE_FETCH_DEBUG; intention++) + for (int intention = device_memory_interface::TR_READ; intention <= device_memory_interface::TR_FETCH; intention++) { static const char *const intnames[] = { "Read", "Write", "Fetch" }; - offs_t 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 @@ -4032,14 +3837,15 @@ void debugger_commands::execute_map(int spacenum, const std::vector<std::string> execute_memdump - execute the memdump command -------------------------------------------------*/ -void debugger_commands::execute_memdump(const std::vector<std::string> ¶ms) +void debugger_commands::execute_memdump(const std::vector<std::string_view> ¶ms) { device_t *root = &m_machine.root_device(); - if ((params.size() >= 2) && !validate_device_parameter(params[1], root)) + if ((params.size() >= 2) && !m_console.validate_device_parameter(params[1], root)) return; - char const *const filename = params.empty() ? "memdump.log" : params[0].c_str(); - FILE *const file = fopen(filename, "w"); + 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); @@ -4098,7 +3904,7 @@ void debugger_commands::execute_memdump(const std::vector<std::string> ¶ms) execute_symlist - execute the symlist command -------------------------------------------------*/ -void debugger_commands::execute_symlist(const std::vector<std::string> ¶ms) +void debugger_commands::execute_symlist(const std::vector<std::string_view> ¶ms) { const char *namelist[1000]; symbol_table *symtable; @@ -4108,7 +3914,7 @@ void debugger_commands::execute_symlist(const std::vector<std::string> ¶ms) { // validate parameters device_t *cpu; - if (!validate_cpu_parameter(params[0], cpu)) + if (!m_console.validate_cpu_parameter(params[0], cpu)) return; symtable = &cpu->debug()->symtable(); m_console.printf("CPU '%s' symbols:\n", cpu->tag()); @@ -4160,7 +3966,7 @@ void debugger_commands::execute_symlist(const std::vector<std::string> ¶ms) execute_softreset - execute the softreset command -------------------------------------------------*/ -void debugger_commands::execute_softreset(const std::vector<std::string> ¶ms) +void debugger_commands::execute_softreset(const std::vector<std::string_view> ¶ms) { m_machine.schedule_soft_reset(); } @@ -4170,7 +3976,7 @@ void debugger_commands::execute_softreset(const std::vector<std::string> ¶ms execute_hardreset - execute the hardreset command -------------------------------------------------*/ -void debugger_commands::execute_hardreset(const std::vector<std::string> ¶ms) +void debugger_commands::execute_hardreset(const std::vector<std::string_view> ¶ms) { m_machine.schedule_hard_reset(); } @@ -4180,7 +3986,7 @@ void debugger_commands::execute_hardreset(const std::vector<std::string> ¶ms mounted files -------------------------------------------------*/ -void debugger_commands::execute_images(const std::vector<std::string> ¶ms) +void debugger_commands::execute_images(const std::vector<std::string_view> ¶ms) { image_interface_enumerator iter(m_machine.root_device()); for (device_image_interface &img : iter) @@ -4210,16 +4016,25 @@ void debugger_commands::execute_images(const std::vector<std::string> ¶ms) execute_mount - execute the image mount command -------------------------------------------------*/ -void debugger_commands::execute_mount(const std::vector<std::string> ¶ms) +void debugger_commands::execute_mount(const std::vector<std::string_view> ¶ms) { for (device_image_interface &img : image_interface_enumerator(m_machine.root_device())) { 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]); + } + else + { + m_console.printf( + "Unable to mount file %s on %s: %s\n", + params[1], + params[0], + !msg.empty() ? msg : err.message()); + } return; } } @@ -4230,7 +4045,7 @@ void debugger_commands::execute_mount(const std::vector<std::string> ¶ms) execute_unmount - execute the image unmount command -------------------------------------------------*/ -void debugger_commands::execute_unmount(const std::vector<std::string> ¶ms) +void debugger_commands::execute_unmount(const std::vector<std::string_view> ¶ms) { for (device_image_interface &img : image_interface_enumerator(m_machine.root_device())) { @@ -4257,9 +4072,9 @@ void debugger_commands::execute_unmount(const std::vector<std::string> ¶ms) natural keyboard input -------------------------------------------------*/ -void debugger_commands::execute_input(const std::vector<std::string> ¶ms) +void debugger_commands::execute_input(const std::vector<std::string_view> ¶ms) { - m_machine.natkeyboard().post_coded(params[0].c_str()); + m_machine.natkeyboard().post_coded(params[0]); } @@ -4268,15 +4083,15 @@ void debugger_commands::execute_input(const std::vector<std::string> ¶ms) keyboard codes -------------------------------------------------*/ -void debugger_commands::execute_dumpkbd(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); |