summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/debug/debugvw.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/debug/debugvw.c')
-rw-r--r--trunk/src/emu/debug/debugvw.c633
1 files changed, 633 insertions, 0 deletions
diff --git a/trunk/src/emu/debug/debugvw.c b/trunk/src/emu/debug/debugvw.c
new file mode 100644
index 00000000000..a0eb13452d2
--- /dev/null
+++ b/trunk/src/emu/debug/debugvw.c
@@ -0,0 +1,633 @@
+/*********************************************************************
+
+ debugvw.c
+
+ Debugger view engine.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "express.h"
+#include "debugvw.h"
+#include "dvtext.h"
+#include "dvstate.h"
+#include "dvdisasm.h"
+#include "dvmemory.h"
+#include "debugcmd.h"
+#include "debugcpu.h"
+#include "debugcon.h"
+#include <ctype.h>
+
+
+
+//**************************************************************************
+// DEBUG VIEW SOURCE
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_source - constructor
+//-------------------------------------------------
+
+debug_view_source::debug_view_source(const char *name, device_t *device)
+ : m_next(NULL),
+ m_name(name),
+ m_device(device)
+{
+}
+
+
+//-------------------------------------------------
+// ~debug_view_source - destructor
+//-------------------------------------------------
+
+debug_view_source::~debug_view_source()
+{
+}
+
+
+
+//**************************************************************************
+// DEBUG VIEW SOURCE LIST
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_source_list - constructor
+//-------------------------------------------------
+
+debug_view_source_list::debug_view_source_list(running_machine &machine)
+ : m_machine(machine),
+ m_head(NULL),
+ m_tail(NULL),
+ m_count(0)
+{
+}
+
+
+//-------------------------------------------------
+// ~debug_view_source_list - destructor
+//-------------------------------------------------
+
+debug_view_source_list::~debug_view_source_list()
+{
+ reset();
+}
+
+
+//-------------------------------------------------
+// index - return the index of a source
+//-------------------------------------------------
+
+int debug_view_source_list::index(const debug_view_source &source) const
+{
+ int result = 0;
+ for (debug_view_source *cursource = m_head; cursource != NULL; cursource = cursource->m_next)
+ {
+ if (cursource == &source)
+ break;
+ result++;
+ }
+ return result;
+}
+
+
+//-------------------------------------------------
+// by_index - return a source given an index
+//-------------------------------------------------
+
+const debug_view_source *debug_view_source_list::by_index(int index) const
+{
+ if (m_head == NULL)
+ return NULL;
+ const debug_view_source *result;
+ for (result = m_head; index > 0 && result->m_next != NULL; result = result->m_next)
+ index--;
+ return result;
+}
+
+
+//-------------------------------------------------
+// reset - free all the view_sources
+//-------------------------------------------------
+
+void debug_view_source_list::reset()
+{
+ // free from the head
+ while (m_head != NULL)
+ {
+ debug_view_source *source = m_head;
+ m_head = source->m_next;
+ auto_free(machine(), source);
+ }
+
+ // reset the tail pointer and index
+ m_tail = NULL;
+ m_count = 0;
+}
+
+
+//-------------------------------------------------
+// append - add a view_source to the end of the
+// list
+//-------------------------------------------------
+
+void debug_view_source_list::append(debug_view_source &source)
+{
+ // set the next and index values
+ source.m_next = NULL;
+
+ // append to the end
+ if (m_tail == NULL)
+ m_head = m_tail = &source;
+ else
+ m_tail->m_next = &source;
+ m_tail = &source;
+ m_count++;
+}
+
+
+//-------------------------------------------------
+// match_device - find the first view that
+// matches the given device
+//-------------------------------------------------
+
+const debug_view_source *debug_view_source_list::match_device(device_t *device) const
+{
+ for (debug_view_source *source = m_head; source != NULL; source = source->m_next)
+ if (device == source->m_device)
+ return source;
+ return m_head;
+}
+
+
+
+//**************************************************************************
+// DEBUG VIEW
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view - constructor
+//-------------------------------------------------
+
+debug_view::debug_view(running_machine &machine, debug_view_type type, debug_view_osd_update_func osdupdate, void *osdprivate)
+ : m_next(NULL),
+ m_type(type),
+ m_source(NULL),
+ m_source_list(machine),
+ m_osdupdate(osdupdate),
+ m_osdprivate(osdprivate),
+ m_visible(10,10),
+ m_total(10,10),
+ m_topleft(0,0),
+ m_cursor(0,0),
+ m_supports_cursor(false),
+ m_cursor_visible(false),
+ m_recompute(true),
+ m_update_level(0),
+ m_update_pending(true),
+ m_osd_update_pending(true),
+ m_viewdata(NULL),
+ m_viewdata_size(0),
+ m_machine(machine)
+{
+ // allocate memory for the buffer
+ m_viewdata_size = m_visible.y * m_visible.x;
+ m_viewdata = auto_alloc_array(machine, debug_view_char, m_viewdata_size);
+}
+
+
+//-------------------------------------------------
+// ~debug_view - destructor
+//-------------------------------------------------
+
+debug_view::~debug_view()
+{
+}
+
+
+//-------------------------------------------------
+// end_update - bracket a sequence of changes so
+// that only one update occurs
+//-------------------------------------------------
+
+void debug_view::end_update()
+{
+ /* if we hit zero, call the update function */
+ if (m_update_level == 1)
+ {
+ while (m_update_pending)
+ {
+ // no longer pending, but flag for the OSD
+ m_update_pending = false;
+ m_osd_update_pending = true;
+
+ // resize the viewdata if needed
+ int size = m_visible.x * m_visible.y;
+ if (size > m_viewdata_size)
+ {
+ m_viewdata_size = size;
+ auto_free(machine(), m_viewdata);
+ m_viewdata = auto_alloc_array(machine(), debug_view_char, m_viewdata_size);
+ }
+
+ // update the view
+ view_update();
+ }
+ }
+
+ // decrement the level
+ m_update_level--;
+}
+
+
+//-------------------------------------------------
+// flush_osd_updates - notify the OSD of any
+// pending updates
+//-------------------------------------------------
+
+void debug_view::flush_osd_updates()
+{
+ if (m_osd_update_pending && m_osdupdate != NULL)
+ (*m_osdupdate)(*this, m_osdprivate);
+ m_osd_update_pending = false;
+}
+
+
+//-------------------------------------------------
+// set_visible_size - set the visible size in
+// rows and columns
+//-------------------------------------------------*/
+
+void debug_view::set_visible_size(debug_view_xy size)
+{
+ if (size.x != m_visible.x || size.y != m_visible.y)
+ {
+ begin_update();
+ m_visible = size;
+ m_update_pending = true;
+ view_notify(VIEW_NOTIFY_VISIBLE_CHANGED);
+ end_update();
+ }
+}
+
+
+//-------------------------------------------------
+// set_visible_position - set the top left
+// position of the visible area in rows and
+// columns
+//-------------------------------------------------
+
+void debug_view::set_visible_position(debug_view_xy pos)
+{
+ if (pos.x != m_topleft.x || pos.y != m_topleft.y)
+ {
+ begin_update();
+ m_topleft = pos;
+ m_update_pending = true;
+ view_notify(VIEW_NOTIFY_VISIBLE_CHANGED);
+ end_update();
+ }
+}
+
+
+//-------------------------------------------------
+// set_cursor_position - set the current cursor
+// position as a row and column
+//-------------------------------------------------
+
+void debug_view::set_cursor_position(debug_view_xy pos)
+{
+ if (pos.x != m_cursor.x || pos.y != m_cursor.y)
+ {
+ begin_update();
+ m_cursor = pos;
+ m_update_pending = true;
+ view_notify(VIEW_NOTIFY_CURSOR_CHANGED);
+ end_update();
+ }
+}
+
+
+//-------------------------------------------------
+// set_cursor_visible - set the visible state of
+// the cursor
+//-------------------------------------------------
+
+void debug_view::set_cursor_visible(bool visible)
+{
+ if (visible != m_cursor_visible)
+ {
+ begin_update();
+ m_cursor_visible = visible;
+ m_update_pending = true;
+ view_notify(VIEW_NOTIFY_CURSOR_CHANGED);
+ end_update();
+ }
+}
+
+
+//-------------------------------------------------
+// set_subview - set the current subview
+//-------------------------------------------------
+
+void debug_view::set_source(const debug_view_source &source)
+{
+ if (&source != m_source)
+ {
+ begin_update();
+ m_source = &source;
+ m_update_pending = true;
+ view_notify(VIEW_NOTIFY_SOURCE_CHANGED);
+ end_update();
+ }
+}
+
+
+//-------------------------------------------------
+// adjust_visible_x_for_cursor - adjust a view's
+// visible X position to ensure the cursor is
+// visible
+//-------------------------------------------------
+
+void debug_view::adjust_visible_x_for_cursor()
+{
+ if (m_cursor.x < m_topleft.x)
+ m_topleft.x = m_cursor.x;
+ else if (m_cursor.x >= m_topleft.x + m_visible.x - 1)
+ m_topleft.x = m_cursor.x - m_visible.x + 2;
+}
+
+
+//-------------------------------------------------
+// adjust_visible_y_for_cursor - adjust a view's
+// visible Y position to ensure the cursor is
+// visible
+//-------------------------------------------------
+
+void debug_view::adjust_visible_y_for_cursor()
+{
+ if (m_cursor.y < m_topleft.y)
+ m_topleft.y = m_cursor.y;
+ else if (m_cursor.y >= m_topleft.y + m_visible.y - 1)
+ m_topleft.y = m_cursor.y - m_visible.y + 2;
+}
+
+
+//-------------------------------------------------
+// view_notify - handle notification of updates
+//-------------------------------------------------
+
+void debug_view::view_notify(debug_view_notification type)
+{
+ // default does nothing
+}
+
+
+//-------------------------------------------------
+// view_char - handle a character typed within
+// the current view
+//-------------------------------------------------
+
+void debug_view::view_char(int chval)
+{
+ // default does nothing
+}
+
+
+
+//**************************************************************************
+// DEBUG VIEW MANAGER
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_manager - constructor
+//-------------------------------------------------
+
+debug_view_manager::debug_view_manager(running_machine &machine)
+ : m_machine(machine),
+ m_viewlist(NULL)
+{
+}
+
+
+//-------------------------------------------------
+// ~debug_view_manager - destructor
+//-------------------------------------------------
+
+debug_view_manager::~debug_view_manager()
+{
+ while (m_viewlist != NULL)
+ {
+ debug_view *oldhead = m_viewlist;
+ m_viewlist = oldhead->m_next;
+ auto_free(machine(), oldhead);
+ }
+}
+
+
+//-------------------------------------------------
+// alloc_view - create a new view
+//-------------------------------------------------
+
+debug_view *debug_view_manager::alloc_view(debug_view_type type, debug_view_osd_update_func osdupdate, void *osdprivate)
+{
+ switch (type)
+ {
+ case DVT_CONSOLE:
+ return append(auto_alloc(machine(), debug_view_console(machine(), osdupdate, osdprivate)));
+
+ case DVT_STATE:
+ return append(auto_alloc(machine(), debug_view_state(machine(), osdupdate, osdprivate)));
+
+ case DVT_DISASSEMBLY:
+ return append(auto_alloc(machine(), debug_view_disasm(machine(), osdupdate, osdprivate)));
+
+ case DVT_MEMORY:
+ return append(auto_alloc(machine(), debug_view_memory(machine(), osdupdate, osdprivate)));
+
+ case DVT_LOG:
+ return append(auto_alloc(machine(), debug_view_log(machine(), osdupdate, osdprivate)));
+
+ case DVT_TIMERS:
+// return append(auto_alloc(machine(), debug_view_timers(machine(), osdupdate, osdprivate)));
+
+ case DVT_ALLOCS:
+// return append(auto_alloc(machine(), debug_view_allocs(machine(), osdupdate, osdprivate)));
+
+ default:
+ fatalerror("Attempt to create invalid debug view type %d\n", type);
+ }
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// free_view - free a view
+//-------------------------------------------------
+
+void debug_view_manager::free_view(debug_view &view)
+{
+ // free us but only if we're in the list
+ for (debug_view **viewptr = &m_viewlist; *viewptr != NULL; viewptr = &(*viewptr)->m_next)
+ if (*viewptr == &view)
+ {
+ *viewptr = view.m_next;
+ auto_free(machine(), &view);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// update_all - force all views to refresh
+//-------------------------------------------------
+
+void debug_view_manager::update_all(debug_view_type type)
+{
+ // loop over each view and force an update
+ for (debug_view *view = m_viewlist; view != NULL; view = view->next())
+ if (type == DVT_NONE || type == view->type())
+ view->force_update();
+}
+
+
+//-------------------------------------------------
+// flush_osd_updates - flush all pending OSD
+// updates
+//-------------------------------------------------
+
+void debug_view_manager::flush_osd_updates()
+{
+ for (debug_view *view = m_viewlist; view != NULL; view = view->m_next)
+ view->flush_osd_updates();
+}
+
+
+//-------------------------------------------------
+// append - append a view to the end of our list
+//-------------------------------------------------
+
+debug_view *debug_view_manager::append(debug_view *view)
+{
+ debug_view **viewptr;
+ for (viewptr = &m_viewlist; *viewptr != NULL; viewptr = &(*viewptr)->m_next) ;
+ *viewptr = view;
+ return view;
+}
+
+
+
+//**************************************************************************
+// DEBUG VIEW EXPRESSION
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_view_expression - constructor
+//-------------------------------------------------
+
+debug_view_expression::debug_view_expression(running_machine &machine)
+ : m_machine(machine),
+ m_dirty(true),
+ m_result(0),
+ m_parsed(debug_cpu_get_global_symtable(machine)),
+ m_string("0")
+{
+}
+
+
+//-------------------------------------------------
+// ~debug_view_expression - destructor
+//-------------------------------------------------
+
+debug_view_expression::~debug_view_expression()
+{
+}
+
+
+//-------------------------------------------------
+// set_context - set the context for the
+// expression
+//-------------------------------------------------
+
+void debug_view_expression::set_context(symbol_table *context)
+{
+ m_parsed.set_symbols((context != NULL) ? context : debug_cpu_get_global_symtable(machine()));
+ m_dirty = true;
+}
+
+
+//-------------------------------------------------
+// recompute - recompute the value of an
+// expression
+//-------------------------------------------------
+
+bool debug_view_expression::recompute()
+{
+ bool changed = m_dirty;
+
+ // if dirty, re-evaluate
+ if (m_dirty)
+ {
+ astring oldstring(m_parsed.original_string());
+ try
+ {
+ m_parsed.parse(m_string);
+ }
+ catch (expression_error &)
+ {
+ m_parsed.parse(oldstring);
+ }
+ }
+
+ // if we have a parsed expression, evalute it
+ if (!m_parsed.is_empty())
+ {
+ // recompute the value of the expression
+ try
+ {
+ UINT64 newresult = m_parsed.execute();
+ if (newresult != m_result)
+ {
+ m_result = newresult;
+ changed = true;
+ }
+ }
+ catch (expression_error &)
+ {
+ }
+ }
+
+ // expression no longer dirty by definition
+ m_dirty = false;
+ return changed;
+}