summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/sdl
diff options
context:
space:
mode:
author R. Belmont <rb6502@users.noreply.github.com>2012-12-25 03:51:20 +0000
committer R. Belmont <rb6502@users.noreply.github.com>2012-12-25 03:51:20 +0000
commita9116a79739841746e3775260730f3ef09b55937 (patch)
tree1c5d22c4d726c7672fd204378cd919bfbc25a90c /src/osd/sdl
parent39b8e6c652b5b2cd8541c348aeb8459e9d2fdc1b (diff)
SDL: Experimental Qt-based debugger [Andrew Gardner, R. Belmont]
Diffstat (limited to 'src/osd/sdl')
-rw-r--r--src/osd/sdl/debugqt.c119
-rw-r--r--src/osd/sdl/debugqtdasmwindow.c200
-rw-r--r--src/osd/sdl/debugqtdasmwindow.h43
-rw-r--r--src/osd/sdl/debugqtlogwindow.c32
-rw-r--r--src/osd/sdl/debugqtlogwindow.h28
-rw-r--r--src/osd/sdl/debugqtmainwindow.c302
-rw-r--r--src/osd/sdl/debugqtmainwindow.h162
-rw-r--r--src/osd/sdl/debugqtmemorywindow.c217
-rw-r--r--src/osd/sdl/debugqtmemorywindow.h44
-rw-r--r--src/osd/sdl/debugqtview.c201
-rw-r--r--src/osd/sdl/debugqtview.h39
-rw-r--r--src/osd/sdl/debugqtwindow.c194
-rw-r--r--src/osd/sdl/debugqtwindow.h51
-rw-r--r--src/osd/sdl/sdl.mak72
14 files changed, 1703 insertions, 1 deletions
diff --git a/src/osd/sdl/debugqt.c b/src/osd/sdl/debugqt.c
new file mode 100644
index 00000000000..72a210ffef0
--- /dev/null
+++ b/src/osd/sdl/debugqt.c
@@ -0,0 +1,119 @@
+//============================================================
+//
+// debugqt.c - SDL/QT debug window handling
+//
+// Copyright (c) 1996-2010, Nicola Salmoria and the MAME Team.
+// Visit http://mamedev.org for licensing and usage restrictions.
+//
+// SDLMAME by Olivier Galibert and R. Belmont
+//
+//============================================================
+
+#if !defined(NO_DEBUGGER)
+
+#include <QtGui/QtGui>
+#include <QtGui/QApplication>
+
+#include "emu.h"
+#include "osdsdl.h"
+#include "debugger.h"
+
+#include "debugqtmainwindow.h"
+
+
+//============================================================
+// "Global" variables to make QT happy
+//============================================================
+
+int qtArgc = 0;
+char** qtArgv = NULL;
+
+bool oneShot = true;
+MainWindow* mainQtWindow = NULL;
+
+
+//============================================================
+// Core functionality
+//============================================================
+
+void sdl_osd_interface::init_debugger()
+{
+ // QT is a magical thing
+ new QApplication(qtArgc, qtArgv);
+}
+
+
+//============================================================
+// Core functionality
+//============================================================
+
+void sdl_osd_interface::wait_for_debugger(device_t &device, bool firststop)
+{
+ if (oneShot)
+ {
+ mainQtWindow = new MainWindow(&device, &machine());
+ mainQtWindow->show();
+ oneShot = false;
+ }
+
+ // Make sure the main window displays the proper cpu
+ mainQtWindow->setProcessor(&device);
+
+ // Run our own QT event loop
+ while (debug_cpu_is_stopped(machine()))
+ {
+ qApp->processEvents(QEventLoop::AllEvents, 1);
+
+ // Refresh everyone if requested
+ if (mainQtWindow->wantsRefresh())
+ {
+ QWidgetList allWidgets = qApp->allWidgets();
+ for (int i = 0; i < allWidgets.length(); i++)
+ allWidgets[i]->update();
+ mainQtWindow->clearRefreshFlag();
+ }
+
+ // Exit if the machine has been instructed to do so
+ if (machine().exit_pending())
+ {
+ break;
+ }
+ }
+}
+
+
+//============================================================
+// Available for video.*
+//============================================================
+
+void debugwin_update_during_game(running_machine &machine)
+{
+ qApp->processEvents(QEventLoop::AllEvents, 1);
+}
+
+
+
+#else
+
+
+#include "sdlinc.h"
+
+#include "emu.h"
+#include "osdepend.h"
+#include "osdsdl.h"
+
+// win32 stubs for linking
+void sdl_osd_interface::init_debugger()
+{
+}
+
+void sdl_osd_interface::wait_for_debugger(device_t &device, bool firststop)
+{
+}
+
+// win32 stubs for linking
+void debugwin_update_during_game(running_machine &machine)
+{
+}
+
+#endif
diff --git a/src/osd/sdl/debugqtdasmwindow.c b/src/osd/sdl/debugqtdasmwindow.c
new file mode 100644
index 00000000000..54cc79684a8
--- /dev/null
+++ b/src/osd/sdl/debugqtdasmwindow.c
@@ -0,0 +1,200 @@
+#include "debugqtdasmwindow.h"
+
+#include "debug/debugcon.h"
+#include "debug/debugcpu.h"
+#include "debug/dvdisasm.h"
+
+
+DasmWindow::DasmWindow(running_machine* machine, QWidget* parent) :
+ WindowQt(machine, parent)
+{
+ QPoint parentPos = parent->pos();
+ setGeometry(parentPos.x()+100, parentPos.y()+100, 800, 400);
+ setWindowTitle("Debug: Disassembly View");
+
+ //
+ // The main frame and its input and log widgets
+ //
+ QFrame* mainWindowFrame = new QFrame(this);
+
+ // The top frame & groupbox that contains the input widgets
+ QFrame* topSubFrame = new QFrame(mainWindowFrame);
+
+ // The input edit
+ m_inputEdit = new QLineEdit(topSubFrame);
+ connect(m_inputEdit, SIGNAL(returnPressed()), this, SLOT(expressionSubmitted()));
+
+ // The cpu combo box
+ m_cpuComboBox = new QComboBox(topSubFrame);
+ m_cpuComboBox->setMinimumWidth(300);
+ connect(m_cpuComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(cpuChanged(int)));
+
+ // The main disasm window
+ m_dasmView = new DebuggerView(DVT_DISASSEMBLY,
+ m_machine,
+ this);
+
+ // Force a recompute of the disassembly region
+ downcast<debug_view_disasm*>(m_dasmView->view())->set_expression("curpc");
+
+ // Populate the combo box & set the proper cpu
+ populateComboBox();
+ //const debug_view_source *source = mem->views[0]->view->source_list().match_device(curcpu);
+ //gtk_combo_box_set_active(zone_w, mem->views[0]->view->source_list().index(*source));
+ //mem->views[0]->view->set_source(*source);
+
+
+ // Layout
+ QHBoxLayout* subLayout = new QHBoxLayout(topSubFrame);
+ subLayout->addWidget(m_inputEdit);
+ subLayout->addWidget(m_cpuComboBox);
+ subLayout->setSpacing(3);
+ subLayout->setContentsMargins(2,2,2,2);
+
+ QVBoxLayout* vLayout = new QVBoxLayout(mainWindowFrame);
+ vLayout->setSpacing(3);
+ vLayout->setContentsMargins(2,2,2,2);
+ vLayout->addWidget(topSubFrame);
+ vLayout->addWidget(m_dasmView);
+
+ setCentralWidget(mainWindowFrame);
+
+ //
+ // Menu bars
+ //
+ // Create two commands
+ QAction* breakpointSetAct = new QAction("Toggle Breakpoint At Cursor", this);
+ QAction* runToCursorAct = new QAction("Run To Cursor", this);
+ breakpointSetAct->setShortcut(Qt::Key_F9);
+ runToCursorAct->setShortcut(Qt::Key_F4);
+ connect(breakpointSetAct, SIGNAL(triggered(bool)), this, SLOT(toggleBreakpointAtCursor(bool)));
+ connect(runToCursorAct, SIGNAL(triggered(bool)), this, SLOT(runToCursor(bool)));
+
+ // Right bar options
+ QActionGroup* rightBarGroup = new QActionGroup(this);
+ QAction* rightActRaw = new QAction("Raw Opcodes", this);
+ QAction* rightActEncrypted = new QAction("Encrypted Opcodes", this);
+ QAction* rightActComments = new QAction("Comments", this);
+ rightActRaw->setCheckable(true);
+ rightActEncrypted->setCheckable(true);
+ rightActComments->setCheckable(true);
+ rightActRaw->setActionGroup(rightBarGroup);
+ rightActEncrypted->setActionGroup(rightBarGroup);
+ rightActComments->setActionGroup(rightBarGroup);
+ rightActRaw->setShortcut(QKeySequence("Ctrl+R"));
+ rightActEncrypted->setShortcut(QKeySequence("Ctrl+E"));
+ rightActComments->setShortcut(QKeySequence("Ctrl+C"));
+ rightActRaw->setChecked(true);
+ connect(rightBarGroup, SIGNAL(triggered(QAction*)), this, SLOT(rightBarChanged(QAction*)));
+
+ // Assemble the options menu
+ QMenu* optionsMenu = menuBar()->addMenu("&Options");
+ optionsMenu->addAction(breakpointSetAct);
+ optionsMenu->addAction(runToCursorAct);
+ optionsMenu->addSeparator();
+ optionsMenu->addActions(rightBarGroup->actions());
+}
+
+
+void DasmWindow::cpuChanged(int index)
+{
+ m_dasmView->view()->set_source(*m_dasmView->view()->source_list().by_index(index));
+ m_dasmView->viewport()->update();
+}
+
+
+void DasmWindow::expressionSubmitted()
+{
+ const QString expression = m_inputEdit->text();
+ downcast<debug_view_disasm*>(m_dasmView->view())->set_expression(expression.toLocal8Bit().data());
+ m_dasmView->viewport()->update();
+}
+
+
+void DasmWindow::toggleBreakpointAtCursor(bool changedTo)
+{
+ if (m_dasmView->view()->cursor_visible())
+ {
+ if (debug_cpu_get_visible_cpu(*m_machine) == m_dasmView->view()->source()->device())
+ {
+ offs_t address = downcast<debug_view_disasm *>(m_dasmView->view())->selected_address();
+ device_debug *cpuinfo = m_dasmView->view()->source()->device()->debug();
+
+ // Find an existing breakpoint at this address
+ INT32 bpindex = -1;
+ for (device_debug::breakpoint* bp = cpuinfo->breakpoint_first();
+ bp != NULL;
+ bp = bp->next())
+ {
+ if (address == bp->address())
+ {
+ bpindex = bp->index();
+ break;
+ }
+ }
+
+ // If none exists, add a new one
+ astring command;
+ if (bpindex == -1)
+ {
+ command.printf("bpset 0x%X", address);
+ }
+ else
+ {
+ command.printf("bpclear 0x%X", bpindex);
+ }
+ debug_console_execute_command(*m_machine, command, 1);
+ }
+ }
+
+ refreshAll();
+}
+
+
+void DasmWindow::runToCursor(bool changedTo)
+{
+ if (m_dasmView->view()->cursor_visible())
+ {
+ if (debug_cpu_get_visible_cpu(*m_machine) == m_dasmView->view()->source()->device())
+ {
+ offs_t address = downcast<debug_view_disasm*>(m_dasmView->view())->selected_address();
+ astring command;
+ command.printf("go 0x%X", address);
+ debug_console_execute_command(*m_machine, command, 1);
+ }
+ }
+}
+
+
+void DasmWindow::rightBarChanged(QAction* changedTo)
+{
+ debug_view_disasm* dasmView = downcast<debug_view_disasm*>(m_dasmView->view());
+ if (changedTo->text() == "Raw Opcodes")
+ {
+ dasmView->set_right_column(DASM_RIGHTCOL_RAW);
+ }
+ else if (changedTo->text() == "Encrypted Opcodes")
+ {
+ dasmView->set_right_column(DASM_RIGHTCOL_ENCRYPTED);
+ }
+ else if (changedTo->text() == "Comments")
+ {
+ dasmView->set_right_column(DASM_RIGHTCOL_COMMENTS);
+ }
+ m_dasmView->viewport()->update();
+}
+
+
+void DasmWindow::populateComboBox()
+{
+ if (m_dasmView == NULL)
+ return;
+
+ m_cpuComboBox->clear();
+ for (const debug_view_source* source = m_dasmView->view()->source_list().head();
+ source != NULL;
+ source = source->next())
+ {
+ m_cpuComboBox->addItem(source->name());
+ }
+}
diff --git a/src/osd/sdl/debugqtdasmwindow.h b/src/osd/sdl/debugqtdasmwindow.h
new file mode 100644
index 00000000000..fec80c44098
--- /dev/null
+++ b/src/osd/sdl/debugqtdasmwindow.h
@@ -0,0 +1,43 @@
+#ifndef __DEBUG_QT_DASM_WINDOW_H__
+#define __DEBUG_QT_DASM_WINDOW_H__
+
+#include <QtGui/QtGui>
+
+#include "debugqtview.h"
+#include "debugqtwindow.h"
+
+
+//============================================================
+// The Disassembly Window.
+//============================================================
+class DasmWindow : public WindowQt
+{
+ Q_OBJECT
+
+public:
+ DasmWindow(running_machine* machine, QWidget* parent=NULL);
+ virtual ~DasmWindow() {}
+
+
+private slots:
+ void cpuChanged(int index);
+ void expressionSubmitted();
+
+ void toggleBreakpointAtCursor(bool changedTo);
+ void runToCursor(bool changedTo);
+ void rightBarChanged(QAction* changedTo);
+
+
+private:
+ void populateComboBox();
+
+
+private:
+ // Widgets
+ QLineEdit* m_inputEdit;
+ QComboBox* m_cpuComboBox;
+ DebuggerView* m_dasmView;
+};
+
+
+#endif
diff --git a/src/osd/sdl/debugqtlogwindow.c b/src/osd/sdl/debugqtlogwindow.c
new file mode 100644
index 00000000000..20cb0f81bd2
--- /dev/null
+++ b/src/osd/sdl/debugqtlogwindow.c
@@ -0,0 +1,32 @@
+#include "debugqtlogwindow.h"
+
+#include "debug/debugcon.h"
+#include "debug/debugcpu.h"
+#include "debug/dvdisasm.h"
+
+
+LogWindow::LogWindow(running_machine* machine, QWidget* parent) :
+ WindowQt(machine, parent)
+{
+ QPoint parentPos = parent->pos();
+ setGeometry(parentPos.x()+100, parentPos.y()+100, 800, 400);
+ setWindowTitle("Debug: Machine Log");
+
+ //
+ // The main frame and its input and log widgets
+ //
+ QFrame* mainWindowFrame = new QFrame(this);
+
+ // The main log view
+ m_logView = new DebuggerView(DVT_LOG,
+ m_machine,
+ this);
+
+ // Layout
+ QVBoxLayout* vLayout = new QVBoxLayout(mainWindowFrame);
+ vLayout->setSpacing(3);
+ vLayout->setContentsMargins(2,2,2,2);
+ vLayout->addWidget(m_logView);
+
+ setCentralWidget(mainWindowFrame);
+}
diff --git a/src/osd/sdl/debugqtlogwindow.h b/src/osd/sdl/debugqtlogwindow.h
new file mode 100644
index 00000000000..474aab79050
--- /dev/null
+++ b/src/osd/sdl/debugqtlogwindow.h
@@ -0,0 +1,28 @@
+#ifndef __DEBUG_QT_LOG_WINDOW_H__
+#define __DEBUG_QT_LOG_WINDOW_H__
+
+#include <QtGui/QtGui>
+
+#include "debugqtview.h"
+#include "debugqtwindow.h"
+
+
+//============================================================
+// The Log Window.
+//============================================================
+class LogWindow : public WindowQt
+{
+ Q_OBJECT
+
+public:
+ LogWindow(running_machine* machine, QWidget* parent=NULL);
+ virtual ~LogWindow() {}
+
+
+private:
+ // Widgets
+ DebuggerView* m_logView;
+};
+
+
+#endif
diff --git a/src/osd/sdl/debugqtmainwindow.c b/src/osd/sdl/debugqtmainwindow.c
new file mode 100644
index 00000000000..0ec0e16b5f6
--- /dev/null
+++ b/src/osd/sdl/debugqtmainwindow.c
@@ -0,0 +1,302 @@
+#include "debugqtmainwindow.h"
+#include "debug/debugcon.h"
+#include "debug/debugcpu.h"
+#include "debug/dvdisasm.h"
+
+
+MainWindow::MainWindow(device_t* processor,
+ running_machine* machine,
+ QWidget* parent) :
+ WindowQt(machine, parent),
+ m_historyIndex(0),
+ m_inputHistory()
+{
+ setGeometry(300, 300, 1000, 600);
+
+ //
+ // The main frame and its input and log widgets
+ //
+ QFrame* mainWindowFrame = new QFrame(this);
+
+ // The input line
+ m_inputEdit = new QLineEdit(mainWindowFrame);
+ connect(m_inputEdit, SIGNAL(returnPressed()), this, SLOT(executeCommand()));
+ m_inputEdit->installEventFilter(this);
+
+
+ // The log view
+ m_consoleView = new DebuggerView(DVT_CONSOLE,
+ m_machine,
+ mainWindowFrame);
+ m_consoleView->setFocusPolicy(Qt::NoFocus);
+ m_consoleView->setPreferBottom(true);
+
+ QVBoxLayout* vLayout = new QVBoxLayout(mainWindowFrame);
+ vLayout->addWidget(m_consoleView);
+ vLayout->addWidget(m_inputEdit);
+ vLayout->setSpacing(3);
+ vLayout->setContentsMargins(4,0,4,2);
+
+ setCentralWidget(mainWindowFrame);
+
+ //
+ // Menu bars
+ //
+ // Create two commands
+ QAction* breakpointSetAct = new QAction("Toggle Breakpoint At Cursor", this);
+ QAction* runToCursorAct = new QAction("Run To Cursor", this);
+ breakpointSetAct->setShortcut(Qt::Key_F9);
+ runToCursorAct->setShortcut(Qt::Key_F4);
+ connect(breakpointSetAct, SIGNAL(triggered(bool)), this, SLOT(toggleBreakpointAtCursor(bool)));
+ connect(runToCursorAct, SIGNAL(triggered(bool)), this, SLOT(runToCursor(bool)));
+
+ // Right bar options
+ QActionGroup* rightBarGroup = new QActionGroup(this);
+ QAction* rightActRaw = new QAction("Raw Opcodes", this);
+ QAction* rightActEncrypted = new QAction("Encrypted Opcodes", this);
+ QAction* rightActComments = new QAction("Comments", this);
+ rightActRaw->setCheckable(true);
+ rightActEncrypted->setCheckable(true);
+ rightActComments->setCheckable(true);
+ rightActRaw->setActionGroup(rightBarGroup);
+ rightActEncrypted->setActionGroup(rightBarGroup);
+ rightActComments->setActionGroup(rightBarGroup);
+ rightActRaw->setShortcut(QKeySequence("Ctrl+R"));
+ rightActEncrypted->setShortcut(QKeySequence("Ctrl+E"));
+ rightActComments->setShortcut(QKeySequence("Ctrl+C"));
+ rightActRaw->setChecked(true);
+ connect(rightBarGroup, SIGNAL(triggered(QAction*)), this, SLOT(rightBarChanged(QAction*)));
+
+ // Assemble the options menu
+ QMenu* optionsMenu = menuBar()->addMenu("&Options");
+ optionsMenu->addAction(breakpointSetAct);
+ optionsMenu->addAction(runToCursorAct);
+ optionsMenu->addSeparator();
+ optionsMenu->addActions(rightBarGroup->actions());
+
+
+ //
+ // Dock windows
+ //
+ QMenu* dockMenu = menuBar()->addMenu("Doc&ks");
+
+ setCorner(Qt::TopRightCorner, Qt::TopDockWidgetArea);
+ setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
+
+ // The processor dock
+ QDockWidget* cpuDock = new QDockWidget("processor", this);
+ cpuDock->setAllowedAreas(Qt::LeftDockWidgetArea);
+ m_procFrame = new ProcessorDockWidget(m_machine, cpuDock);
+ cpuDock->setWidget(dynamic_cast<QWidget*>(m_procFrame));
+
+ addDockWidget(Qt::LeftDockWidgetArea, cpuDock);
+ dockMenu->addAction(cpuDock->toggleViewAction());
+
+ // The disassembly dock
+ QDockWidget* dasmDock = new QDockWidget("dasm", this);
+ dasmDock->setAllowedAreas(Qt::TopDockWidgetArea);
+ m_dasmFrame = new DasmDockWidget(m_machine, dasmDock);
+ dasmDock->setWidget(m_dasmFrame);
+
+ addDockWidget(Qt::TopDockWidgetArea, dasmDock);
+ dockMenu->addAction(dasmDock->toggleViewAction());
+
+ // Window title
+ astring title;
+ title.printf("Debug: %s - %s '%s'", m_machine->system().name, processor->name(), processor->tag());
+ setWindowTitle(title.cstr());
+}
+
+
+void MainWindow::setProcessor(device_t* processor)
+{
+ // Cpu swap
+ m_procFrame->view()->view()->set_source(*m_procFrame->view()->view()->source_list().match_device(processor));
+ m_dasmFrame->view()->view()->set_source(*m_dasmFrame->view()->view()->source_list().match_device(processor));
+
+ // Scrollbar refresh - seems I should be able to do in the DebuggerView
+ m_dasmFrame->view()->verticalScrollBar()->setValue(m_dasmFrame->view()->view()->visible_position().y);
+ m_dasmFrame->view()->verticalScrollBar()->setValue(m_dasmFrame->view()->view()->visible_position().y);
+
+ // Window title
+ astring title;
+ title.printf("Debug: %s - %s '%s'", m_machine->system().name, processor->name(), processor->tag());
+ setWindowTitle(title.cstr());
+}
+
+
+// Used to intercept the user clicking 'X' in the upper corner
+void MainWindow::closeEvent(QCloseEvent* event)
+{
+ debugActQuit();
+}
+
+
+// Used to intercept the user hitting the up arrow in the input widget
+bool MainWindow::eventFilter(QObject* obj, QEvent* event)
+{
+ // Only filter keypresses
+ QKeyEvent* keyEvent = NULL;
+ if (event->type() == QEvent::KeyPress)
+ {
+ keyEvent = static_cast<QKeyEvent*>(event);
+ }
+ else
+ {
+ return QObject::eventFilter(obj, event);
+ }
+
+ // Catch up & down keys
+ if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down)
+ {
+ if (keyEvent->key() == Qt::Key_Up)
+ {
+ if (m_historyIndex > 0)
+ m_historyIndex--;
+ }
+ else if (keyEvent->key() == Qt::Key_Down)
+ {
+ if (m_historyIndex < m_inputHistory.size())
+ m_historyIndex++;
+ }
+
+ // Populate the input edit or clear it if you're at the end
+ if (m_historyIndex == m_inputHistory.size())
+ {
+ m_inputEdit->setText("");
+ }
+ else
+ {
+ m_inputEdit->setText(m_inputHistory[m_historyIndex]);
+ }
+ }
+ else if (keyEvent->key() == Qt::Key_Enter)
+ {
+ executeCommand(false);
+ }
+ else
+ {
+ return QObject::eventFilter(obj, event);
+ }
+
+ return true;
+}
+
+
+void MainWindow::toggleBreakpointAtCursor(bool changedTo)
+{
+ debug_view_disasm* dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view());
+ if (dasmView->cursor_visible())
+ {
+ if (debug_cpu_get_visible_cpu(*m_machine) == dasmView->source()->device())
+ {
+ offs_t address = downcast<debug_view_disasm *>(dasmView)->selected_address();
+ device_debug *cpuinfo = dasmView->source()->device()->debug();
+
+ // Find an existing breakpoint at this address
+ INT32 bpindex = -1;
+ for (device_debug::breakpoint* bp = cpuinfo->breakpoint_first();
+ bp != NULL;
+ bp = bp->next())
+ {
+ if (address == bp->address())
+ {
+ bpindex = bp->index();
+ break;
+ }
+ }
+
+ // If none exists, add a new one
+ astring command;
+ if (bpindex == -1)
+ {
+ command.printf("bpset 0x%X", address);
+ }
+ else
+ {
+ command.printf("bpclear 0x%X", bpindex);
+ }
+ debug_console_execute_command(*m_machine, command, 1);
+ }
+ }
+
+ refreshAll();
+}
+
+
+void MainWindow::runToCursor(bool changedTo)
+{
+ debug_view_disasm* dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view());
+ if (dasmView->cursor_visible())
+ {
+ if (debug_cpu_get_visible_cpu(*m_machine) == dasmView->source()->device())
+ {
+ offs_t address = downcast<debug_view_disasm*>(dasmView)->selected_address();
+ astring command;
+ command.printf("go 0x%X", address);
+ debug_console_execute_command(*m_machine, command, 1);
+ }
+ }
+}
+
+
+void MainWindow::rightBarChanged(QAction* changedTo)
+{
+ debug_view_disasm* dasmView = downcast<debug_view_disasm*>(m_dasmFrame->view()->view());
+ if (changedTo->text() == "Raw Opcodes")
+ {
+ dasmView->set_right_column(DASM_RIGHTCOL_RAW);
+ }
+ else if (changedTo->text() == "Encrypted Opcodes")
+ {
+ dasmView->set_right_column(DASM_RIGHTCOL_ENCRYPTED);
+ }
+ else if (changedTo->text() == "Comments")
+ {
+ dasmView->set_right_column(DASM_RIGHTCOL_COMMENTS);
+ }
+ m_dasmFrame->view()->viewport()->update();
+}
+
+
+void MainWindow::executeCommand(bool withClear)
+{
+ debug_console_execute_command(*m_machine,
+ m_inputEdit->text().toLocal8Bit().data(),
+ true);
+
+ // Add history & set the index to be the top of the stack
+ addToHistory(m_inputEdit->text());
+
+ // Clear out the text and reset the history pointer only if asked
+ if (withClear)
+ {
+ m_inputEdit->clear();
+ m_historyIndex = m_inputHistory.size();
+ }
+
+ // Refresh
+ m_consoleView->viewport()->update();
+ m_procFrame->view()->update();
+ m_dasmFrame->view()->update();
+}
+
+
+void MainWindow::addToHistory(const QString& command)
+{
+ if (command == "")
+ return;
+
+ // Always push back when there is no previous history
+ if (m_inputHistory.size() == 0)
+ {
+ m_inputHistory.push_back(m_inputEdit->text());
+ return;
+ }
+
+ // If there is previous history, make sure it's not what you just executed
+ if (m_inputHistory.back() != m_inputEdit->text())
+ {
+ m_inputHistory.push_back(m_inputEdit->text());
+ }
+}
diff --git a/src/osd/sdl/debugqtmainwindow.h b/src/osd/sdl/debugqtmainwindow.h
new file mode 100644
index 00000000000..683b8c6a4b1
--- /dev/null
+++ b/src/osd/sdl/debugqtmainwindow.h
@@ -0,0 +1,162 @@
+#ifndef __DEBUG_QT_MAIN_WINDOW_H__
+#define __DEBUG_QT_MAIN_WINDOW_H__
+
+#include <QtGui/QtGui>
+#include <vector>
+
+#include "debug/dvdisasm.h"
+
+#include "debugqtview.h"
+#include "debugqtwindow.h"
+
+class DasmDockWidget;
+class ProcessorDockWidget;
+
+
+//============================================================
+// The Main Window. Contains processor and dasm docks.
+//============================================================
+class MainWindow : public WindowQt
+{
+ Q_OBJECT
+
+public:
+ MainWindow(device_t* processor,
+ running_machine* machine,
+ QWidget* parent=NULL);
+ virtual ~MainWindow() {}
+
+ void setProcessor(device_t* processor);
+
+
+protected:
+ // Used to intercept the user clicking 'X' in the upper corner
+ void closeEvent(QCloseEvent* event);
+
+ // Used to intercept the user hitting the up arrow in the input widget
+ bool eventFilter(QObject* obj, QEvent* event);
+
+
+private slots:
+ void toggleBreakpointAtCursor(bool changedTo);
+ void runToCursor(bool changedTo);
+ void rightBarChanged(QAction* changedTo);
+
+ void executeCommand(bool withClear=true);
+
+
+private:
+ // Widgets and docks
+ QLineEdit* m_inputEdit;
+ DebuggerView* m_consoleView;
+ ProcessorDockWidget* m_procFrame;
+ DasmDockWidget* m_dasmFrame;
+
+ // Terminal history
+ int m_historyIndex;
+ std::vector<QString> m_inputHistory;
+ void addToHistory(const QString& command);
+};
+
+
+//============================================================
+// Docks with the Main Window. Disassembly.
+//============================================================
+class DasmDockWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DasmDockWidget(running_machine* machine, QWidget* parent=NULL) :
+ QWidget(parent),
+ m_machine(machine)
+ {
+ m_dasmView = new DebuggerView(DVT_DISASSEMBLY,
+ m_machine,
+ this);
+
+ // Force a recompute of the disassembly region
+ downcast<debug_view_disasm*>(m_dasmView->view())->set_expression("curpc");
+
+ QVBoxLayout* dvLayout = new QVBoxLayout(this);
+ dvLayout->addWidget(m_dasmView);
+ dvLayout->setContentsMargins(4,0,4,0);
+ }
+
+
+ virtual ~DasmDockWidget() {}
+
+
+ DebuggerView* view() { return m_dasmView; }
+
+
+ QSize minimumSizeHint() const
+ {
+ return QSize(150,150);
+ }
+
+
+ QSize sizeHint() const
+ {
+ return QSize(150,200);
+ }
+
+
+private:
+ DebuggerView* m_dasmView;
+
+ running_machine* m_machine;
+};
+
+
+//============================================================
+// Docks with the Main Window. Processor information.
+//============================================================
+class ProcessorDockWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ProcessorDockWidget(running_machine* machine,
+ QWidget* parent=NULL) :
+ QWidget(parent),
+ m_processorView(NULL),
+ m_machine(machine)
+ {
+ m_processorView = new DebuggerView(DVT_STATE,
+ m_machine,
+ this);
+ m_processorView->setFocusPolicy(Qt::NoFocus);
+
+ QVBoxLayout* cvLayout = new QVBoxLayout(this);
+ cvLayout->addWidget(m_processorView);
+ cvLayout->setContentsMargins(4,0,4,2);
+ }
+
+
+ virtual ~ProcessorDockWidget() {}
+
+
+ DebuggerView* view() { return m_processorView; }
+
+
+ QSize minimumSizeHint() const
+ {
+ return QSize(150,300);
+ }
+
+
+ QSize sizeHint() const
+ {
+ return QSize(200,300);
+ }
+
+
+private:
+ DebuggerView* m_processorView;
+
+ running_machine* m_machine;
+};
+
+
+#endif
diff --git a/src/osd/sdl/debugqtmemorywindow.c b/src/osd/sdl/debugqtmemorywindow.c
new file mode 100644
index 00000000000..718a0a5b3e7
--- /dev/null
+++ b/src/osd/sdl/debugqtmemorywindow.c
@@ -0,0 +1,217 @@
+#include "debugqtmemorywindow.h"
+
+#include "debug/dvmemory.h"
+#include "debug/debugvw.h"
+#include "debug/debugcon.h"
+#include "debug/debugcpu.h"
+
+
+MemoryWindow::MemoryWindow(running_machine* machine, QWidget* parent) :
+ WindowQt(machine, parent)
+{
+ QPoint parentPos = parent->pos();
+ setGeometry(parentPos.x()+100, parentPos.y()+100, 800, 400);
+ setWindowTitle("Debug: Memory View");
+
+ //
+ // The main frame and its input and log widgets
+ //
+ QFrame* mainWindowFrame = new QFrame(this);
+
+ // The top frame & groupbox that contains the input widgets
+ QFrame* topSubFrame = new QFrame(mainWindowFrame);
+
+ // The input edit
+ m_inputEdit = new QLineEdit(topSubFrame);
+ connect(m_inputEdit, SIGNAL(returnPressed()), this, SLOT(expressionSubmitted()));
+
+ // The memory space combo box
+ m_memoryComboBox = new QComboBox(topSubFrame);
+ m_memoryComboBox->setMinimumWidth(300);
+ connect(m_memoryComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(memoryRegionChanged(int)));
+
+ // The main memory window
+ m_memTable = new DebuggerView(DVT_MEMORY,
+ m_machine,
+ this);
+
+ // Populate the combo box
+ populateComboBox();
+
+
+ // Layout
+ QHBoxLayout* subLayout = new QHBoxLayout(topSubFrame);
+ subLayout->addWidget(m_inputEdit);
+ subLayout->addWidget(m_memoryComboBox);
+ subLayout->setSpacing(3);
+ subLayout->setContentsMargins(2,2,2,2);
+
+ QVBoxLayout* vLayout = new QVBoxLayout(mainWindowFrame);
+ vLayout->setSpacing(3);
+ vLayout->setContentsMargins(2,2,2,2);
+ vLayout->addWidget(topSubFrame);
+ vLayout->addWidget(m_memTable);
+
+ setCentralWidget(mainWindowFrame);
+
+ //
+ // Menu bars
+ //
+ // Create a byte-chunk group
+ QActionGroup* chunkGroup = new QActionGroup(this);
+ QAction* chunkActOne = new QAction("1-byte chunks", this);
+ QAction* chunkActTwo = new QAction("2-byte chunks", this);
+ QAction* chunkActFour = new QAction("4-byte chunks", this);
+ chunkActOne->setCheckable(true);
+ chunkActTwo->setCheckable(true);
+ chunkActFour->setCheckable(true);
+ chunkActOne->setActionGroup(chunkGroup);
+ chunkActTwo->setActionGroup(chunkGroup);
+ chunkActFour->setActionGroup(chunkGroup);
+ chunkActOne->setShortcut(QKeySequence("Ctrl+1"));
+ chunkActTwo->setShortcut(QKeySequence("Ctrl+2"));
+ chunkActFour->setShortcut(QKeySequence("Ctrl+4"));
+ chunkActOne->setChecked(true);
+ connect(chunkGroup, SIGNAL(triggered(QAction*)), this, SLOT(chunkChanged(QAction*)));
+
+ // Create a address display group
+ QActionGroup* addressGroup = new QActionGroup(this);
+ QAction* addressActLogical = new QAction("Logical Addresses", this);
+ QAction* addressActPhysical = new QAction("Physical Addresses", this);
+ addressActLogical->setCheckable(true);
+ addressActPhysical->setCheckable(true);
+ addressActLogical->setActionGroup(addressGroup);
+ addressActPhysical->setActionGroup(addressGroup);
+ addressActLogical->setShortcut(QKeySequence("Ctrl+G"));
+ addressActPhysical->setShortcut(QKeySequence("Ctrl+Y"));
+ addressActLogical->setChecked(true);
+ connect(addressGroup, SIGNAL(triggered(QAction*)), this, SLOT(addressChanged(QAction*)));
+
+ // Create a reverse view radio
+ QAction* reverseAct = new QAction("Reverse View", this);
+ reverseAct->setCheckable(true);
+ reverseAct->setShortcut(QKeySequence("Ctrl+R"));
+ connect(reverseAct, SIGNAL(toggled(bool)), this, SLOT(reverseChanged(bool)));
+
+ // Create increase and decrease bytes-per-line actions
+ QAction* increaseBplAct = new QAction("Increase Bytes Per Line", this);
+ QAction* decreaseBplAct = new QAction("Decrease Bytes Per Line", this);
+ increaseBplAct->setShortcut(QKeySequence("Ctrl+P"));
+ decreaseBplAct->setShortcut(QKeySequence("Ctrl+O"));
+ connect(increaseBplAct, SIGNAL(triggered(bool)), this, SLOT(increaseBytesPerLine(bool)));
+ connect(decreaseBplAct, SIGNAL(triggered(bool)), this, SLOT(decreaseBytesPerLine(bool)));
+
+ // Assemble the options menu
+ QMenu* optionsMenu = menuBar()->addMenu("&Options");
+ optionsMenu->addActions(chunkGroup->actions());
+ optionsMenu->addSeparator();
+ optionsMenu->addActions(addressGroup->actions());
+ optionsMenu->addSeparator();
+ optionsMenu->addAction(reverseAct);
+ optionsMenu->addSeparator();
+ optionsMenu->addAction(increaseBplAct);
+ optionsMenu->addAction(decreaseBplAct);
+}
+
+
+void MemoryWindow::memoryRegionChanged(int index)
+{
+ m_memTable->view()->set_source(*m_memTable->view()->source_list().by_index(index));
+ m_memTable->viewport()->update();
+}
+
+
+void MemoryWindow::expressionSubmitted()
+{
+ const QString expression = m_inputEdit->text();
+ downcast<debug_view_memory*>(m_memTable->view())->set_expression(expression.toLocal8Bit().data());
+
+ // Make the cursor pop
+ m_memTable->view()->set_cursor_visible(true);
+
+ // Check where the cursor is and adjust the scroll accordingly
+ debug_view_xy cursorPosition = m_memTable->view()->cursor_position();
+ // TODO: check if the region is already visible?
+ m_memTable->verticalScrollBar()->setValue(cursorPosition.y);
+
+ m_memTable->update();
+ m_memTable->viewport()->update();
+}
+
+
+void MemoryWindow::chunkChanged(QAction* changedTo)
+{
+ debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view());
+ if (changedTo->text() == "1-byte chunks")
+ {
+ memView->set_bytes_per_chunk(1);
+ }
+ else if (changedTo->text() == "2-byte chunks")
+ {
+ memView->set_bytes_per_chunk(2);
+ }
+ else if (changedTo->text() == "4-byte chunks")
+ {
+ memView->set_bytes_per_chunk(4);
+ }
+ m_memTable->viewport()->update();
+}
+
+
+void MemoryWindow::addressChanged(QAction* changedTo)
+{
+ debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view());
+ if (changedTo->text() == "Logical Addresses")
+ {
+ memView->set_physical(false);
+ }
+ else if (changedTo->text() == "Physical Addresses")
+ {
+ memView->set_physical(true);
+ }
+ m_memTable->viewport()->update();
+}
+
+
+void MemoryWindow::reverseChanged(bool changedTo)
+{
+ debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view());
+ memView->set_reverse(changedTo);
+ m_memTable->viewport()->update();
+}
+
+
+void MemoryWindow::increaseBytesPerLine(bool changedTo)
+{
+ debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view());
+ memView->set_chunks_per_row(memView->chunks_per_row() + 1);
+ m_memTable->viewport()->update();
+}
+
+
+void MemoryWindow::decreaseBytesPerLine(bool checked)
+{
+ debug_view_memory* memView = downcast<debug_view_memory*>(m_memTable->view());
+ memView->set_chunks_per_row(memView->chunks_per_row() - 1);
+ m_memTable->viewport()->update();
+}
+
+
+void MemoryWindow::populateComboBox()
+{
+ if (m_memTable == NULL)
+ return;
+
+ m_memoryComboBox->clear();
+ for (const debug_view_source* source = m_memTable->view()->source_list().head();
+ source != NULL;
+ source = source->next())
+ {
+ m_memoryComboBox->addItem(source->name());
+ }
+
+ // TODO: Set to the proper memory view
+ //const debug_view_source *source = mem->views[0]->view->source_list().match_device(curcpu);
+ //gtk_combo_box_set_active(zone_w, mem->views[0]->view->source_list().index(*source));
+ //mem->views[0]->view->set_source(*source);
+}
diff --git a/src/osd/sdl/debugqtmemorywindow.h b/src/osd/sdl/debugqtmemorywindow.h
new file mode 100644
index 00000000000..d08ca0ff394
--- /dev/null
+++ b/src/osd/sdl/debugqtmemorywindow.h
@@ -0,0 +1,44 @@
+#ifndef __DEBUG_QT_MEMORY_WINDOW_H__
+#define __DEBUG_QT_MEMORY_WINDOW_H__
+
+#include <QtGui/QtGui>
+
+#include "debugqtview.h"
+#include "debugqtwindow.h"
+
+
+//============================================================
+// The Memory Window.
+//============================================================
+class MemoryWindow : public WindowQt
+{
+ Q_OBJECT
+
+public:
+ MemoryWindow(running_machine* machine, QWidget* parent=NULL);
+ virtual ~MemoryWindow() {}
+
+
+private slots:
+ void memoryRegionChanged(int index);
+ void expressionSubmitted();
+ void chunkChanged(QAction* changedTo);
+ void addressChanged(QAction* changedTo);
+ void reverseChanged(bool changedTo);
+ void increaseBytesPerLine(bool changedTo);
+ void decreaseBytesPerLine(bool checked=false);
+
+
+private:
+ void populateComboBox();
+
+
+private:
+ // Widgets
+ QLineEdit* m_inputEdit;
+ QComboBox* m_memoryComboBox;
+ DebuggerView* m_memTable;
+};
+
+
+#endif
diff --git a/src/osd/sdl/debugqtview.c b/src/osd/sdl/debugqtview.c
new file mode 100644
index 00000000000..c86272099bd
--- /dev/null
+++ b/src/osd/sdl/debugqtview.c
@@ -0,0 +1,201 @@
+#include <QtGui/QtGui>
+
+#include "debugqtview.h"
+
+
+DebuggerView::DebuggerView(const debug_view_type& type,
+ running_machine* machine,
+ QWidget* parent) :
+ QAbstractScrollArea(parent),
+ m_preferBottom(false),
+ m_view(NULL),
+ m_machine(machine)
+{
+ QFont viewFontRequest("Courier");
+ viewFontRequest.setFixedPitch(true);
+ viewFontRequest.setPointSize(12);
+ setFont(viewFontRequest);
+
+ m_view = m_machine->debug_view().alloc_view(type,
+ DebuggerView::debuggerViewUpdate,
+ this);
+}
+
+
+void DebuggerView::paintEvent(QPaintEvent* event)
+{
+ // Tell the MAME debug view how much real estate is available
+ QFontMetrics actualFont = fontMetrics();
+ const int fontWidth = actualFont.maxWidth();
+ const int fontHeight = actualFont.height();
+ m_view->set_visible_size(debug_view_xy(width()/fontWidth, height()/fontHeight));
+
+
+ // Handle the scroll bars
+ const int verticalScrollCharDiff = m_view->total_size().y - m_view->visible_size().y;
+ const int scrollSize = verticalScrollCharDiff < 0 ? 0 : verticalScrollCharDiff;
+ bool atEnd = false;
+ if (verticalScrollBar()->value() == verticalScrollBar()->maximum())
+ {
+ atEnd = true;
+ }
+ verticalScrollBar()->setRange(0, scrollSize);
+ if (m_preferBottom && atEnd)
+ {
+ verticalScrollBar()->setValue(scrollSize);
+ }
+ m_view->set_visible_position(debug_view_xy(0, verticalScrollBar()->value()));
+
+
+ // Draw the viewport widget
+ QPainter painter(viewport());
+ painter.fillRect(0, 0, width(), height(), QBrush(Qt::white));
+ painter.setBackgroundMode(Qt::OpaqueMode);
+ painter.setBackground(QColor(255,255,255));
+
+ // Background control
+ QBrush bgBrush;
+ bgBrush.setStyle(Qt::SolidPattern);
+ painter.setPen(QPen(QColor(0,0,0)));
+
+ size_t viewDataOffset = 0;
+ const debug_view_xy& visibleCharDims = m_view->visible_size();
+ for (int y = 0; y < visibleCharDims.y; y++)
+ {
+ for (int x = 0; x < visibleCharDims.x; x++)
+ {
+ const unsigned char textAttr = m_view->viewdata()[viewDataOffset].attrib;
+
+ if (x == 0 || textAttr != m_view->viewdata()[viewDataOffset-1].attrib)
+ {
+ // Text color handling
+ QColor fgColor(0,0,0);
+ QColor bgColor(255,255,255);
+
+ if(textAttr & DCA_ANCILLARY)
+ {
+ bgColor.setRgb(0xe0, 0xe0, 0xe0);
+ }
+ if(textAttr & DCA_SELECTED)
+ {
+ bgColor.setRgb(0xff, 0x80, 0x80);
+ }
+ if(textAttr & DCA_CURRENT)
+ {
+ bgColor.setRgb(0xff, 0xff, 0x00);
+ }
+ if(textAttr & DCA_CHANGED)
+ {
+ fgColor.setRgb(0xff, 0x00, 0x00);
+ }
+ if(textAttr & DCA_INVALID)
+ {
+ fgColor.setRgb(0x00, 0x00, 0xff);
+ }
+ if(textAttr & DCA_DISABLED)
+ {
+ fgColor.setRgb((fgColor.red() + bgColor.red()) >> 1,
+ (fgColor.green() + bgColor.green()) >> 1,
+ (fgColor.blue() + bgColor.blue()) >> 1);
+ }
+ if(textAttr & DCA_COMMENT)
+ {
+ fgColor.setRgb(0x00, 0x80, 0x00);
+ }
+
+ bgBrush.setColor(bgColor);
+ painter.setBackground(bgBrush);
+ painter.setPen(QPen(fgColor));
+ }
+
+ // There is a touchy interplay between font height, drawing difference, visible position, etc
+ // To test, set the bgcolor to something crazy and see where stuff gets drawn
+ painter.drawText(x*fontWidth,
+ y*fontHeight + fontHeight,
+ QString(m_view->viewdata()[viewDataOffset].byte));
+ viewDataOffset++;
+ }
+ }
+}
+
+
+void DebuggerView::keyPressEvent(QKeyEvent* event)
+{
+ if (m_view == NULL)
+ return QWidget::keyPressEvent(event);
+
+ Qt::KeyboardModifiers keyMods = QApplication::keyboardModifiers();
+ bool ctrlDown = keyMods.testFlag(Qt::ControlModifier);
+
+ int keyPress = -1;
+ switch (event->key())
+ {
+ case Qt::Key_Up:
+ keyPress = DCH_UP;
+ break;
+ case Qt::Key_Down:
+ keyPress = DCH_DOWN;
+ break;
+ case Qt::Key_Left:
+ keyPress = DCH_LEFT;
+ if (ctrlDown) keyPress = DCH_CTRLLEFT;
+ break;
+ case Qt::Key_Right:
+ keyPress = DCH_RIGHT;
+ if (ctrlDown) keyPress = DCH_CTRLRIGHT;
+ break;
+ case Qt::Key_PageUp:
+ keyPress = DCH_PUP;
+ break;
+ case Qt::Key_PageDown:
+ keyPress = DCH_PDOWN;
+ break;
+ case Qt::Key_Home:
+ keyPress = DCH_HOME;
+ if (ctrlDown) keyPress = DCH_CTRLHOME;
+ break;
+ case Qt::Key_End:
+ keyPress = DCH_END;
+ if (ctrlDown) keyPress = DCH_CTRLEND;
+ break;
+ case Qt::Key_0: keyPress = '0'; break;
+ case Qt::Key_1: keyPress = '1'; break;
+ case Qt::Key_2: keyPress = '2'; break;
+ case Qt::Key_3: keyPress = '3'; break;
+ case Qt::Key_4: keyPress = '4'; break;
+ case Qt::Key_5: keyPress = '5'; break;
+ case Qt::Key_6: keyPress = '6'; break;
+ case Qt::Key_7: keyPress = '7'; break;
+ case Qt::Key_8: keyPress = '8'; break;
+ case Qt::Key_9: keyPress = '9'; break;
+ case Qt::Key_A: keyPress = 'a'; break;
+ case Qt::Key_B: keyPress = 'b'; break;
+ case Qt::Key_C: keyPress = 'c'; break;
+ case Qt::Key_D: keyPress = 'd'; break;
+ case Qt::Key_E: keyPress = 'e'; break;
+ case Qt::Key_F: keyPress = 'f'; break;
+ default:
+ return QWidget::keyPressEvent(event);
+ }
+
+ m_view->set_cursor_visible(true);
+ m_view->process_char(keyPress);
+
+ // Catch the view up with the cursor
+ verticalScrollBar()->setValue(m_view->visible_position().y);
+
+ viewport()->update();
+ update();
+}
+
+
+void DebuggerView::debuggerViewUpdate(debug_view& debugView, void* osdPrivate)
+{
+ // Get a handle to the DebuggerView being updated & redraw
+ DebuggerView* dView = (DebuggerView*)osdPrivate;
+ dView->verticalScrollBar()->setValue(dView->view()->visible_position().y);
+ dView->viewport()->update();
+ dView->update();
+}
+
+
diff --git a/src/osd/sdl/debugqtview.h b/src/osd/sdl/debugqtview.h
new file mode 100644
index 00000000000..4bf963114eb
--- /dev/null
+++ b/src/osd/sdl/debugqtview.h
@@ -0,0 +1,39 @@
+#ifndef __DEBUG_QT_VIEW_H__
+#define __DEBUG_QT_VIEW_H__
+
+#include <QtGui/QtGui>
+
+#include "debug/debugvw.h"
+
+
+class DebuggerView : public QAbstractScrollArea
+{
+public:
+ DebuggerView(const debug_view_type& type,
+ running_machine* machine,
+ QWidget* parent=NULL);
+ virtual ~DebuggerView() {}
+
+ void paintEvent(QPaintEvent* event);
+
+ // Callback to allow MAME to refresh the view
+ static void debuggerViewUpdate(debug_view& debugView, void* osdPrivate);
+
+ // Setters and accessors
+ void setPreferBottom(bool pb) { m_preferBottom = pb; }
+ debug_view* view() { return m_view; }
+
+
+protected:
+ void keyPressEvent(QKeyEvent* event);
+
+
+private:
+ bool m_preferBottom;
+
+ debug_view* m_view;
+ running_machine* m_machine;
+};
+
+
+#endif
diff --git a/src/osd/sdl/debugqtwindow.c b/src/osd/sdl/debugqtwindow.c
new file mode 100644
index 00000000000..091c6f842b9
--- /dev/null
+++ b/src/osd/sdl/debugqtwindow.c
@@ -0,0 +1,194 @@
+#include <QtGui/QtGui>
+
+#include "emu.h"
+#include "debugger.h"
+
+#include "debugqtwindow.h"
+#include "debugqtlogwindow.h"
+#include "debugqtdasmwindow.h"
+#include "debugqtmemorywindow.h"
+
+bool WindowQt::s_refreshAll = false;
+
+
+WindowQt::WindowQt(running_machine* machine, QWidget* parent) :
+ QMainWindow(parent),
+ m_machine(machine)
+{
+ // The Debug menu bar
+ QAction* debugActOpenMemory = new QAction("New &Memory Window", this);
+ debugActOpenMemory->setShortcut(QKeySequence("Ctrl+M"));
+ connect(debugActOpenMemory, SIGNAL(triggered()), this, SLOT(debugActOpenMemory()));
+
+ QAction* debugActOpenDasm = new QAction("New &Dasm Window", this);
+ debugActOpenDasm->setShortcut(QKeySequence("Ctrl+D"));
+ connect(debugActOpenDasm, SIGNAL(triggered()), this, SLOT(debugActOpenDasm()));
+
+ QAction* debugActOpenLog = new QAction("New &Log Window", this);
+ debugActOpenLog->setShortcut(QKeySequence("Ctrl+L"));
+ connect(debugActOpenLog, SIGNAL(triggered()), this, SLOT(debugActOpenLog()));
+
+ QAction* dbgActRun = new QAction("Run", this);
+ dbgActRun->setShortcut(Qt::Key_F5);
+ connect(dbgActRun, SIGNAL(triggered()), this, SLOT(debugActRun()));
+
+ QAction* dbgActRunAndHide = new QAction("Run And Hide Debugger", this);
+ dbgActRunAndHide->setShortcut(Qt::Key_F12);
+ connect(dbgActRunAndHide, SIGNAL(triggered()), this, SLOT(debugActRunAndHide()));
+
+ QAction* dbgActRunToNextCpu = new QAction("Run to Next CPU", this);
+ dbgActRunToNextCpu->setShortcut(Qt::Key_F6);
+ connect(dbgActRunToNextCpu, SIGNAL(triggered()), this, SLOT(debugActRunToNextCpu()));
+
+ QAction* dbgActRunNextInt = new QAction("Run to Next Interrupt on This CPU", this);
+ dbgActRunNextInt->setShortcut(Qt::Key_F7);
+ connect(dbgActRunNextInt, SIGNAL(triggered()), this, SLOT(debugActRunNextInt()));
+
+ QAction* dbgActRunNextVBlank = new QAction("Run to Next VBlank", this);
+ dbgActRunNextVBlank->setShortcut(Qt::Key_F8);
+ connect(dbgActRunNextVBlank, SIGNAL(triggered()), this, SLOT(debugActRunNextVBlank()));
+
+ QAction* dbgActStepInto = new QAction("Step Into", this);
+ dbgActStepInto->setShortcut(Qt::Key_F11);
+ connect(dbgActStepInto, SIGNAL(triggered()), this, SLOT(debugActStepInto()));
+
+ QAction* dbgActStepOver = new QAction("Step Over", this);
+ dbgActStepOver->setShortcut(Qt::Key_F10);
+ connect(dbgActStepOver, SIGNAL(triggered()), this, SLOT(debugActStepOver()));
+
+ QAction* dbgActStepOut = new QAction("Step Out", this);
+ dbgActStepOut->setShortcut(QKeySequence("Shift+F11"));
+ connect(dbgActStepOut, SIGNAL(triggered()), this, SLOT(debugActStepOut()));
+
+ QAction* dbgActSoftReset = new QAction("Soft Reset", this);
+ dbgActSoftReset->setShortcut(Qt::Key_F3);
+ connect(dbgActSoftReset, SIGNAL(triggered()), this, SLOT(debugActSoftReset()));
+
+ QAction* dbgActHardReset = new QAction("Hard Reset", this);
+ dbgActHardReset->setShortcut(QKeySequence("Shift+F3"));
+ connect(dbgActHardReset, SIGNAL(triggered()), this, SLOT(debugActHardReset()));
+
+ QAction* dbgActClose = new QAction("Close &Window", this);
+ dbgActClose->setShortcut(QKeySequence::Close);
+ connect(dbgActClose, SIGNAL(triggered()), this, SLOT(debugActClose()));
+
+ QAction* dbgActQuit = new QAction("&Quit", this);
+ dbgActQuit->setShortcut(QKeySequence::Quit);
+ connect(dbgActQuit, SIGNAL(triggered()), this, SLOT(debugActQuit()));
+
+ // Construct the menu
+ QMenu* debugMenu = menuBar()->addMenu("&Debug");
+ debugMenu->addAction(debugActOpenMemory);
+ debugMenu->addAction(debugActOpenDasm);
+ debugMenu->addAction(debugActOpenLog);
+ debugMenu->addSeparator();
+ debugMenu->addAction(dbgActRun);
+ debugMenu->addAction(dbgActRunToNextCpu);
+ debugMenu->addAction(dbgActRunNextInt);
+ debugMenu->addAction(dbgActRunNextVBlank);
+ debugMenu->addSeparator();
+ debugMenu->addAction(dbgActStepInto);
+ debugMenu->addAction(dbgActStepOver);
+ debugMenu->addAction(dbgActStepOut);
+ debugMenu->addSeparator();
+ debugMenu->addAction(dbgActSoftReset);
+ debugMenu->addAction(dbgActHardReset);
+ debugMenu->addSeparator();
+ debugMenu->addAction(dbgActClose);
+ debugMenu->addAction(dbgActQuit);
+}
+
+
+void WindowQt::debugActOpenMemory()
+{
+ MemoryWindow* foo = new MemoryWindow(m_machine, this);
+ // A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon
+ // foo->setWindowFlags(Qt::Dialog);
+ // foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint);
+ foo->show();
+}
+
+
+void WindowQt::debugActOpenDasm()
+{
+ DasmWindow* foo = new DasmWindow(m_machine, this);
+ // A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon
+ // foo->setWindowFlags(Qt::Dialog);
+ // foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint);
+ foo->show();
+}
+
+
+void WindowQt::debugActOpenLog()
+{
+ LogWindow* foo = new LogWindow(m_machine, this);
+ // A valiant effort, but it just doesn't wanna' hide behind the main window & not make a new toolbar icon
+ // foo->setWindowFlags(Qt::Dialog);
+ // foo->setWindowFlags(foo->windowFlags() & ~Qt::WindowStaysOnTopHint);
+ foo->show();
+}
+
+
+void WindowQt::debugActRun()
+{
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->go();
+}
+
+void WindowQt::debugActRunAndHide()
+{
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->go();
+ // TODO: figure out hide
+}
+
+void WindowQt::debugActRunToNextCpu()
+{
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->go_next_device();
+}
+
+void WindowQt::debugActRunNextInt()
+{
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->go_interrupt();
+}
+
+void WindowQt::debugActRunNextVBlank()
+{
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->go_vblank();
+}
+
+void WindowQt::debugActStepInto()
+{
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->single_step();
+}
+
+void WindowQt::debugActStepOver()
+{
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->single_step_over();
+}
+
+void WindowQt::debugActStepOut()
+{
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->single_step_out();
+}
+
+void WindowQt::debugActSoftReset()
+{
+ m_machine->schedule_soft_reset();
+}
+
+void WindowQt::debugActHardReset()
+{
+ // TODO: Figure out segfault
+ m_machine->schedule_hard_reset();
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->go();
+}
+
+void WindowQt::debugActClose()
+{
+ close();
+}
+
+void WindowQt::debugActQuit()
+{
+ m_machine->schedule_exit();
+ qApp->closeAllWindows();
+}
diff --git a/src/osd/sdl/debugqtwindow.h b/src/osd/sdl/debugqtwindow.h
new file mode 100644
index 00000000000..bc687a41899
--- /dev/null
+++ b/src/osd/sdl/debugqtwindow.h
@@ -0,0 +1,51 @@
+#ifndef __DEBUG_QT_WINDOW_H__
+#define __DEBUG_QT_WINDOW_H__
+
+#include <QtGui/QtGui>
+
+#include "emu.h"
+
+
+//============================================================
+// The Qt window that everyone derives from.
+//============================================================
+class WindowQt : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ WindowQt(running_machine* machine, QWidget* parent=NULL);
+ virtual ~WindowQt() {}
+
+ // The interface to an all-window refresh
+ void refreshAll() { s_refreshAll = true; }
+ bool wantsRefresh() { return s_refreshAll; }
+ void clearRefreshFlag() { s_refreshAll = false; }
+
+
+protected slots:
+ void debugActOpenMemory();
+ void debugActOpenDasm();
+ void debugActOpenLog();
+ void debugActRun();
+ void debugActRunAndHide();
+ void debugActRunToNextCpu();
+ void debugActRunNextInt();
+ void debugActRunNextVBlank();
+ void debugActStepInto();
+ void debugActStepOver();
+ void debugActStepOut();
+ void debugActSoftReset();
+ void debugActHardReset();
+ void debugActClose();
+ void debugActQuit();
+
+
+protected:
+ running_machine* m_machine;
+
+ static bool s_refreshAll;
+};
+
+
+#endif
diff --git a/src/osd/sdl/sdl.mak b/src/osd/sdl/sdl.mak
index e68a197119a..378dc59d60e 100644
--- a/src/osd/sdl/sdl.mak
+++ b/src/osd/sdl/sdl.mak
@@ -76,6 +76,8 @@ USE_DISPATCH_GL = 1
# (currently defaults disabled due to causing issues with mouse capture, esp. in MESS)
NO_USE_XINPUT = 1
+# uncomment to try the experimental new Qt debugger (Linux only for now)
+#USE_QTDEBUG = 1
###########################################################################
################## END USER-CONFIGURABLE OPTIONS ######################
@@ -227,7 +229,10 @@ endif
ifeq ($(TARGETOS),macosx)
BASE_TARGETOS = unix
DEFS += -DSDLMAME_UNIX -DSDLMAME_MACOSX -DSDLMAME_DARWIN
+
+ifndef USE_QTDEBUG
DEBUGOBJS = $(SDLOBJ)/debugosx.o
+endif
SYNC_IMPLEMENTATION = ntc
SDLMAIN = $(SDLOBJ)/SDLMain_tmpl.o
SDLUTILMAIN = $(SDLOBJ)/SDLMain_tmpl.o
@@ -275,6 +280,7 @@ SDL_NETWORK = pcap
ifndef GTK_INSTALL_ROOT
NO_DEBUGGER = 1
else
+ifndef QT_USEDEBUG
DEBUGOBJS = $(SDLOBJ)/debugwin.o $(SDLOBJ)/dview.o $(SDLOBJ)/debug-sup.o $(SDLOBJ)/debug-intf.o
LIBS += -lgtk-win32-2.0 -lgdk-win32-2.0 -lgmodule-2.0 -lglib-2.0 -lgobject-2.0 \
-lpango-1.0 -latk-1.0 -lgdk_pixbuf-2.0
@@ -284,12 +290,20 @@ INCPATH += -I$(GTK_INSTALL_ROOT)/include/gtk-2.0 -I$(GTK_INSTALL_ROOT)/include/g
-I$(GTK_INSTALL_ROOT)/include/atk-1.0 \
-I$(GTK_INSTALL_ROOT)/lib/glib-2.0/include -I$(GTK_INSTALL_ROOT)/lib/gtk-2.0/include
LDFLAGS += -L$(GTK_INSTALL_ROOT)/lib
+endif
endif # GTK_INSTALL_ROOT
# enable UNICODE
DEFS += -Dmain=utf8_main -DUNICODE -D_UNICODE
LDFLAGS += -municode
+# Qt
+ifdef QT_USEDEBUG
+QT_INSTALL_HEADERS = $(shell qmake -query QT_INSTALL_HEADERS)
+INCPATH += -I$(QT_INSTALL_HEADERS)/QtCore -I$(QT_INSTALL_HEADERS)/QtGui -I$(QT_INSTALL_HEADERS)
+QT_LIBS += -L$(shell qmake -query QT_INSTALL_LIBS) -lqtmain -lQtGui -lQtCore -lgdi32 -lcomdlg32 -loleaut32 -limm32 -lwinmm -lwinspool -lmsimg32 -lole32 -luuid -lws2_32 -ladvapi32 -lshell32 -luser32 -lkernel32 -mwindows
+endif
+
endif
ifeq ($(TARGETOS),os2)
@@ -366,8 +380,14 @@ OSDCLEAN = sdlclean
# add the debugger includes
INCPATH += -Isrc/debug
+# copy off the include paths before the sdlprefix & sdl-config stuff shows up
+MOCINCPATH := $(INCPATH)
+
# add the prefix file
INCPATH += -include $(SDLSRC)/sdlprefix.h
+INCPATH += -I/work/src/m/sdl
+MOCINCPATH += -I/work/src/m/sdl
+
#-------------------------------------------------
# BASE_TARGETOS specific configurations
@@ -398,6 +418,28 @@ ifeq ($(TARGETOS),macosx)
OSDCOREOBJS += $(SDLOBJ)/osxutils.o
SDLOS_TARGETOS = macosx
+ifdef USE_QTDEBUG
+MOC = @moc
+$(SDLOBJ)/%.moc.c: $(SDLSRC)/%.h
+ $(MOC) $(MOCINCPATH) $(DEFS) $< -o $@
+
+DEBUGOBJS = \
+ $(SDLOBJ)/debugqt.o \
+ $(SDLOBJ)/debugqtview.o \
+ $(SDLOBJ)/debugqtwindow.o \
+ $(SDLOBJ)/debugqtlogwindow.o \
+ $(SDLOBJ)/debugqtdasmwindow.o \
+ $(SDLOBJ)/debugqtmainwindow.o \
+ $(SDLOBJ)/debugqtmemorywindow.o \
+ $(SDLOBJ)/debugqtwindow.moc.o \
+ $(SDLOBJ)/debugqtlogwindow.moc.o \
+ $(SDLOBJ)/debugqtdasmwindow.moc.o \
+ $(SDLOBJ)/debugqtmainwindow.moc.o \
+ $(SDLOBJ)/debugqtmemorywindow.moc.o
+
+LIBS += -framework QtCore -framework QtGui
+endif
+
ifndef MACOSX_USE_LIBSDL
# Compile using framework (compile using libSDL is the exception)
LIBS += -framework SDL -framework Cocoa -framework OpenGL -lpthread
@@ -417,8 +459,29 @@ endif # MACOSX_USE_LIBSDL
else # ifeq ($(TARGETOS),macosx)
DEFS += -DSDLMAME_UNIX
-DEBUGOBJS = $(SDLOBJ)/debugwin.o $(SDLOBJ)/dview.o $(SDLOBJ)/debug-sup.o $(SDLOBJ)/debug-intf.o
+
+ifdef USE_QTDEBUG
+MOC = @moc-qt4
+$(SDLOBJ)/%.moc.c: $(SDLSRC)/%.h
+ $(MOC) $(MOCINCPATH) $(DEFS) $< -o $@
+
+DEBUGOBJS = \
+ $(SDLOBJ)/debugqt.o \
+ $(SDLOBJ)/debugqtview.o \
+ $(SDLOBJ)/debugqtwindow.o \
+ $(SDLOBJ)/debugqtlogwindow.o \
+ $(SDLOBJ)/debugqtdasmwindow.o \
+ $(SDLOBJ)/debugqtmainwindow.o \
+ $(SDLOBJ)/debugqtmemorywindow.o \
+ $(SDLOBJ)/debugqtwindow.moc.o \
+ $(SDLOBJ)/debugqtlogwindow.moc.o \
+ $(SDLOBJ)/debugqtdasmwindow.moc.o \
+ $(SDLOBJ)/debugqtmainwindow.moc.o \
+ $(SDLOBJ)/debugqtmemorywindow.moc.o
+endif
+
LIBGL = -lGL
+
ifeq ($(NO_X11),1)
NO_DEBUGGER = 1
endif
@@ -573,6 +636,12 @@ CCOMFLAGS += `pkg-config --cflags-only-other gtk+-2.0` `pkg-config --cflags-only
LIBS += `pkg-config --libs gtk+-2.0` `pkg-config --libs gconf-2.0`
#CCOMFLAGS += -DGTK_DISABLE_DEPRECATED
+# The newer debugger uses QT
+ifdef USE_QTDEBUG
+INCPATH += `pkg-config QtGui --cflags`
+LIBS += `pkg-config QtGui --libs`
+endif
+
# some systems still put important things in a different prefix
LIBS += -L/usr/X11/lib -L/usr/X11R6/lib -L/usr/openwin/lib
# make sure we can find X headers
@@ -647,6 +716,7 @@ $(LIBOCORE): $(OSDCOREOBJS)
$(LIBOSD): $(OSDOBJS)
+
#-------------------------------------------------
# Tools
#-------------------------------------------------