summaryrefslogblamecommitdiffstatshomepage
path: root/src/emu/debug/dvwpoints.cpp
blob: b186cee4d71d8bfb6bd35be6c724e81c5b18341a (plain) (tree)
1
2
3
4
5
6
7
8

                                





                                                                      




                                                                            

                  

 



























                                                                               
                                                                                                       



































































                                                                                                        











                                                                                                                                
                                            




                                       






















                                                           
                                                                                                
         
                                 

                                                                                                     


                                                 
                                           



                                                   





                                                                                   
                                                          


                          

                                                                                                             
                                                
                                                                                                                   
                                                
                                                                                                       
                                                
                                                                                                             
                                                
                                                                                                                   
                                                
                                                                                                          
                                                
                                                                                                                         
                                                
                                                                                                                



                                                                               
                                     
 
                                              
                                                                  


                                   
                                                                             

         


                                


 
                                                                              
 

                                             
                                                                         


 
                                                 
 
                           
                                                             

                          
                                                                         
                                                                                             
                 
                                                                                                                                      
                                                       



                               

                                                                                                     




                                                   
                    




                                                                
                             

                                                        
                                                               
                                        

                               

               

                                                   
                                                       
 


                            
                                
                                         

































                                                                               
                                                                                          
                 
                                                                       
                                                     
                 
         
 

                                                   
                              
                                                      
                                                        
                 


                                                                                                  
                                        
                                                 













                                                                                                                                                         
                                                         



                                                                       
 
                                                        
                                                                                                  
                         
                                                                               


                                                                 

                                                                                                    
                         
                 
                    
                 





                                                                     

                 
 
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/*********************************************************************

    dvwpoints.c

    Watchpoint debugger view.

***************************************************************************/

#include "emu.h"
#include "dvwpoints.h"

#include <iomanip>



static int cIndexAscending(const void* a, const void* b)
{
	const device_debug::watchpoint* left = *(device_debug::watchpoint**)a;
	const device_debug::watchpoint* right = *(device_debug::watchpoint**)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::watchpoint* left = *(device_debug::watchpoint**)a;
	const device_debug::watchpoint* right = *(device_debug::watchpoint**)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::watchpoint* left = *(device_debug::watchpoint**)a;
	const device_debug::watchpoint* right = *(device_debug::watchpoint**)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 cSpaceAscending(const void* a, const void* b)
{
	const device_debug::watchpoint* left = *(device_debug::watchpoint**)a;
	const device_debug::watchpoint* right = *(device_debug::watchpoint**)b;
	return strcmp(left->space().name(), right->space().name());
}

static int cSpaceDescending(const void* a, const void* b)
{
	return cSpaceAscending(b, a);
}

static int cAddressAscending(const void* a, const void* b)
{
	const device_debug::watchpoint* left = *(device_debug::watchpoint**)a;
	const device_debug::watchpoint* right = *(device_debug::watchpoint**)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 cTypeAscending(const void* a, const void* b)
{
	const device_debug::watchpoint* left = *(device_debug::watchpoint**)a;
	const device_debug::watchpoint* right = *(device_debug::watchpoint**)b;
	return left->type() - right->type();
}

static int cTypeDescending(const void* a, const void* b)
{
	return cTypeAscending(b, a);
}

static int cConditionAscending(const void* a, const void* b)
{
	const device_debug::watchpoint* left = *(device_debug::watchpoint**)a;
	const device_debug::watchpoint* right = *(device_debug::watchpoint**)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::watchpoint* left = *(device_debug::watchpoint**)a;
	const device_debug::watchpoint* right = *(device_debug::watchpoint**)b;
	return strcmp(left->action(), right->action());
}

static int cActionDescending(const void* a, const void* b)
{
	return cActionAscending(b, a);
}


//**************************************************************************
//  DEBUG VIEW WATCH POINTS
//**************************************************************************

static const int tableBreaks[] = { 5, 9, 31, 42, 60, 67, 86, 100 };

//-------------------------------------------------
//  debug_view_watchpoints - constructor
//-------------------------------------------------

debug_view_watchpoints::debug_view_watchpoints(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate)
	: debug_view(machine, DVT_WATCH_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_watchpoints - destructor
//-------------------------------------------------

debug_view_watchpoints::~debug_view_watchpoints()
{
}


//-------------------------------------------------
//  enumerate_sources - enumerate all possible
//  sources for a disassembly view
//-------------------------------------------------

void debug_view_watchpoints::enumerate_sources()
{
	// start with an empty list
	m_source_list.reset();

	// iterate over devices with disassembly interfaces
	for (device_disasm_interface &dasm : disasm_interface_iterator(machine().root_device()))
	{
		std::string name;
		name = string_format("%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_watchpoints::view_click(const int button, const debug_view_xy& pos)
{
	bool const 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 == &cSpaceAscending) ? &cSpaceDescending : &cSpaceAscending;
		else if (pos.x < tableBreaks[4])
			m_sortType = (m_sortType == &cAddressAscending) ? &cAddressDescending : &cAddressAscending;
		else if (pos.x < tableBreaks[5])
			m_sortType = (m_sortType == &cTypeAscending) ? &cTypeDescending : &cTypeAscending;
		else if (pos.x < tableBreaks[6])
			m_sortType = (m_sortType == &cConditionAscending) ? &cConditionDescending : &cConditionAscending;
		else if (pos.x < tableBreaks[7])
			m_sortType = (m_sortType == &cActionAscending) ? &cActionDescending : &cActionAscending;
	}
	else
	{
		// Gather a sorted list of all the watchpoints for all the CPUs
		gather_watchpoints();

		int const wpIndex = pos.y - 1;
		if ((wpIndex >= m_buffer.size()) || (wpIndex < 0))
			return;

		// Enable / disable
		m_buffer[wpIndex]->setEnabled(!m_buffer[wpIndex]->enabled());
	}

	begin_update();
	m_update_pending = true;
	end_update();
}


void debug_view_watchpoints::pad_ostream_to_length(std::ostream& str, int len)
{
	auto const current = str.tellp();
	if (current < decltype(current)(len))
		str << std::setw(decltype(current)(len) - current) << "";
}


void debug_view_watchpoints::gather_watchpoints()
{
	m_buffer.resize(0);
	for (const debug_view_source &source : m_source_list)
	{
		// Collect
		device_debug &debugInterface = *source.device()->debug();
		for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; ++spacenum)
		{
			for (device_debug::watchpoint *wp = debugInterface.watchpoint_first(spacenum); wp != nullptr; wp = wp->next())
				m_buffer.push_back(wp);
		}
	}

	// And now for the sort
	if (!m_buffer.empty())
		qsort(&m_buffer[0], m_buffer.size(), sizeof(device_debug::watchpoint *), m_sortType);
}


//-------------------------------------------------
//  view_update - update the contents of the
//  watchpoints view
//-------------------------------------------------

void debug_view_watchpoints::view_update()
{
	// Gather a list of all the watchpoints for all the CPUs
	gather_watchpoints();

	// 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];
	util::ovectorstream linebuf;
	linebuf.reserve(ARRAY_LENGTH(tableBreaks) - 1);

	// Header
	if (m_visible.y > 0)
	{
		linebuf.clear();
		linebuf.rdbuf()->clear();
		linebuf << "ID";
		if (m_sortType == &cIndexAscending) linebuf.put('\\');
		else if (m_sortType == &cIndexDescending) linebuf.put('/');
		pad_ostream_to_length(linebuf, tableBreaks[0]);
		linebuf << "En";
		if (m_sortType == &cEnabledAscending) linebuf.put('\\');
		else if (m_sortType == &cEnabledDescending) linebuf.put('/');
		pad_ostream_to_length(linebuf, tableBreaks[1]);
		linebuf << "CPU";
		if (m_sortType == &cCpuAscending) linebuf.put('\\');
		else if (m_sortType == &cCpuDescending) linebuf.put('/');
		pad_ostream_to_length(linebuf, tableBreaks[2]);
		linebuf << "Space";
		if (m_sortType == &cSpaceAscending) linebuf.put('\\');
		else if (m_sortType == &cSpaceDescending) linebuf.put('/');
		pad_ostream_to_length(linebuf, tableBreaks[3]);
		linebuf << "Addresses";
		if (m_sortType == &cAddressAscending) linebuf.put('\\');
		else if (m_sortType == &cAddressDescending) linebuf.put('/');
		pad_ostream_to_length(linebuf, tableBreaks[4]);
		linebuf << "Type";
		if (m_sortType == &cTypeAscending) linebuf.put('\\');
		else if (m_sortType == &cTypeDescending) linebuf.put('/');
		pad_ostream_to_length(linebuf, tableBreaks[5]);
		linebuf << "Condition";
		if (m_sortType == &cConditionAscending) linebuf.put('\\');
		else if (m_sortType == &cConditionDescending) linebuf.put('/');
		pad_ostream_to_length(linebuf, tableBreaks[6]);
		linebuf << "Action";
		if (m_sortType == &cActionAscending) linebuf.put('\\');
		else if (m_sortType == &cActionDescending) linebuf.put('/');
		pad_ostream_to_length(linebuf, tableBreaks[7]);

		auto const &text(linebuf.vec());
		for (UINT32 i = m_topleft.x; i < (m_topleft.x + m_visible.x); i++, dest++)
		{
			dest->byte = (i < text.size()) ? text[i] : ' ';
			dest->attrib = DCA_ANCILLARY;
		}
	}

	for (int row = 1; row < m_visible.y; row++)
	{
		// watchpoints
		int const wpi = row + m_topleft.y - 1;
		if ((wpi < m_buffer.size()) && wpi >= 0)
		{
			static char const *const types[] = { "unkn ", "read ", "write", "r/w  " };
			device_debug::watchpoint *const wp = m_buffer[wpi];

			linebuf.clear();
			linebuf.rdbuf()->clear();
			util::stream_format(linebuf, "%2X", wp->index());
			pad_ostream_to_length(linebuf, tableBreaks[0]);
			linebuf.put(wp->enabled() ? 'X' : 'O');
			pad_ostream_to_length(linebuf, tableBreaks[1]);
			linebuf << wp->debugInterface()->device().tag();
			pad_ostream_to_length(linebuf, tableBreaks[2]);
			linebuf << wp->space().name();
			pad_ostream_to_length(linebuf, tableBreaks[3]);
			util::stream_format(linebuf, "%0*X", wp->space().addrchars(), wp->space().byte_to_address(wp->address()));
			linebuf.put('-');
			util::stream_format(linebuf, "%0*X", wp->space().addrchars(), wp->space().byte_to_address_end(wp->address() + wp->length()) - 1);
			pad_ostream_to_length(linebuf, tableBreaks[4]);
			linebuf << types[wp->type() & 3];
			pad_ostream_to_length(linebuf, tableBreaks[5]);
			if (strcmp(wp->condition(), "1"))
				linebuf << wp->condition();
			pad_ostream_to_length(linebuf, tableBreaks[6]);
			linebuf << wp->action();
			pad_ostream_to_length(linebuf, tableBreaks[7]);

			auto const &text(linebuf.vec());
			for (UINT32 i = m_topleft.x; i < (m_topleft.x + m_visible.x); i++, dest++)
			{
				dest->byte = (i < text.size()) ? text[i] : ' ';
				dest->attrib = DCA_NORMAL;

				// Color disabled watchpoints red
				if ((i >= tableBreaks[0]) && (i < tableBreaks[1]) && !wp->enabled())
					dest->attrib |= DCA_CHANGED;
			}
		}
		else
		{
			// Fill the remaining vertical space
			for (int i = 0; i < m_visible.x; i++, dest++)
			{
				dest->byte = ' ';
				dest->attrib = DCA_NORMAL;
			}
		}
	}
}