1
// $Id: DebuggerForm.cpp 6484 2007-05-18 11:44:34Z edwinv $
3
#include "DebuggerForm.h"
4
#include "DockableWidgetArea.h"
5
#include "DockableWidget.h"
6
#include "DisasmViewer.h"
8
#include "CPURegsViewer.h"
9
#include "FlagsViewer.h"
10
#include "StackViewer.h"
11
#include "SlotViewer.h"
12
#include "CommClient.h"
13
#include "ConnectDialog.h"
14
#include "SymbolManager.h"
15
#include "PreferencesDialog.h"
16
#include "BreakpointDialog.h"
17
#include "DebuggableViewer.h"
21
#include <QMessageBox>
28
#include <QVBoxLayout>
29
#include <QHBoxLayout>
31
#include <QStringList>
36
class QueryPauseHandler : public SimpleCommand
39
QueryPauseHandler(DebuggerForm& form_)
40
: SimpleCommand("set pause")
45
virtual void replyOk(const QString& message)
47
bool checked = message.trimmed() == "on";
48
form.systemPauseAction->setChecked(checked);
56
class QueryBreakedHandler : public SimpleCommand
59
QueryBreakedHandler(DebuggerForm& form_)
60
: SimpleCommand("debug breaked")
65
virtual void replyOk(const QString& message)
67
form.finalizeConnection(message.trimmed() == "1");
75
class ListBreakPointsHandler : public SimpleCommand
78
ListBreakPointsHandler(DebuggerForm& form_)
79
: SimpleCommand("debug list_bp")
84
virtual void replyOk(const QString& message)
86
form.breakpoints.setBreakpoints(message);
87
form.disasmView->update();
94
class CPURegRequest : public ReadDebugBlockCommand
97
CPURegRequest(DebuggerForm& form_)
98
: ReadDebugBlockCommand("{CPU regs}", 0, 28, buf)
103
virtual void replyOk(const QString& message)
106
form.regsView->setData(buf);
112
unsigned char buf[28];
115
class ListDebuggablesHandler : public SimpleCommand
118
ListDebuggablesHandler(DebuggerForm& form_)
119
: SimpleCommand("debug list")
124
virtual void replyOk(const QString& message)
126
form.setDebuggables(message);
133
class DebuggableSizeHandler : public SimpleCommand
136
DebuggableSizeHandler(const QString& debuggable_, DebuggerForm& form_)
137
: SimpleCommand(QString("debug size %1").arg(debuggable_))
138
, debuggable(debuggable_)
143
virtual void replyOk(const QString& message)
145
form.setDebuggableSize(debuggable, message.toInt());
154
DebuggerForm::DebuggerForm(QWidget* parent)
155
: QMainWindow(parent)
156
, comm(CommClient::instance())
165
void DebuggerForm::createActions()
167
systemConnectAction = new QAction(tr("&Connect"), this);
168
systemConnectAction->setShortcut(tr("Ctrl+C"));
169
systemConnectAction->setStatusTip(tr("Connect to openMSX"));
170
systemConnectAction->setIcon(QIcon(":/icons/connect.png"));
172
systemDisconnectAction = new QAction(tr("&Disconnect"), this);
173
systemDisconnectAction->setShortcut(tr(""));
174
systemDisconnectAction->setStatusTip(tr("Disconnect from openMSX"));
175
systemDisconnectAction->setIcon(QIcon(":/icons/disconnect.png"));
176
systemDisconnectAction->setEnabled(false);
178
systemPauseAction = new QAction(tr("&Pause emulator"), this);
179
systemPauseAction->setShortcut(Qt::Key_Pause);
180
systemPauseAction->setStatusTip(tr("Pause the emulation"));
181
systemPauseAction->setIcon(QIcon(":/icons/pause.png"));
182
systemPauseAction->setCheckable(true);
183
systemPauseAction->setEnabled(false);
185
systemSymbolManagerAction = new QAction(tr("&Symbol mananger ..."), this);
186
systemSymbolManagerAction->setStatusTip(tr("Start the symbol manager"));
187
systemSymbolManagerAction->setIcon(QIcon(":/icons/symmanager.png"));
189
systemPreferencesAction = new QAction(tr("Pre&ferences ..."), this);
190
systemPreferencesAction->setStatusTip(tr("Set the global debugger preferences"));
192
systemQuitAction = new QAction(tr("&Quit"), this);
193
systemQuitAction->setShortcut(tr("Ctrl+Q"));
194
systemQuitAction->setStatusTip(tr("Quit the openMSX debugger"));
196
viewRegistersAction = new QAction(tr("CPU &Registers"), this);
197
viewRegistersAction->setStatusTip(tr("Toggle the cpu registers display"));
198
viewRegistersAction->setCheckable(true);
200
viewFlagsAction = new QAction(tr("CPU &Flags"), this);
201
viewFlagsAction->setStatusTip(tr("Toggle the cpu flags display"));
202
viewFlagsAction->setCheckable(true);
204
viewStackAction = new QAction(tr("Stack"), this);
205
viewStackAction->setStatusTip(tr("Toggle the stack display"));
206
viewStackAction->setCheckable(true);
208
viewSlotsAction = new QAction(tr("Slots"), this);
209
viewSlotsAction->setStatusTip(tr("Toggle the slots display"));
210
viewSlotsAction->setCheckable(true);
212
viewMemoryAction = new QAction(tr("Memory"), this);
213
viewMemoryAction->setStatusTip(tr("Toggle the main memory display"));
214
viewMemoryAction->setCheckable(true);
216
viewDebuggableViewerAction = new QAction(tr("Add debuggable viewer"), this);
217
viewDebuggableViewerAction->setStatusTip(tr("Add a hex viewer for debuggables"));
219
executeBreakAction = new QAction(tr("Break"), this);
220
executeBreakAction->setShortcut(tr("CRTL+B"));
221
executeBreakAction->setStatusTip(tr("Halt the execution and enter debug mode"));
222
executeBreakAction->setIcon(QIcon(":/icons/break.png"));
223
executeBreakAction->setEnabled(false);
225
executeRunAction = new QAction(tr("Run"), this);
226
executeRunAction->setShortcut(tr("F9"));
227
executeRunAction->setStatusTip(tr("Leave debug mode and resume execution"));
228
executeRunAction->setIcon(QIcon(":/icons/run.png"));
229
executeRunAction->setEnabled(false);
231
executeStepAction = new QAction(tr("Step into"), this);
232
executeStepAction->setShortcut(tr("F7"));
233
executeStepAction->setStatusTip(tr("Execute a single instruction"));
234
executeStepAction->setIcon(QIcon(":/icons/stepinto.png"));
235
executeStepAction->setEnabled(false);
237
executeStepOverAction = new QAction(tr("Step over"), this);
238
executeStepOverAction->setShortcut(tr("F8"));
239
executeStepOverAction->setStatusTip(tr("Execute the next instruction including any called subroutines"));
240
executeStepOverAction->setIcon(QIcon(":/icons/stepover.png"));
241
executeStepOverAction->setEnabled(false);
243
executeStepOutAction = new QAction(tr("Step out"), this);
244
executeStepOutAction->setShortcut(tr("F11"));
245
executeStepOutAction->setStatusTip(tr("Resume execution until the current routine has finished"));
246
executeStepOutAction->setIcon(QIcon(":/icons/stepout.png"));
247
executeStepOutAction->setEnabled(false);
249
executeRunToAction = new QAction(tr("Run to"), this);
250
executeRunToAction->setShortcut(tr("F4"));
251
executeRunToAction->setStatusTip(tr("Resume execution until the selected line is reached"));
252
executeRunToAction->setIcon(QIcon(":/icons/runto.png"));
253
executeRunToAction->setEnabled(false);
255
breakpointToggleAction = new QAction(tr("Toggle"), this);
256
breakpointToggleAction->setShortcut(tr("F5"));
257
breakpointToggleAction->setStatusTip(tr("Toggle breakpoint on/off at cursor"));
258
breakpointToggleAction->setIcon(QIcon(":/icons/break.png"));
259
breakpointToggleAction->setEnabled(false);
261
breakpointAddAction = new QAction(tr("Add ..."), this);
262
breakpointAddAction->setShortcut(tr("CTRL+B"));
263
breakpointAddAction->setStatusTip(tr("Add a breakpoint at a location"));
264
breakpointAddAction->setEnabled(false);
266
helpAboutAction = new QAction(tr("&About"), this);
267
executeRunToAction->setStatusTip(tr("Show the appliction information"));
269
connect(systemConnectAction, SIGNAL(triggered()), this, SLOT(systemConnect()));
270
connect(systemDisconnectAction, SIGNAL(triggered()), this, SLOT(systemDisconnect()));
271
connect(systemPauseAction, SIGNAL(triggered()), this, SLOT(systemPause()));
272
connect(systemSymbolManagerAction, SIGNAL(triggered()), this, SLOT(systemSymbolManager()));
273
connect(systemPreferencesAction, SIGNAL(triggered()), this, SLOT(systemPreferences()));
274
connect(systemQuitAction, SIGNAL(triggered()), this, SLOT(close()));
275
connect(viewRegistersAction, SIGNAL(triggered()), this, SLOT(toggleRegisterDisplay()));
276
connect(viewFlagsAction, SIGNAL(triggered()), this, SLOT(toggleFlagsDisplay()));
277
connect(viewStackAction, SIGNAL(triggered()), this, SLOT(toggleStackDisplay()));
278
connect(viewSlotsAction, SIGNAL(triggered()), this, SLOT(toggleSlotsDisplay()));
279
connect(viewMemoryAction, SIGNAL(triggered()), this, SLOT(toggleMemoryDisplay()));
280
connect(viewDebuggableViewerAction, SIGNAL(triggered()), this, SLOT(addDebuggableViewer()));
281
connect(executeBreakAction, SIGNAL(triggered()), this, SLOT(executeBreak()));
282
connect(executeRunAction, SIGNAL(triggered()), this, SLOT(executeRun()));
283
connect(executeStepAction, SIGNAL(triggered()), this, SLOT(executeStep()));
284
connect(executeStepOverAction, SIGNAL(triggered()), this, SLOT(executeStepOver()));
285
connect(executeRunToAction, SIGNAL(triggered()), this, SLOT(executeRunTo()));
286
connect(executeStepOutAction, SIGNAL(triggered()), this, SLOT(executeStepOut()));
287
connect(breakpointToggleAction, SIGNAL(triggered()), this, SLOT(breakpointToggle()));
288
connect(breakpointAddAction, SIGNAL(triggered()), this, SLOT(breakpointAdd()));
289
connect(helpAboutAction, SIGNAL(triggered()), this, SLOT(showAbout()));
292
void DebuggerForm::createMenus()
294
// create system menu
295
systemMenu = menuBar()->addMenu(tr("&System"));
296
systemMenu->addAction(systemConnectAction);
297
systemMenu->addAction(systemDisconnectAction);
298
systemMenu->addSeparator();
299
systemMenu->addAction(systemPauseAction);
300
systemMenu->addSeparator();
301
systemMenu->addAction(systemSymbolManagerAction);
302
systemMenu->addSeparator();
303
systemMenu->addAction(systemPreferencesAction);
304
systemMenu->addSeparator();
305
systemMenu->addAction(systemQuitAction);
307
// create execute menu
308
viewMenu = menuBar()->addMenu(tr("&View"));
309
viewMenu->addAction(viewRegistersAction);
310
viewMenu->addAction(viewFlagsAction);
311
viewMenu->addAction(viewStackAction);
312
viewMenu->addAction(viewSlotsAction);
313
viewMenu->addAction(viewMemoryAction);
314
viewMenu->addSeparator();
315
viewMenu->addAction(viewDebuggableViewerAction);
316
connect( viewMenu, SIGNAL( aboutToShow() ), this, SLOT( updateViewMenu() ) );
318
// create execute menu
319
executeMenu = menuBar()->addMenu(tr("&Execute"));
320
executeMenu->addAction(executeBreakAction);
321
executeMenu->addAction(executeRunAction);
322
executeMenu->addSeparator();
323
executeMenu->addAction(executeStepAction);
324
executeMenu->addAction(executeStepOverAction);
325
executeMenu->addAction(executeStepOutAction);
326
executeMenu->addAction(executeRunToAction);
328
// create breakpoint menu
329
breakpointMenu = menuBar()->addMenu(tr("&Breakpoint"));
330
breakpointMenu->addAction(breakpointToggleAction);
331
breakpointMenu->addAction(breakpointAddAction);
334
helpMenu = menuBar()->addMenu(tr("&Help"));
335
helpMenu->addAction(helpAboutAction);
338
void DebuggerForm::createToolbars()
340
// create debug toolbar
341
systemToolbar = addToolBar(tr("System"));
342
systemToolbar->addAction(systemConnectAction);
343
systemToolbar->addAction(systemDisconnectAction);
344
systemToolbar->addSeparator();
345
systemToolbar->addAction(systemPauseAction);
346
systemToolbar->addSeparator();
347
systemToolbar->addAction(systemSymbolManagerAction);
349
// create debug toolbar
350
executeToolbar = addToolBar(tr("Execution"));
351
executeToolbar->addAction(executeBreakAction);
352
executeToolbar->addAction(executeRunAction);
353
executeToolbar->addSeparator();
354
executeToolbar->addAction(executeStepAction);
355
executeToolbar->addAction(executeStepOverAction);
356
executeToolbar->addAction(executeStepOutAction);
357
executeToolbar->addAction(executeRunToAction);
360
void DebuggerForm::createStatusbar()
362
// create the statusbar
363
statusBar()->showMessage("No emulation running.");
366
void DebuggerForm::createForm()
368
setWindowTitle("openMSX Debugger");
370
mainArea = new DockableWidgetArea;
371
dockMan.addDockArea( mainArea );
372
setCentralWidget(mainArea);
375
* Create main widgets and append them to the list first
377
DockableWidget *dw = new DockableWidget( dockMan );
379
// create the disasm viewer widget
380
disasmView = new DisasmViewer;
381
dw->setWidget(disasmView);
382
dw->setTitle(tr("Code view"));
383
dw->setId("CODEVIEW");
384
dw->setFloating(false);
385
dw->setDestroyable(false);
386
dw->setMovable(false);
387
dw->setClosable(false);
388
connect( this, SIGNAL( settingsChanged() ),
389
disasmView, SLOT( settingsChanged() ) );
390
connect( this, SIGNAL( symbolsChanged() ),
391
disasmView, SLOT( symbolsChanged() ) );
392
connect( dw, SIGNAL( visibilityChanged(DockableWidget*) ),
393
this, SLOT( dockWidgetVisibilityChanged(DockableWidget*) ) );
395
// create the memory view widget
396
hexView = new HexViewer;
397
dw = new DockableWidget( dockMan );
398
dw->setWidget(hexView);
399
dw->setTitle(tr("Main memory"));
401
dw->setFloating(false);
402
dw->setDestroyable(false);
403
dw->setMovable(true);
404
dw->setClosable(true);
405
connect( dw, SIGNAL( visibilityChanged(DockableWidget*) ),
406
this, SLOT( dockWidgetVisibilityChanged(DockableWidget*) ) );
408
// create register viewer
409
regsView = new CPURegsViewer;
410
dw = new DockableWidget( dockMan );
411
dw->setWidget(regsView);
412
dw->setTitle(tr("CPU registers"));
413
dw->setId("REGISTERS");
414
dw->setFloating(false);
415
dw->setDestroyable(false);
416
dw->setMovable(true);
417
dw->setClosable(true);
418
connect( dw, SIGNAL( visibilityChanged(DockableWidget*) ),
419
this, SLOT( dockWidgetVisibilityChanged(DockableWidget*) ) );
421
// create flags viewer
422
flagsView = new FlagsViewer;
423
dw = new DockableWidget( dockMan );
424
dw->setWidget(flagsView);
425
dw->setTitle(tr("Flags"));
427
dw->setFloating(false);
428
dw->setDestroyable(false);
429
dw->setMovable(true);
430
dw->setClosable(true);
431
connect( dw, SIGNAL( visibilityChanged(DockableWidget*) ),
432
this, SLOT( dockWidgetVisibilityChanged(DockableWidget*) ) );
434
// create stack viewer
435
stackView = new StackViewer;
436
dw = new DockableWidget( dockMan );
437
dw->setWidget(stackView);
438
dw->setTitle(tr("Stack"));
440
dw->setFloating(false);
441
dw->setDestroyable(false);
442
dw->setMovable(true);
443
dw->setClosable(true);
444
connect( dw, SIGNAL( visibilityChanged(DockableWidget*) ),
445
this, SLOT( dockWidgetVisibilityChanged(DockableWidget*) ) );
447
// create slot viewer
448
slotView = new SlotViewer;
449
dw = new DockableWidget( dockMan );
450
dw->setWidget(slotView);
451
dw->setTitle(tr("Memory layout"));
453
dw->setFloating(false);
454
dw->setDestroyable(false);
455
dw->setMovable(true);
456
dw->setClosable(true);
457
connect( dw, SIGNAL( visibilityChanged(DockableWidget*) ),
458
this, SLOT( dockWidgetVisibilityChanged(DockableWidget*) ) );
461
restoreGeometry( Settings::get().value( "Layout/WindowGeometry", saveGeometry() ).toByteArray() );
463
QStringList list = Settings::get().value( "Layout/WidgetLayout" ).toStringList();
465
if( !list.size() || !list.at(0).startsWith("CODEVIEW ") ) {
467
list.append( "CODEVIEW D V R 0 -1 -1" );
468
list.append( "REGISTERS D V R 0 -1 -1" );
469
list.append( "FLAGS D V R 0 -1 -1" );
470
int regW = dockMan.findDockableWidget("REGISTERS")->sizeHint().width();
471
int regH = dockMan.findDockableWidget("REGISTERS")->sizeHint().height();
472
int codeW = dockMan.findDockableWidget("CODEVIEW")->sizeHint().width();
473
int codeH = dockMan.findDockableWidget("CODEVIEW")->sizeHint().height();
474
int flagW = dockMan.findDockableWidget("FLAGS")->sizeHint().width();
475
int slotW = dockMan.findDockableWidget("SLOTS")->sizeHint().width();
476
list.append( QString("SLOTS D V R 0 -1 %1").arg(regH) );
477
list.append( QString("STACK D V R 0 -1 %1").arg(codeH) );
478
list.append( QString("MEMORY D V B %1 %2 %3").arg(codeW)
479
.arg(regW + flagW + slotW)
480
.arg(codeH - regH) );
484
for( int i = 0; i < list.size(); i++ ) {
485
QStringList s = list.at(i).split(" ", QString::SkipEmptyParts);
487
if( (dw = dockMan.findDockableWidget(s.at(0))) ) {
488
if( s.at(1) == "D" ) {
490
DockableWidgetLayout::DockSide side;
492
side = DockableWidgetLayout::TOP;
493
else if( s.at(3) == "L" )
494
side = DockableWidgetLayout::LEFT;
495
else if( s.at(3) == "R" )
496
side = DockableWidgetLayout::RIGHT;
498
side = DockableWidgetLayout::BOTTOM;
499
dockMan.insertWidget( dw, 0, side, s.at(4).toInt(), s.at(5).toInt(), s.at(6).toInt() );
500
if( s.at(2) == "H" ) dw->hide();
501
} else if( s.at(1) == "F" ) {
503
dw->setFloating(true, s.at(2) == "V");
504
dw->resize( s.at(5).toInt(), s.at(6).toInt() );
505
dw->move( s.at(3).toInt(), s.at(4).toInt() );
510
// disable all widgets
513
connect(regsView, SIGNAL(pcChanged(quint16)),
514
disasmView, SLOT(setProgramCounter(quint16)));
515
connect(regsView, SIGNAL(flagsChanged(quint8)),
516
flagsView, SLOT(setFlags(quint8)));
517
connect(regsView, SIGNAL(spChanged(quint16)),
518
stackView, SLOT(setStackPointer(quint16)));
519
connect(disasmView, SIGNAL(toggleBreakpoint(int)),
520
SLOT(breakpointToggle(int)));
522
connect(&comm, SIGNAL(connectionReady()),
523
SLOT(initConnection()));
524
connect(&comm, SIGNAL(updateParsed(const QString&, const QString&, const QString&)),
525
SLOT(handleUpdate(const QString&, const QString&, const QString&)));
526
connect(&comm, SIGNAL(connectionTerminated()),
527
SLOT(connectionClosed()));
530
// added four bytes as runover buffer for dasm
531
// otherwise dasm would need to check the buffer end continously.
532
breakpoints.setMemoryLayout(&memLayout);
533
mainMemory = new unsigned char[65536 + 4];
534
memset(mainMemory, 0, 65536 + 4);
535
disasmView->setMemory(mainMemory);
536
disasmView->setBreakpoints(&breakpoints);
537
disasmView->setMemoryLayout(&memLayout);
538
disasmView->setSymbolTable(&symTable);
539
hexView->setDebuggable("memory", 65536);
540
stackView->setData(mainMemory, 65536);
541
slotView->setMemoryLayout(&memLayout);
544
DebuggerForm::~DebuggerForm()
549
void DebuggerForm::closeEvent( QCloseEvent *e )
552
Settings::get().setValue( "Layout/WindowGeometry", saveGeometry() );
554
QStringList layoutList;
555
// fill layout list with docked widgets
556
dockMan.getConfig( 0, layoutList );
557
// append floating widgets
558
QList<DockableWidget*>::const_iterator it = dockMan.managedWidgets().begin();
559
while( it != dockMan.managedWidgets().end() ) {
560
if( (*it)->isFloating() ) {
561
QString s("%1 F %2 %3 %4 %5 %6");
562
s = s.arg( (*it)->id() );
563
if( (*it)->isHidden() )
567
s = s.arg( (*it)->x() ).arg( (*it)->y() )
568
.arg( (*it)->width() ).arg( (*it)->height() );
569
layoutList.append( s );
573
Settings::get().setValue( "Layout/WidgetLayout", layoutList );
575
QMainWindow::closeEvent(e);
578
void DebuggerForm::initConnection()
580
systemConnectAction->setEnabled(false);
581
systemDisconnectAction->setEnabled(true);
583
comm.sendCommand(new QueryPauseHandler(*this));
584
comm.sendCommand(new QueryBreakedHandler(*this));
586
comm.sendCommand(new SimpleCommand("update enable status"));
588
comm.sendCommand(new ListDebuggablesHandler(*this));
590
// define 'debug_bin2hex' proc for internal use
591
comm.sendCommand(new SimpleCommand(
592
"proc debug_bin2hex { input } {\n"
594
" foreach i [split $input {}] {\n"
595
" append result [format %02X [scan $i %c]] \"\"\n"
600
// define 'debug_memmapper' proc for internal use
601
comm.sendCommand(new SimpleCommand(
602
"proc debug_memmapper { } {\n"
604
" for { set page 0 } { $page < 4 } { incr page } {\n"
605
" set tmp [get_selected_slot $page]\n"
606
" append result [lindex $tmp 0] [lindex $tmp 1] \"\\n\"\n"
607
" if { [lsearch [debug list] \"MapperIO\"] != -1} {\n"
608
" append result [debug read \"MapperIO\" $page] \"\\n\"\n"
610
" append result \"0\\n\"\n"
613
" for { set ps 0 } { $ps < 4 } { incr ps } {\n"
614
" if [machine_info issubslotted $ps] {\n"
615
" append result \"1\\n\"\n"
616
" for { set ss 0 } { $ss < 4 } { incr ss } {\n"
617
" append result [get_mapper_size $ps $ss] \"\\n\"\n"
620
" append result \"0\\n\"\n"
621
" append result [get_mapper_size $ps 0] \"\\n\"\n"
628
void DebuggerForm::connectionClosed()
630
systemPauseAction->setEnabled(false);
631
executeBreakAction->setEnabled(false);
632
executeRunAction->setEnabled(false);
633
executeStepAction->setEnabled(false);
634
executeStepOverAction->setEnabled(false);
635
executeStepOutAction->setEnabled(false);
636
executeRunToAction->setEnabled(false);
637
systemDisconnectAction->setEnabled(false);
638
systemConnectAction->setEnabled(true);
640
QList<DockableWidget*>::const_iterator it = dockMan.managedWidgets().begin();
641
while( it != dockMan.managedWidgets().end() ) {
642
(*it)->widget()->setEnabled(false);
647
void DebuggerForm::finalizeConnection(bool halted)
649
systemPauseAction->setEnabled(true);
658
QList<DockableWidget*>::const_iterator it = dockMan.managedWidgets().begin();
659
while( it != dockMan.managedWidgets().end() ) {
660
(*it)->widget()->setEnabled(true);
665
void DebuggerForm::handleUpdate(const QString& type, const QString& name,
666
const QString& message)
668
if (type == "status") {
670
if (message == "suspended") {
675
} else if (name == "paused") {
676
pauseStatusChanged(message == "true");
681
void DebuggerForm::pauseStatusChanged(bool isPaused)
683
systemPauseAction->setChecked(isPaused);
686
void DebuggerForm::breakOccured()
692
void DebuggerForm::updateData()
694
comm.sendCommand(new ListBreakPointsHandler(*this));
697
// note that a register update is processed, a signal is sent to other
698
// widgets as well. Any dependent updates shoud be called before this one.
699
CPURegRequest* regs = new CPURegRequest(*this);
700
comm.sendCommand(regs);
702
// refresh memory viewer
705
// refresh slot viewer
708
emit emulationChanged();
711
void DebuggerForm::setBreakMode()
713
executeBreakAction->setEnabled(false);
714
executeRunAction->setEnabled(true);
715
executeStepAction->setEnabled(true);
716
executeStepOverAction->setEnabled(true);
717
executeStepOutAction->setEnabled(true);
718
executeRunToAction->setEnabled(true);
719
breakpointToggleAction->setEnabled(true);
720
breakpointAddAction->setEnabled(true);
723
void DebuggerForm::setRunMode()
725
executeBreakAction->setEnabled(true);
726
executeRunAction->setEnabled(false);
727
executeStepAction->setEnabled(false);
728
executeStepOverAction->setEnabled(false);
729
executeStepOutAction->setEnabled(false);
730
executeRunToAction->setEnabled(false);
731
breakpointToggleAction->setEnabled(false);
732
breakpointAddAction->setEnabled(false);
735
void DebuggerForm::systemConnect()
737
OpenMSXConnection* connection = ConnectDialog::getConnection(this);
739
comm.connectToOpenMSX(connection);
743
void DebuggerForm::systemDisconnect()
745
comm.closeConnection();
748
void DebuggerForm::systemPause()
750
comm.sendCommand(new SimpleCommand(QString("set pause ") +
751
(systemPauseAction->isChecked() ? "true" : "false")));
754
void DebuggerForm::systemSymbolManager()
756
SymbolManager symManager( symTable, this );
758
emit symbolsChanged();
761
void DebuggerForm::systemPreferences()
763
PreferencesDialog prefs( this );
765
emit settingsChanged();
768
void DebuggerForm::executeBreak()
770
comm.sendCommand(new SimpleCommand("debug break"));
773
void DebuggerForm::executeRun()
775
comm.sendCommand(new SimpleCommand("debug cont"));
779
void DebuggerForm::executeStep()
781
comm.sendCommand(new SimpleCommand("debug step"));
785
void DebuggerForm::executeStepOver()
787
comm.sendCommand(new SimpleCommand("step_over"));
791
void DebuggerForm::executeRunTo()
793
comm.sendCommand(new SimpleCommand(
794
"run_to " + QString::number(disasmView->cursorAddress())));
798
void DebuggerForm::executeStepOut()
803
void DebuggerForm::breakpointToggle(int addr)
805
// toggle address unspecified, use cursor address
806
if (addr < 0) addr = disasmView->cursorAddress();
809
if (breakpoints.isBreakpoint(addr)) {
810
cmd = "debug remove_bp " + breakpoints.idString(addr);
812
int p = (addr & 0xC000) >> 14;
813
cmd.sprintf("debug set_bp %i { [ pc_in_slot %c %c %i ] }",
814
addr, memLayout.primarySlot[p],
815
memLayout.secondarySlot[p],
816
memLayout.mapperSegment[p]);
818
comm.sendCommand(new SimpleCommand(cmd));
820
comm.sendCommand(new ListBreakPointsHandler(*this));
823
void DebuggerForm::breakpointAdd()
825
BreakpointDialog bpd( memLayout, this );
827
if( bpd.address() > 0 ) {
828
QString cmd("debug set_bp %1 { [ pc_in_slot %2 %3 %4 ] }");
829
cmd = cmd.arg( bpd.address() );
831
if( bpd.slot() == -1 )
834
cmd = cmd.arg(bpd.slot());
836
if( bpd.subslot() == -1 )
839
cmd = cmd.arg(bpd.subslot());
841
if( bpd.segment() == -1 )
844
cmd = cmd.arg(bpd.segment());
846
comm.sendCommand(new SimpleCommand(cmd));
848
comm.sendCommand(new ListBreakPointsHandler(*this));
853
void DebuggerForm::showAbout()
856
this, "openMSX Debugger", QString(Version::FULL_VERSION.c_str())
860
void DebuggerForm::toggleRegisterDisplay()
862
toggleView( qobject_cast<DockableWidget*>(regsView->parentWidget()));
865
void DebuggerForm::toggleFlagsDisplay()
867
toggleView( qobject_cast<DockableWidget*>(flagsView->parentWidget()));
870
void DebuggerForm::toggleStackDisplay()
872
toggleView( qobject_cast<DockableWidget*>(stackView->parentWidget()));
875
void DebuggerForm::toggleSlotsDisplay()
877
toggleView( qobject_cast<DockableWidget*>(slotView->parentWidget()));
880
void DebuggerForm::toggleMemoryDisplay()
882
toggleView( qobject_cast<DockableWidget*>(hexView->parentWidget()));
885
void DebuggerForm::toggleView( DockableWidget* widget )
887
if( widget->isHidden() ) {
892
dockMan.visibilityChanged( widget );
895
void DebuggerForm::addDebuggableViewer()
897
// create new debuggable viewer window
898
DebuggableViewer *viewer = new DebuggableViewer;
899
DockableWidget *dw = new DockableWidget( dockMan );
900
dw->setWidget(viewer);
901
dw->setTitle(tr("Debuggable hex view"));
902
dw->setId("DEBUGVIEW");
903
dw->setFloating(true);
904
dw->setDestroyable(true);
905
dw->setMovable(true);
906
dw->setClosable(true);
907
connect( dw, SIGNAL( visibilityChanged(DockableWidget*) ),
908
this, SLOT( dockWidgetVisibilityChanged(DockableWidget*) ) );
909
connect( this, SIGNAL( debuggablesChanged(const QMap<QString,int>&) ),
910
viewer, SLOT( setDebuggables(const QMap<QString,int>&) ) );
911
connect( this, SIGNAL( emulationChanged() ),
912
viewer, SLOT( refresh() ) );
913
viewer->setDebuggables( debuggables );
914
viewer->setEnabled( disasmView->isEnabled() );
917
void DebuggerForm::dockWidgetVisibilityChanged( DockableWidget *w )
919
dockMan.visibilityChanged( w );
923
void DebuggerForm::updateViewMenu()
925
viewRegistersAction->setChecked( regsView->parentWidget()->isVisible() );
926
viewFlagsAction->setChecked( flagsView->isVisible() );
927
viewStackAction->setChecked( stackView->isVisible() );
928
viewSlotsAction->setChecked( slotView->isVisible() );
929
viewMemoryAction->setChecked( hexView->isVisible() );
932
void DebuggerForm::setDebuggables( const QString& list )
936
// process result string
937
QStringList l = list.split(" ", QString::SkipEmptyParts);
939
for( int i = 0; i < l.size(); i++ ) {
941
// combine multiple words
943
while( !d.endsWith("}") ) {
948
// set initial size to zero
951
// find the size for all debuggables
952
QMap<QString,int>::iterator it = debuggables.begin();
953
while( it != debuggables.end() ) {
954
comm.sendCommand(new DebuggableSizeHandler(it.key(), *this));
959
void DebuggerForm::setDebuggableSize( const QString& debuggable, int size )
961
debuggables[debuggable] = size;
962
// emit update if size of last debuggable was set
963
if( debuggable == debuggables.keys().last() )
964
emit debuggablesChanged( debuggables );