1//============================================================================
2//
3// SSSS tt lll lll
4// SS SS tt ll ll
5// SS tttttt eeee ll ll aaaa
6// SSSS tt ee ee ll ll aa
7// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8// SS SS tt ee ll ll aa aa
9// SSSS ttt eeeee llll llll aaaaa
10//
11// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
12// and the Stella Team
13//
14// See the file "License.txt" for information on usage and redistribution of
15// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16//============================================================================
17
18#include "Cart.hxx"
19#include "Widget.hxx"
20#include "Dialog.hxx"
21#include "Settings.hxx"
22#include "StellaKeys.hxx"
23#include "EventHandler.hxx"
24#include "TabWidget.hxx"
25#include "TiaInfoWidget.hxx"
26#include "TiaOutputWidget.hxx"
27#include "TiaZoomWidget.hxx"
28#include "AudioWidget.hxx"
29#include "PromptWidget.hxx"
30#include "CpuWidget.hxx"
31#include "RiotRamWidget.hxx"
32#include "RiotWidget.hxx"
33#include "RomWidget.hxx"
34#include "TiaWidget.hxx"
35#include "CartDebugWidget.hxx"
36#include "CartRamWidget.hxx"
37#include "DataGridOpsWidget.hxx"
38#include "EditTextWidget.hxx"
39#include "MessageBox.hxx"
40#include "Debugger.hxx"
41#include "DebuggerParser.hxx"
42#include "ConsoleFont.hxx"
43#include "ConsoleBFont.hxx"
44#include "ConsoleMediumFont.hxx"
45#include "ConsoleMediumBFont.hxx"
46#include "StellaMediumFont.hxx"
47#include "OptionsDialog.hxx"
48#include "StateManager.hxx"
49#include "DebuggerDialog.hxx"
50
51// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
52DebuggerDialog::DebuggerDialog(OSystem& osystem, DialogContainer& parent,
53 int x, int y, int w, int h)
54 : Dialog(osystem, parent, x, y, w, h),
55 myTab(nullptr),
56 myRomTab(nullptr),
57 myFatalError(nullptr),
58 myFirstLoad(true)
59{
60 createFont(); // Font is sized according to available space
61
62 addTiaArea();
63 addTabArea();
64 addStatusArea();
65 addRomArea();
66
67 // Inform the TIA output widget about its associated zoom widget
68 myTiaOutput->setZoomWidget(myTiaZoom);
69
70 myOptions = make_unique<OptionsDialog>(osystem, parent, this, w, h,
71 Menu::AppMode::debugger);
72}
73
74// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
75void DebuggerDialog::loadConfig()
76{
77 // set initial focus to myPrompt
78 if (myFirstLoad)
79 {
80 setFocus(myPrompt);
81 myFirstLoad = false;
82 }
83
84 myTab->loadConfig();
85 myTiaInfo->loadConfig();
86 myTiaOutput->loadConfig();
87 myTiaZoom->loadConfig();
88 myCpu->loadConfig();
89 myRam->loadConfig();
90 myRomTab->loadConfig();
91
92 myMessageBox->setText("");
93}
94
95// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
96void DebuggerDialog::handleKeyDown(StellaKey key, StellaMod mod, bool repeated)
97{
98 if(key == KBDK_GRAVE && !StellaModTest::isShift(mod))
99 {
100 // Swallow backtick, so we don't see it when exiting the debugger
101 instance().eventHandler().enableTextEvents(false);
102 }
103
104 // special debugger keys first (cannot be remapped)
105 if (StellaModTest::isControl(mod))
106 {
107 switch (key)
108 {
109 case KBDK_S:
110 doStep();
111 return;
112 case KBDK_T:
113 doTrace();
114 return;
115 case KBDK_L:
116 doScanlineAdvance();
117 return;
118 case KBDK_F:
119 doAdvance();
120 return;
121 default:
122 break;
123 }
124 }
125
126 // handle emulation keys second (can be remapped)
127 Event::Type event = instance().eventHandler().eventForKey(EventMode::kEmulationMode, key, mod);
128 switch (event)
129 {
130 // events which can be handled 1:1
131 case Event::ToggleP0Collision:
132 case Event::ToggleP0Bit:
133 case Event::ToggleP1Collision:
134 case Event::ToggleP1Bit:
135 case Event::ToggleM0Collision:
136 case Event::ToggleM0Bit:
137 case Event::ToggleM1Collision:
138 case Event::ToggleM1Bit:
139 case Event::ToggleBLCollision:
140 case Event::ToggleBLBit:
141 case Event::TogglePFCollision:
142 case Event::TogglePFBit:
143 case Event::ToggleFixedColors:
144 case Event::ToggleCollisions:
145 case Event::ToggleBits:
146
147 case Event::ToggleTimeMachine:
148
149 case Event::SaveState:
150 case Event::SaveAllStates:
151 case Event::ChangeState:
152 case Event::LoadState:
153 case Event::LoadAllStates:
154
155 case Event::ConsoleColor:
156 case Event::ConsoleBlackWhite:
157 case Event::ConsoleColorToggle:
158 case Event::Console7800Pause:
159 case Event::ConsoleLeftDiffA:
160 case Event::ConsoleLeftDiffB:
161 case Event::ConsoleLeftDiffToggle:
162 case Event::ConsoleRightDiffA:
163 case Event::ConsoleRightDiffB:
164 case Event::ConsoleRightDiffToggle:
165 instance().eventHandler().handleEvent(event);
166 return;
167
168 // events which need special handling in debugger
169 case Event::TakeSnapshot:
170 instance().debugger().parser().run("savesnap");
171 return;
172
173 case Event::Rewind1Menu:
174 doRewind();
175 return;
176
177 case Event::Rewind10Menu:
178 doRewind10();
179 return;
180
181 case Event::RewindAllMenu:
182 doRewindAll();
183 return;
184
185 case Event::Unwind1Menu:
186 doUnwind();
187 return;
188
189 case Event::Unwind10Menu:
190 doUnwind10();
191 return;
192
193 case Event::UnwindAllMenu:
194 doUnwindAll();
195 return;
196
197 default:
198 break;
199 }
200
201 Dialog::handleKeyDown(key, mod);
202}
203
204// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
205void DebuggerDialog::handleCommand(CommandSender* sender, int cmd,
206 int data, int id)
207{
208 // We reload the tabs in the cases where the actions could possibly
209 // change their contents
210 switch(cmd)
211 {
212 case kDDStepCmd:
213 doStep();
214 break;
215
216 case kDDTraceCmd:
217 doTrace();
218 break;
219
220 case kDDAdvCmd:
221 doAdvance();
222 break;
223
224 case kDDSAdvCmd:
225 doScanlineAdvance();
226 break;
227
228 case kDDRewindCmd:
229 doRewind();
230 break;
231
232 case kDDUnwindCmd:
233 doUnwind();
234 break;
235
236 case kDDExitCmd:
237 doExitDebugger();
238 break;
239
240 case kDDExitFatalCmd:
241 doExitRom();
242 break;
243
244 case kDDOptionsCmd:
245 myOptions->open();
246 loadConfig();
247 break;
248
249 case RomWidget::kInvalidateListing:
250 // Only do a full redraw if the disassembly tab is actually showing
251 myRom->invalidate(myRomTab->getActiveTab() == 0);
252 break;
253
254 default:
255 Dialog::handleCommand(sender, cmd, data, id);
256 }
257}
258
259// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
260void DebuggerDialog::doStep()
261{
262 instance().debugger().parser().run("step");
263 setDirty();
264}
265
266// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
267void DebuggerDialog::doTrace()
268{
269 instance().debugger().parser().run("trace");
270 setDirty();
271}
272
273// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
274void DebuggerDialog::doAdvance()
275{
276 instance().debugger().parser().run("frame #1");
277 setDirty();
278}
279
280// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
281void DebuggerDialog::doScanlineAdvance()
282{
283 instance().debugger().parser().run("scanline #1");
284 setDirty();
285}
286
287// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
288void DebuggerDialog::doRewind()
289{
290 instance().debugger().parser().run("rewind");
291 setDirty();
292}
293
294// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
295void DebuggerDialog::doUnwind()
296{
297 instance().debugger().parser().run("unwind");
298 setDirty();
299}
300
301// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
302void DebuggerDialog::doRewind10()
303{
304 instance().debugger().parser().run("rewind #10");
305 setDirty();
306}
307
308// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
309void DebuggerDialog::doUnwind10()
310{
311 instance().debugger().parser().run("unwind #10");
312 setDirty();
313}
314
315// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
316void DebuggerDialog::doRewindAll()
317{
318 instance().debugger().parser().run("rewind #1000");
319 setDirty();
320}
321
322// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
323void DebuggerDialog::doUnwindAll()
324{
325 instance().debugger().parser().run("unwind #1000");
326 setDirty();
327}
328
329// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
330void DebuggerDialog::doExitDebugger()
331{
332 instance().debugger().parser().run("run");
333 setDirty();
334}
335
336// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
337void DebuggerDialog::doExitRom()
338{
339 instance().debugger().parser().run("exitrom");
340 setDirty();
341}
342
343// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
344void DebuggerDialog::createFont()
345{
346 string fontSize = instance().settings().getString("dbg.fontsize");
347 int fontStyle = instance().settings().getInt("dbg.fontstyle");
348
349 if(fontSize == "large")
350 {
351 // Large font doesn't use fontStyle at all
352 myLFont = make_unique<GUI::Font>(GUI::stellaMediumDesc);
353 myNFont = make_unique<GUI::Font>(GUI::stellaMediumDesc);
354 }
355 else if(fontSize == "medium")
356 {
357 switch(fontStyle)
358 {
359 case 1:
360 myLFont = make_unique<GUI::Font>(GUI::consoleMediumBDesc);
361 myNFont = make_unique<GUI::Font>(GUI::consoleMediumDesc);
362 break;
363 case 2:
364 myLFont = make_unique<GUI::Font>(GUI::consoleMediumDesc);
365 myNFont = make_unique<GUI::Font>(GUI::consoleMediumBDesc);
366 break;
367 case 3:
368 myLFont = make_unique<GUI::Font>(GUI::consoleMediumBDesc);
369 myNFont = make_unique<GUI::Font>(GUI::consoleMediumBDesc);
370 break;
371 default: // default to zero
372 myLFont = make_unique<GUI::Font>(GUI::consoleMediumDesc);
373 myNFont = make_unique<GUI::Font>(GUI::consoleMediumDesc);
374 break;
375 }
376 }
377 else
378 {
379 switch(fontStyle)
380 {
381 case 1:
382 myLFont = make_unique<GUI::Font>(GUI::consoleBDesc);
383 myNFont = make_unique<GUI::Font>(GUI::consoleDesc);
384 break;
385 case 2:
386 myLFont = make_unique<GUI::Font>(GUI::consoleDesc);
387 myNFont = make_unique<GUI::Font>(GUI::consoleBDesc);
388 break;
389 case 3:
390 myLFont = make_unique<GUI::Font>(GUI::consoleBDesc);
391 myNFont = make_unique<GUI::Font>(GUI::consoleBDesc);
392 break;
393 default: // default to zero
394 myLFont = make_unique<GUI::Font>(GUI::consoleDesc);
395 myNFont = make_unique<GUI::Font>(GUI::consoleDesc);
396 break;
397 }
398 }
399}
400
401// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
402void DebuggerDialog::showFatalMessage(const string& msg)
403{
404 myFatalError = make_unique<GUI::MessageBox>(this, *myLFont, msg, _w/2, _h/2,
405 kDDExitFatalCmd, "Exit ROM", "Continue", "Fatal error");
406 myFatalError->show();
407}
408
409// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
410void DebuggerDialog::addTiaArea()
411{
412 const Common::Rect& r = getTiaBounds();
413 myTiaOutput =
414 new TiaOutputWidget(this, *myNFont, r.x(), r.y(), r.w(), r.h());
415}
416
417// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
418void DebuggerDialog::addTabArea()
419{
420 const Common::Rect& r = getTabBounds();
421 const int vBorder = 4;
422
423 // The tab widget
424 // Since there are two tab widgets in this dialog, we specifically
425 // assign an ID of 0
426 myTab = new TabWidget(this, *myLFont, r.x(), r.y() + vBorder,
427 r.w(), r.h() - vBorder);
428 myTab->setID(0);
429 addTabWidget(myTab);
430
431 const int widWidth = r.w() - vBorder;
432 const int widHeight = r.h() - myTab->getTabHeight() - vBorder - 4;
433 int tabID;
434
435 // The Prompt/console tab
436 tabID = myTab->addTab("Prompt");
437 myPrompt = new PromptWidget(myTab, *myNFont,
438 2, 2, widWidth - 4, widHeight);
439 myTab->setParentWidget(tabID, myPrompt);
440 addToFocusList(myPrompt->getFocusList(), myTab, tabID);
441
442 // The TIA tab
443 tabID = myTab->addTab("TIA");
444 TiaWidget* tia = new TiaWidget(myTab, *myLFont, *myNFont,
445 2, 2, widWidth, widHeight);
446 myTab->setParentWidget(tabID, tia);
447 addToFocusList(tia->getFocusList(), myTab, tabID);
448
449 // The input/output tab (includes RIOT and INPTx from TIA)
450 tabID = myTab->addTab("I/O");
451 RiotWidget* riot = new RiotWidget(myTab, *myLFont, *myNFont,
452 2, 2, widWidth, widHeight);
453 myTab->setParentWidget(tabID, riot);
454 addToFocusList(riot->getFocusList(), myTab, tabID);
455
456 // The Audio tab
457 tabID = myTab->addTab("Audio");
458 AudioWidget* aud = new AudioWidget(myTab, *myLFont, *myNFont,
459 2, 2, widWidth, widHeight);
460 myTab->setParentWidget(tabID, aud);
461 addToFocusList(aud->getFocusList(), myTab, tabID);
462
463 myTab->setActiveTab(0);
464}
465
466// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
467void DebuggerDialog::addStatusArea()
468{
469 const int lineHeight = myLFont->getLineHeight();
470 const Common::Rect& r = getStatusBounds();
471 int xpos, ypos;
472
473 xpos = r.x(); ypos = r.y();
474 myTiaInfo = new TiaInfoWidget(this, *myLFont, *myNFont, xpos, ypos, r.w());
475
476 ypos += myTiaInfo->getHeight() + 10;
477 myTiaZoom = new TiaZoomWidget(this, *myNFont, xpos+10, ypos,
478 r.w()-10, r.h()-lineHeight-ypos-10);
479 addToFocusList(myTiaZoom->getFocusList());
480
481 xpos += 10; ypos += myTiaZoom->getHeight() + 10;
482 myMessageBox = new EditTextWidget(this, *myLFont,
483 xpos, ypos, myTiaZoom->getWidth(),
484 myLFont->getLineHeight(), "");
485 myMessageBox->setEditable(false, false);
486 myMessageBox->clearFlags(Widget::FLAG_RETAIN_FOCUS);
487 myMessageBox->setTextColor(kTextColorEm);
488}
489
490// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
491void DebuggerDialog::addRomArea()
492{
493 static uInt32 LEFT_ARROW[11] =
494 {
495 0b0000010,
496 0b0000110,
497 0b0001110,
498 0b0011110,
499 0b0111110,
500 0b1111110,
501 0b0111110,
502 0b0011110,
503 0b0001110,
504 0b0000110,
505 0b0000010
506 };
507 static uInt32 RIGHT_ARROW[11] =
508 {
509 0b0100000,
510 0b0110000,
511 0b0111000,
512 0b0111100,
513 0b0111110,
514 0b0111111,
515 0b0111110,
516 0b0111100,
517 0b0111000,
518 0b0110000,
519 0b0100000
520 };
521
522 const Common::Rect& r = getRomBounds();
523 const int VBORDER = 4;
524 WidgetArray wid1, wid2;
525 ButtonWidget* b;
526
527 int bwidth = myLFont->getStringWidth("Frame +1 "),
528 bheight = myLFont->getLineHeight() + 2;
529 int buttonX = r.x() + r.w() - bwidth - 5, buttonY = r.y() + 5;
530
531 b = new ButtonWidget(this, *myLFont, buttonX, buttonY,
532 bwidth, bheight, "Step", kDDStepCmd, true);
533 wid2.push_back(b);
534 buttonY += bheight + 4;
535 b = new ButtonWidget(this, *myLFont, buttonX, buttonY,
536 bwidth, bheight, "Trace", kDDTraceCmd, true);
537 wid2.push_back(b);
538 buttonY += bheight + 4;
539 b = new ButtonWidget(this, *myLFont, buttonX, buttonY,
540 bwidth, bheight, "Scan +1", kDDSAdvCmd, true);
541 wid2.push_back(b);
542 buttonY += bheight + 4;
543 b = new ButtonWidget(this, *myLFont, buttonX, buttonY,
544 bwidth, bheight, "Frame +1", kDDAdvCmd, true);
545 wid2.push_back(b);
546 buttonY += bheight + 4;
547 b = new ButtonWidget(this, *myLFont, buttonX, buttonY,
548 bwidth, bheight, "Exit", kDDExitCmd);
549 wid2.push_back(b);
550 addCancelWidget(b);
551
552 bwidth = bheight; // 7 + 12;
553 bheight = bheight * 3 + 4 * 2;
554 buttonX -= (bwidth + 5);
555 buttonY = r.y() + 5;
556
557 myRewindButton =
558 new ButtonWidget(this, *myLFont, buttonX, buttonY,
559 bwidth, bheight, LEFT_ARROW, 7, 11, kDDRewindCmd, true);
560 myRewindButton->clearFlags(Widget::FLAG_ENABLED);
561
562 buttonY += bheight + 4;
563 bheight = (myLFont->getLineHeight() + 2) * 2 + 4 * 1;
564
565 myUnwindButton =
566 new ButtonWidget(this, *myLFont, buttonX, buttonY,
567 bwidth, bheight, RIGHT_ARROW, 7, 11, kDDUnwindCmd, true);
568 myUnwindButton->clearFlags(Widget::FLAG_ENABLED);
569
570 int xpos = buttonX - 8*myLFont->getMaxCharWidth() - 20, ypos = 30;
571
572 bwidth = myLFont->getStringWidth("Options " + ELLIPSIS);
573 bheight = myLFont->getLineHeight() + 2;
574
575 b = new ButtonWidget(this, *myLFont, xpos, r.y() + 5, bwidth, bheight,
576 "Options" + ELLIPSIS, kDDOptionsCmd);
577 wid1.push_back(b);
578 wid1.push_back(myRewindButton);
579 wid1.push_back(myUnwindButton);
580
581 DataGridOpsWidget* ops = new DataGridOpsWidget(this, *myLFont, xpos, ypos);
582
583 int max_w = xpos - r.x() - 10;
584 xpos = r.x() + 10; ypos = 10;
585 myCpu = new CpuWidget(this, *myLFont, *myNFont, xpos, ypos, max_w);
586 addToFocusList(myCpu->getFocusList());
587
588 addToFocusList(wid1);
589 addToFocusList(wid2);
590
591 xpos = r.x() + 10; ypos += myCpu->getHeight() + 10;
592 myRam = new RiotRamWidget(this, *myLFont, *myNFont, xpos, ypos, r.w() - 10);
593 addToFocusList(myRam->getFocusList());
594
595 // Add the DataGridOpsWidget to any widgets which contain a
596 // DataGridWidget which we want controlled
597 myCpu->setOpsWidget(ops);
598 myRam->setOpsWidget(ops);
599
600 ////////////////////////////////////////////////////////////////////
601 // Disassembly area
602
603 xpos = r.x() + VBORDER; ypos += myRam->getHeight() + 5;
604 const int tabWidth = r.w() - VBORDER - 1;
605 const int tabHeight = r.h() - ypos - 1;
606 int tabID;
607
608 // Since there are two tab widgets in this dialog, we specifically
609 // assign an ID of 1
610 myRomTab = new TabWidget(
611 this, *myLFont, xpos, ypos, tabWidth, tabHeight);
612 myRomTab->setID(1);
613 addTabWidget(myRomTab);
614
615 // The main disassembly tab
616 tabID = myRomTab->addTab(" Disassembly ", TabWidget::AUTO_WIDTH);
617 myRom = new RomWidget(myRomTab, *myLFont, *myNFont, 2, 2, tabWidth - 1,
618 tabHeight - myRomTab->getTabHeight() - 2);
619 myRomTab->setParentWidget(tabID, myRom);
620 addToFocusList(myRom->getFocusList(), myRomTab, tabID);
621
622 // The 'cart-specific' information tab (optional)
623
624 tabID = myRomTab->addTab(" " + instance().console().cartridge().name() + " ", TabWidget::AUTO_WIDTH);
625 myCartInfo = instance().console().cartridge().infoWidget(
626 myRomTab, *myLFont, *myNFont, 2, 2, tabWidth - 1,
627 tabHeight - myRomTab->getTabHeight() - 2);
628 if(myCartInfo != nullptr)
629 {
630 myRomTab->setParentWidget(tabID, myCartInfo);
631 addToFocusList(myCartInfo->getFocusList(), myRomTab, tabID);
632 tabID = myRomTab->addTab(" States ", TabWidget::AUTO_WIDTH);
633 }
634
635 // The 'cart-specific' state tab
636 myCartDebug = instance().console().cartridge().debugWidget(
637 myRomTab, *myLFont, *myNFont, 2, 2, tabWidth - 1,
638 tabHeight - myRomTab->getTabHeight() - 2);
639 if(myCartDebug) // TODO - make this always non-null
640 {
641 myRomTab->setParentWidget(tabID, myCartDebug);
642 addToFocusList(myCartDebug->getFocusList(), myRomTab, tabID);
643
644 // The cartridge RAM tab
645 if (myCartDebug->internalRamSize() > 0)
646 {
647 tabID = myRomTab->addTab(" Cartridge RAM ", TabWidget::AUTO_WIDTH);
648 myCartRam =
649 new CartRamWidget(myRomTab, *myLFont, *myNFont, 2, 2, tabWidth - 1,
650 tabHeight - myRomTab->getTabHeight() - 2, *myCartDebug);
651 if(myCartRam) // TODO - make this always non-null
652 {
653 myRomTab->setParentWidget(tabID, myCartRam);
654 addToFocusList(myCartRam->getFocusList(), myRomTab, tabID);
655 myCartRam->setOpsWidget(ops);
656 }
657 }
658 }
659
660 myRomTab->setActiveTab(0);
661}
662
663// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
664Common::Rect DebuggerDialog::getTiaBounds() const
665{
666 // The area showing the TIA image (NTSC and PAL supported, up to 260 lines)
667 return Common::Rect(0, 0, 320, std::max(260, int(_h * 0.35)));
668}
669
670// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
671Common::Rect DebuggerDialog::getRomBounds() const
672{
673 // The ROM area is the full area to the right of the tabs
674 const Common::Rect& status = getStatusBounds();
675 return Common::Rect(status.x() + status.w() + 1, 0, _w, _h);
676}
677
678// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
679Common::Rect DebuggerDialog::getStatusBounds() const
680{
681 // The status area is the full area to the right of the TIA image
682 // extending as far as necessary
683 // 30% of any space above 1030 pixels will be allocated to this area
684 const Common::Rect& tia = getTiaBounds();
685
686 int x1 = tia.x() + tia.w() + 1;
687 int y1 = 0;
688 int x2 = tia.x() + tia.w() + 225 + (_w > 1030 ? int(0.35 * (_w - 1030)) : 0);
689 int y2 = tia.y() + tia.h();
690
691 return Common::Rect(x1, y1, x2, y2);
692}
693
694// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
695Common::Rect DebuggerDialog::getTabBounds() const
696{
697 // The tab area is the full area below the TIA image
698 const Common::Rect& tia = getTiaBounds();
699 const Common::Rect& status = getStatusBounds();
700
701 return Common::Rect(0, tia.y() + tia.h() + 1,
702 status.x() + status.w() + 1, _h);
703}
704