mirror of
https://github.com/holub/mame
synced 2025-04-19 23:12:11 +03:00
Debugger changes
- Added exception points as a new class of "points" triggering on specific exception numbers, with a similar set of commands to breakpoints and registerpoints. - Removed the per-instruction callback hook from device_debug. Only one driver was using this (rmnimbus.cpp), and what it was doing with it could be done more cleanly with exception points. - Change the type of the action string parameter for "points"-creating methods and make some parameters optional for those. - Change trace file logging to use a std::ostream instead of FILE * to take better advantage of strformat.
This commit is contained in:
parent
f52b402f24
commit
d8d588262d
134
docs/source/debugger/exceptionpoint.rst
Normal file
134
docs/source/debugger/exceptionpoint.rst
Normal file
@ -0,0 +1,134 @@
|
||||
.. _debugger-exceptionpoint-list:
|
||||
|
||||
Exception Point Debugger Commands
|
||||
=================================
|
||||
|
||||
:ref:`debugger-command-epset`
|
||||
sets a new exception point
|
||||
:ref:`debugger-command-epclear`
|
||||
clears a specific exception point or all exception points
|
||||
:ref:`debugger-command-epdisable`
|
||||
disables a specific exception point or all exception points
|
||||
:ref:`debugger-command-epenable`
|
||||
enables a specific exception point or all exception points
|
||||
:ref:`debugger-command-eplist`
|
||||
lists exception points
|
||||
|
||||
Exception points halt execution and activate the debugger when
|
||||
a CPU raises a particular exception number.
|
||||
|
||||
|
||||
.. _debugger-command-epset:
|
||||
|
||||
epset
|
||||
-----
|
||||
|
||||
**ep[set] <type>[,<condition>[,<action>]]**
|
||||
|
||||
Sets a new exception point for exceptions of type **<type>**. The
|
||||
optional **<condition>** parameter lets you specify an expression that
|
||||
will be evaluated each time the exception point is hit. If the result
|
||||
of the expression is true (non-zero), the exception point will actually
|
||||
halt execution at the start of the exception handler; otherwise,
|
||||
execution will continue with no notification. The optional **<action>**
|
||||
parameter provides a command that is executed whenever the exception
|
||||
point is hit and the **<condition>** is true. Note that you may need to
|
||||
embed the action within braces ``{ }`` in order to prevent commas and
|
||||
semicolons from being interpreted as applying to the ``epset`` command
|
||||
itself.
|
||||
|
||||
The numbering of exceptions depends upon the CPU type. Causes of
|
||||
exceptions may include internally or externally vectored interrupts,
|
||||
errors occurring within instructions and system calls.
|
||||
|
||||
Each exception point that is set is assigned an index which can be used
|
||||
in other exception point commands to reference this exception point.
|
||||
|
||||
Examples:
|
||||
|
||||
``ep 2``
|
||||
Set an exception that will halt execution whenever the visible CPU
|
||||
raises exception number 2.
|
||||
|
||||
Back to :ref:`debugger-exceptionpoint-list`
|
||||
|
||||
|
||||
.. _debugger-command-epclear:
|
||||
|
||||
epclear
|
||||
-------
|
||||
|
||||
**epclear [<epnum>[,…]]**
|
||||
|
||||
The epclear command clears exception points. If **<epnum>** is
|
||||
specified, only the requested exception points are cleared, otherwise
|
||||
all exception points are cleared.
|
||||
|
||||
Examples:
|
||||
|
||||
``epclear 3``
|
||||
Clear exception point index 3.
|
||||
|
||||
``epclear``
|
||||
Clear all exception points.
|
||||
|
||||
Back to :ref:`debugger-exceptionpoint-list`
|
||||
|
||||
|
||||
.. _debugger-command-epdisable:
|
||||
|
||||
epdisable
|
||||
---------
|
||||
|
||||
**epdisable [<epnum>[,…]]**
|
||||
|
||||
The epdisable command disables exception points. If **<epnum>** is
|
||||
specified, only the requested exception points are disabled, otherwise
|
||||
all exception points are disabled. Note that disabling an exception
|
||||
point does not delete it, it just temporarily marks the exception
|
||||
point as inactive.
|
||||
|
||||
Examples:
|
||||
|
||||
``epdisable 3``
|
||||
Disable exception point index 3.
|
||||
|
||||
``epdisable``
|
||||
Disable all exception points.
|
||||
|
||||
Back to :ref:`debugger-exceptionpoint-list`
|
||||
|
||||
|
||||
.. _debugger-command-epenable:
|
||||
|
||||
epenable
|
||||
--------
|
||||
|
||||
**epenable [<epnum>[,…]]**
|
||||
|
||||
The epenable command enables exception points. If **<epnum>** is
|
||||
specified, only the requested exception points are enabled, otherwise
|
||||
all exception points are enabled.
|
||||
|
||||
Examples:
|
||||
|
||||
``epenable 3``
|
||||
Enable exception point index 3.
|
||||
|
||||
``epenable``
|
||||
Enable all exception points.
|
||||
|
||||
Back to :ref:`debugger-exceptionpoint-list`
|
||||
|
||||
|
||||
.. _debugger-command-eplist:
|
||||
|
||||
eplist
|
||||
------
|
||||
|
||||
**eplist**
|
||||
|
||||
The eplist command lists all the current exception points, along with
|
||||
their index and any conditions or actions attached to them.
|
||||
|
||||
Back to :ref:`debugger-exceptionpoint-list`
|
@ -50,6 +50,7 @@ name of a command, to see documentation directly in MAME.
|
||||
breakpoint
|
||||
watchpoint
|
||||
registerpoints
|
||||
exceptionpoint
|
||||
annotation
|
||||
cheats
|
||||
image
|
||||
|
@ -282,6 +282,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));
|
||||
@ -471,8 +478,9 @@ bool debugger_commands::validate_boolean_parameter(std::string_view param, bool
|
||||
return true;
|
||||
|
||||
// evaluate the expression; success if no error
|
||||
bool const is_true = util::streqlower(param, "true");
|
||||
bool const is_false = util::streqlower(param, "false");
|
||||
using namespace std::literals;
|
||||
bool const is_true = util::streqlower(param, "true"sv);
|
||||
bool const is_false = util::streqlower(param, "false"sv);
|
||||
|
||||
if (is_true || is_false)
|
||||
{
|
||||
@ -1153,7 +1161,7 @@ void debugger_commands::execute_tracelog(const std::vector<std::string_view> &pa
|
||||
/* then do a printf */
|
||||
std::ostringstream buffer;
|
||||
if (mini_printf(buffer, params[0], params.size() - 1, &values[1]))
|
||||
m_console.get_visible_cpu()->debug()->trace_printf("%s", std::move(buffer).str().c_str());
|
||||
m_console.get_visible_cpu()->debug()->trace_printf("%s", std::move(buffer).str());
|
||||
}
|
||||
|
||||
|
||||
@ -1189,7 +1197,7 @@ void debugger_commands::execute_tracesym(const std::vector<std::string_view> &pa
|
||||
// then do a printf
|
||||
std::ostringstream buffer;
|
||||
if (mini_printf(buffer, format.str(), params.size(), values))
|
||||
m_console.get_visible_cpu()->debug()->trace_printf("%s", std::move(buffer).str().c_str());
|
||||
m_console.get_visible_cpu()->debug()->trace_printf("%s", std::move(buffer).str());
|
||||
}
|
||||
|
||||
|
||||
@ -1819,12 +1827,12 @@ void debugger_commands::execute_bpset(const std::vector<std::string_view> ¶m
|
||||
return;
|
||||
|
||||
// param 3 is the action
|
||||
std::string action;
|
||||
std::string_view action;
|
||||
if (params.size() > 2 && !debug_command_parameter_command(action = params[2]))
|
||||
return;
|
||||
|
||||
// set the breakpoint
|
||||
int const bpnum = debug->breakpoint_set(address, condition.is_empty() ? nullptr : condition.original_string(), action.c_str());
|
||||
int const bpnum = debug->breakpoint_set(address, condition.is_empty() ? nullptr : condition.original_string(), action);
|
||||
m_console.printf("Breakpoint %X set\n", bpnum);
|
||||
}
|
||||
|
||||
@ -1966,16 +1974,20 @@ void debugger_commands::execute_wpset(int spacenum, const std::vector<std::strin
|
||||
|
||||
// param 3 is the type
|
||||
read_or_write type;
|
||||
if (util::streqlower(params[2], "r"))
|
||||
type = read_or_write::READ;
|
||||
else if (util::streqlower(params[2], "w"))
|
||||
type = read_or_write::WRITE;
|
||||
else if (util::streqlower(params[2], "rw") || util::streqlower(params[2], "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
|
||||
@ -1984,12 +1996,12 @@ void debugger_commands::execute_wpset(int spacenum, const std::vector<std::strin
|
||||
return;
|
||||
|
||||
// param 5 is the action
|
||||
std::string action;
|
||||
std::string_view action;
|
||||
if (params.size() > 4 && !debug_command_parameter_command(action = params[4]))
|
||||
return;
|
||||
|
||||
// set the watchpoint
|
||||
int const wpnum = debug->watchpoint_set(*space, type, address, length, (condition.is_empty()) ? nullptr : condition.original_string(), action.c_str());
|
||||
int const wpnum = debug->watchpoint_set(*space, type, address, length, (condition.is_empty()) ? nullptr : condition.original_string(), action);
|
||||
m_console.printf("Watchpoint %X set\n", wpnum);
|
||||
}
|
||||
|
||||
@ -2133,12 +2145,12 @@ void debugger_commands::execute_rpset(const std::vector<std::string_view> ¶m
|
||||
return;
|
||||
|
||||
// param 2 is the action
|
||||
std::string action;
|
||||
std::string_view action;
|
||||
if (params.size() > 1 && !debug_command_parameter_command(action = params[1]))
|
||||
return;
|
||||
|
||||
// set the registerpoint
|
||||
int const rpnum = cpu->debug()->registerpoint_set(condition.original_string(), action.c_str());
|
||||
int const rpnum = cpu->debug()->registerpoint_set(condition.original_string(), action);
|
||||
m_console.printf("Registerpoint %X set\n", rpnum);
|
||||
}
|
||||
|
||||
@ -2201,6 +2213,148 @@ 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 (!validate_cpu_parameter(std::string_view(), cpu))
|
||||
return;
|
||||
|
||||
// param 1 is the exception type
|
||||
u64 type;
|
||||
if (!validate_number_parameter(params[0], type))
|
||||
return;
|
||||
|
||||
// param 2 is the condition
|
||||
parsed_expression condition(cpu->debug()->symtable());
|
||||
if (params.size() > 1 && !debug_command_parameter_expression(params[1], condition))
|
||||
return;
|
||||
|
||||
// param 3 is the action
|
||||
std::string_view action;
|
||||
if (params.size() > 2 && !debug_command_parameter_command(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 (!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
|
||||
@ -2221,7 +2375,7 @@ void debugger_commands::execute_rplist(const std::vector<std::string_view> ¶
|
||||
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++;
|
||||
@ -3129,30 +3283,34 @@ void debugger_commands::execute_cheatnext(bool initial, const std::vector<std::s
|
||||
|
||||
// decode condition
|
||||
u8 condition;
|
||||
if (util::streqlower(params[0], "all"))
|
||||
condition = CHEAT_ALL;
|
||||
else if (util::streqlower(params[0], "equal") || util::streqlower(params[0], "eq"))
|
||||
condition = (params.size() > 1) ? CHEAT_EQUALTO : CHEAT_EQUAL;
|
||||
else if (util::streqlower(params[0], "notequal") || util::streqlower(params[0], "ne"))
|
||||
condition = (params.size() > 1) ? CHEAT_NOTEQUALTO : CHEAT_NOTEQUAL;
|
||||
else if (util::streqlower(params[0], "decrease") || util::streqlower(params[0], "de") || params[0] == "-")
|
||||
condition = (params.size() > 1) ? CHEAT_DECREASEOF : CHEAT_DECREASE;
|
||||
else if (util::streqlower(params[0], "increase") || util::streqlower(params[0], "in") || params[0] == "+")
|
||||
condition = (params.size() > 1) ? CHEAT_INCREASEOF : CHEAT_INCREASE;
|
||||
else if (util::streqlower(params[0], "decreaseorequal") || util::streqlower(params[0], "deeq"))
|
||||
condition = CHEAT_DECREASE_OR_EQUAL;
|
||||
else if (util::streqlower(params[0], "increaseorequal") || util::streqlower(params[0], "ineq"))
|
||||
condition = CHEAT_INCREASE_OR_EQUAL;
|
||||
else if (util::streqlower(params[0], "smallerof") || util::streqlower(params[0], "lt") || params[0] == "<")
|
||||
condition = CHEAT_SMALLEROF;
|
||||
else if (util::streqlower(params[0], "greaterof") || util::streqlower(params[0], "gt") || params[0] == ">")
|
||||
condition = CHEAT_GREATEROF;
|
||||
else if (util::streqlower(params[0], "changedby") || util::streqlower(params[0], "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++;
|
||||
@ -3754,17 +3912,16 @@ void debugger_commands::execute_dasm(const std::vector<std::string_view> ¶ms
|
||||
|
||||
void debugger_commands::execute_trace(const std::vector<std::string_view> ¶ms, bool trace_over)
|
||||
{
|
||||
std::string action;
|
||||
std::string_view action;
|
||||
bool detect_loops = true;
|
||||
bool logerror = false;
|
||||
device_t *cpu;
|
||||
const char *mode;
|
||||
std::string filename(params[0]);
|
||||
|
||||
// replace macros
|
||||
strreplace(filename, "{game}", m_machine.basename());
|
||||
|
||||
// validate parameters
|
||||
device_t *cpu;
|
||||
if (!validate_cpu_parameter(params.size() > 1 ? params[1] : std::string_view(), cpu))
|
||||
return;
|
||||
if (params.size() > 2)
|
||||
@ -3775,9 +3932,10 @@ void debugger_commands::execute_trace(const std::vector<std::string_view> ¶m
|
||||
std::string flag;
|
||||
while (std::getline(stream, flag, '|'))
|
||||
{
|
||||
if (util::streqlower(flag, "noloop"))
|
||||
using namespace std::literals;
|
||||
if (util::streqlower(flag, "noloop"sv))
|
||||
detect_loops = false;
|
||||
else if (util::streqlower(flag, "logerror"))
|
||||
else if (util::streqlower(flag, "logerror"sv))
|
||||
logerror = true;
|
||||
else
|
||||
{
|
||||
@ -3790,19 +3948,22 @@ void debugger_commands::execute_trace(const std::vector<std::string_view> ¶m
|
||||
return;
|
||||
|
||||
// open the file
|
||||
FILE *f = nullptr;
|
||||
if (!util::streqlower(filename, "off"))
|
||||
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);
|
||||
f = std::make_unique<std::ofstream>(filename.c_str(), mode);
|
||||
if (!f)
|
||||
{
|
||||
m_console.printf("Error opening file '%s'\n", params[0]);
|
||||
@ -3811,7 +3972,7 @@ void debugger_commands::execute_trace(const std::vector<std::string_view> ¶m
|
||||
}
|
||||
|
||||
// do it
|
||||
cpu->debug()->trace(f, trace_over, detect_loops, logerror, action.c_str());
|
||||
cpu->debug()->trace(std::move(f), trace_over, detect_loops, logerror, action);
|
||||
if (f)
|
||||
m_console.printf("Tracing CPU '%s' to file %s\n", cpu->tag(), filename);
|
||||
else
|
||||
|
@ -148,6 +148,10 @@ private:
|
||||
void execute_rpclear(const std::vector<std::string_view> ¶ms);
|
||||
void execute_rpdisenable(bool enable, const std::vector<std::string_view> ¶ms);
|
||||
void execute_rplist(const std::vector<std::string_view> ¶ms);
|
||||
void execute_epset(const std::vector<std::string_view> ¶ms);
|
||||
void execute_epclear(const std::vector<std::string_view> ¶ms);
|
||||
void execute_epdisenable(bool enable, const std::vector<std::string_view> ¶ms);
|
||||
void execute_eplist(const std::vector<std::string_view> ¶ms);
|
||||
void execute_statesave(const std::vector<std::string_view> ¶ms);
|
||||
void execute_stateload(const std::vector<std::string_view> ¶ms);
|
||||
void execute_rewind(const std::vector<std::string_view> ¶ms);
|
||||
|
@ -47,6 +47,7 @@ debugger_cpu::debugger_cpu(running_machine &machine)
|
||||
, m_bpindex(1)
|
||||
, m_wpindex(1)
|
||||
, m_rpindex(1)
|
||||
, m_epindex(1)
|
||||
, m_wpdata(0)
|
||||
, m_wpaddr(0)
|
||||
, m_wpsize(0)
|
||||
@ -424,7 +425,6 @@ device_debug::device_debug(device_t &device)
|
||||
, m_disasm(nullptr)
|
||||
, m_flags(0)
|
||||
, m_symtable(std::make_unique<symbol_table>(device.machine(), &device.machine().debugger().cpu().global_symtable(), &device))
|
||||
, m_instrhook(nullptr)
|
||||
, m_stepaddr(0)
|
||||
, m_stepsleft(0)
|
||||
, m_delay_steps(0)
|
||||
@ -438,7 +438,8 @@ device_debug::device_debug(device_t &device)
|
||||
, m_pc_history_index(0)
|
||||
, m_pc_history_valid(0)
|
||||
, m_bplist()
|
||||
, m_rplist(std::make_unique<std::forward_list<debug_registerpoint>>())
|
||||
, m_rplist()
|
||||
, m_eplist()
|
||||
, m_triggered_breakpoint(nullptr)
|
||||
, m_triggered_watchpoint(nullptr)
|
||||
, m_trace(nullptr)
|
||||
@ -549,6 +550,7 @@ device_debug::~device_debug()
|
||||
breakpoint_clear_all();
|
||||
watchpoint_clear_all();
|
||||
registerpoint_clear_all();
|
||||
exceptionpoint_clear_all();
|
||||
}
|
||||
|
||||
void device_debug::write_tracking(address_space &space, offs_t address, u64 data)
|
||||
@ -672,10 +674,39 @@ void device_debug::exception_hook(int exception)
|
||||
if (matched)
|
||||
{
|
||||
m_device.machine().debugger().cpu().set_execution_stopped();
|
||||
m_device.machine().debugger().console().printf("Stopped on exception (CPU '%s', exception %d, PC=%X)\n", m_device.tag(), exception, m_state->pcbase());
|
||||
m_device.machine().debugger().console().printf("Stopped on exception (CPU '%s', exception %X, PC=%X)\n", m_device.tag(), exception, m_state->pcbase());
|
||||
compute_debug_flags();
|
||||
}
|
||||
}
|
||||
|
||||
// see if any exception points match
|
||||
if (!m_eplist.empty())
|
||||
{
|
||||
auto epitp = m_eplist.equal_range(exception);
|
||||
for (auto epit = epitp.first; epit != epitp.second; ++epit)
|
||||
{
|
||||
debug_exceptionpoint &ep = *epit->second;
|
||||
if (ep.hit(exception))
|
||||
{
|
||||
// halt in the debugger by default
|
||||
debugger_cpu &debugcpu = m_device.machine().debugger().cpu();
|
||||
debugcpu.set_execution_stopped();
|
||||
|
||||
// if we hit, evaluate the action
|
||||
if (!ep.m_action.empty())
|
||||
m_device.machine().debugger().console().execute_command(ep.m_action, false);
|
||||
|
||||
// print a notification, unless the action made us go again
|
||||
if (debugcpu.is_stopped())
|
||||
{
|
||||
debugcpu.set_execution_stopped();
|
||||
m_device.machine().debugger().console().printf("Stopped at exception point %X (CPU '%s', PC=%X)\n", ep.m_index, m_device.tag(), exception, m_state->pcbase());
|
||||
compute_debug_flags();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -744,10 +775,6 @@ void device_debug::instruction_hook(offs_t curpc)
|
||||
if (m_trace != nullptr)
|
||||
m_trace->update(curpc);
|
||||
|
||||
// per-instruction hook?
|
||||
if (!debugcpu.is_stopped() && (m_flags & DEBUG_FLAG_HOOKED) != 0 && (*m_instrhook)(m_device, curpc))
|
||||
debugcpu.set_execution_stopped();
|
||||
|
||||
// handle single stepping
|
||||
if (!debugcpu.is_stopped() && (m_flags & DEBUG_FLAG_STEPPING_ANY) != 0)
|
||||
{
|
||||
@ -892,22 +919,6 @@ void device_debug::instruction_hook(offs_t curpc)
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// set_instruction_hook - set a hook to be
|
||||
// called on each instruction for a given device
|
||||
//-------------------------------------------------
|
||||
|
||||
void device_debug::set_instruction_hook(debug_instruction_hook_func hook)
|
||||
{
|
||||
// set the hook and also the CPU's flag for fast knowledge of the hook
|
||||
m_instrhook = hook;
|
||||
if (hook != nullptr)
|
||||
m_flags |= DEBUG_FLAG_HOOKED;
|
||||
else
|
||||
m_flags &= ~DEBUG_FLAG_HOOKED;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// ignore - ignore/observe a given device
|
||||
//-------------------------------------------------
|
||||
@ -1151,7 +1162,7 @@ const debug_breakpoint *device_debug::breakpoint_find(offs_t address) const
|
||||
// returning its index
|
||||
//-------------------------------------------------
|
||||
|
||||
int device_debug::breakpoint_set(offs_t address, const char *condition, const char *action)
|
||||
int device_debug::breakpoint_set(offs_t address, const char *condition, std::string_view action)
|
||||
{
|
||||
// allocate a new one and hook it into our list
|
||||
u32 id = m_device.machine().debugger().cpu().get_breakpoint_index();
|
||||
@ -1238,7 +1249,7 @@ void device_debug::breakpoint_enable_all(bool enable)
|
||||
// returning its index
|
||||
//-------------------------------------------------
|
||||
|
||||
int device_debug::watchpoint_set(address_space &space, read_or_write type, offs_t address, offs_t length, const char *condition, const char *action)
|
||||
int device_debug::watchpoint_set(address_space &space, read_or_write type, offs_t address, offs_t length, const char *condition, std::string_view action)
|
||||
{
|
||||
if (space.spacenum() >= int(m_wplist.size()))
|
||||
m_wplist.resize(space.spacenum()+1);
|
||||
@ -1325,15 +1336,15 @@ void device_debug::watchpoint_enable_all(bool enable)
|
||||
// returning its index
|
||||
//-------------------------------------------------
|
||||
|
||||
int device_debug::registerpoint_set(const char *condition, const char *action)
|
||||
int device_debug::registerpoint_set(const char *condition, std::string_view action)
|
||||
{
|
||||
// allocate a new one
|
||||
u32 id = m_device.machine().debugger().cpu().get_registerpoint_index();
|
||||
m_rplist->emplace_front(*m_symtable, id, condition, action);
|
||||
m_rplist.emplace_front(*m_symtable, id, condition, action);
|
||||
|
||||
// update the flags and return the index
|
||||
breakpoint_update_flags();
|
||||
return m_rplist->front().m_index;
|
||||
return m_rplist.front().m_index;
|
||||
}
|
||||
|
||||
|
||||
@ -1345,10 +1356,10 @@ int device_debug::registerpoint_set(const char *condition, const char *action)
|
||||
bool device_debug::registerpoint_clear(int index)
|
||||
{
|
||||
// scan the list to see if we own this registerpoint
|
||||
for (auto brp = m_rplist->before_begin(); std::next(brp) != m_rplist->end(); ++brp)
|
||||
for (auto brp = m_rplist.before_begin(); std::next(brp) != m_rplist.end(); ++brp)
|
||||
if (std::next(brp)->m_index == index)
|
||||
{
|
||||
m_rplist->erase_after(brp);
|
||||
m_rplist.erase_after(brp);
|
||||
breakpoint_update_flags();
|
||||
return true;
|
||||
}
|
||||
@ -1365,7 +1376,7 @@ bool device_debug::registerpoint_clear(int index)
|
||||
void device_debug::registerpoint_clear_all()
|
||||
{
|
||||
// clear the list
|
||||
m_rplist->clear();
|
||||
m_rplist.clear();
|
||||
breakpoint_update_flags();
|
||||
}
|
||||
|
||||
@ -1378,7 +1389,7 @@ void device_debug::registerpoint_clear_all()
|
||||
bool device_debug::registerpoint_enable(int index, bool enable)
|
||||
{
|
||||
// scan the list to see if we own this conditionpoint
|
||||
for (debug_registerpoint &rp : *m_rplist)
|
||||
for (debug_registerpoint &rp : m_rplist)
|
||||
if (rp.m_index == index)
|
||||
{
|
||||
rp.m_enabled = enable;
|
||||
@ -1399,11 +1410,96 @@ bool device_debug::registerpoint_enable(int index, bool enable)
|
||||
void device_debug::registerpoint_enable_all(bool enable)
|
||||
{
|
||||
// apply the enable to all registerpoints we own
|
||||
for (debug_registerpoint &rp : *m_rplist)
|
||||
for (debug_registerpoint &rp : m_rplist)
|
||||
registerpoint_enable(rp.index(), enable);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// exceptionpoint_set - set a new exception
|
||||
// point, returning its index
|
||||
//-------------------------------------------------
|
||||
|
||||
int device_debug::exceptionpoint_set(int exception, const char *condition, std::string_view action)
|
||||
{
|
||||
// allocate a new one and hook it into our list
|
||||
u32 id = m_device.machine().debugger().cpu().get_exceptionpoint_index();
|
||||
m_eplist.emplace(exception, std::make_unique<debug_exceptionpoint>(this, *m_symtable, id, exception, condition, action));
|
||||
|
||||
// return the index
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// exceptionpoint_clear - clear an exception
|
||||
// point by index, returning true if we found it
|
||||
//-------------------------------------------------
|
||||
|
||||
bool device_debug::exceptionpoint_clear(int index)
|
||||
{
|
||||
// scan the list to see if we own this breakpoint
|
||||
for (auto epit = m_eplist.begin(); epit != m_eplist.end(); ++epit)
|
||||
if (epit->second->m_index == index)
|
||||
{
|
||||
m_eplist.erase(epit);
|
||||
return true;
|
||||
}
|
||||
|
||||
// we don't own it, return false
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// exceptionpoint_clear_all - clear all exception
|
||||
// points
|
||||
//-------------------------------------------------
|
||||
|
||||
void device_debug::exceptionpoint_clear_all()
|
||||
{
|
||||
// clear the list
|
||||
m_eplist.clear();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// exceptionpoint_enable - enable/disable an
|
||||
// exception point by index, returning true if we
|
||||
// found it
|
||||
//-------------------------------------------------
|
||||
|
||||
bool device_debug::exceptionpoint_enable(int index, bool enable)
|
||||
{
|
||||
// scan the list to see if we own this exception point
|
||||
for (auto &epp : m_eplist)
|
||||
{
|
||||
debug_exceptionpoint &ep = *epp.second;
|
||||
if (ep.m_index == index)
|
||||
{
|
||||
ep.m_enabled = enable;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// we don't own it, return false
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// exceptionpoint_enable_all - enable/disable all
|
||||
// exception points
|
||||
//-------------------------------------------------
|
||||
|
||||
void device_debug::exceptionpoint_enable_all(bool enable)
|
||||
{
|
||||
// apply the enable to all exception points we own
|
||||
for (auto &epp : m_eplist)
|
||||
exceptionpoint_enable(epp.second->index(), enable);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// history_pc - return an entry from the PC
|
||||
// history
|
||||
@ -1600,31 +1696,14 @@ u32 device_debug::compute_opcode_crc32(offs_t pc) const
|
||||
// trace - trace execution of a given device
|
||||
//-------------------------------------------------
|
||||
|
||||
void device_debug::trace(FILE *file, bool trace_over, bool detect_loops, bool logerror, const char *action)
|
||||
void device_debug::trace(std::unique_ptr<std::ostream> &&file, bool trace_over, bool detect_loops, bool logerror, std::string_view action)
|
||||
{
|
||||
// delete any existing tracers
|
||||
m_trace = nullptr;
|
||||
|
||||
// if we have a new file, make a new tracer
|
||||
if (file != nullptr)
|
||||
m_trace = std::make_unique<tracer>(*this, *file, trace_over, detect_loops, logerror, action);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// trace_printf - output data into the given
|
||||
// device's tracefile, if tracing
|
||||
//-------------------------------------------------
|
||||
|
||||
void device_debug::trace_printf(const char *fmt, ...)
|
||||
{
|
||||
if (m_trace != nullptr)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
m_trace->vprintf(fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
m_trace = std::make_unique<tracer>(*this, std::move(file), trace_over, detect_loops, logerror, action);
|
||||
}
|
||||
|
||||
|
||||
@ -1652,7 +1731,7 @@ void device_debug::compute_debug_flags()
|
||||
|
||||
// if we're tracking history, or we're hooked, or stepping, or stopping at a breakpoint
|
||||
// make sure we call the hook
|
||||
if ((m_flags & (DEBUG_FLAG_HISTORY | DEBUG_FLAG_HOOKED | DEBUG_FLAG_STEPPING_ANY | DEBUG_FLAG_STOP_PC | DEBUG_FLAG_LIVE_BP)) != 0)
|
||||
if ((m_flags & (DEBUG_FLAG_HISTORY | DEBUG_FLAG_STEPPING_ANY | DEBUG_FLAG_STOP_PC | DEBUG_FLAG_LIVE_BP)) != 0)
|
||||
machine.debug_flags |= DEBUG_FLAG_CALL_HOOK;
|
||||
|
||||
// also call if we are tracing
|
||||
@ -1753,7 +1832,7 @@ void device_debug::breakpoint_update_flags()
|
||||
if (!(m_flags & DEBUG_FLAG_LIVE_BP))
|
||||
{
|
||||
// see if there are any enabled registerpoints
|
||||
for (debug_registerpoint &rp : *m_rplist)
|
||||
for (debug_registerpoint &rp : m_rplist)
|
||||
{
|
||||
if (rp.m_enabled)
|
||||
{
|
||||
@ -1803,7 +1882,7 @@ void device_debug::breakpoint_check(offs_t pc)
|
||||
}
|
||||
|
||||
// see if we have any matching registerpoints
|
||||
for (debug_registerpoint &rp : *m_rplist)
|
||||
for (debug_registerpoint &rp : m_rplist)
|
||||
{
|
||||
if (rp.hit())
|
||||
{
|
||||
@ -1836,10 +1915,10 @@ void device_debug::breakpoint_check(offs_t pc)
|
||||
// tracer - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
device_debug::tracer::tracer(device_debug &debug, FILE &file, bool trace_over, bool detect_loops, bool logerror, const char *action)
|
||||
device_debug::tracer::tracer(device_debug &debug, std::unique_ptr<std::ostream> &&file, bool trace_over, bool detect_loops, bool logerror, std::string_view action)
|
||||
: m_debug(debug)
|
||||
, m_file(file)
|
||||
, m_action((action != nullptr) ? action : "")
|
||||
, m_file(std::move(file))
|
||||
, m_action(action)
|
||||
, m_detect_loops(detect_loops)
|
||||
, m_logerror(logerror)
|
||||
, m_loops(0)
|
||||
@ -1858,7 +1937,7 @@ device_debug::tracer::tracer(device_debug &debug, FILE &file, bool trace_over, b
|
||||
device_debug::tracer::~tracer()
|
||||
{
|
||||
// make sure we close the file if we can
|
||||
fclose(&m_file);
|
||||
m_file.reset();
|
||||
}
|
||||
|
||||
|
||||
@ -1894,7 +1973,7 @@ void device_debug::tracer::update(offs_t pc)
|
||||
|
||||
// if we just finished looping, indicate as much
|
||||
if (m_loops != 0)
|
||||
fprintf(&m_file, "\n (loops for %d instructions)\n\n", m_loops);
|
||||
util::stream_format(*m_file, "\n (loops for %d instructions)\n\n", m_loops);
|
||||
m_loops = 0;
|
||||
}
|
||||
|
||||
@ -1909,7 +1988,7 @@ void device_debug::tracer::update(offs_t pc)
|
||||
buffer.disassemble(pc, instruction, next_pc, size, dasmresult);
|
||||
|
||||
// output the result
|
||||
fprintf(&m_file, "%s: %s\n", buffer.pc_to_string(pc).c_str(), instruction.c_str());
|
||||
util::stream_format(*m_file, "%s: %s\n", buffer.pc_to_string(pc), instruction);
|
||||
|
||||
// do we need to step the trace over this instruction?
|
||||
if (m_trace_over && (dasmresult & util::disasm_interface::SUPPORTED) != 0 && (dasmresult & util::disasm_interface::STEP_OVER) != 0)
|
||||
@ -1927,7 +2006,7 @@ void device_debug::tracer::update(offs_t pc)
|
||||
// log this PC
|
||||
m_nextdex = (m_nextdex + 1) % TRACE_LOOPS;
|
||||
m_history[m_nextdex] = pc;
|
||||
fflush(&m_file);
|
||||
m_file->flush();
|
||||
}
|
||||
|
||||
|
||||
@ -1935,11 +2014,11 @@ void device_debug::tracer::update(offs_t pc)
|
||||
// vprintf - generic print to the trace file
|
||||
//-------------------------------------------------
|
||||
|
||||
void device_debug::tracer::vprintf(const char *format, va_list va)
|
||||
void device_debug::tracer::vprintf(util::format_argument_pack<std::ostream> const &args)
|
||||
{
|
||||
// pass through to the file
|
||||
vfprintf(&m_file, format, va);
|
||||
fflush(&m_file);
|
||||
util::stream_format(*m_file, args);
|
||||
m_file->flush();
|
||||
}
|
||||
|
||||
|
||||
@ -1950,7 +2029,7 @@ void device_debug::tracer::vprintf(const char *format, va_list va)
|
||||
|
||||
void device_debug::tracer::flush()
|
||||
{
|
||||
fflush(&m_file);
|
||||
m_file->flush();
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,9 +29,6 @@ constexpr int COMMENT_VERSION = 1;
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
typedef int (*debug_instruction_hook_func)(device_t &device, offs_t curpc);
|
||||
|
||||
|
||||
// ======================> device_debug
|
||||
|
||||
// [TODO] This whole thing is terrible.
|
||||
@ -59,9 +56,6 @@ public:
|
||||
void privilege_hook();
|
||||
void instruction_hook(offs_t curpc);
|
||||
|
||||
// hooks into our operations
|
||||
void set_instruction_hook(debug_instruction_hook_func hook);
|
||||
|
||||
// debugger focus
|
||||
void ignore(bool ignore = true);
|
||||
bool observing() const { return ((m_flags & DEBUG_FLAG_OBSERVING) != 0); }
|
||||
@ -94,7 +88,7 @@ public:
|
||||
// breakpoints
|
||||
const auto &breakpoint_list() const { return m_bplist; }
|
||||
const debug_breakpoint *breakpoint_find(offs_t address) const;
|
||||
int breakpoint_set(offs_t address, const char *condition = nullptr, const char *action = nullptr);
|
||||
int breakpoint_set(offs_t address, const char *condition = nullptr, std::string_view action = {});
|
||||
bool breakpoint_clear(int index);
|
||||
void breakpoint_clear_all();
|
||||
bool breakpoint_enable(int index, bool enable = true);
|
||||
@ -104,7 +98,7 @@ public:
|
||||
// watchpoints
|
||||
int watchpoint_space_count() const { return m_wplist.size(); }
|
||||
const std::vector<std::unique_ptr<debug_watchpoint>> &watchpoint_vector(int spacenum) const { return m_wplist[spacenum]; }
|
||||
int watchpoint_set(address_space &space, read_or_write type, offs_t address, offs_t length, const char *condition, const char *action);
|
||||
int watchpoint_set(address_space &space, read_or_write type, offs_t address, offs_t length, const char *condition = nullptr, std::string_view action = {});
|
||||
bool watchpoint_clear(int wpnum);
|
||||
void watchpoint_clear_all();
|
||||
bool watchpoint_enable(int index, bool enable = true);
|
||||
@ -113,12 +107,20 @@ public:
|
||||
debug_watchpoint *triggered_watchpoint() { debug_watchpoint *ret = m_triggered_watchpoint; m_triggered_watchpoint = nullptr; return ret; }
|
||||
|
||||
// registerpoints
|
||||
const std::forward_list<debug_registerpoint> ®isterpoint_list() const { return *m_rplist; }
|
||||
int registerpoint_set(const char *condition, const char *action = nullptr);
|
||||
const std::forward_list<debug_registerpoint> ®isterpoint_list() const { return m_rplist; }
|
||||
int registerpoint_set(const char *condition, std::string_view action = {});
|
||||
bool registerpoint_clear(int index);
|
||||
void registerpoint_clear_all();
|
||||
bool registerpoint_enable(int index, bool enable = true);
|
||||
void registerpoint_enable_all(bool enable = true );
|
||||
void registerpoint_enable_all(bool enable = true);
|
||||
|
||||
// exception points
|
||||
const auto &exceptionpoint_list() const { return m_eplist; }
|
||||
int exceptionpoint_set(int exception, const char *condition = nullptr, std::string_view action = {});
|
||||
bool exceptionpoint_clear(int index);
|
||||
void exceptionpoint_clear_all();
|
||||
bool exceptionpoint_enable(int index, bool enable = true);
|
||||
void exceptionpoint_enable_all(bool enable = true);
|
||||
|
||||
// comments
|
||||
void comment_add(offs_t address, const char *comment, rgb_t color);
|
||||
@ -147,8 +149,12 @@ public:
|
||||
void track_mem_data_clear() { m_track_mem_set.clear(); }
|
||||
|
||||
// tracing
|
||||
void trace(FILE *file, bool trace_over, bool detect_loops, bool logerror, const char *action);
|
||||
void trace_printf(const char *fmt, ...) ATTR_PRINTF(2,3);
|
||||
void trace(std::unique_ptr<std::ostream> &&file, bool trace_over, bool detect_loops, bool logerror, std::string_view action);
|
||||
template <typename Format, typename... Params> void trace_printf(Format &&fmt, Params &&...args)
|
||||
{
|
||||
if (m_trace != nullptr)
|
||||
m_trace->vprintf(util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...));
|
||||
}
|
||||
void trace_flush() { if (m_trace != nullptr) m_trace->flush(); }
|
||||
|
||||
void reset_transient_flag() { m_flags &= ~DEBUG_FLAG_TRANSIENT; }
|
||||
@ -182,7 +188,6 @@ private:
|
||||
// global state
|
||||
u32 m_flags; // debugging flags for this CPU
|
||||
std::unique_ptr<symbol_table> m_symtable; // symbol table for expression evaluation
|
||||
debug_instruction_hook_func m_instrhook; // per-instruction callback hook
|
||||
|
||||
// stepping information
|
||||
offs_t m_stepaddr; // step target address for DEBUG_FLAG_STEPPING_OVER or DEBUG_FLAG_STEPPING_BRANCH
|
||||
@ -208,7 +213,8 @@ private:
|
||||
// breakpoints and watchpoints
|
||||
std::multimap<offs_t, std::unique_ptr<debug_breakpoint>> m_bplist; // list of breakpoints
|
||||
std::vector<std::vector<std::unique_ptr<debug_watchpoint>>> m_wplist; // watchpoint lists for each address space
|
||||
std::unique_ptr<std::forward_list<debug_registerpoint>> m_rplist; // list of registerpoints
|
||||
std::forward_list<debug_registerpoint> m_rplist; // list of registerpoints
|
||||
std::multimap<offs_t, std::unique_ptr<debug_exceptionpoint>> m_eplist; // list of exception points
|
||||
|
||||
debug_breakpoint * m_triggered_breakpoint; // latest breakpoint that was triggered
|
||||
debug_watchpoint * m_triggered_watchpoint; // latest watchpoint that was triggered
|
||||
@ -217,11 +223,11 @@ private:
|
||||
class tracer
|
||||
{
|
||||
public:
|
||||
tracer(device_debug &debug, FILE &file, bool trace_over, bool detect_loops, bool logerror, const char *action);
|
||||
tracer(device_debug &debug, std::unique_ptr<std::ostream> &&file, bool trace_over, bool detect_loops, bool logerror, std::string_view action);
|
||||
~tracer();
|
||||
|
||||
void update(offs_t pc);
|
||||
void vprintf(const char *format, va_list va);
|
||||
void vprintf(util::format_argument_pack<std::ostream> const &args);
|
||||
void flush();
|
||||
bool logerror() const { return m_logerror; }
|
||||
|
||||
@ -229,7 +235,7 @@ private:
|
||||
static const int TRACE_LOOPS = 64;
|
||||
|
||||
device_debug & m_debug; // reference to our owner
|
||||
FILE & m_file; // tracing file for this CPU
|
||||
std::unique_ptr<std::ostream> m_file; // tracing file for this CPU
|
||||
std::string m_action; // action to perform during a trace
|
||||
offs_t m_history[TRACE_LOOPS]; // history of recent PCs
|
||||
bool m_detect_loops; // whether or not we should detect loops
|
||||
@ -312,7 +318,6 @@ private:
|
||||
static constexpr u32 DEBUG_FLAG_HISTORY = 0x00000002; // tracking this CPU's history
|
||||
static constexpr u32 DEBUG_FLAG_TRACING = 0x00000004; // tracing this CPU
|
||||
static constexpr u32 DEBUG_FLAG_TRACING_OVER = 0x00000008; // tracing this CPU with step over behavior
|
||||
static constexpr u32 DEBUG_FLAG_HOOKED = 0x00000010; // per-instruction callback hook
|
||||
static constexpr u32 DEBUG_FLAG_STEPPING = 0x00000020; // CPU is single stepping
|
||||
static constexpr u32 DEBUG_FLAG_STEPPING_OVER = 0x00000040; // CPU is stepping over a function
|
||||
static constexpr u32 DEBUG_FLAG_STEPPING_OUT = 0x00000080; // CPU is stepping out of a function
|
||||
@ -384,6 +389,7 @@ public:
|
||||
u32 get_breakpoint_index() { return m_bpindex++; }
|
||||
u32 get_watchpoint_index() { return m_wpindex++; }
|
||||
u32 get_registerpoint_index() { return m_rpindex++; }
|
||||
u32 get_exceptionpoint_index() { return m_epindex++; }
|
||||
|
||||
// setters
|
||||
void set_break_cpu(device_t * breakcpu) { m_breakcpu = breakcpu; }
|
||||
@ -426,6 +432,7 @@ private:
|
||||
u32 m_bpindex;
|
||||
u32 m_wpindex;
|
||||
u32 m_rpindex;
|
||||
u32 m_epindex;
|
||||
|
||||
u64 m_wpdata;
|
||||
u64 m_wpaddr;
|
||||
|
@ -46,6 +46,7 @@ const help_item f_static_help_list[] =
|
||||
" Breakpoints\n"
|
||||
" Watchpoints\n"
|
||||
" Registerpoints\n"
|
||||
" Exception Points\n"
|
||||
" Expressions\n"
|
||||
" Comments\n"
|
||||
" Cheats\n"
|
||||
@ -190,6 +191,18 @@ const help_item f_static_help_list[] =
|
||||
" rpenable [<rpnum>[,...]] -- enables given registerpoints or all if no <rpnum> specified\n"
|
||||
" rplist [<CPU>] -- lists all the registerpoints\n"
|
||||
},
|
||||
{
|
||||
"exceptionpoints",
|
||||
"\n"
|
||||
"Exception Point Commands\n"
|
||||
"Type help <command> for further details on each command\n"
|
||||
"\n"
|
||||
" ep[set] <type>[,<condition>[,<action>]] -- sets exception point on <type>\n"
|
||||
" epclear [<epnum>] -- clears a given exception point or all if no <epnum> specified\n"
|
||||
" epdisable [<epnum>] -- disabled a given exception point or all if no <epnum> specified\n"
|
||||
" epenable [<epnum>] -- enables a given exception point or all if no <epnum> specified\n"
|
||||
" eplist -- lists all the registerpoints\n"
|
||||
},
|
||||
{
|
||||
"expressions",
|
||||
"\n"
|
||||
@ -1554,6 +1567,92 @@ const help_item f_static_help_list[] =
|
||||
"The rplist command lists all the current registerpoints, along with their index and any "
|
||||
"actions attached to them.\n"
|
||||
},
|
||||
{
|
||||
"epset",
|
||||
"\n"
|
||||
" ep[set] <type>[,<condition>[,<action>]]\n"
|
||||
"\n"
|
||||
"Sets a new exception point for exceptions of type <type> on the currently visible CPU. "
|
||||
"The optional <condition> parameter lets you specify an expression that will be evaluated "
|
||||
"each time the exception point is hit. If the result of the expression is true (non-zero), "
|
||||
"the exception point will actually halt execution at the start of the exception handler; "
|
||||
"otherwise, execution will continue with no notification. The optional <action> parameter "
|
||||
"provides a command that is executed whenever the exception point is hit and the "
|
||||
"<condition> is true. Note that you may need to embed the action within braces { } in order "
|
||||
"to prevent commas and semicolons from being interpreted as applying to the epset command "
|
||||
"itself.\n"
|
||||
"\n"
|
||||
"The numbering of exceptions depends upon the CPU type. Causes of exceptions may include "
|
||||
"internally or externally vectored interrupts, errors occurring within instructions and "
|
||||
"system calls.\n"
|
||||
"\n"
|
||||
"Each exception point that is set is assigned an index which can be used in other "
|
||||
"exception point commands to reference this exception point.\n"
|
||||
"\n"
|
||||
"Examples:\n"
|
||||
"\n"
|
||||
"ep 2\n"
|
||||
" Set an exception that will halt execution whenever the visible CPU raises exception "
|
||||
"number 2.\n"
|
||||
},
|
||||
{
|
||||
"epclear",
|
||||
"\n"
|
||||
" epclear [<epnum>[,...]]\n"
|
||||
"\n"
|
||||
"The epclear command clears exception points. If <epnum> is specified, only the requested "
|
||||
"exception points are cleared, otherwise all exception points are cleared.\n"
|
||||
"\n"
|
||||
"Examples:\n"
|
||||
"\n"
|
||||
"epclear 3\n"
|
||||
" Clear exception point index 3.\n"
|
||||
"\n"
|
||||
"epclear\n"
|
||||
" Clear all exception points.\n"
|
||||
},
|
||||
{
|
||||
"epdisable",
|
||||
"\n"
|
||||
" epdisable [<epnum>[,...]]\n"
|
||||
"\n"
|
||||
"The epdisable command disables exception points. If <epnum> is specified, only the requested "
|
||||
"exception points are disabled, otherwise all exception points are disabled. Note that "
|
||||
"disabling an exception point does not delete it, it just temporarily marks the exception "
|
||||
"point as inactive.\n"
|
||||
"\n"
|
||||
"Examples:\n"
|
||||
"\n"
|
||||
"epdisable 3\n"
|
||||
" Disable exception point index 3.\n"
|
||||
"\n"
|
||||
"epdisable\n"
|
||||
" Disable all exception points.\n"
|
||||
},
|
||||
{
|
||||
"epenable",
|
||||
"\n"
|
||||
" epenable [<epnum>[,...]]\n"
|
||||
"\n"
|
||||
"The epenable command enables exception points. If <epnum> is specified, only the "
|
||||
"requested exception points are enabled, otherwise all exception points are enabled.\n"
|
||||
"\n"
|
||||
"Examples:\n"
|
||||
"\n"
|
||||
"epenable 3\n"
|
||||
" Enable exception point index 3.\n"
|
||||
"\n"
|
||||
"epenable\n"
|
||||
" Enable all exception points.\n"
|
||||
},
|
||||
{
|
||||
"eplist",
|
||||
"\n"
|
||||
" eplist\n"
|
||||
"\n"
|
||||
"The eplist command lists all the current exception points, along with their index and "
|
||||
"any conditions or actions attached to them.\n"
|
||||
},
|
||||
{
|
||||
"map",
|
||||
"\n"
|
||||
|
@ -71,7 +71,7 @@ static bool cConditionDescending(const debug_breakpoint *a, const debug_breakpoi
|
||||
|
||||
static bool cActionAscending(const debug_breakpoint *a, const debug_breakpoint *b)
|
||||
{
|
||||
return strcmp(a->action(), b->action()) < 0;
|
||||
return a->action() < b->action();
|
||||
}
|
||||
|
||||
static bool cActionDescending(const debug_breakpoint *a, const debug_breakpoint *b)
|
||||
|
@ -62,7 +62,7 @@ bool cConditionDescending(std::pair<device_t *, debug_registerpoint const *> con
|
||||
|
||||
bool cActionAscending(std::pair<device_t *, debug_registerpoint const *> const &a, std::pair<device_t *, debug_registerpoint const *> const &b)
|
||||
{
|
||||
return strcmp(a.second->action(), b.second->action()) < 0;
|
||||
return a.second->action() < b.second->action();
|
||||
}
|
||||
|
||||
bool cActionDescending(std::pair<device_t *, debug_registerpoint const *> const &a, std::pair<device_t *, debug_registerpoint const *> const &b)
|
||||
|
@ -28,13 +28,13 @@ debug_breakpoint::debug_breakpoint(
|
||||
int index,
|
||||
offs_t address,
|
||||
const char *condition,
|
||||
const char *action) :
|
||||
std::string_view action) :
|
||||
m_debugInterface(debugInterface),
|
||||
m_index(index),
|
||||
m_enabled(true),
|
||||
m_address(address),
|
||||
m_condition(symbols, condition ? condition : "1"),
|
||||
m_action(action ? action : "")
|
||||
m_action(action)
|
||||
{
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ debug_watchpoint::debug_watchpoint(
|
||||
offs_t address,
|
||||
offs_t length,
|
||||
const char *condition,
|
||||
const char *action) :
|
||||
std::string_view action) :
|
||||
m_debugInterface(debugInterface),
|
||||
m_phr(nullptr),
|
||||
m_phw(nullptr),
|
||||
@ -99,7 +99,7 @@ debug_watchpoint::debug_watchpoint(
|
||||
m_address(address & space.addrmask()),
|
||||
m_length(length),
|
||||
m_condition(symbols, condition ? condition : "1"),
|
||||
m_action(action ? action : ""),
|
||||
m_action(action),
|
||||
m_installing(false)
|
||||
{
|
||||
std::fill(std::begin(m_start_address), std::end(m_start_address), 0);
|
||||
@ -431,11 +431,11 @@ void debug_watchpoint::triggered(read_or_write type, offs_t address, u64 data, u
|
||||
// debug_registerpoint - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
debug_registerpoint::debug_registerpoint(symbol_table &symbols, int index, const char *condition, const char *action)
|
||||
debug_registerpoint::debug_registerpoint(symbol_table &symbols, int index, const char *condition, std::string_view action)
|
||||
: m_index(index),
|
||||
m_enabled(true),
|
||||
m_condition(symbols, (condition != nullptr) ? condition : "1"),
|
||||
m_action((action != nullptr) ? action : "")
|
||||
m_action(action)
|
||||
{
|
||||
}
|
||||
|
||||
@ -465,3 +465,59 @@ bool debug_registerpoint::hit()
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DEBUG EXCEPTION POINT
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// debug_exceptionpoint - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
debug_exceptionpoint::debug_exceptionpoint(
|
||||
device_debug *debugInterface,
|
||||
symbol_table &symbols,
|
||||
int index,
|
||||
int type,
|
||||
const char *condition,
|
||||
std::string_view action)
|
||||
: m_debugInterface(debugInterface),
|
||||
m_index(index),
|
||||
m_enabled(true),
|
||||
m_type(type),
|
||||
m_condition(symbols, (condition != nullptr) ? condition : "1"),
|
||||
m_action(action)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// hit - detect a hit
|
||||
//-------------------------------------------------
|
||||
|
||||
bool debug_exceptionpoint::hit(int exception)
|
||||
{
|
||||
// don't hit if disabled
|
||||
if (!m_enabled)
|
||||
return false;
|
||||
|
||||
// must match our type
|
||||
if (m_type != exception)
|
||||
return false;
|
||||
|
||||
// must satisfy the condition
|
||||
if (!m_condition.is_empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
return (m_condition.execute() != 0);
|
||||
}
|
||||
catch (expression_error &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public:
|
||||
int index,
|
||||
offs_t address,
|
||||
const char *condition = nullptr,
|
||||
const char *action = nullptr);
|
||||
std::string_view action = {});
|
||||
|
||||
// getters
|
||||
const device_debug *debugInterface() const { return m_debugInterface; }
|
||||
@ -44,7 +44,7 @@ public:
|
||||
bool enabled() const { return m_enabled; }
|
||||
offs_t address() const { return m_address; }
|
||||
const char *condition() const { return m_condition.original_string(); }
|
||||
const char *action() const { return m_action.c_str(); }
|
||||
const std::string &action() const { return m_action; }
|
||||
|
||||
// setters
|
||||
void setEnabled(bool value) { m_enabled = value; } // FIXME: need to update breakpoint flags but it's a private method
|
||||
@ -77,7 +77,7 @@ public:
|
||||
offs_t address,
|
||||
offs_t length,
|
||||
const char *condition = nullptr,
|
||||
const char *action = nullptr);
|
||||
std::string_view action = {});
|
||||
~debug_watchpoint();
|
||||
|
||||
// getters
|
||||
@ -128,13 +128,13 @@ class debug_registerpoint
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
debug_registerpoint(symbol_table &symbols, int index, const char *condition, const char *action = nullptr);
|
||||
debug_registerpoint(symbol_table &symbols, int index, const char *condition, std::string_view action = {});
|
||||
|
||||
// getters
|
||||
int index() const { return m_index; }
|
||||
bool enabled() const { return m_enabled; }
|
||||
const char *condition() const { return m_condition.original_string(); }
|
||||
const char *action() const { return m_action.c_str(); }
|
||||
const std::string &action() const { return m_action; }
|
||||
|
||||
private:
|
||||
// internals
|
||||
@ -146,4 +146,42 @@ private:
|
||||
std::string m_action; // action
|
||||
};
|
||||
|
||||
// ======================> debug_exceptionpoint
|
||||
|
||||
class debug_exceptionpoint
|
||||
{
|
||||
friend class device_debug;
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
debug_exceptionpoint(
|
||||
device_debug* debugInterface,
|
||||
symbol_table &symbols,
|
||||
int index,
|
||||
int type,
|
||||
const char *condition = nullptr,
|
||||
std::string_view action = {});
|
||||
|
||||
// getters
|
||||
const device_debug *debugInterface() const { return m_debugInterface; }
|
||||
int index() const { return m_index; }
|
||||
bool enabled() const { return m_enabled; }
|
||||
int type() const { return m_type; }
|
||||
const char *condition() const { return m_condition.original_string(); }
|
||||
const std::string &action() const { return m_action; }
|
||||
|
||||
// setters
|
||||
void setEnabled(bool value) { m_enabled = value; }
|
||||
|
||||
private:
|
||||
// internals
|
||||
bool hit(int exception);
|
||||
const device_debug * m_debugInterface; // the interface we were created from
|
||||
int m_index; // user reported index
|
||||
bool m_enabled; // enabled?
|
||||
int m_type; // exception type
|
||||
parsed_expression m_condition; // condition
|
||||
std::string m_action; // action
|
||||
};
|
||||
|
||||
#endif // MAME_EMU_DEBUG_POINTS_H
|
||||
|
@ -99,6 +99,7 @@ class symbol_table;
|
||||
class debug_breakpoint;
|
||||
class debug_watchpoint;
|
||||
class debug_registerpoint;
|
||||
class debug_exceptionpoint;
|
||||
|
||||
// declared in debugger.h
|
||||
class debugger_manager;
|
||||
|
@ -87,13 +87,6 @@ public:
|
||||
|
||||
void nimbus(machine_config &config);
|
||||
|
||||
uint32_t m_debug_machine = 0;
|
||||
uint32_t m_debug_trap = 0;
|
||||
|
||||
void decode_subbios(device_t *device, offs_t pc);
|
||||
void decode_subbios_return(device_t *device, offs_t pc);
|
||||
void decode_dos21(device_t *device, offs_t pc);
|
||||
|
||||
private:
|
||||
required_device<i80186_cpu_device> m_maincpu;
|
||||
required_device<i8031_device> m_iocpu;
|
||||
|
@ -63,10 +63,6 @@ chdman createhd -o ST125N.chd -chs 41921,1,1 -ss 512
|
||||
#include <functional>
|
||||
|
||||
#include "rmnimbus.h"
|
||||
#include "debugger.h"
|
||||
#include "debug/debugcmd.h"
|
||||
#include "debug/debugcon.h"
|
||||
#include "debug/debugcpu.h"
|
||||
#include "imagedev/floppy.h"
|
||||
|
||||
|
||||
@ -136,52 +132,6 @@ chdman createhd -o ST125N.chd -chs 41921,1,1 -ss 512
|
||||
#define LOG_IOU 0
|
||||
#define LOG_RAM 0
|
||||
|
||||
/* Debugging */
|
||||
|
||||
#define DEBUG_SET(flags) ((m_debug_machine & (flags))==(flags))
|
||||
#define DEBUG_SET_STATE(flags) ((state->m_debug_machine & (flags))==(flags))
|
||||
|
||||
#define DEBUG_NONE 0x0000000
|
||||
#define DECODE_BIOS 0x0000002
|
||||
#define DECODE_BIOS_RAW 0x0000004
|
||||
#define DECODE_DOS21 0x0000008
|
||||
|
||||
/* Nimbus sub-bios structures for debugging */
|
||||
|
||||
struct t_area_params
|
||||
{
|
||||
uint16_t ofs_brush;
|
||||
uint16_t seg_brush;
|
||||
uint16_t ofs_data;
|
||||
uint16_t seg_data;
|
||||
uint16_t count;
|
||||
};
|
||||
|
||||
struct t_plot_string_params
|
||||
{
|
||||
uint16_t ofs_font;
|
||||
uint16_t seg_font;
|
||||
uint16_t ofs_data;
|
||||
uint16_t seg_data;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint16_t length;
|
||||
};
|
||||
|
||||
struct t_nimbus_brush
|
||||
{
|
||||
uint16_t style;
|
||||
uint16_t style_index;
|
||||
uint16_t colour1;
|
||||
uint16_t colour2;
|
||||
uint16_t transparency;
|
||||
uint16_t boundary_spec;
|
||||
uint16_t boundary_colour;
|
||||
uint16_t save_colour;
|
||||
};
|
||||
|
||||
|
||||
static int instruction_hook(device_t &device, offs_t curpc);
|
||||
|
||||
void rmnimbus_state::external_int(uint8_t vector, bool state)
|
||||
{
|
||||
@ -218,648 +168,11 @@ void rmnimbus_state::machine_start()
|
||||
{
|
||||
m_nimbus_mouse.m_mouse_timer = timer_alloc(FUNC(rmnimbus_state::do_mouse), this);
|
||||
|
||||
/* setup debug commands */
|
||||
if (machine().debug_flags & DEBUG_FLAG_ENABLED)
|
||||
{
|
||||
using namespace std::placeholders;
|
||||
machine().debugger().console().register_command("nimbus_debug", CMDFLAG_NONE, 0, 1, std::bind(&rmnimbus_state::debug_command, this, _1));
|
||||
|
||||
/* set up the instruction hook */
|
||||
m_maincpu->debug()->set_instruction_hook(instruction_hook);
|
||||
}
|
||||
|
||||
m_debug_machine=DEBUG_NONE;
|
||||
m_debug_trap=0;
|
||||
m_voice_enabled=false;
|
||||
m_fdc->dden_w(0);
|
||||
//m_fdc->overide_delays(64,m_fdc->get_cmd_delay());
|
||||
}
|
||||
|
||||
void rmnimbus_state::debug_command(const std::vector<std::string_view> ¶ms)
|
||||
{
|
||||
if (params.size() > 0)
|
||||
{
|
||||
uint64_t temp;
|
||||
if (!machine().debugger().commands().validate_number_parameter(params[0], temp))
|
||||
return;
|
||||
m_debug_machine = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
machine().debugger().console().printf("Error usage : nimbus_debug <debuglevel>\n");
|
||||
machine().debugger().console().printf("Current debuglevel=%02X\n", m_debug_machine);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------
|
||||
instruction_hook - per-instruction hook
|
||||
-----------------------------------------------*/
|
||||
|
||||
static int instruction_hook(device_t &device, offs_t curpc)
|
||||
{
|
||||
rmnimbus_state *state = device.machine().driver_data<rmnimbus_state>();
|
||||
address_space &space = device.memory().space(AS_PROGRAM);
|
||||
uint8_t *addr_ptr;
|
||||
uint8_t first;
|
||||
|
||||
addr_ptr = (uint8_t*)space.get_read_ptr(curpc);
|
||||
|
||||
first = (curpc & 0x01) ? 1 : 0;
|
||||
|
||||
if(DEBUG_SET_STATE(DECODE_BIOS) && (curpc == state->m_debug_trap) && (0 != state->m_debug_trap))
|
||||
{
|
||||
state->decode_subbios_return(&device,curpc);
|
||||
}
|
||||
|
||||
if ((addr_ptr !=nullptr) && (addr_ptr[first]==0xCD))
|
||||
{
|
||||
if(DEBUG_SET_STATE(DECODE_BIOS) && (addr_ptr[first+1]==0xF0))
|
||||
state->decode_subbios(&device,curpc);
|
||||
|
||||
if(DEBUG_SET_STATE(DECODE_DOS21) && (addr_ptr[first+1]==0x21))
|
||||
state->decode_dos21(&device,curpc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_subbios_return(device_t *device, offs_t pc)
|
||||
{
|
||||
uint16_t ax = m_maincpu->state_int(I8086_AX);
|
||||
uint16_t ds = m_maincpu->state_int(I8086_DS);
|
||||
uint16_t si = m_maincpu->state_int(I8086_SI);
|
||||
|
||||
if(!DEBUG_SET(DECODE_BIOS_RAW))
|
||||
{
|
||||
logerror("at %05X sub-bios return code : %04X\n",pc,ax);
|
||||
decode_dssi_generic(ds,si);
|
||||
logerror("=======================================================================\n");
|
||||
}
|
||||
else
|
||||
logerror("%05X :: %04X\n",pc,ax);
|
||||
|
||||
m_debug_trap=0;
|
||||
}
|
||||
|
||||
#define set_type(type_name) sprintf(type_str,type_name)
|
||||
#define set_drv(drv_name) sprintf(drv_str,drv_name)
|
||||
#define set_func(func_name) sprintf(func_str,func_name)
|
||||
|
||||
void rmnimbus_state::decode_subbios(device_t *device,offs_t pc)
|
||||
{
|
||||
char type_str[80];
|
||||
char drv_str[80];
|
||||
char func_str[80];
|
||||
|
||||
void (rmnimbus_state::*dump_dssi)(uint16_t, uint16_t) = &rmnimbus_state::decode_dssi_none;
|
||||
|
||||
uint16_t ax = m_maincpu->state_int(I8086_AX);
|
||||
uint16_t bx = m_maincpu->state_int(I8086_BX);
|
||||
uint16_t cx = m_maincpu->state_int(I8086_CX);
|
||||
uint16_t ds = m_maincpu->state_int(I8086_DS);
|
||||
uint16_t si = m_maincpu->state_int(I8086_SI);
|
||||
|
||||
// Set the address to trap after the sub-bios call.
|
||||
m_debug_trap=pc+2;
|
||||
|
||||
// *** TEMP Don't show f_enquire_display_line calls !
|
||||
if((cx==6) && (ax==43))
|
||||
return;
|
||||
// *** END TEMP
|
||||
|
||||
if(!DEBUG_SET(DECODE_BIOS_RAW))
|
||||
{
|
||||
logerror("=======================================================================\n");
|
||||
logerror("Sub-bios call at %08X, AX=%04X, BX=%04X, CX=%04X, DS:SI=%04X:%04X\n",pc,ax,bx,cx,ds,si);
|
||||
}
|
||||
|
||||
set_type("invalid");
|
||||
set_drv("invalid");
|
||||
set_func("invalid");
|
||||
|
||||
switch (cx)
|
||||
{
|
||||
case 0 :
|
||||
{
|
||||
set_type("t_mummu");
|
||||
set_drv("d_mummu");
|
||||
|
||||
switch (ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
case 1 : set_func("f_add_type_code"); break;
|
||||
case 2 : set_func("f_del_typc_code"); break;
|
||||
case 3 : set_func("f_get_TCB"); break;
|
||||
case 4 : set_func("f_add_driver_code"); break;
|
||||
case 5 : set_func("f_del_driver_code"); break;
|
||||
case 6 : set_func("f_get_DCB"); break;
|
||||
case 7 : set_func("f_get_copyright"); break;
|
||||
}
|
||||
}; break;
|
||||
|
||||
case 1 :
|
||||
{
|
||||
set_type("t_character");
|
||||
set_drv("d_printer");
|
||||
|
||||
switch(ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
case 1 : set_func("f_get_output_status"); break;
|
||||
case 2 : set_func("f_output_character"); break;
|
||||
case 3 : set_func("f_get_input_status"); break;
|
||||
case 4 : set_func("f_get_and_remove"); break;
|
||||
case 5 : set_func("f_get_no_remove"); break;
|
||||
case 6 : set_func("f_get_last_and_remove"); break;
|
||||
case 7 : set_func("f_get_last_no_remove"); break;
|
||||
case 8 : set_func("f_set_IO_parameters"); break;
|
||||
}
|
||||
}; break;
|
||||
|
||||
case 2 :
|
||||
{
|
||||
set_type("t_disk");
|
||||
|
||||
switch(bx)
|
||||
{
|
||||
case 0 : set_drv("d_floppy"); break;
|
||||
case 1 : set_drv("d_winchester"); break;
|
||||
case 2 : set_drv("d_tape"); break;
|
||||
case 3 : set_drv("d_rompack"); break;
|
||||
case 4 : set_drv("d_eeprom"); break;
|
||||
}
|
||||
|
||||
dump_dssi = &rmnimbus_state::decode_dssi_generic;
|
||||
|
||||
switch(ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
case 1 : set_func("f_initialise_unit"); break;
|
||||
case 2 : set_func("f_pseudo_init_unit"); break;
|
||||
case 3 : set_func("f_get_device_status"); break;
|
||||
case 4 : set_func("f_read_n_sectors"); dump_dssi = &rmnimbus_state::decode_dssi_f_rw_sectors; break;
|
||||
case 5 : set_func("f_write_n_sectors"); dump_dssi = &rmnimbus_state::decode_dssi_f_rw_sectors; break;
|
||||
case 6 : set_func("f_verify_n_sectors"); dump_dssi = &rmnimbus_state::decode_dssi_f_rw_sectors; break;
|
||||
case 7 : set_func("f_media_check"); break;
|
||||
case 8 : set_func("f_recalibrate"); break;
|
||||
case 9 : set_func("f_motors_off"); break;
|
||||
}
|
||||
|
||||
}; break;
|
||||
|
||||
case 3 :
|
||||
{
|
||||
set_type("t_piconet");
|
||||
set_drv("d_piconet");
|
||||
|
||||
switch(ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
case 1 : set_func("f_get_slave_status"); break;
|
||||
case 2 : set_func("f_get_slave_map"); break;
|
||||
case 3 : set_func("f_change_slave_addr"); break;
|
||||
case 4 : set_func("f_read_slave_control"); break;
|
||||
case 5 : set_func("f_write_slave_control"); break;
|
||||
case 6 : set_func("f_send_data_byte"); break;
|
||||
case 7 : set_func("f_request_data_byte"); break;
|
||||
case 8 : set_func("f_send_data_block"); break;
|
||||
case 9 : set_func("f_request_data_block"); break;
|
||||
case 10 : set_func("f_reset_slave"); break;
|
||||
|
||||
}
|
||||
}; break;
|
||||
|
||||
case 4 :
|
||||
{
|
||||
set_type("t_tick");
|
||||
set_drv("d_tick");
|
||||
|
||||
switch(ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
case 1 : set_func("f_ticks_per_second"); break;
|
||||
case 2 : set_func("f_link_tick_routine"); break;
|
||||
case 3 : set_func("f_unlink_tick_routine"); break;
|
||||
}
|
||||
}; break;
|
||||
|
||||
case 5 :
|
||||
{
|
||||
set_type("t_graphics_input");
|
||||
|
||||
switch(bx)
|
||||
{
|
||||
case 0 : set_drv("d_mouse"); break;
|
||||
case 1 : set_drv("d_joystick_1"); break;
|
||||
case 2 : set_drv("d_joystick_2"); break;
|
||||
}
|
||||
|
||||
|
||||
switch(ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
case 1 : set_func("f_graphics_input_cold_start"); break;
|
||||
case 2 : set_func("f_graphics_input_device_off"); break;
|
||||
case 3 : set_func("f_return_button_status"); break;
|
||||
case 4 : set_func("f_return_switch_and_button_stat"); break;
|
||||
case 5 : set_func("f_start_tracking"); break;
|
||||
case 6 : set_func("f_stop_tracking"); break;
|
||||
case 7 : set_func("f_enquire_position"); break;
|
||||
case 8 : set_func("f_set_position"); break;
|
||||
|
||||
case 10 : set_func("f_return_button_press_info"); break;
|
||||
case 11 : set_func("f_return_button_release_info"); break;
|
||||
case 12 : set_func("f_set_gain/f_set_squeaks_per_pixel_ratio"); break;
|
||||
case 13 : set_func("f_enquire_graphics_in_misc_data"); break;
|
||||
}
|
||||
}; break;
|
||||
|
||||
case 6 :
|
||||
{
|
||||
set_type("t_graphics_output");
|
||||
set_drv("d_ngc_screen");
|
||||
|
||||
switch(ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
case 1 : set_func("f_graphics_output_cold_start"); break;
|
||||
case 2 : set_func("f_graphics_output_warm_start"); break;
|
||||
case 3 : set_func("f_graphics_output_off"); break;
|
||||
case 4 : set_func("f_reinit_graphics_output"); break;
|
||||
case 5 : set_func("f_polymarker"); break;
|
||||
case 6 : set_func("f_polyline"); dump_dssi = &rmnimbus_state::decode_dssi_f_fill_area; break;
|
||||
case 7 : set_func("f_fill_area"); dump_dssi = &rmnimbus_state::decode_dssi_f_fill_area; break;
|
||||
case 8 : set_func("f_flood_fill_area"); break;
|
||||
case 9 : set_func("f_plot_character_string"); dump_dssi = &rmnimbus_state::decode_dssi_f_plot_character_string; break;
|
||||
case 10 : set_func("f_define_graphics_clipping_area"); break;
|
||||
case 11 : set_func("f_enquire_clipping_area_limits"); break;
|
||||
case 12 : set_func("f_select_graphics_clipping_area"); break;
|
||||
case 13 : set_func("f_enq_selctd_graphics_clip_area"); break;
|
||||
case 14 : set_func("f_set_clt_element"); break;
|
||||
case 15 : set_func("f_enquire_clt_element"); break;
|
||||
case 16 : set_func("f_set_new_clt"); dump_dssi = &rmnimbus_state::decode_dssi_f_set_new_clt; break;
|
||||
case 17 : set_func("f_enquire_clt_contents"); break;
|
||||
case 18 : set_func("f_define_dithering_pattern"); break;
|
||||
case 19 : set_func("f_enquire_dithering_pattern"); break;
|
||||
case 20 : set_func("f_draw_sprite"); break;
|
||||
case 21 : set_func("f_move_sprite"); break;
|
||||
case 22 : set_func("f_erase_sprite"); break;
|
||||
case 23 : set_func("f_read_pixel"); break;
|
||||
case 24 : set_func("f_read_to_limit"); break;
|
||||
case 25 : set_func("f_read_area_pixel"); break;
|
||||
case 26 : set_func("f_write_area_pixel"); break;
|
||||
case 27 : set_func("f_copy_area_pixel"); break;
|
||||
|
||||
case 29 : set_func("f_read_area_word"); break;
|
||||
case 30 : set_func("f_write_area_word"); break;
|
||||
case 31 : set_func("f_copy_area_word"); break;
|
||||
case 32 : set_func("f_swap_area_word"); break;
|
||||
case 33 : set_func("f_set_border_colour"); break;
|
||||
case 34 : set_func("f_enquire_border_colour"); break;
|
||||
case 35 : set_func("f_enquire_miscellaneous_data"); break;
|
||||
case 36 : set_func("f_circle"); break;
|
||||
|
||||
case 38 : set_func("f_arc_of_ellipse"); break;
|
||||
case 39 : set_func("f_isin"); break;
|
||||
case 40 : set_func("f_icos"); break;
|
||||
case 41 : set_func("f_define_hatching_pattern"); break;
|
||||
case 42 : set_func("f_enquire_hatching_pattern"); break;
|
||||
case 43 : set_func("f_enquire_display_line"); break;
|
||||
case 44 : set_func("f_plonk_logo"); break;
|
||||
}
|
||||
}; break;
|
||||
|
||||
case 7 :
|
||||
{
|
||||
set_type("t_zend");
|
||||
switch(ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
}
|
||||
}; break;
|
||||
|
||||
case 8 :
|
||||
{
|
||||
set_type("t_zep");
|
||||
switch(ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
}
|
||||
}; break;
|
||||
|
||||
case 9 :
|
||||
{
|
||||
set_type("t_raw_console");
|
||||
|
||||
switch(bx)
|
||||
{
|
||||
case 0 :
|
||||
{
|
||||
set_drv("d_screen");
|
||||
|
||||
switch(ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
case 1 : set_func("f_plonk_char"); dump_dssi = &rmnimbus_state::decode_dssi_f_plonk_char; break;
|
||||
case 2 : set_func("f_plonk_cursor"); break;
|
||||
case 3 : set_func("f_kill_cursor"); break;
|
||||
case 4 : set_func("f_scroll"); break;
|
||||
case 5 : set_func("f_width"); dump_dssi = &rmnimbus_state::decode_dssi_generic; break;
|
||||
case 6 : set_func("f_get_char_set"); break;
|
||||
case 7 : set_func("f_set_char_set"); break;
|
||||
case 8 : set_func("f_reset_char_set"); break;
|
||||
case 9 : set_func("f_set_plonk_parameters"); break;
|
||||
case 10 : set_func("f_set_cursor_flash_rate"); break;
|
||||
}
|
||||
}; break;
|
||||
|
||||
case 1 :
|
||||
{
|
||||
set_drv("d_keyboard");
|
||||
|
||||
switch(ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
case 1 : set_func("f_init_keyboard"); break;
|
||||
case 2 : set_func("f_get_last_key_code"); break;
|
||||
case 3 : set_func("f_get_bitmap"); break;
|
||||
}
|
||||
}; break;
|
||||
}
|
||||
}; break;
|
||||
|
||||
case 10 :
|
||||
{
|
||||
set_type("t_acoustics");
|
||||
|
||||
switch(bx)
|
||||
{
|
||||
case 0 :
|
||||
{
|
||||
set_drv("d_sound");
|
||||
|
||||
switch(ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
case 1 : set_func("f_sound_enable"); break;
|
||||
case 2 : set_func("f_play_note"); break;
|
||||
case 3 : set_func("f_get_queue_status"); break;
|
||||
}
|
||||
}; break;
|
||||
|
||||
case 1 :
|
||||
{
|
||||
set_drv("d_voice");
|
||||
|
||||
switch(ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
case 1 : set_func("f_talk"); break;
|
||||
case 2 : set_func("f_wait_and_talk"); break;
|
||||
case 3 : set_func("f_test_talking"); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}; break;
|
||||
|
||||
case 11 :
|
||||
{
|
||||
set_type("t_hard_sums");
|
||||
switch(ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
}
|
||||
}; break;
|
||||
}
|
||||
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
{
|
||||
(this->*dump_dssi)(ds, si);
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("Type=%s, Driver=%s, Function=%s\n",type_str,drv_str,func_str);
|
||||
|
||||
(this->*dump_dssi)(ds, si);
|
||||
logerror("=======================================================================\n");
|
||||
}
|
||||
}
|
||||
|
||||
static inline void *get_regpair_ptr(address_space &space, uint16_t segment, uint16_t offset)
|
||||
{
|
||||
int addr;
|
||||
|
||||
addr=((segment<<4)+offset);
|
||||
|
||||
return space.get_read_ptr(addr);
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_dssi_none(uint16_t ds, uint16_t si)
|
||||
{
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_dssi_generic(uint16_t ds, uint16_t si)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
uint16_t *params;
|
||||
int count;
|
||||
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
return;
|
||||
|
||||
params=(uint16_t *)get_regpair_ptr(space,ds,si);
|
||||
|
||||
for(count=0; count<10; count++)
|
||||
logerror("%04X ",params[count]);
|
||||
|
||||
logerror("\n");
|
||||
}
|
||||
|
||||
|
||||
void rmnimbus_state::decode_dssi_f_fill_area(uint16_t ds, uint16_t si)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
|
||||
uint16_t *addr_ptr;
|
||||
t_area_params *area_params;
|
||||
t_nimbus_brush *brush;
|
||||
int cocount;
|
||||
|
||||
area_params = (t_area_params *)get_regpair_ptr(space,ds,si);
|
||||
|
||||
if (!DEBUG_SET(DECODE_BIOS_RAW))
|
||||
OUTPUT_SEGOFS("SegBrush:OfsBrush",area_params->seg_brush,area_params->ofs_brush);
|
||||
|
||||
brush=(t_nimbus_brush *)space.get_read_ptr(LINEAR_ADDR(area_params->seg_brush,area_params->ofs_brush));
|
||||
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
{
|
||||
logerror("\tdw\t%04X, %04X, %04X, %04X, %04X, %04X, %04X, %04X, %04X, ",
|
||||
brush->style,brush->style_index,brush->colour1,brush->colour2,
|
||||
brush->transparency,brush->boundary_spec,brush->boundary_colour,brush->save_colour,
|
||||
area_params->count);
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("Brush params\n");
|
||||
logerror("Style=%04X, StyleIndex=%04X\n",brush->style,brush->style_index);
|
||||
logerror("Colour1=%04X, Colour2=%04X\n",brush->colour1,brush->colour2);
|
||||
logerror("transparency=%04X, boundary_spec=%04X\n",brush->transparency,brush->boundary_spec);
|
||||
logerror("boundary colour=%04X, save colour=%04X\n",brush->boundary_colour,brush->save_colour);
|
||||
|
||||
|
||||
OUTPUT_SEGOFS("SegData:OfsData",area_params->seg_data,area_params->ofs_data);
|
||||
}
|
||||
|
||||
addr_ptr = (uint16_t *)space.get_read_ptr(LINEAR_ADDR(area_params->seg_data,area_params->ofs_data));
|
||||
for(cocount=0; cocount < area_params->count; cocount++)
|
||||
{
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
{
|
||||
if(cocount!=(area_params->count-1))
|
||||
logerror("%04X, %04X, ",addr_ptr[cocount*2],addr_ptr[(cocount*2)+1]);
|
||||
else
|
||||
logerror("%04X, %04X ",addr_ptr[cocount*2],addr_ptr[(cocount*2)+1]);
|
||||
}
|
||||
else
|
||||
logerror("x=%d y=%d\n",addr_ptr[cocount*2],addr_ptr[(cocount*2)+1]);
|
||||
}
|
||||
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
logerror("\n");
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_dssi_f_plot_character_string(uint16_t ds, uint16_t si)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
|
||||
uint8_t *char_ptr;
|
||||
t_plot_string_params *plot_string_params;
|
||||
int charno;
|
||||
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
return;
|
||||
|
||||
plot_string_params=(t_plot_string_params *)get_regpair_ptr(space,ds,si);
|
||||
|
||||
OUTPUT_SEGOFS("SegFont:OfsFont",plot_string_params->seg_font,plot_string_params->ofs_font);
|
||||
OUTPUT_SEGOFS("SegData:OfsData",plot_string_params->seg_data,plot_string_params->ofs_data);
|
||||
|
||||
logerror("x=%d, y=%d, length=%d\n",plot_string_params->x,plot_string_params->y,plot_string_params->length);
|
||||
|
||||
char_ptr=(uint8_t*)space.get_read_ptr(LINEAR_ADDR(plot_string_params->seg_data,plot_string_params->ofs_data));
|
||||
|
||||
if (plot_string_params->length==0xFFFF)
|
||||
logerror("%s",char_ptr);
|
||||
else
|
||||
for(charno=0;charno<plot_string_params->length;charno++)
|
||||
logerror("%c",char_ptr[charno]);
|
||||
|
||||
logerror("\n");
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_dssi_f_set_new_clt(uint16_t ds, uint16_t si)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
uint16_t *new_colours;
|
||||
int colour;
|
||||
new_colours=(uint16_t *)get_regpair_ptr(space,ds,si);
|
||||
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
return;
|
||||
|
||||
OUTPUT_SEGOFS("SegColours:OfsColours",ds,si);
|
||||
|
||||
for(colour=0;colour<16;colour++)
|
||||
logerror("colour #%02X=%04X\n",colour,new_colours[colour]);
|
||||
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_dssi_f_plonk_char(uint16_t ds, uint16_t si)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
uint16_t *params;
|
||||
params=(uint16_t *)get_regpair_ptr(space,ds,si);
|
||||
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
return;
|
||||
|
||||
OUTPUT_SEGOFS("SegParams:OfsParams",ds,si);
|
||||
|
||||
logerror("plonked_char=%c\n",params[0]);
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_dssi_f_rw_sectors(uint16_t ds, uint16_t si)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
uint16_t *params;
|
||||
int param_no;
|
||||
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
return;
|
||||
|
||||
params=(uint16_t *)get_regpair_ptr(space,ds,si);
|
||||
|
||||
logerror("unitno=%04X, count=%02X, first_sector=%08X buffer=%04X:%04X (%05X)\n",
|
||||
params[0],
|
||||
params[1],
|
||||
((params[3] * 65536)+params[2]),
|
||||
params[5],params[4],
|
||||
((params[5]*16)+params[4])
|
||||
);
|
||||
|
||||
for(param_no=0;param_no<16;param_no++)
|
||||
logerror("%04X ",params[param_no]);
|
||||
|
||||
logerror("\n");
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_dos21(device_t *device,offs_t pc)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
//uint16_t *params;
|
||||
char *path;
|
||||
|
||||
uint16_t ax = m_maincpu->state_int(I8086_AX);
|
||||
uint16_t bx = m_maincpu->state_int(I8086_BX);
|
||||
uint16_t cx = m_maincpu->state_int(I8086_CX);
|
||||
uint16_t dx = m_maincpu->state_int(I8086_DX);
|
||||
uint16_t cs = m_maincpu->state_int(I8086_CS);
|
||||
uint16_t ds = m_maincpu->state_int(I8086_DS);
|
||||
uint16_t es = m_maincpu->state_int(I8086_ES);
|
||||
uint16_t ss = m_maincpu->state_int(I8086_SS);
|
||||
|
||||
uint16_t si = m_maincpu->state_int(I8086_SI);
|
||||
uint16_t di = m_maincpu->state_int(I8086_DI);
|
||||
uint16_t bp = m_maincpu->state_int(I8086_BP);
|
||||
|
||||
uint8_t dosfn = ax >> 8; // Dos function is AH, upper half of AX.
|
||||
|
||||
logerror("=======================================================================\n");
|
||||
logerror("DOS Int 0x21 call at %05X\n",pc);
|
||||
logerror("AX=%04X, BX=%04X, CX=%04X, DX=%04X\n",ax,bx,cx,dx);
|
||||
logerror("CS=%04X, DS=%04X, ES=%04X, SS=%04X\n",cs,ds,es,ss);
|
||||
logerror("SI=%04X, DI=%04X, BP=%04X\n",si,di,bp);
|
||||
logerror("=======================================================================\n");
|
||||
|
||||
if (((dosfn >= 0x39) && (dosfn <= 0x3d))
|
||||
|| (0x43 == dosfn)
|
||||
|| (0x4e == dosfn)
|
||||
|| (0x56 == dosfn)
|
||||
|| ((dosfn >= 0x5a) && (dosfn <= 0x5b)) )
|
||||
{
|
||||
path=(char *)get_regpair_ptr(space,ds,dx);
|
||||
logerror("Path at DS:DX=%s\n",path);
|
||||
|
||||
if (0x56 == dosfn)
|
||||
{
|
||||
path=(char *)get_regpair_ptr(space,es,di);
|
||||
logerror("Path at ES:DI=%s\n",path);
|
||||
}
|
||||
logerror("=======================================================================\n");
|
||||
}
|
||||
}
|
||||
|
||||
#define CBUFLEN 32
|
||||
|
||||
offs_t rmnimbus_state::dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer ¶ms)
|
||||
|
@ -1211,15 +1211,15 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_Z(const char *buf)
|
||||
return REPLY_OK;
|
||||
case 2:
|
||||
// write watchpoint
|
||||
debug->watchpoint_set(*m_address_space, read_or_write::WRITE, offset, kind, nullptr, nullptr);
|
||||
debug->watchpoint_set(*m_address_space, read_or_write::WRITE, offset, kind);
|
||||
return REPLY_OK;
|
||||
case 3:
|
||||
// read watchpoint
|
||||
debug->watchpoint_set(*m_address_space, read_or_write::READ, offset, kind, nullptr, nullptr);
|
||||
debug->watchpoint_set(*m_address_space, read_or_write::READ, offset, kind);
|
||||
return REPLY_OK;
|
||||
case 4:
|
||||
// access watchpoint
|
||||
debug->watchpoint_set(*m_address_space, read_or_write::READWRITE, offset, kind, nullptr, nullptr);
|
||||
debug->watchpoint_set(*m_address_space, read_or_write::READWRITE, offset, kind);
|
||||
return REPLY_OK;
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@
|
||||
// if it doesn't exist, add a new one
|
||||
if (bp == nullptr)
|
||||
{
|
||||
uint32_t const bpnum = device.debug()->breakpoint_set(address, nullptr, nullptr);
|
||||
uint32_t const bpnum = device.debug()->breakpoint_set(address);
|
||||
machine->debugger().console().printf("Breakpoint %X set\n", bpnum);
|
||||
}
|
||||
else
|
||||
|
@ -149,7 +149,7 @@ void DasmWindow::toggleBreakpointAtCursor(bool changedTo)
|
||||
// If none exists, add a new one
|
||||
if (!bp)
|
||||
{
|
||||
int32_t bpindex = cpuinfo->breakpoint_set(address, nullptr, nullptr);
|
||||
int32_t bpindex = cpuinfo->breakpoint_set(address);
|
||||
m_machine.debugger().console().printf("Breakpoint %X set\n", bpindex);
|
||||
}
|
||||
else
|
||||
|
@ -174,7 +174,7 @@ bool disasmbasewin_info::handle_command(WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
if (bp == nullptr)
|
||||
{
|
||||
int32_t bpindex = debug->breakpoint_set(address, nullptr, nullptr);
|
||||
int32_t bpindex = debug->breakpoint_set(address);
|
||||
machine().debugger().console().printf("Breakpoint %X set\n", bpindex);
|
||||
}
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user