mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
QT Debugger improvements [Andrew Gardner]
- Save and load window locations. - Preliminary work on "run and hide" and "hard reset" (don't crash on one of my copmilers but do on another - more work to do!) - Fixed color when cursor is the same as PC in debug view. - Closing the main window now shuts down the machine (same as quit) - Help now wraps to the log window size.
This commit is contained in:
parent
183b9f0638
commit
ba61a286f3
@ -258,7 +258,7 @@ void debug_command_init(running_machine &machine)
|
||||
}
|
||||
|
||||
/* add all the commands */
|
||||
debug_console_register_command(machine, "help", CMDFLAG_NONE, 0, 0, 1, execute_help);
|
||||
debug_console_register_command(machine, "help", CMDFLAG_NONE, 0, 0, 2, execute_help);
|
||||
debug_console_register_command(machine, "print", CMDFLAG_NONE, 0, 1, MAX_COMMAND_PARAMS, execute_print);
|
||||
debug_console_register_command(machine, "printf", CMDFLAG_NONE, 0, 1, MAX_COMMAND_PARAMS, execute_printf);
|
||||
debug_console_register_command(machine, "logerror", CMDFLAG_NONE, 0, 1, MAX_COMMAND_PARAMS, execute_logerror);
|
||||
@ -643,8 +643,14 @@ static void execute_help(running_machine &machine, int ref, int params, const ch
|
||||
{
|
||||
if (params == 0)
|
||||
debug_console_printf_wrap(machine, 80, "%s\n", debug_get_help(""));
|
||||
else
|
||||
else if (params == 1)
|
||||
debug_console_printf_wrap(machine, 80, "%s\n", debug_get_help(param[0]));
|
||||
else if (params == 2)
|
||||
{
|
||||
UINT64 width;
|
||||
debug_command_parameter_number(machine, param[1], &width);
|
||||
debug_console_printf_wrap(machine, (int)width, "%s\n", debug_get_help(param[0]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,9 +16,13 @@
|
||||
|
||||
#include "emu.h"
|
||||
#include "osdsdl.h"
|
||||
#include "config.h"
|
||||
#include "debugger.h"
|
||||
|
||||
#include "debugqtmainwindow.h"
|
||||
#include "debugqtmemorywindow.h"
|
||||
#include "debugqtdasmwindow.h"
|
||||
#include "debugqtlogwindow.h"
|
||||
|
||||
|
||||
//============================================================
|
||||
@ -32,14 +36,184 @@ bool oneShot = true;
|
||||
MainWindow* mainQtWindow = NULL;
|
||||
|
||||
|
||||
//============================================================
|
||||
// XML configuration save/load
|
||||
//============================================================
|
||||
|
||||
// Global variable used to feed the xml configuration callbacks
|
||||
std::vector<WindowQtConfig> xmlConfigurations;
|
||||
|
||||
static void xml_configuration_load(running_machine &machine, int config_type, xml_data_node *parentnode)
|
||||
{
|
||||
xml_data_node *wnode;
|
||||
|
||||
// We only care about game files
|
||||
if (config_type != CONFIG_TYPE_GAME)
|
||||
return;
|
||||
|
||||
// Might not have any data
|
||||
if (parentnode == NULL)
|
||||
return;
|
||||
|
||||
xmlConfigurations.clear();
|
||||
|
||||
// Configuration load
|
||||
for (wnode = xml_get_sibling(parentnode->child, "window"); wnode != NULL; wnode = xml_get_sibling(wnode->next, "window"))
|
||||
{
|
||||
WindowQtConfig config;
|
||||
config.m_size.setX(xml_get_attribute_int(wnode, "size_x", config.m_size.x()));
|
||||
config.m_size.setY(xml_get_attribute_int(wnode, "size_y", config.m_size.y()));
|
||||
config.m_position.setX(xml_get_attribute_int(wnode, "position_x", config.m_position.x()));
|
||||
config.m_position.setY(xml_get_attribute_int(wnode, "position_y", config.m_position.y()));
|
||||
config.m_type = (WindowQtConfig::WindowType)xml_get_attribute_int(wnode, "type", config.m_type);
|
||||
xmlConfigurations.push_back(config);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void xml_configuration_save(running_machine &machine, int config_type, xml_data_node *parentnode)
|
||||
{
|
||||
// We only care about game files
|
||||
if (config_type != CONFIG_TYPE_GAME)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < xmlConfigurations.size(); i++)
|
||||
{
|
||||
// Create an xml node
|
||||
xml_data_node *debugger_node;
|
||||
debugger_node = xml_add_child(parentnode, "window", NULL);
|
||||
if (debugger_node == NULL)
|
||||
continue;
|
||||
|
||||
xml_set_attribute_int(debugger_node, "type", xmlConfigurations[i].m_type);
|
||||
xml_set_attribute_int(debugger_node, "position_x", xmlConfigurations[i].m_position.x());
|
||||
xml_set_attribute_int(debugger_node, "position_y", xmlConfigurations[i].m_position.y());
|
||||
xml_set_attribute_int(debugger_node, "size_x", xmlConfigurations[i].m_size.x());
|
||||
xml_set_attribute_int(debugger_node, "size_y", xmlConfigurations[i].m_size.y());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void gather_save_configurations()
|
||||
{
|
||||
xmlConfigurations.clear();
|
||||
|
||||
// Loop over all the open windows
|
||||
foreach (QWidget* widget, QApplication::topLevelWidgets())
|
||||
{
|
||||
if (!widget->isVisible())
|
||||
continue;
|
||||
|
||||
if (!widget->isWindow() || widget->windowType() != Qt::Window)
|
||||
continue;
|
||||
|
||||
// Figure out its type
|
||||
WindowQtConfig::WindowType type = WindowQtConfig::WIN_TYPE_UNKNOWN;
|
||||
if (dynamic_cast<MainWindow*>(widget))
|
||||
type = WindowQtConfig::WIN_TYPE_MAIN;
|
||||
else if (dynamic_cast<MemoryWindow*>(widget))
|
||||
type = WindowQtConfig::WIN_TYPE_MEMORY;
|
||||
else if (dynamic_cast<DasmWindow*>(widget))
|
||||
type = WindowQtConfig::WIN_TYPE_DISASM;
|
||||
else if (dynamic_cast<LogWindow*>(widget))
|
||||
type = WindowQtConfig::WIN_TYPE_LOG;
|
||||
|
||||
WindowQtConfig config;
|
||||
config.m_type = type;
|
||||
config.m_position.setX(widget->geometry().topLeft().x());
|
||||
config.m_position.setY(widget->geometry().topLeft().y());
|
||||
config.m_size.setX(widget->size().width());
|
||||
config.m_size.setY(widget->size().height());
|
||||
xmlConfigurations.push_back(config);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// Utilities
|
||||
//============================================================
|
||||
|
||||
static void load_and_clear_main_window_config(std::vector<WindowQtConfig>& configs)
|
||||
{
|
||||
if (configs.size() == 0)
|
||||
return;
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < configs.size(); i++)
|
||||
{
|
||||
if (configs[i].m_type == WindowQtConfig::WIN_TYPE_MAIN)
|
||||
{
|
||||
mainQtWindow->setGeometry(configs[i].m_position.x(), configs[i].m_position.y(),
|
||||
configs[i].m_size.x(), configs[i].m_size.y());
|
||||
break;
|
||||
}
|
||||
}
|
||||
configs.erase(configs.begin()+i);
|
||||
}
|
||||
|
||||
|
||||
static void setup_additional_startup_windows(running_machine& machine, std::vector<WindowQtConfig>& configs)
|
||||
{
|
||||
for (int i = 0; i < configs.size(); i++)
|
||||
{
|
||||
WindowQt* foo = NULL;
|
||||
switch (configs[i].m_type)
|
||||
{
|
||||
case WindowQtConfig::WIN_TYPE_MEMORY:
|
||||
foo = new MemoryWindow(&machine); break;
|
||||
case WindowQtConfig::WIN_TYPE_DISASM:
|
||||
foo = new DasmWindow(&machine); break;
|
||||
case WindowQtConfig::WIN_TYPE_LOG:
|
||||
foo = new LogWindow(&machine); break;
|
||||
default: break;
|
||||
}
|
||||
foo->setGeometry(configs[i].m_position.x(), configs[i].m_position.y(),
|
||||
configs[i].m_size.x(), configs[i].m_size.y());
|
||||
foo->show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void bring_main_window_to_front()
|
||||
{
|
||||
foreach (QWidget* widget, QApplication::topLevelWidgets())
|
||||
{
|
||||
if (!dynamic_cast<MainWindow*>(widget))
|
||||
continue;
|
||||
widget->activateWindow();
|
||||
widget->raise();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// Core functionality
|
||||
//============================================================
|
||||
|
||||
void sdl_osd_interface::init_debugger()
|
||||
{
|
||||
// QT is a magical thing
|
||||
new QApplication(qtArgc, qtArgv);
|
||||
if (qApp == NULL)
|
||||
{
|
||||
// If you're starting from scratch, create a new qApp
|
||||
new QApplication(qtArgc, qtArgv);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If you're doing a hard reset, clear out existing widgets & get ready for re-init
|
||||
foreach (QWidget* widget, QApplication::topLevelWidgets())
|
||||
{
|
||||
if (!widget->isWindow() || widget->windowType() != Qt::Window)
|
||||
continue;
|
||||
delete widget;
|
||||
}
|
||||
oneShot = true;
|
||||
}
|
||||
|
||||
// Setup the configuration XML saving and loading
|
||||
config_register(machine(),
|
||||
"debugger",
|
||||
config_saveload_delegate(FUNC(xml_configuration_load), &machine()),
|
||||
config_saveload_delegate(FUNC(xml_configuration_save), &machine()));
|
||||
}
|
||||
|
||||
|
||||
@ -49,14 +223,26 @@ void sdl_osd_interface::init_debugger()
|
||||
|
||||
void sdl_osd_interface::wait_for_debugger(device_t &device, bool firststop)
|
||||
{
|
||||
// Dialog initialization
|
||||
if (oneShot)
|
||||
{
|
||||
mainQtWindow = new MainWindow(&device, &machine());
|
||||
mainQtWindow = new MainWindow(&machine());
|
||||
load_and_clear_main_window_config(xmlConfigurations);
|
||||
setup_additional_startup_windows(machine(), xmlConfigurations);
|
||||
mainQtWindow->show();
|
||||
oneShot = false;
|
||||
}
|
||||
|
||||
// Make sure the main window displays the proper cpu
|
||||
// Insure all top level widgets are visible & bring main window to front
|
||||
foreach (QWidget* widget, QApplication::topLevelWidgets())
|
||||
{
|
||||
if (!widget->isWindow() || widget->windowType() != Qt::Window)
|
||||
continue;
|
||||
widget->show();
|
||||
}
|
||||
bring_main_window_to_front();
|
||||
|
||||
// Set the main window to display the proper cpu
|
||||
mainQtWindow->setProcessor(&device);
|
||||
|
||||
// Run our own QT event loop
|
||||
@ -73,9 +259,25 @@ void sdl_osd_interface::wait_for_debugger(device_t &device, bool firststop)
|
||||
mainQtWindow->clearRefreshFlag();
|
||||
}
|
||||
|
||||
// Exit if the machine has been instructed to do so
|
||||
if (machine().exit_pending())
|
||||
// Hide all top level widgets if requested
|
||||
if (mainQtWindow->wantsHide())
|
||||
{
|
||||
foreach (QWidget* widget, QApplication::topLevelWidgets())
|
||||
{
|
||||
if (!widget->isWindow() || widget->windowType() != Qt::Window)
|
||||
continue;
|
||||
widget->hide();
|
||||
}
|
||||
mainQtWindow->clearHideFlag();
|
||||
}
|
||||
|
||||
// Exit if the machine has been instructed to do so (scheduled event == exit || hard_reset)
|
||||
if (machine().scheduled_event_pending())
|
||||
{
|
||||
// Keep a list of windows we want to save.
|
||||
// We need to do this here because by the time xml_configuration_save gets called
|
||||
// all the QT windows are already gone.
|
||||
gather_save_configurations();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -8,10 +8,14 @@
|
||||
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");
|
||||
|
||||
if (parent != NULL)
|
||||
{
|
||||
QPoint parentPos = parent->pos();
|
||||
setGeometry(parentPos.x()+100, parentPos.y()+100, 800, 400);
|
||||
}
|
||||
|
||||
//
|
||||
// The main frame and its input and log widgets
|
||||
//
|
||||
|
@ -8,10 +8,14 @@
|
||||
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");
|
||||
|
||||
if (parent != NULL)
|
||||
{
|
||||
QPoint parentPos = parent->pos();
|
||||
setGeometry(parentPos.x()+100, parentPos.y()+100, 800, 400);
|
||||
}
|
||||
|
||||
//
|
||||
// The main frame and its input and log widgets
|
||||
//
|
||||
|
@ -4,9 +4,7 @@
|
||||
#include "debug/dvdisasm.h"
|
||||
|
||||
|
||||
MainWindow::MainWindow(device_t* processor,
|
||||
running_machine* machine,
|
||||
QWidget* parent) :
|
||||
MainWindow::MainWindow(running_machine* machine, QWidget* parent) :
|
||||
WindowQt(machine, parent),
|
||||
m_historyIndex(0),
|
||||
m_inputHistory()
|
||||
@ -100,11 +98,6 @@ MainWindow::MainWindow(device_t* processor,
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
@ -261,18 +254,32 @@ void MainWindow::rightBarChanged(QAction* changedTo)
|
||||
|
||||
void MainWindow::executeCommand(bool withClear)
|
||||
{
|
||||
if (m_inputEdit->text() == "")
|
||||
QString command = m_inputEdit->text();
|
||||
|
||||
// A blank command is a "silent step"
|
||||
if (command == "")
|
||||
{
|
||||
debug_cpu_get_visible_cpu(*m_machine)->debug()->single_step();
|
||||
return;
|
||||
}
|
||||
|
||||
// If the user asked for help on a specific command, enhance the call
|
||||
if (command.trimmed().startsWith("help", Qt::CaseInsensitive))
|
||||
{
|
||||
if (command.split(" ", QString::SkipEmptyParts).length() == 2)
|
||||
{
|
||||
const int width = m_consoleView->view()->visible_size().x;
|
||||
command.append(QString(", %1").arg(width, 1, 16));
|
||||
}
|
||||
}
|
||||
|
||||
// Send along the command
|
||||
debug_console_execute_command(*m_machine,
|
||||
m_inputEdit->text().toLocal8Bit().data(),
|
||||
command.toLocal8Bit().data(),
|
||||
true);
|
||||
|
||||
// Add history & set the index to be the top of the stack
|
||||
addToHistory(m_inputEdit->text());
|
||||
addToHistory(command);
|
||||
|
||||
// Clear out the text and reset the history pointer only if asked
|
||||
if (withClear)
|
||||
@ -288,6 +295,12 @@ void MainWindow::executeCommand(bool withClear)
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::debugActClose()
|
||||
{
|
||||
m_machine->schedule_exit();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::addToHistory(const QString& command)
|
||||
{
|
||||
if (command == "")
|
||||
|
@ -21,9 +21,7 @@ class MainWindow : public WindowQt
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow(device_t* processor,
|
||||
running_machine* machine,
|
||||
QWidget* parent=NULL);
|
||||
MainWindow(running_machine* machine, QWidget* parent=NULL);
|
||||
virtual ~MainWindow() {}
|
||||
|
||||
void setProcessor(device_t* processor);
|
||||
@ -44,6 +42,9 @@ private slots:
|
||||
|
||||
void executeCommand(bool withClear=true);
|
||||
|
||||
// Closing the main window actually exits the program
|
||||
void debugActClose();
|
||||
|
||||
|
||||
private:
|
||||
// Widgets and docks
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "debugqtmemorywindow.h"
|
||||
|
||||
#include "debug/dvmemory.h"
|
||||
#include "debug/debugvw.h"
|
||||
#include "debug/debugcon.h"
|
||||
#include "debug/debugcpu.h"
|
||||
|
||||
@ -9,10 +8,14 @@
|
||||
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");
|
||||
|
||||
if (parent != NULL)
|
||||
{
|
||||
QPoint parentPos = parent->pos();
|
||||
setGeometry(parentPos.x()+100, parentPos.y()+100, 800, 400);
|
||||
}
|
||||
|
||||
//
|
||||
// The main frame and its input and log widgets
|
||||
//
|
||||
|
@ -89,6 +89,10 @@ void DebuggerView::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
bgColor.setRgb(0xff, 0xff, 0x00);
|
||||
}
|
||||
if ((textAttr & DCA_SELECTED) && (textAttr & DCA_CURRENT))
|
||||
{
|
||||
bgColor.setRgb(0xff,0xc0,0x80);
|
||||
}
|
||||
if(textAttr & DCA_CHANGED)
|
||||
{
|
||||
fgColor.setRgb(0xff, 0x00, 0x00);
|
||||
|
@ -9,12 +9,15 @@
|
||||
#include "debugqtmemorywindow.h"
|
||||
|
||||
bool WindowQt::s_refreshAll = false;
|
||||
bool WindowQt::s_hideAll = false;
|
||||
|
||||
|
||||
WindowQt::WindowQt(running_machine* machine, QWidget* parent) :
|
||||
QMainWindow(parent),
|
||||
m_machine(machine)
|
||||
{
|
||||
//setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
|
||||
// The Debug menu bar
|
||||
QAction* debugActOpenMemory = new QAction("New &Memory Window", this);
|
||||
debugActOpenMemory->setShortcut(QKeySequence("Ctrl+M"));
|
||||
@ -83,6 +86,7 @@ WindowQt::WindowQt(running_machine* machine, QWidget* parent) :
|
||||
debugMenu->addAction(debugActOpenLog);
|
||||
debugMenu->addSeparator();
|
||||
debugMenu->addAction(dbgActRun);
|
||||
debugMenu->addAction(dbgActRunAndHide);
|
||||
debugMenu->addAction(dbgActRunToNextCpu);
|
||||
debugMenu->addAction(dbgActRunNextInt);
|
||||
debugMenu->addAction(dbgActRunNextVBlank);
|
||||
@ -137,7 +141,7 @@ void WindowQt::debugActRun()
|
||||
void WindowQt::debugActRunAndHide()
|
||||
{
|
||||
debug_cpu_get_visible_cpu(*m_machine)->debug()->go();
|
||||
// TODO: figure out hide
|
||||
hideAll();
|
||||
}
|
||||
|
||||
void WindowQt::debugActRunToNextCpu()
|
||||
@ -173,13 +177,12 @@ void WindowQt::debugActStepOut()
|
||||
void WindowQt::debugActSoftReset()
|
||||
{
|
||||
m_machine->schedule_soft_reset();
|
||||
debug_cpu_get_visible_cpu(*m_machine)->debug()->single_step();
|
||||
}
|
||||
|
||||
void WindowQt::debugActHardReset()
|
||||
{
|
||||
// TODO: Figure out segfault
|
||||
m_machine->schedule_hard_reset();
|
||||
debug_cpu_get_visible_cpu(*m_machine)->debug()->go();
|
||||
}
|
||||
|
||||
void WindowQt::debugActClose()
|
||||
@ -190,5 +193,4 @@ void WindowQt::debugActClose()
|
||||
void WindowQt::debugActQuit()
|
||||
{
|
||||
m_machine->schedule_exit();
|
||||
qApp->closeAllWindows();
|
||||
}
|
||||
|
@ -22,6 +22,10 @@ public:
|
||||
bool wantsRefresh() { return s_refreshAll; }
|
||||
void clearRefreshFlag() { s_refreshAll = false; }
|
||||
|
||||
void hideAll() { s_hideAll = true; }
|
||||
bool wantsHide() { return s_hideAll; }
|
||||
void clearHideFlag() { s_hideAll = false; }
|
||||
|
||||
|
||||
protected slots:
|
||||
void debugActOpenMemory();
|
||||
@ -37,7 +41,7 @@ protected slots:
|
||||
void debugActStepOut();
|
||||
void debugActSoftReset();
|
||||
void debugActHardReset();
|
||||
void debugActClose();
|
||||
virtual void debugActClose();
|
||||
void debugActQuit();
|
||||
|
||||
|
||||
@ -45,7 +49,37 @@ protected:
|
||||
running_machine* m_machine;
|
||||
|
||||
static bool s_refreshAll;
|
||||
static bool s_hideAll;
|
||||
};
|
||||
|
||||
|
||||
//=======================================================================
|
||||
// A way to store the configuration of a window long enough to use it.
|
||||
//=======================================================================
|
||||
class WindowQtConfig
|
||||
{
|
||||
public:
|
||||
// This is a holdover from the old debugger - TODO: remove
|
||||
enum WindowType
|
||||
{
|
||||
WIN_TYPE_MAIN = 0x01,
|
||||
WIN_TYPE_MEMORY = 0x02,
|
||||
WIN_TYPE_DISASM = 0x04,
|
||||
WIN_TYPE_LOG = 0x08,
|
||||
WIN_TYPE_UNKNOWN = 0x10,
|
||||
};
|
||||
|
||||
public:
|
||||
WindowQtConfig() :
|
||||
m_type(WIN_TYPE_MAIN),
|
||||
m_size(800, 600),
|
||||
m_position(120, 120)
|
||||
{}
|
||||
~WindowQtConfig() {}
|
||||
|
||||
WindowType m_type;
|
||||
QPoint m_size;
|
||||
QPoint m_position;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user