diff --git a/src/debugger/RiotDebug.cxx b/src/debugger/RiotDebug.cxx index 72ea6d484..f1852fcc0 100644 --- a/src/debugger/RiotDebug.cxx +++ b/src/debugger/RiotDebug.cxx @@ -393,13 +393,13 @@ string RiotDebug::toString() << " 295/TIM8T=" << Debugger::invIfChanged(state.TIM8T, oldstate.TIM8T) << " 296/TIM64T=" << Debugger::invIfChanged(state.TIM64T, oldstate.TIM64T) << " 297/T1024T=" << Debugger::invIfChanged(state.T1024T, oldstate.T1024T) + << " Divider=" << Debugger::invIfChanged(state.TIMDIV, oldstate.TIMDIV) << endl << "0x284/INTIM=" << Debugger::invIfChanged(state.INTIM, oldstate.INTIM) << " 285/TIMINT=" << Debugger::invIfChanged(state.TIMINT, oldstate.TIMINT) << " Timer_Clocks=" << Debugger::invIfChanged(state.TIMCLKS, oldstate.TIMCLKS) << " INTIM_Clocks=" << Debugger::invIfChanged(state.INTIMCLKS, oldstate.INTIMCLKS) - << " Divider=" << Debugger::invIfChanged(state.TIMDIV, oldstate.TIMDIV) << endl << "Left/P0diff: " << diffP0String() << " Right/P1diff: " << diffP1String() diff --git a/src/debugger/gui/RiotWidget.cxx b/src/debugger/gui/RiotWidget.cxx index d6c1f857c..3970609bb 100644 --- a/src/debugger/gui/RiotWidget.cxx +++ b/src/debugger/gui/RiotWidget.cxx @@ -17,10 +17,10 @@ #include "Settings.hxx" #include "DataGridWidget.hxx" -#include "EditTextWidget.hxx" #include "FrameBuffer.hxx" #include "GuiObject.hxx" #include "OSystem.hxx" +#include "EventHandler.hxx" #include "Debugger.hxx" #include "RiotDebug.hxx" #include "PopUpWidget.hxx" @@ -51,10 +51,13 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont, : Widget(boss, lfont, x, y, w, h), CommandSender(boss) { - const int fontWidth = lfont.getMaxCharWidth(), - fontHeight = lfont.getFontHeight(), - lineHeight = lfont.getLineHeight(); - int xpos = 10, ypos = 25, lwidth = 8 * fontWidth, col = 0; + const int fontHeight = lfont.getFontHeight(), + hGap = _fontWidth, + vGap = fontHeight / 2, + hBorder = 10, + vBorder = 10; + int xpos = hBorder, ypos = vBorder + _lineHeight, + lwidth = _fontWidth * 8 + hGap; StaticTextWidget* t = nullptr; VariantList items; @@ -70,9 +73,8 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont, StringList labels; #define CREATE_IO_REGS(desc, bits, bitsID, editable) \ - t = new StaticTextWidget(boss, lfont, xpos, ypos+2, lwidth, fontHeight, \ - desc); \ - xpos += t->getWidth() + 5; \ + new StaticTextWidget(boss, lfont, xpos, ypos + 2, desc); \ + xpos = hBorder + lwidth; \ (bits) = new ToggleBitWidget(boss, nfont, xpos, ypos, 8, 1, 1, labels); \ (bits)->setTarget(this); \ (bits)->setID(bitsID); \ @@ -82,14 +84,13 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont, // SWCHA bits in 'poke' mode labels.clear(); CREATE_IO_REGS("SWCHA(W)", mySWCHAWriteBits, kSWCHABitsID, true) - col = xpos + mySWCHAWriteBits->getWidth() + 25; // remember this for adding widgets to the second column // SWACNT bits - xpos = 10; ypos += lineHeight + 5; + xpos = hBorder; ypos += _lineHeight + vGap / 2; CREATE_IO_REGS("SWACNT", mySWACNTBits, kSWACNTBitsID, true) // SWCHA bits in 'peek' mode - xpos = 10; ypos += lineHeight + 5; + xpos = hBorder; ypos += _lineHeight + vGap / 2; labels.clear(); labels.emplace_back("Left right"); labels.emplace_back("Left left"); @@ -102,16 +103,16 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont, CREATE_IO_REGS("SWCHA(R)", mySWCHAReadBits, kSWCHARBitsID, true) // SWCHB bits in 'poke' mode - xpos = 10; ypos += 2 * lineHeight; + xpos = hBorder; ypos = mySWCHAReadBits->getBottom() + vGap * 2; labels.clear(); CREATE_IO_REGS("SWCHB(W)", mySWCHBWriteBits, kSWCHBBitsID, true) // SWBCNT bits - xpos = 10; ypos += lineHeight + 5; + xpos = hBorder; ypos += _lineHeight + vGap / 2; CREATE_IO_REGS("SWBCNT", mySWBCNTBits, kSWBCNTBitsID, true) // SWCHB bits in 'peek' mode - xpos = 10; ypos += lineHeight + 5; + xpos = hBorder; ypos += _lineHeight + vGap / 2; labels.clear(); labels.emplace_back("Right difficulty"); labels.emplace_back("Left difficulty"); @@ -127,53 +128,65 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont, static constexpr std::array writeNames = { "TIM1T", "TIM8T", "TIM64T", "T1024T" }; - xpos = 10; ypos += 2*lineHeight; + ypos += _lineHeight + vGap * 4; for(int row = 0; row < 4; ++row) { - t = new StaticTextWidget(boss, lfont, xpos, ypos + row*lineHeight + 2, - lwidth, fontHeight, writeNames[row], TextAlign::Left); + myTimWriteLabel[row] = new StaticTextWidget(boss, lfont, hBorder, ypos + row * _lineHeight + 2, + writeNames[row]); } - xpos += t->getWidth() + 5; + xpos = hBorder + lwidth; myTimWrite = new DataGridWidget(boss, nfont, xpos, ypos, 1, 4, 2, 8, Common::Base::Fmt::_16); myTimWrite->setTarget(this); myTimWrite->setID(kTimWriteID); addFocusWidget(myTimWrite); - t = new StaticTextWidget(boss, lfont, myTimWrite->getRight() + _fontWidth, ypos + 2 , "#"); - myTimClocks = new DataGridWidget(boss, nfont, t->getRight() + _fontWidth / 2, ypos, + t = new StaticTextWidget(boss, lfont, + myTimWrite->getRight() + hGap * 2, + ypos + _lineHeight * 1.5 + 2 , "#"); + myTimAvail = new DataGridWidget(boss, nfont, t->getRight() + hGap / 2, t->getTop() - 2, 1, 1, 6, 30, Common::Base::Fmt::_10_6); - myTimClocks->setToolTip("Number of CPU cycles available for current timer interval.\n"); - myTimClocks->setTarget(this); - myTimClocks->setEditable(false); + myTimAvail->setToolTip("Number of CPU cycles available for current timer interval.\n"); + myTimAvail->setTarget(this); + myTimAvail->setEditable(false); // Timer registers (RO) - static constexpr std::array readNames = { - "INTIM", "TIMINT", "Total Clks", "INTIM Clks", "Divider #" + static constexpr std::array readNames = { + "INTIM", " Clocks", "TIMINT" }; - xpos = 10; ypos += myTimWrite->getHeight() + lineHeight / 2; - for(int row = 0; row < 5; ++row) + ypos = myTimWrite->getBottom() + _lineHeight / 2; + for(int row = 0; row < 3; ++row) { - t = new StaticTextWidget(boss, lfont, xpos, ypos + row * lineHeight + 2, + t = new StaticTextWidget(boss, lfont, hBorder, ypos + row * _lineHeight + 2, readNames[row]); } - xpos += t->getWidth() + _fontWidth / 2; - myTimRead = new DataGridWidget(boss, nfont, xpos, ypos, 1, 4, 4, 30, Common::Base::Fmt::_16); - myTimRead->setToolTip(0, 1, "Timer interrupt flag in bit 7.\n"); - myTimRead->setToolTip(0, 2, "Number of CPU cycles since last TIMxxT write.\n"); + xpos = hBorder + lwidth; + myTimRead = new DataGridWidget(boss, nfont, xpos, ypos, 1, 3, 2, 30, Common::Base::Fmt::_16); + myTimRead->setToolTip(0, 1, "Remaining timer interval clocks.\n"); + myTimRead->setToolTip(0, 2, "Timer interrupt flag in bit 7.\n"); myTimRead->setTarget(this); myTimRead->setEditable(false); - ypos += myTimRead->getHeight() - 1; - myTimDivider = new DataGridWidget(boss, nfont, xpos, ypos, 1, 1, 4, 12, Common::Base::Fmt::_10_4); - myTimDivider->setTarget(this); - myTimDivider->setEditable(false); + t = new StaticTextWidget(boss, lfont, + myTimWrite->getRight() + hGap * 2, + ypos + _lineHeight * 0.5 + 2 , "#"); + new StaticTextWidget(boss, lfont, + myTimWrite->getRight() + hGap * 2, + ypos + _lineHeight * 1.5 + 2 , "#"); + myTimTotal = new DataGridWidget(boss, nfont, t->getRight() + hGap / 2, t->getTop() - 2, + 1, 2, 6, 30, Common::Base::Fmt::_10_6); + myTimTotal->setToolTip(0, 0, "Number of CPU cycles since last TIMxxT write.\n"); + myTimTotal->setToolTip(0, 1, "Number of CPU cycles remaining.\n"); + myTimTotal->setTarget(this); + myTimTotal->setEditable(false); + // Controller ports - xpos = col; ypos = 10; + int col = mySWCHAWriteBits->getRight() + hGap * 2.5; + xpos = col; ypos = vBorder; myLeftControl = addControlWidget(boss, lfont, xpos, ypos, instance().console().leftController()); addToFocusList(myLeftControl->getFocusList()); - xpos += myLeftControl->getWidth() + 15; + xpos = myLeftControl->getRight() + hGap * 1.5; myRightControl = addControlWidget(boss, lfont, xpos, ypos, instance().console().rightController()); addToFocusList(myRightControl->getFocusList()); @@ -182,13 +195,13 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont, static constexpr std::array contLeftReadNames = { "INPT0", "INPT1", "INPT4" }; - xpos = col; ypos += myLeftControl->getHeight() + 2 * lineHeight; + xpos = myLeftControl->getLeft(); ypos += myLeftControl->getHeight() + 2 * _lineHeight; for(int row = 0; row < 3; ++row) { - new StaticTextWidget(boss, lfont, xpos, ypos + row*lineHeight + 2, - 5*fontWidth, fontHeight, contLeftReadNames[row], TextAlign::Left); + t = new StaticTextWidget(boss, lfont, xpos, ypos + row * _lineHeight + 2, + contLeftReadNames[row]); } - xpos += 5*fontWidth + 5; + xpos = t->getRight() + hGap; myLeftINPT = new DataGridWidget(boss, nfont, xpos, ypos, 1, 3, 2, 8, Common::Base::Fmt::_16); myLeftINPT->setTarget(this); myLeftINPT->setEditable(false); @@ -197,23 +210,23 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont, static constexpr std::array contRightReadNames = { "INPT2", "INPT3", "INPT5" }; - xpos = col + myLeftControl->getWidth() + 15; + xpos = myRightControl->getLeft(); for(int row = 0; row < 3; ++row) { - new StaticTextWidget(boss, lfont, xpos, ypos + row*lineHeight + 2, - 5*fontWidth, fontHeight, contRightReadNames[row], TextAlign::Left); + t = new StaticTextWidget(boss, lfont, xpos, ypos + row*_lineHeight + 2, + contRightReadNames[row]); } - xpos += 5*fontWidth + 5; + xpos = t->getRight() + hGap; myRightINPT = new DataGridWidget(boss, nfont, xpos, ypos, 1, 3, 2, 8, Common::Base::Fmt::_16); myRightINPT->setTarget(this); myRightINPT->setEditable(false); // TIA INPTx VBLANK bits (D6-latch, D7-dump) (R) - xpos = col + 20; ypos += myLeftINPT->getHeight() + lineHeight; + xpos = col + hGap * 2; ypos = myLeftINPT->getBottom() + vGap; myINPTLatch = new CheckboxWidget(boss, lfont, xpos, ypos, "INPT latch (VBlank D6)"); myINPTLatch->setTarget(this); myINPTLatch->setEditable(false); - ypos += lineHeight + 5; + ypos += _lineHeight + vGap / 2; myINPTDump = new CheckboxWidget(boss, lfont, xpos, ypos, "INPT dump to gnd (VBlank D7)"); myINPTDump->setTarget(this); myINPTDump->setEditable(false); @@ -221,57 +234,63 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont, // PO & P1 difficulty switches int pwidth = lfont.getStringWidth("B/easy"); lwidth = lfont.getStringWidth("Right Diff "); - xpos = col; ypos += 2 * lineHeight; - const int col2_ypos = ypos; + xpos = col; ypos = myINPTDump->getBottom() + vGap * 4; items.clear(); VarList::push_back(items, "B/easy", "b"); VarList::push_back(items, "A/hard", "a"); - myP0Diff = new PopUpWidget(boss, lfont, xpos, ypos, pwidth, lineHeight, items, + myP0Diff = new PopUpWidget(boss, lfont, xpos, ypos, pwidth, _lineHeight, items, "Left Diff ", lwidth, kP0DiffChanged); myP0Diff->setTarget(this); addFocusWidget(myP0Diff); - ypos += myP0Diff->getHeight() + 5; - myP1Diff = new PopUpWidget(boss, lfont, xpos, ypos, pwidth, lineHeight, items, + ypos = myP0Diff->getBottom() + vGap / 2; + myP1Diff = new PopUpWidget(boss, lfont, xpos, ypos, pwidth, _lineHeight, items, "Right Diff ", lwidth, kP1DiffChanged); myP1Diff->setTarget(this); addFocusWidget(myP1Diff); // TV Type - ypos += myP1Diff->getHeight() + 5; + ypos = myP1Diff->getBottom() + vGap / 2; items.clear(); VarList::push_back(items, "B&W", "bw"); VarList::push_back(items, "Color", "color"); - myTVType = new PopUpWidget(boss, lfont, xpos, ypos, pwidth, lineHeight, items, + myTVType = new PopUpWidget(boss, lfont, xpos, ypos, pwidth, _lineHeight, items, "TV Type ", lwidth, kTVTypeChanged); + myTVType->setToolTip("Atari 2600 Color/B&W switch."); myTVType->setTarget(this); addFocusWidget(myTVType); // 2600/7800 mode - lwidth = lfont.getStringWidth("Console") + 29; - pwidth = lfont.getStringWidth("Atari 2600") + 6; - new StaticTextWidget(boss, lfont, 10, ypos+1, "Console"); - myConsole = new EditTextWidget(boss, lfont, 10 + lwidth, ypos - 1, pwidth, lineHeight); - myConsole->setEditable(false, true); + pwidth = lfont.getStringWidth("Atari 2600"); + items.clear(); + VarList::push_back(items, "Atari 2600", "2600"); + VarList::push_back(items, "Atari 7800", "7800"); + + new StaticTextWidget(boss, lfont, hBorder, ypos + 1, "Console"); + myConsole = new PopUpWidget(boss, lfont, mySWCHBReadBits->getLeft(), ypos - 1, + pwidth, _lineHeight, items, "", 0, kConsoleID); + myConsole->setTarget(this); + myConsole->setToolTip("Emulated console."); addFocusWidget(myConsole); - // Select and Reset - xpos += myP0Diff->getWidth() + 20; ypos = col2_ypos + 1; + // Select, Reset and Pause + xpos = myP0Diff->getRight() + hGap * 2; ypos = myP0Diff->getTop() + 1; mySelect = new CheckboxWidget(boss, lfont, xpos, ypos, "Select", CheckboxWidget::kCheckActionCmd); mySelect->setID(kSelectID); mySelect->setTarget(this); addFocusWidget(mySelect); - ypos += myP0Diff->getHeight() + 5; + ypos = myP1Diff->getTop() + 1; myReset = new CheckboxWidget(boss, lfont, xpos, ypos, "Reset", CheckboxWidget::kCheckActionCmd); myReset->setID(kResetID); myReset->setTarget(this); addFocusWidget(myReset); - ypos += myP0Diff->getHeight() + 5; + ypos = myTVType->getTop() + 1; myPause = new CheckboxWidget(boss, lfont, xpos, ypos, "Pause", CheckboxWidget::kCheckActionCmd); + myPause->setToolTip("Atari 7800 pause switch."); myPause->setID(kPauseID); myPause->setTarget(this); addFocusWidget(myPause); @@ -349,41 +368,45 @@ void RiotWidget::loadConfig() alist.push_back(kTim1024TID); vlist.push_back(state.T1024T); changed.push_back(state.T1024T != oldstate.T1024T); myTimWrite->setList(alist, vlist, changed); + myTimWriteLabel[0]->setEnabled(state.TIM1T); + myTimWriteLabel[1]->setEnabled(state.TIM8T); + myTimWriteLabel[2]->setEnabled(state.TIM64T); + myTimWriteLabel[3]->setEnabled(state.T1024T); alist.clear(); vlist.clear(); changed.clear(); alist.push_back(0); + Int32 avail = 0; if(state.TIM1T) - vlist.push_back((state.TIM1T - 1) * 1); + avail = (state.TIM1T - 1) * 1; else if(state.TIM8T) - vlist.push_back((state.TIM8T - 1) * 8); + avail = (state.TIM8T - 1) * 8; else if(state.TIM64T) - vlist.push_back((state.TIM64T - 1) * 64); + avail = (state.TIM64T - 1) * 64; else if(state.T1024T) - vlist.push_back((state.T1024T - 1) * 1024); - else - vlist.push_back(0); + avail = (state.T1024T - 1) * 1024; + vlist.push_back(avail); changed.push_back(state.TIM1T != oldstate.TIM1T || state.TIM8T != oldstate.TIM8T || state.TIM64T != oldstate.TIM64T || state.T1024T != oldstate.T1024T); - myTimClocks->setList(alist, vlist, changed); + myTimAvail->setList(alist, vlist, changed); // Update timer read registers alist.clear(); vlist.clear(); changed.clear(); alist.push_back(0); vlist.push_back(state.INTIM); changed.push_back(state.INTIM != oldstate.INTIM); - alist.push_back(0); vlist.push_back(state.TIMINT); - changed.push_back(state.TIMINT != oldstate.TIMINT); - alist.push_back(0); vlist.push_back(state.TIMCLKS); - changed.push_back(state.TIMCLKS != oldstate.TIMCLKS); alist.push_back(0); vlist.push_back(state.INTIMCLKS); changed.push_back(state.INTIMCLKS != oldstate.INTIMCLKS); + alist.push_back(0); vlist.push_back(state.TIMINT); + changed.push_back(state.TIMINT != oldstate.TIMINT); myTimRead->setList(alist, vlist, changed); alist.clear(); vlist.clear(); changed.clear(); - alist.push_back(0); vlist.push_back(state.TIMDIV); - changed.push_back(state.TIMDIV != oldstate.TIMDIV); - myTimDivider->setList(alist, vlist, changed); + alist.push_back(0); vlist.push_back(state.TIMCLKS); + changed.push_back(state.TIMCLKS != oldstate.TIMCLKS); + alist.push_back(0); vlist.push_back(avail - state.TIMCLKS); + changed.push_back(state.TIMCLKS != oldstate.TIMCLKS); + myTimTotal->setList(alist, vlist, changed); // Console switches (inverted, since 'selected' in the UI // means 'grounded' in the system) @@ -391,8 +414,7 @@ void RiotWidget::loadConfig() myP1Diff->setSelectedIndex(riot.diffP1(), state.swchbReadBits[0] != oldstate.swchbReadBits[0]); const bool devSettings = instance().settings().getBool("dev.settings"); - myConsole->setText(instance().settings().getString(devSettings ? "dev.console" : "plr.console") == "7800" ? "Atari 7800" : "Atari 2600"); - myConsole->setEditable(false, true); + myConsole->setSelected(instance().settings().getString(devSettings ? "dev.console" : "plr.console")); myTVType->setSelectedIndex(riot.tvType(), state.swchbReadBits[4] != oldstate.swchbReadBits[4]); myPause->setState(!riot.tvType(), state.swchbReadBits[4] != oldstate.swchbReadBits[4]); @@ -486,6 +508,16 @@ void RiotWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) } break; + case kConsoleID: + { + Settings& settings = instance().settings(); + const string& prefix = settings.getBool("dev.settings") ? "dev." : "plr."; + + settings.setValue(prefix + "console", myConsole->getSelectedTag()); + instance().eventHandler().set7800Mode(); + break; + } + case CheckboxWidget::kCheckActionCmd: switch(id) { diff --git a/src/debugger/gui/RiotWidget.hxx b/src/debugger/gui/RiotWidget.hxx index 6a1a8f99e..ad9862a8c 100644 --- a/src/debugger/gui/RiotWidget.hxx +++ b/src/debugger/gui/RiotWidget.hxx @@ -19,6 +19,7 @@ #define RIOT_WIDGET_HXX class GuiObject; +class StaticTextWidget; class ButtonWidget; class DataGridWidget; class PopUpWidget; @@ -26,7 +27,6 @@ class ToggleBitWidget; class ControllerWidget; class Controller; -#include "Widget.hxx" #include "Command.hxx" class RiotWidget : public Widget, public CommandSender @@ -58,10 +58,11 @@ class RiotWidget : public Widget, public CommandSender CheckboxWidget* myINPTLatch{nullptr}; CheckboxWidget* myINPTDump{nullptr}; + std::array myTimWriteLabel{nullptr}; DataGridWidget* myTimWrite{nullptr}; - DataGridWidget* myTimClocks{nullptr}; + DataGridWidget* myTimAvail{nullptr}; DataGridWidget* myTimRead{nullptr}; - DataGridWidget* myTimDivider{nullptr}; + DataGridWidget* myTimTotal{nullptr}; ControllerWidget *myLeftControl{nullptr}, *myRightControl{nullptr}; PopUpWidget *myP0Diff{nullptr}, *myP1Diff{nullptr}; @@ -70,7 +71,7 @@ class RiotWidget : public Widget, public CommandSender CheckboxWidget* myReset{nullptr}; CheckboxWidget* myPause{nullptr}; - EditTextWidget* myConsole{nullptr}; + PopUpWidget *myConsole{nullptr}; // ID's for the various widgets // We need ID's, since there are more than one of several types of widgets @@ -78,7 +79,7 @@ class RiotWidget : public Widget, public CommandSender kTim1TID, kTim8TID, kTim64TID, kTim1024TID, kTimWriteID, kSWCHABitsID, kSWACNTBitsID, kSWCHBBitsID, kSWBCNTBitsID, kP0DiffChanged, kP1DiffChanged, kTVTypeChanged, kSelectID, kResetID, - kSWCHARBitsID, kSWCHBRBitsID, kPauseID + kSWCHARBitsID, kSWCHBRBitsID, kPauseID, kConsoleID }; private: diff --git a/src/gui/DeveloperDialog.cxx b/src/gui/DeveloperDialog.cxx index ea167b831..645d43745 100644 --- a/src/gui/DeveloperDialog.cxx +++ b/src/gui/DeveloperDialog.cxx @@ -145,7 +145,7 @@ void DeveloperDialog::addEmulationTab(const GUI::Font& font) myConsoleWidget = new PopUpWidget(myTab, font, HBORDER + INDENT * 1, ypos, pwidth, lineHeight, items, "Console ", lwidth, kConsole); myConsoleWidget->setToolTip("Emulate Color/B&W/Pause key and zero\n" - "page RAM initialization differenly."); + "page RAM initialization differently."); wid.push_back(myConsoleWidget); ypos += lineHeight + VGAP;