diff options
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 |
commit | a9116a79739841746e3775260730f3ef09b55937 (patch) | |
tree | 1c5d22c4d726c7672fd204378cd919bfbc25a90c /src/osd/sdl | |
parent | 39b8e6c652b5b2cd8541c348aeb8459e9d2fdc1b (diff) |
SDL: Experimental Qt-based debugger [Andrew Gardner, R. Belmont]
Diffstat (limited to 'src/osd/sdl')
-rw-r--r-- | src/osd/sdl/debugqt.c | 119 | ||||
-rw-r--r-- | src/osd/sdl/debugqtdasmwindow.c | 200 | ||||
-rw-r--r-- | src/osd/sdl/debugqtdasmwindow.h | 43 | ||||
-rw-r--r-- | src/osd/sdl/debugqtlogwindow.c | 32 | ||||
-rw-r--r-- | src/osd/sdl/debugqtlogwindow.h | 28 | ||||
-rw-r--r-- | src/osd/sdl/debugqtmainwindow.c | 302 | ||||
-rw-r--r-- | src/osd/sdl/debugqtmainwindow.h | 162 | ||||
-rw-r--r-- | src/osd/sdl/debugqtmemorywindow.c | 217 | ||||
-rw-r--r-- | src/osd/sdl/debugqtmemorywindow.h | 44 | ||||
-rw-r--r-- | src/osd/sdl/debugqtview.c | 201 | ||||
-rw-r--r-- | src/osd/sdl/debugqtview.h | 39 | ||||
-rw-r--r-- | src/osd/sdl/debugqtwindow.c | 194 | ||||
-rw-r--r-- | src/osd/sdl/debugqtwindow.h | 51 | ||||
-rw-r--r-- | src/osd/sdl/sdl.mak | 72 |
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 #------------------------------------------------- |