summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/debug/dvbpoints.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/debug/dvbpoints.cpp')
-rw-r--r--src/emu/debug/dvbpoints.cpp319
1 files changed, 319 insertions, 0 deletions
diff --git a/src/emu/debug/dvbpoints.cpp b/src/emu/debug/dvbpoints.cpp
new file mode 100644
index 00000000000..2e4e16de68f
--- /dev/null
+++ b/src/emu/debug/dvbpoints.cpp
@@ -0,0 +1,319 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/*********************************************************************
+
+ dvbpoints.c
+
+ Breakpoint debugger view.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "dvbpoints.h"
+
+
+
+// Sorting functors for the qsort function
+static int cIndexAscending(const void* a, const void* b)
+{
+ const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
+ const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
+ return left->index() - right->index();
+}
+
+static int cIndexDescending(const void* a, const void* b)
+{
+ return cIndexAscending(b, a);
+}
+
+static int cEnabledAscending(const void* a, const void* b)
+{
+ const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
+ const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
+ return (left->enabled() ? 1 : 0) - (right->enabled() ? 1 : 0);
+}
+
+static int cEnabledDescending(const void* a, const void* b)
+{
+ return cEnabledAscending(b, a);
+}
+
+static int cCpuAscending(const void* a, const void* b)
+{
+ const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
+ const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
+ return strcmp(left->debugInterface()->device().tag(), right->debugInterface()->device().tag());
+}
+
+static int cCpuDescending(const void* a, const void* b)
+{
+ return cCpuAscending(b, a);
+}
+
+static int cAddressAscending(const void* a, const void* b)
+{
+ const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
+ const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
+ return (left->address() > right->address()) ? 1 : (left->address() < right->address()) ? -1 : 0;
+}
+
+static int cAddressDescending(const void* a, const void* b)
+{
+ return cAddressAscending(b, a);
+}
+
+static int cConditionAscending(const void* a, const void* b)
+{
+ const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
+ const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
+ return strcmp(left->condition(), right->condition());
+}
+
+static int cConditionDescending(const void* a, const void* b)
+{
+ return cConditionAscending(b, a);
+}
+
+static int cActionAscending(const void* a, const void* b)
+{
+ const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
+ const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
+ return strcmp(left->action(), right->action());
+}
+
+static int cActionDescending(const void* a, const void* b)
+{
+ return cActionAscending(b, a);
+}
+
+
+//**************************************************************************
+// DEBUG VIEW BREAK POINTS
+//**************************************************************************
+
+static const int tableBreaks[] = { 5, 9, 31, 45, 63, 80 };
+
+
+//-------------------------------------------------
+// debug_view_breakpoints - constructor
+//-------------------------------------------------
+
+debug_view_breakpoints::debug_view_breakpoints(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate)
+ : debug_view(machine, DVT_BREAK_POINTS, osdupdate, osdprivate),
+ m_sortType(cIndexAscending)
+{
+ // fail if no available sources
+ enumerate_sources();
+ if (m_source_list.count() == 0)
+ throw std::bad_alloc();
+}
+
+
+//-------------------------------------------------
+// ~debug_view_breakpoints - destructor
+//-------------------------------------------------
+
+debug_view_breakpoints::~debug_view_breakpoints()
+{
+}
+
+
+//-------------------------------------------------
+// enumerate_sources - enumerate all possible
+// sources for a disassembly view
+//-------------------------------------------------
+
+void debug_view_breakpoints::enumerate_sources()
+{
+ // start with an empty list
+ m_source_list.reset();
+
+ // iterate over devices with disassembly interfaces
+ disasm_interface_iterator iter(machine().root_device());
+ for (device_disasm_interface *dasm = iter.first(); dasm != NULL; dasm = iter.next())
+ {
+ std::string name;
+ strprintf(name, "%s '%s'", dasm->device().name(), dasm->device().tag());
+ m_source_list.append(*global_alloc(debug_view_source(name.c_str(), &dasm->device())));
+ }
+
+ // reset the source to a known good entry
+ set_source(*m_source_list.first());
+}
+
+
+//-------------------------------------------------
+// view_click - handle a mouse click within the
+// current view
+//-------------------------------------------------
+
+void debug_view_breakpoints::view_click(const int button, const debug_view_xy& pos)
+{
+ bool clickedTopRow = (m_topleft.y == pos.y);
+
+ if (clickedTopRow)
+ {
+ if (pos.x < tableBreaks[0])
+ m_sortType = (m_sortType == &cIndexAscending) ? &cIndexDescending : &cIndexAscending;
+ else if (pos.x < tableBreaks[1])
+ m_sortType = (m_sortType == &cEnabledAscending) ? &cEnabledDescending : &cEnabledAscending;
+ else if (pos.x < tableBreaks[2])
+ m_sortType = (m_sortType == &cCpuAscending) ? &cCpuDescending : &cCpuAscending;
+ else if (pos.x < tableBreaks[3])
+ m_sortType = (m_sortType == &cAddressAscending) ? &cAddressDescending : &cAddressAscending;
+ else if (pos.x < tableBreaks[4])
+ m_sortType = (m_sortType == &cConditionAscending) ? &cConditionDescending : &cConditionAscending;
+ else if (pos.x < tableBreaks[5])
+ m_sortType = (m_sortType == &cActionAscending) ? &cActionDescending : &cActionAscending;
+ }
+ else
+ {
+ // Gather a sorted list of all the breakpoints for all the CPUs
+ gather_breakpoints();
+
+ int bpIndex = pos.y - 1;
+ if ((bpIndex >= m_buffer.size()) || (bpIndex < 0))
+ return;
+
+ // Enable / disable
+ m_buffer[bpIndex]->setEnabled(!m_buffer[bpIndex]->enabled());
+
+ machine().debug_view().update_all(DVT_DISASSEMBLY);
+ }
+
+ begin_update();
+ m_update_pending = true;
+ end_update();
+}
+
+
+void debug_view_breakpoints::pad_astring_to_length(std::string& str, int len)
+{
+ int diff = len - str.length();
+ if (diff > 0)
+ {
+ std::string buffer;
+ for (int i = 0; i < diff; i++)
+ strcatprintf(buffer, " ");
+ strcatprintf(str, "%s", buffer.c_str());
+ }
+}
+
+
+void debug_view_breakpoints::gather_breakpoints()
+{
+ m_buffer.resize(0);
+ for (const debug_view_source *source = m_source_list.first(); source != NULL; source = source->next())
+ {
+ // Collect
+ device_debug &debugInterface = *source->device()->debug();
+ for (device_debug::breakpoint *bp = debugInterface.breakpoint_first(); bp != NULL; bp = bp->next())
+ m_buffer.push_back(bp);
+ }
+
+ // And now for the sort
+ if (!m_buffer.empty())
+ qsort(&m_buffer[0], m_buffer.size(), sizeof(device_debug::breakpoint *), m_sortType);
+}
+
+
+//-------------------------------------------------
+// view_update - update the contents of the
+// breakpoints view
+//-------------------------------------------------
+
+void debug_view_breakpoints::view_update()
+{
+ // Gather a list of all the breakpoints for all the CPUs
+ gather_breakpoints();
+
+ // Set the view region so the scroll bars update
+ m_total.x = tableBreaks[ARRAY_LENGTH(tableBreaks) - 1];
+ m_total.y = m_buffer.size() + 1;
+ if (m_total.y < 10)
+ m_total.y = 10;
+
+ // Draw
+ debug_view_char *dest = &m_viewdata[0];
+ std::string linebuf;
+
+ // Header
+ if (m_visible.y > 0)
+ {
+ linebuf.clear();
+ linebuf.append("ID");
+ if (m_sortType == &cIndexAscending) linebuf.push_back('\\');
+ else if (m_sortType == &cIndexDescending) linebuf.push_back('/');
+ pad_astring_to_length(linebuf, tableBreaks[0]);
+ linebuf.append("En");
+ if (m_sortType == &cEnabledAscending) linebuf.push_back('\\');
+ else if (m_sortType == &cEnabledDescending) linebuf.push_back('/');
+ pad_astring_to_length(linebuf, tableBreaks[1]);
+ linebuf.append("CPU");
+ if (m_sortType == &cCpuAscending) linebuf.push_back('\\');
+ else if (m_sortType == &cCpuDescending) linebuf.push_back('/');
+ pad_astring_to_length(linebuf, tableBreaks[2]);
+ linebuf.append("Address");
+ if (m_sortType == &cAddressAscending) linebuf.push_back('\\');
+ else if (m_sortType == &cAddressDescending) linebuf.push_back('/');
+ pad_astring_to_length(linebuf, tableBreaks[3]);
+ linebuf.append("Condition");
+ if (m_sortType == &cConditionAscending) linebuf.push_back('\\');
+ else if (m_sortType == &cConditionDescending) linebuf.push_back('/');
+ pad_astring_to_length(linebuf, tableBreaks[4]);
+ linebuf.append("Action");
+ if (m_sortType == &cActionAscending) linebuf.push_back('\\');
+ else if (m_sortType == &cActionDescending) linebuf.push_back('/');
+ pad_astring_to_length(linebuf, tableBreaks[5]);
+
+ for (UINT32 i = m_topleft.x; i < (m_topleft.x + m_visible.x); i++, dest++)
+ {
+ dest->byte = (i < linebuf.length()) ? linebuf[i] : ' ';
+ dest->attrib = DCA_ANCILLARY;
+ }
+ }
+
+ for (int row = 1; row < m_visible.y; row++)
+ {
+ // Breakpoints
+ int bpi = row + m_topleft.y - 1;
+ if ((bpi < m_buffer.size()) && (bpi >= 0))
+ {
+ device_debug::breakpoint *const bp = m_buffer[bpi];
+
+ linebuf.clear();
+ strcatprintf(linebuf, "%2X", bp->index());
+ pad_astring_to_length(linebuf, tableBreaks[0]);
+ linebuf.push_back(bp->enabled() ? 'X' : 'O');
+ pad_astring_to_length(linebuf, tableBreaks[1]);
+ linebuf.append(bp->debugInterface()->device().tag());
+ pad_astring_to_length(linebuf, tableBreaks[2]);
+ linebuf.append(core_i64_hex_format(bp->address(), bp->debugInterface()->logaddrchars()));
+ pad_astring_to_length(linebuf, tableBreaks[3]);
+ if (strcmp(bp->condition(), "1"))
+ linebuf.append(bp->condition());
+ pad_astring_to_length(linebuf, tableBreaks[4]);
+ linebuf.append(bp->action());
+ pad_astring_to_length(linebuf, tableBreaks[5]);
+
+ for (UINT32 i = m_topleft.x; i < (m_topleft.x + m_visible.x); i++, dest++)
+ {
+ dest->byte = (i < linebuf.length()) ? linebuf[i] : ' ';
+ dest->attrib = DCA_NORMAL;
+
+ // Color disabled breakpoints red
+ if ((i >= tableBreaks[0]) && (i < tableBreaks[1]) && !bp->enabled())
+ dest->attrib |= DCA_CHANGED;
+ }
+ }
+ else
+ {
+ // Fill the remaining vertical space
+ for (UINT32 i = m_topleft.x; i < (m_topleft.x + m_visible.x); i++, dest++)
+ {
+ dest->byte = ' ';
+ dest->attrib = DCA_NORMAL;
+ }
+ }
+ }
+}