diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index d5e56a98a..78e59aa2a 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -877,7 +877,7 @@ std::array Debugger::ourBuiltinFunctions = { { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Names are defined here, but processed in YaccParser -std::array Debugger::ourPseudoRegisters = { { +std::array Debugger::ourPseudoRegisters = { { // Debugger::PseudoRegister Debugger::ourPseudoRegisters[NUM_PSEUDO_REGS] = { { "_bank", "Currently selected bank" }, { "_cclocks", "Color clocks on current scanline" }, @@ -885,6 +885,7 @@ std::array Debugger::ourPseudoRegisters = { { { "_cycleslo", "Lower 32 bits of number of cycles since emulation started" }, { "_fcount", "Number of frames since emulation started" }, { "_fcycles", "Number of cycles since frame started" }, + { "_fwsynccycles", "Number of cycles skipped by WSYNC since frame started" }, { "_icycles", "Number of cycles of last instruction" }, { "_scan", "Current scanline count" }, { "_scanend", "Scanline count at end of last frame" }, diff --git a/src/debugger/Debugger.hxx b/src/debugger/Debugger.hxx index d594820c6..8ba5c626f 100644 --- a/src/debugger/Debugger.hxx +++ b/src/debugger/Debugger.hxx @@ -363,7 +363,7 @@ class Debugger : public DialogContainer string name, help; }; static std::array ourBuiltinFunctions; - static std::array ourPseudoRegisters; + static std::array ourPseudoRegisters; private: // rewind/unwind n states diff --git a/src/debugger/TIADebug.cxx b/src/debugger/TIADebug.cxx index abde49c69..01b870d68 100644 --- a/src/debugger/TIADebug.cxx +++ b/src/debugger/TIADebug.cxx @@ -149,6 +149,7 @@ const DebuggerState& TIADebug::getState() myState.info.push_back(scanlines()); myState.info.push_back(scanlinesLastFrame()); myState.info.push_back(clocksThisLine()); + myState.info.push_back(frameWsyncCycles()); return myState; } @@ -258,6 +259,7 @@ void TIADebug::saveOldState() myOldState.info.push_back(scanlines()); myOldState.info.push_back(scanlinesLastFrame()); myOldState.info.push_back(clocksThisLine()); + myOldState.info.push_back(frameWsyncCycles()); } /* the set methods now use mySystem.poke(). This will save us the @@ -909,6 +911,12 @@ int TIADebug::frameCycles() const return myTIA.frameCycles(); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int TIADebug::frameWsyncCycles() const +{ + return myTIA.frameWSyncCycles(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int TIADebug::cyclesLo() const { diff --git a/src/debugger/TIADebug.hxx b/src/debugger/TIADebug.hxx index cf6171d17..0a2e21663 100644 --- a/src/debugger/TIADebug.hxx +++ b/src/debugger/TIADebug.hxx @@ -169,6 +169,7 @@ class TIADebug : public DebuggerSystem int scanlinesLastFrame() const; int frameCount() const; int frameCycles() const; + int frameWsyncCycles() const; int cyclesLo() const; int cyclesHi() const; int clocksThisLine() const; diff --git a/src/debugger/gui/CpuWidget.cxx b/src/debugger/gui/CpuWidget.cxx index 3493e53f8..31f939f01 100644 --- a/src/debugger/gui/CpuWidget.cxx +++ b/src/debugger/gui/CpuWidget.cxx @@ -39,6 +39,7 @@ CpuWidget::CpuWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& n const int fontWidth = lfont.getMaxCharWidth(), fontHeight = lfont.getFontHeight(), lineHeight = lfont.getLineHeight(); + const int VGAP = 2; int xpos, ypos, lwidth; // Create a 1x1 grid with label for the PC register @@ -58,7 +59,7 @@ CpuWidget::CpuWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& n myPCLabel->setEditable(false, true); // Create a 1x4 grid with labels for the other CPU registers - xpos = x + lwidth; ypos += myPCGrid->getHeight() + 1; + xpos = x + lwidth; ypos = myPCGrid->getBottom() + VGAP; myCpuGrid = new DataGridWidget(boss, nfont, xpos, ypos, 1, 4, 2, 8, Common::Base::Fmt::_16); myCpuGrid->setTarget(this); @@ -88,17 +89,11 @@ CpuWidget::CpuWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& n int src_y = ypos, src_w = (max_w - xpos + x) - 10; for(int i = 0; i < 4; ++i) { - myCpuDataSrc[i] = new EditTextWidget(boss, nfont, xpos, src_y, src_w, - fontHeight+1, ""); + myCpuDataSrc[i] = new EditTextWidget(boss, nfont, xpos, src_y, src_w, fontHeight + 1); myCpuDataSrc[i]->setEditable(false, true); - src_y += fontHeight+2; + src_y += fontHeight + 2; } - // Last write destination address - new StaticTextWidget(boss, lfont, xpos - fontWidth * 4.5, src_y + 4, "Dest"); - myCpuDataDest = new EditTextWidget(boss, nfont, xpos, src_y + 2, src_w, fontHeight+1); - myCpuDataDest->setEditable(false, true); - // Add labels for other CPU registers xpos = x; const std::array labels = { "SP ", "A ", "X ", "Y " }; @@ -121,7 +116,7 @@ CpuWidget::CpuWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& n } // Create a bitfield widget for changing the processor status - xpos = x; ypos += 4*lineHeight + 2; + xpos = x; ypos = myCpuGrid->getBottom() + VGAP; new StaticTextWidget(boss, lfont, xpos, ypos + 2, lwidth-2, fontHeight, "PS ", TextAlign::Left); myPSRegister = new ToggleBitWidget(boss, nfont, xpos+lwidth, ypos, 8, 1); @@ -140,6 +135,14 @@ CpuWidget::CpuWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& n } myPSRegister->setList(off, on); + // Last write destination address + xpos = myCpuDataSrc[0]->getLeft(); + new StaticTextWidget(boss, lfont, xpos - fontWidth * 4.5, ypos + 2, "Dest"); + myCpuDataDest = new EditTextWidget(boss, nfont, xpos, ypos, src_w, fontHeight + 1); + myCpuDataDest->setEditable(false, true); + + + _h = ypos + myPSRegister->getHeight() - y; } diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index be9ad7515..d7855e2f5 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -589,7 +589,7 @@ void DebuggerDialog::addRomArea() DataGridOpsWidget* ops = new DataGridOpsWidget(this, *myLFont, xpos, ypos); int max_w = xpos - r.x() - 10; - xpos = r.x() + 10; ypos = 10; + xpos = r.x() + 10; ypos = 5; myCpu = new CpuWidget(this, *myLFont, *myNFont, xpos, ypos, max_w); addToFocusList(myCpu->getFocusList()); diff --git a/src/debugger/gui/RamWidget.cxx b/src/debugger/gui/RamWidget.cxx index de09949e4..28a3d3ce8 100644 --- a/src/debugger/gui/RamWidget.cxx +++ b/src/debugger/gui/RamWidget.cxx @@ -53,8 +53,9 @@ RamWidget::RamWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& n // Add RAM grid (with scrollbar) int xpos = x + _font.getStringWidth("xxxx"); + bool useScrollbar = ramsize / numrows > 16; myRamGrid = new DataGridWidget(_boss, _nfont, xpos, ypos, - 16, myNumRows, 2, 8, Common::Base::Fmt::_16, true); + 16, myNumRows, 2, 8, Common::Base::Fmt::_16, useScrollbar); myRamGrid->setTarget(this); myRamGrid->setID(kRamGridID); addFocusWidget(myRamGrid); @@ -144,7 +145,6 @@ RamWidget::RamWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& n // Add Hex display of selected RAM cell xpos -= 4.5 * myFontWidth; - //s = new StaticTextWidget(boss, lfont, xpos, ypos, "$"); myHexValue = new DataGridWidget(boss, nfont, xpos, ypos - 2, 1, 1, 2, 8, Common::Base::Fmt::_16); myHexValue->setTarget(this); diff --git a/src/debugger/gui/TiaInfoWidget.cxx b/src/debugger/gui/TiaInfoWidget.cxx index 21681d2c0..35998d498 100644 --- a/src/debugger/gui/TiaInfoWidget.cxx +++ b/src/debugger/gui/TiaInfoWidget.cxx @@ -36,85 +36,82 @@ TiaInfoWidget::TiaInfoWidget(GuiObject* boss, const GUI::Font& lfont, { bool longstr = 11 + 32 * lfont.getMaxCharWidth() + 9 + EditTextWidget::calcWidth(lfont) * 3 <= max_w; - const int VGAP = 5; + const int VGAP = lfont.getLineHeight() / 4; + const int VBORDER = 5 + 1; x += 11; const int lineHeight = lfont.getLineHeight(); - int xpos = x, ypos = y + 10; - int lwidth = lfont.getStringWidth(longstr ? "Frame Cycle " : "F. Cycle "); + int xpos = x, ypos = y + VBORDER; + int lwidth = lfont.getStringWidth(longstr ? "Frame Cycle" : "F. Cycle") + _fontWidth * 0.5; + int l2width = lwidth - lfont.getMaxCharWidth() * 3; int fwidth = EditTextWidget::calcWidth(lfont, 5); int twidth = EditTextWidget::calcWidth(lfont, 8); - // Add frame info - // 1st column - new StaticTextWidget(boss, lfont, xpos, ypos, lwidth, lineHeight, - longstr ? "Frame Count " : "Frame ", - TextAlign::Left); - xpos += lwidth; - myFrameCount = new EditTextWidget(boss, nfont, xpos, ypos-1, fwidth, lineHeight, ""); + // Left column + // Left: Frame Count + new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Frame Count " : "Frame "); + myFrameCount = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight); myFrameCount->setEditable(false, true); + // Left: Frame Cycle xpos = x; ypos += lineHeight + VGAP; - new StaticTextWidget(boss, lfont, xpos, ypos, lwidth, lineHeight, - longstr ? "Frame Cycle " : "F. Cycle ", - TextAlign::Left); - xpos += lwidth; - myFrameCycles = new EditTextWidget(boss, nfont, xpos, ypos-1, fwidth, lineHeight, ""); + new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Frame Cycle " : "F. Cycle "); + myFrameCycles = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight); myFrameCycles->setEditable(false, true); - xpos = x; ypos += lineHeight + VGAP; - new StaticTextWidget(boss, lfont, xpos, ypos, lwidth, lineHeight, - "Total ", TextAlign::Left); - xpos += lfont.getStringWidth("Total "); - myTotalCycles = new EditTextWidget(boss, nfont, xpos, ypos - 1, twidth, lineHeight, ""); + // Left: WSync Cycles + ypos += lineHeight + VGAP; + new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "WSync Cycl. " : "WSync C. "); + myWSyncCylces = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight); + myWSyncCylces->setEditable(false, true); + + // Left: Total Cycles + ypos += lineHeight + VGAP; + new StaticTextWidget(boss, lfont, xpos, ypos + 1, "Total "); + myTotalCycles = new EditTextWidget(boss, nfont, xpos + l2width, ypos - 1, twidth, lineHeight); myTotalCycles->setEditable(false, true); - xpos = x; ypos += lineHeight + VGAP; - new StaticTextWidget(boss, lfont, xpos, ypos, lwidth, lineHeight, - "Delta ", TextAlign::Left); - xpos = x + lfont.getStringWidth("Delta "); - myDeltaCycles = new EditTextWidget(boss, nfont, xpos, ypos - 1, twidth, lineHeight, ""); + // Left: Delta Cycles + ypos += lineHeight + VGAP; + new StaticTextWidget(boss, lfont, xpos, ypos + 1, "Delta "); + myDeltaCycles = new EditTextWidget(boss, nfont, xpos + l2width, ypos - 1, twidth, lineHeight); myDeltaCycles->setEditable(false, true); - // 2nd column - xpos = x + lwidth + myFrameCycles->getWidth() + 9; ypos = y + 10; + // Right column + xpos = myFrameCycles->getRight() + _fontWidth * 1.25; ypos = y + VBORDER; lwidth = lfont.getStringWidth(longstr ? "Color Clock " : "Pixel Pos "); fwidth = EditTextWidget::calcWidth(lfont, 3); - new StaticTextWidget(boss, lfont, xpos, ypos, longstr ? "Scanline" : "Scn Ln"); - myScanlineCountLast = new EditTextWidget(boss, nfont, xpos+lwidth, ypos-1, fwidth, - lineHeight, ""); + // Right: Scanline + new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Scanline" : "Scn Ln"); + myScanlineCountLast = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight); myScanlineCountLast->setEditable(false, true); myScanlineCount = new EditTextWidget(boss, nfont, - xpos+lwidth - myScanlineCountLast->getWidth() - 2, ypos-1, fwidth, - lineHeight, ""); + xpos + lwidth - myScanlineCountLast->getWidth() - 2, ypos - 1, + fwidth, lineHeight); myScanlineCount->setEditable(false, true); + // Right: Scan Cycle ypos += lineHeight + VGAP; - new StaticTextWidget(boss, lfont, xpos, ypos, lwidth, lineHeight, - longstr ? "Scan Cycle " : "Scn Cycle", TextAlign::Left); - myScanlineCycles = new EditTextWidget(boss, nfont, xpos+lwidth, ypos-1, fwidth, - lineHeight, ""); + new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Scan Cycle " : "Scn Cycle"); + myScanlineCycles = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight); myScanlineCycles->setEditable(false, true); + // Right: Pixel Pos ypos += lineHeight + VGAP; - new StaticTextWidget(boss, lfont, xpos, ypos, lwidth, lineHeight, - "Pixel Pos ", TextAlign::Left); - myPixelPosition = new EditTextWidget(boss, nfont, xpos+lwidth, ypos-1, fwidth, - lineHeight, ""); + new StaticTextWidget(boss, lfont, xpos, ypos + 1, "Pixel Pos "); + myPixelPosition = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight); myPixelPosition->setEditable(false, true); + // Right: Color Clock ypos += lineHeight + VGAP; - new StaticTextWidget(boss, lfont, xpos, ypos, lwidth, lineHeight, - longstr ? "Color Clock " : "Color Clk ", TextAlign::Left); - - myColorClocks = new EditTextWidget(boss, nfont, xpos+lwidth, ypos-1, fwidth, - lineHeight, ""); + new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Color Clock " : "Color Clk "); + myColorClocks = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight); myColorClocks->setEditable(false, true); // Calculate actual dimensions - _w = myColorClocks->getAbsX() + myColorClocks->getWidth() - x; - _h = ypos + lineHeight; + _w = myColorClocks->getRight() - x; + _h = myDeltaCycles->getBottom(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -159,4 +156,7 @@ void TiaInfoWidget::loadConfig() clk != oldTia.info[6]); myColorClocks->setText(Common::Base::toString(clk, Common::Base::Fmt::_10), clk != oldTia.info[6]); + + myWSyncCylces->setText(Common::Base::toString(tia.frameWsyncCycles(), Common::Base::Fmt::_10_5), + tia.frameWsyncCycles() != oldTia.info[7]); } diff --git a/src/debugger/gui/TiaInfoWidget.hxx b/src/debugger/gui/TiaInfoWidget.hxx index 2f7796162..c0e029879 100644 --- a/src/debugger/gui/TiaInfoWidget.hxx +++ b/src/debugger/gui/TiaInfoWidget.hxx @@ -38,12 +38,13 @@ class TiaInfoWidget : public Widget, public CommandSender private: EditTextWidget* myFrameCount{nullptr}; EditTextWidget* myFrameCycles{nullptr}; - EditTextWidget* myTotalCycles{ nullptr }; + EditTextWidget* myTotalCycles{nullptr}; + EditTextWidget* myDeltaCycles{nullptr}; + EditTextWidget* myWSyncCylces{nullptr}; EditTextWidget* myScanlineCount{nullptr}; EditTextWidget* myScanlineCountLast{nullptr}; EditTextWidget* myScanlineCycles{nullptr}; - EditTextWidget* myDeltaCycles{ nullptr }; EditTextWidget* myPixelPosition{nullptr}; EditTextWidget* myColorClocks{nullptr}; diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx index 78a44fc55..e0f6e2dda 100644 --- a/src/emucore/tia/TIA.cxx +++ b/src/emucore/tia/TIA.cxx @@ -163,6 +163,7 @@ void TIA::initialize() myDelayQueue.reset(); myCyclesAtFrameStart = 0; + myFrameWsyncCycles = 0; if (myFrameManager) myFrameManager->reset(); @@ -279,6 +280,7 @@ bool TIA::save(Serializer& out) const out.putByteArray(myShadowRegisters.data(), myShadowRegisters.size()); out.putLong(myCyclesAtFrameStart); + out.putLong(myFrameWsyncCycles); out.putInt(myFrameBufferScanlines); out.putInt(myFrontBufferScanlines); @@ -351,6 +353,7 @@ bool TIA::load(Serializer& in) in.getByteArray(myShadowRegisters.data(), myShadowRegisters.size()); myCyclesAtFrameStart = in.getLong(); + myFrameWsyncCycles = in.getLong(); myFrameBufferScanlines = in.getInt(); myFrontBufferScanlines = in.getInt(); @@ -1304,6 +1307,7 @@ void TIA::updateEmulation() void TIA::onFrameStart() { myXAtRenderingStart = 0; + myFrameWsyncCycles = 0; // Check for colour-loss emulation if (myColorLossEnabled) @@ -1351,6 +1355,7 @@ void TIA::onHalt() { mySubClock += (TIAConstants::H_CLOCKS - myHctr) % TIAConstants::H_CLOCKS; mySystem->incrementCycles(mySubClock / TIAConstants::CYCLE_CLOCKS); + myFrameWsyncCycles += mySubClock / TIAConstants::CYCLE_CLOCKS; mySubClock %= TIAConstants::CYCLE_CLOCKS; } diff --git a/src/emucore/tia/TIA.hxx b/src/emucore/tia/TIA.hxx index 18609f087..a7c262117 100644 --- a/src/emucore/tia/TIA.hxx +++ b/src/emucore/tia/TIA.hxx @@ -334,6 +334,13 @@ class TIA : public Device return uInt32(mySystem->cycles() - myCyclesAtFrameStart); } + /** + Answers the system cycles used by WSYNC from the start of the current frame. + */ + uInt32 frameWSyncCycles() const { + return uInt32(myFrameWsyncCycles); + } + /** * Get the CPU cycles since the last dump ports change. * @@ -939,6 +946,11 @@ class TIA : public Device */ uInt64 myCyclesAtFrameStart{0}; + /** + * System cycles used by WSYNC during current frame. + */ + uInt64 myFrameWsyncCycles{0}; + /** * The frame manager can change during our lifetime, so we buffer those two. */ diff --git a/src/yacc/YaccParser.cxx b/src/yacc/YaccParser.cxx index 4de3c965f..f55450ad1 100644 --- a/src/yacc/YaccParser.cxx +++ b/src/yacc/YaccParser.cxx @@ -254,6 +254,8 @@ TiaMethod getTiaSpecial(char* ch) return &TIADebug::frameCount; else if(BSPF::equalsIgnoreCase(ch, "_fcycles")) return &TIADebug::frameCycles; + else if(BSPF::equalsIgnoreCase(ch, "_fwsynccycles")) + return &TIADebug::frameWsyncCycles; else if(BSPF::equalsIgnoreCase(ch, "_cyclesLo")) return &TIADebug::cyclesLo; else if(BSPF::equalsIgnoreCase(ch, "_cyclesHi"))