diff options
Diffstat (limited to 'src/emu/debug/dvbpoints.cpp')
-rw-r--r-- | src/emu/debug/dvbpoints.cpp | 319 |
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; + } + } + } +} |