fully resolved #165 (added timer read cycles count)

refined TiaInfoWidget again
added doc
This commit is contained in:
thrust26 2020-10-13 15:11:35 +02:00
parent f6d78e57b1
commit 7eece4e994
18 changed files with 125 additions and 44 deletions

View File

@ -753,6 +753,8 @@ that holds 'number of scanlines' on an actual console).</p>
<tr><td> _cycleslo</td><td> Lower 32 bits of number of cycles since emulation started</td></tr> <tr><td> _cycleslo</td><td> Lower 32 bits of number of cycles since emulation started</td></tr>
<tr><td> _fcount</td><td> Number of frames since emulation started</td></tr> <tr><td> _fcount</td><td> Number of frames since emulation started</td></tr>
<tr><td> _fcycles</td><td> Number of cycles since frame started</td></tr> <tr><td> _fcycles</td><td> Number of cycles since frame started</td></tr>
<tr><td> _ftimreadcycles</td><td>Number of cycles used by timer reads since frame started</td></tr>
<tr><td> _fwsynccycles</td><td>Number of cycles skipped by WSYNC since frame started</td></tr>
<tr><td> _icycles</td><td> Number of cycles of last instruction</td></tr> <tr><td> _icycles</td><td> Number of cycles of last instruction</td></tr>
<tr><td> _scan</td><td> Current scanline count</td></tr> <tr><td> _scan</td><td> Current scanline count</td></tr>
<tr><td> _scanend</td><td> Scanline count at end of last frame</td></tr> <tr><td> _scanend</td><td> Scanline count at end of last frame</td></tr>
@ -1137,12 +1139,16 @@ as illustrated:</p>
<p><img src="graphics/debugger_tiainfo.png"></p> <p><img src="graphics/debugger_tiainfo.png"></p>
<p>The indicators are as follows (note that all these are read-only):</p> <p>The indicators are as follows (note that all these are read-only):</p>
<ul> <ul>
<li><b>Frame Count</b>: The number of frames since this ROM was loaded or reset.</li>
<li><b>Frame Cycle</b>: The number of CPU cycles that have been executed this frame since <li><b>Frame Cycle</b>: The number of CPU cycles that have been executed this frame since
VSYNC was cleared at scanline 0.</li> VSYNC was cleared at scanline 0.</li>
<li><b>WSync Cycl.</b>: The number of CPU cycles that have been skipped by WSYNC this frame since
VSYNC was cleared at scanline 0.</li>
<li><b>Timer Cycl.</b>: The number of CPU cycles (approximately) that have been used by timer read loops since
VSYNC was cleared at scanline 0.</li>
<li><b>Total</b>: The total number of CPU cycles since this ROM was loaded or reset.</li> <li><b>Total</b>: The total number of CPU cycles since this ROM was loaded or reset.</li>
<li><b>Delta</b>: The number of CPU cycles that have been executed since the last debugger <li><b>Delta</b>: The number of CPU cycles that have been executed since the last debugger
interrupt.</li> interrupt.</li>
<li><b>Frame Cnt.</b>: The number of frames since this ROM was loaded or reset.</li>
<li><b>Scanline</b>: The scanline that's currently being drawn, and the count from the <li><b>Scanline</b>: The scanline that's currently being drawn, and the count from the
previous frame. Scanline 0 is the one on which VSYNC is cleared (after being set for previous frame. Scanline 0 is the one on which VSYNC is cleared (after being set for
3 scanlines, as per the Stella Programmer's Guide).</li> 3 scanlines, as per the Stella Programmer's Guide).</li>
@ -1275,10 +1281,9 @@ are lost (they will NOT end up in the Carry flag).</p>
<p>This is a spreadsheet-like GUI for inspecting and changing the contents <p>This is a spreadsheet-like GUI for inspecting and changing the contents
of the 2600's zero-page RAM.</p> of the 2600's zero-page RAM.</p>
<p>You can navigate with either the mouse or the keyboard arrow keys. <p>You can navigate with either the mouse or the keyboard arrow keys.
To change a RAM location, either double-click on it or press Enter while To change a RAM location, either double-click on it or press 'Enter' while
it's highlighted. Enter the new value (hex only for now, sorry), then it's highlighted. Enter the new value (hex, other formats using the bottom textboxes), then
press Enter to make the change. If you change your mind, press Escape press 'Enter' to make the change. The currently selected RAM cell
and the original value will be restored. The currently selected RAM cell
can also be changed by using the can also be changed by using the
<a href="#DataOpButtons"><b>Data Operations Buttons</b></a> or the associated <a href="#DataOpButtons"><b>Data Operations Buttons</b></a> or the associated
shortcut keys.</p> shortcut keys.</p>
@ -1289,7 +1294,8 @@ more comprehensive. It will undo <b>all</b> operations on <b>all</b> cells
since you first made a change.</p> since you first made a change.</p>
<p>The UI objects at the bottom refer to the currently selected RAM cell. <p>The UI objects at the bottom refer to the currently selected RAM cell.
The 'Label' textbox shows the label attached to this RAM location (if any), The 'Label' textbox shows the label attached to this RAM location (if any),
and the other two textboxes show the decimal and binary equivalent value.</p> and the other three textboxes show the hex, decimal and binary equivalent value.
The values can be edited here too.</p>
<p>The remaining buttons to the right are further explained in the next section.</p> <p>The remaining buttons to the right are further explained in the next section.</p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -877,7 +877,7 @@ std::array<Debugger::BuiltinFunction, 18> Debugger::ourBuiltinFunctions = { {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Names are defined here, but processed in YaccParser // Names are defined here, but processed in YaccParser
std::array<Debugger::PseudoRegister, 15> Debugger::ourPseudoRegisters = { { std::array<Debugger::PseudoRegister, 16> Debugger::ourPseudoRegisters = { {
// Debugger::PseudoRegister Debugger::ourPseudoRegisters[NUM_PSEUDO_REGS] = { // Debugger::PseudoRegister Debugger::ourPseudoRegisters[NUM_PSEUDO_REGS] = {
{ "_bank", "Currently selected bank" }, { "_bank", "Currently selected bank" },
{ "_cclocks", "Color clocks on current scanline" }, { "_cclocks", "Color clocks on current scanline" },
@ -885,6 +885,7 @@ std::array<Debugger::PseudoRegister, 15> Debugger::ourPseudoRegisters = { {
{ "_cycleslo", "Lower 32 bits of number of cycles since emulation started" }, { "_cycleslo", "Lower 32 bits of number of cycles since emulation started" },
{ "_fcount", "Number of frames since emulation started" }, { "_fcount", "Number of frames since emulation started" },
{ "_fcycles", "Number of cycles since frame started" }, { "_fcycles", "Number of cycles since frame started" },
{ "_ftimreadcycles","Number of cycles used by timer reads since frame started" },
{ "_fwsynccycles", "Number of cycles skipped by WSYNC since frame started" }, { "_fwsynccycles", "Number of cycles skipped by WSYNC since frame started" },
{ "_icycles", "Number of cycles of last instruction" }, { "_icycles", "Number of cycles of last instruction" },
{ "_scan", "Current scanline count" }, { "_scan", "Current scanline count" },

View File

@ -363,7 +363,7 @@ class Debugger : public DialogContainer
string name, help; string name, help;
}; };
static std::array<BuiltinFunction, 18> ourBuiltinFunctions; static std::array<BuiltinFunction, 18> ourBuiltinFunctions;
static std::array<PseudoRegister, 15> ourPseudoRegisters; static std::array<PseudoRegister, 16> ourPseudoRegisters;
private: private:
// rewind/unwind n states // rewind/unwind n states

View File

@ -68,6 +68,8 @@ const DebuggerState& RiotDebug::getState()
myState.INTIMCLKS = intimClocks(); myState.INTIMCLKS = intimClocks();
myState.TIMDIV = timDivider(); myState.TIMDIV = timDivider();
myState.timReadCycles = timReadCycles();
return myState; return myState;
} }
@ -111,6 +113,8 @@ void RiotDebug::saveOldState()
myOldState.TIMCLKS = timClocks(); myOldState.TIMCLKS = timClocks();
myOldState.INTIMCLKS = intimClocks(); myOldState.INTIMCLKS = intimClocks();
myOldState.TIMDIV = timDivider(); myOldState.TIMDIV = timDivider();
myOldState.timReadCycles = timReadCycles();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -247,6 +251,12 @@ int RiotDebug::timWrappedOnWrite() const
return mySystem.m6532().myTimWrappedOnWrite; return mySystem.m6532().myTimWrappedOnWrite;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int RiotDebug::timReadCycles() const
{
return mySystem.m6532().myTimReadCycles;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool RiotDebug::diffP0(int newVal) bool RiotDebug::diffP0(int newVal)
{ {

View File

@ -41,6 +41,7 @@ class RiotState : public DebuggerState
uInt8 TIM1T{0}, TIM8T{0}, TIM64T{0}, T1024T{0}, INTIM{0}, TIMINT{0}; uInt8 TIM1T{0}, TIM8T{0}, TIM64T{0}, T1024T{0}, INTIM{0}, TIMINT{0};
Int32 TIMCLKS{0}, INTIMCLKS{0}, TIMDIV{0}; Int32 TIMCLKS{0}, INTIMCLKS{0}, TIMDIV{0};
uInt16 timReadCycles;
// These are actually from the TIA, but are I/O related // These are actually from the TIA, but are I/O related
uInt8 INPT0{0}, INPT1{0}, INPT2{0}, INPT3{0}, INPT4{0}, INPT5{0}; uInt8 INPT0{0}, INPT1{0}, INPT2{0}, INPT3{0}, INPT4{0}, INPT5{0};
@ -83,6 +84,8 @@ class RiotDebug : public DebuggerSystem
int timWrappedOnRead() const; int timWrappedOnRead() const;
int timWrappedOnWrite() const; int timWrappedOnWrite() const;
int timReadCycles() const;
/* Console switches */ /* Console switches */
bool diffP0(int newVal = -1); bool diffP0(int newVal = -1);
bool diffP1(int newVal = -1); bool diffP1(int newVal = -1);

View File

@ -478,20 +478,21 @@ void DebuggerDialog::addStatusArea()
{ {
const int lineHeight = myLFont->getLineHeight(); const int lineHeight = myLFont->getLineHeight();
const Common::Rect& r = getStatusBounds(); const Common::Rect& r = getStatusBounds();
const int HBORDER = 10;
const int VGAP = lineHeight / 3;
int xpos, ypos; int xpos, ypos;
xpos = r.x(); ypos = r.y(); xpos = r.x() + HBORDER; ypos = r.y();
myTiaInfo = new TiaInfoWidget(this, *myLFont, *myNFont, xpos, ypos, r.w()); myTiaInfo = new TiaInfoWidget(this, *myLFont, *myNFont, xpos, ypos, r.w() - HBORDER);
ypos += myTiaInfo->getHeight() + 8; ypos = myTiaInfo->getBottom() + VGAP;
myTiaZoom = new TiaZoomWidget(this, *myNFont, xpos + 10, ypos, myTiaZoom = new TiaZoomWidget(this, *myNFont, xpos, ypos,
r.w() - 10, r.h() - lineHeight - ypos - 3); r.w() - HBORDER, r.h() - ypos - VGAP - lineHeight + 3);
addToFocusList(myTiaZoom->getFocusList()); addToFocusList(myTiaZoom->getFocusList());
xpos += 10; ypos += myTiaZoom->getHeight() + 6; ypos = myTiaZoom->getBottom() + VGAP;
myMessageBox = new EditTextWidget(this, *myLFont, myMessageBox = new EditTextWidget(this, *myLFont, xpos, ypos,
xpos, ypos, myTiaZoom->getWidth(), myTiaZoom->getWidth(), lineHeight);
myLFont->getLineHeight(), "");
myMessageBox->setEditable(false, false); myMessageBox->setEditable(false, false);
myMessageBox->clearFlags(Widget::FLAG_RETAIN_FOCUS); myMessageBox->clearFlags(Widget::FLAG_RETAIN_FOCUS);
myMessageBox->setTextColor(kTextColorEm); myMessageBox->setTextColor(kTextColorEm);

View File

@ -19,6 +19,7 @@
#include "Font.hxx" #include "Font.hxx"
#include "OSystem.hxx" #include "OSystem.hxx"
#include "Debugger.hxx" #include "Debugger.hxx"
#include "RiotDebug.hxx"
#include "TIADebug.hxx" #include "TIADebug.hxx"
#include "TIA.hxx" #include "TIA.hxx"
#include "Widget.hxx" #include "Widget.hxx"
@ -34,55 +35,71 @@ TiaInfoWidget::TiaInfoWidget(GuiObject* boss, const GUI::Font& lfont,
: Widget(boss, lfont, x, y, 16, 16), : Widget(boss, lfont, x, y, 16, 16),
CommandSender(boss) CommandSender(boss)
{ {
bool longstr = 11 + 32 * lfont.getMaxCharWidth() + 9
+ EditTextWidget::calcWidth(lfont) * 3 <= max_w;
const int VGAP = lfont.getLineHeight() / 4; const int VGAP = lfont.getLineHeight() / 4;
const int VBORDER = 5 + 1; const int VBORDER = 5 + 1;
const int COLUMN_GAP = _fontWidth * 1.25;
x += 11; bool longstr = lfont.getStringWidth("Frame Cycle12345") + _fontWidth * 0.5
+ COLUMN_GAP + lfont.getStringWidth("Scanline262262")
+ EditTextWidget::calcWidth(lfont) * 3 <= max_w;
const int lineHeight = lfont.getLineHeight(); const int lineHeight = lfont.getLineHeight();
int xpos = x, ypos = y + VBORDER; int xpos = x, ypos = y + VBORDER;
int lwidth = lfont.getStringWidth(longstr ? "Frame Cycle" : "F. Cycle") + _fontWidth * 0.5; int lwidth = lfont.getStringWidth(longstr ? "Frame Cycle" : "F. Cycle");
int l2width = lwidth - lfont.getMaxCharWidth() * 3; int lwidth8 = lwidth - lfont.getMaxCharWidth() * 3;
int lwidthR = lfont.getStringWidth(longstr ? "Frame Cnt." : "Frame ");
int fwidth = EditTextWidget::calcWidth(lfont, 5); int fwidth = EditTextWidget::calcWidth(lfont, 5);
int twidth = EditTextWidget::calcWidth(lfont, 8); const int twidth = EditTextWidget::calcWidth(lfont, 8);
const int LGAP = (max_w - lwidth - EditTextWidget::calcWidth(lfont, 5)
- lwidthR - EditTextWidget::calcWidth(lfont, 5)) / 4;
lwidth += LGAP;
lwidth8 += LGAP;
lwidthR += LGAP;
// Left column // 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 // Left: Frame Cycle
xpos = x; ypos += lineHeight + VGAP; xpos = x;
new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Frame Cycle " : "F. Cycle "); new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Frame Cycle" : "F. Cycle");
myFrameCycles = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight); myFrameCycles = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight);
myFrameCycles->setEditable(false, true); myFrameCycles->setEditable(false, true);
// Left: WSync Cycles // Left: WSync Cycles
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "WSync Cycl. " : "WSync C. "); new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "WSync Cycl." : "WSync C.");
myWSyncCylces = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight); myWSyncCylces = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight);
myWSyncCylces->setEditable(false, true); myWSyncCylces->setEditable(false, true);
// Left: Timer Cycles
ypos += lineHeight + VGAP;
new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Timer Cycl." : "Timer C.");
myTimerCylces = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight);
myTimerCylces->setEditable(false, true);
// Left: Total Cycles // Left: Total Cycles
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
new StaticTextWidget(boss, lfont, xpos, ypos + 1, "Total "); new StaticTextWidget(boss, lfont, xpos, ypos + 1, "Total");
myTotalCycles = new EditTextWidget(boss, nfont, xpos + l2width, ypos - 1, twidth, lineHeight); myTotalCycles = new EditTextWidget(boss, nfont, xpos + lwidth8, ypos - 1, twidth, lineHeight);
myTotalCycles->setEditable(false, true); myTotalCycles->setEditable(false, true);
// Left: Delta Cycles // Left: Delta Cycles
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
new StaticTextWidget(boss, lfont, xpos, ypos + 1, "Delta "); new StaticTextWidget(boss, lfont, xpos, ypos + 1, "Delta");
myDeltaCycles = new EditTextWidget(boss, nfont, xpos + l2width, ypos - 1, twidth, lineHeight); myDeltaCycles = new EditTextWidget(boss, nfont, xpos + lwidth8, ypos - 1, twidth, lineHeight);
myDeltaCycles->setEditable(false, true); myDeltaCycles->setEditable(false, true);
// Right column // Right column
xpos = myFrameCycles->getRight() + _fontWidth * 1.25; ypos = y + VBORDER; xpos = x + max_w - lwidthR - EditTextWidget::calcWidth(lfont, 5); ypos = y + VBORDER;
lwidth = lfont.getStringWidth(longstr ? "Color Clock " : "Pixel Pos "); //xpos = myDeltaCycles->getRight() + LGAP * 2; ypos = y + VBORDER;
// Right: Frame Count
new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Frame Cnt." : "Frame");
myFrameCount = new EditTextWidget(boss, nfont, xpos + lwidthR, ypos - 1, fwidth, lineHeight);
myFrameCount->setEditable(false, true);
lwidth = lfont.getStringWidth(longstr ? "Color Clock " : "Pixel Pos ") + LGAP;
fwidth = EditTextWidget::calcWidth(lfont, 3); fwidth = EditTextWidget::calcWidth(lfont, 3);
// Right: Scanline // Right: Scanline
ypos += lineHeight + VGAP;
new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Scanline" : "Scn Ln"); new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Scanline" : "Scn Ln");
myScanlineCountLast = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight); myScanlineCountLast = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight);
myScanlineCountLast->setEditable(false, true); myScanlineCountLast->setEditable(false, true);
@ -93,25 +110,25 @@ TiaInfoWidget::TiaInfoWidget(GuiObject* boss, const GUI::Font& lfont,
// Right: Scan Cycle // Right: Scan Cycle
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Scan Cycle " : "Scn Cycle"); new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Scan Cycle" : "Scn Cycle");
myScanlineCycles = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight); myScanlineCycles = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight);
myScanlineCycles->setEditable(false, true); myScanlineCycles->setEditable(false, true);
// Right: Pixel Pos // Right: Pixel Pos
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
new StaticTextWidget(boss, lfont, xpos, ypos + 1, "Pixel Pos "); new StaticTextWidget(boss, lfont, xpos, ypos + 1, "Pixel Pos");
myPixelPosition = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight); myPixelPosition = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight);
myPixelPosition->setEditable(false, true); myPixelPosition->setEditable(false, true);
// Right: Color Clock // Right: Color Clock
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Color Clock " : "Color Clk "); new StaticTextWidget(boss, lfont, xpos, ypos + 1, longstr ? "Color Clock" : "Color Clk");
myColorClocks = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight); myColorClocks = new EditTextWidget(boss, nfont, xpos + lwidth, ypos - 1, fwidth, lineHeight);
myColorClocks->setEditable(false, true); myColorClocks->setEditable(false, true);
// Calculate actual dimensions // Calculate actual dimensions
_w = myColorClocks->getRight() - x; _w = myColorClocks->getRight() - x;
_h = myDeltaCycles->getBottom(); _h = myColorClocks->getBottom();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -131,6 +148,8 @@ void TiaInfoWidget::loadConfig()
Debugger& dbg = instance().debugger(); Debugger& dbg = instance().debugger();
TIADebug& tia = dbg.tiaDebug(); TIADebug& tia = dbg.tiaDebug();
const TiaState& oldTia = static_cast<const TiaState&>(tia.getOldState()); const TiaState& oldTia = static_cast<const TiaState&>(tia.getOldState());
RiotDebug& riot = dbg.riotDebug();
const RiotState& oldRiot = static_cast<const RiotState&>(riot.getOldState());
myFrameCount->setText(Common::Base::toString(tia.frameCount(), Common::Base::Fmt::_10_5), myFrameCount->setText(Common::Base::toString(tia.frameCount(), Common::Base::Fmt::_10_5),
tia.frameCount() != oldTia.info[0]); tia.frameCount() != oldTia.info[0]);
@ -159,4 +178,7 @@ void TiaInfoWidget::loadConfig()
myWSyncCylces->setText(Common::Base::toString(tia.frameWsyncCycles(), Common::Base::Fmt::_10_5), myWSyncCylces->setText(Common::Base::toString(tia.frameWsyncCycles(), Common::Base::Fmt::_10_5),
tia.frameWsyncCycles() != oldTia.info[7]); tia.frameWsyncCycles() != oldTia.info[7]);
myTimerCylces->setText(Common::Base::toString(riot.timReadCycles(), Common::Base::Fmt::_10_5),
riot.timReadCycles() != oldRiot.timReadCycles);
} }

View File

@ -41,6 +41,7 @@ class TiaInfoWidget : public Widget, public CommandSender
EditTextWidget* myTotalCycles{nullptr}; EditTextWidget* myTotalCycles{nullptr};
EditTextWidget* myDeltaCycles{nullptr}; EditTextWidget* myDeltaCycles{nullptr};
EditTextWidget* myWSyncCylces{nullptr}; EditTextWidget* myWSyncCylces{nullptr};
EditTextWidget* myTimerCylces{nullptr};
EditTextWidget* myScanlineCount{nullptr}; EditTextWidget* myScanlineCount{nullptr};
EditTextWidget* myScanlineCountLast{nullptr}; EditTextWidget* myScanlineCountLast{nullptr};

View File

@ -226,6 +226,7 @@ uInt8 M6532::peek(uInt16 addr)
if (!myWrappedThisCycle) myInterruptFlag &= ~TimerBit; if (!myWrappedThisCycle) myInterruptFlag &= ~TimerBit;
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
myTimWrappedOnRead = myWrappedThisCycle; myTimWrappedOnRead = myWrappedThisCycle;
myTimReadCycles += 7;
#endif #endif
return myTimer; return myTimer;
} }
@ -236,6 +237,9 @@ uInt8 M6532::peek(uInt16 addr)
// PA7 Flag is always cleared after accessing TIMINT // PA7 Flag is always cleared after accessing TIMINT
uInt8 result = myInterruptFlag; uInt8 result = myInterruptFlag;
myInterruptFlag &= ~PA7Bit; myInterruptFlag &= ~PA7Bit;
#ifdef DEBUGGER_SUPPORT
myTimReadCycles += 7;
#endif
return result; return result;
} }
@ -376,6 +380,9 @@ bool M6532::save(Serializer& out) const
out.putBool(myWrappedThisCycle); out.putBool(myWrappedThisCycle);
out.putLong(myLastCycle); out.putLong(myLastCycle);
out.putLong(mySetTimerCycle); out.putLong(mySetTimerCycle);
#ifdef DEBUGGER_SUPPORT
out.putInt(myTimReadCycles);
#endif
out.putByte(myDDRA); out.putByte(myDDRA);
out.putByte(myDDRB); out.putByte(myDDRB);
@ -408,6 +415,9 @@ bool M6532::load(Serializer& in)
myWrappedThisCycle = in.getBool(); myWrappedThisCycle = in.getBool();
myLastCycle = in.getLong(); myLastCycle = in.getLong();
mySetTimerCycle = in.getLong(); mySetTimerCycle = in.getLong();
#ifdef DEBUGGER_SUPPORT
myTimReadCycles = in.getInt();
#endif
myDDRA = in.getByte(); myDDRA = in.getByte();
myDDRB = in.getByte(); myDDRB = in.getByte();

View File

@ -137,6 +137,11 @@ class M6532 : public Device
@return The access counters as comma separated string @return The access counters as comma separated string
*/ */
string getAccessCounters() const override; string getAccessCounters() const override;
/**
Reset the timer read CPU cycle counter
*/
void resetTimReadCylces() { myTimReadCycles = 0; }
#endif #endif
private: private:
@ -254,6 +259,8 @@ class M6532 : public Device
// Detect timer being accessed on wraparound // Detect timer being accessed on wraparound
bool myTimWrappedOnRead{false}; bool myTimWrappedOnRead{false};
bool myTimWrappedOnWrite{false}; bool myTimWrappedOnWrite{false};
// Timer read CPU cycles
uInt16 myTimReadCycles{0};
#endif // DEBUGGER_SUPPORT #endif // DEBUGGER_SUPPORT
private: private:

View File

@ -17,6 +17,7 @@
#include "TIA.hxx" #include "TIA.hxx"
#include "M6502.hxx" #include "M6502.hxx"
#include "M6532.hxx"
#include "Control.hxx" #include "Control.hxx"
#include "Paddles.hxx" #include "Paddles.hxx"
#include "DelayQueueIteratorImpl.hxx" #include "DelayQueueIteratorImpl.hxx"
@ -162,8 +163,10 @@ void TIA::initialize()
myDelayQueue.reset(); myDelayQueue.reset();
#ifdef DEBUGGER_SUPPORT
myCyclesAtFrameStart = 0; myCyclesAtFrameStart = 0;
myFrameWsyncCycles = 0; myFrameWsyncCycles = 0;
#endif
if (myFrameManager) if (myFrameManager)
myFrameManager->reset(); myFrameManager->reset();
@ -279,8 +282,10 @@ bool TIA::save(Serializer& out) const
out.putByteArray(myShadowRegisters.data(), myShadowRegisters.size()); out.putByteArray(myShadowRegisters.data(), myShadowRegisters.size());
#ifdef DEBUGGER_SUPPORT
out.putLong(myCyclesAtFrameStart); out.putLong(myCyclesAtFrameStart);
out.putLong(myFrameWsyncCycles); out.putLong(myFrameWsyncCycles);
#endif
out.putInt(myFrameBufferScanlines); out.putInt(myFrameBufferScanlines);
out.putInt(myFrontBufferScanlines); out.putInt(myFrontBufferScanlines);
@ -352,8 +357,10 @@ bool TIA::load(Serializer& in)
in.getByteArray(myShadowRegisters.data(), myShadowRegisters.size()); in.getByteArray(myShadowRegisters.data(), myShadowRegisters.size());
#ifdef DEBUGGER_SUPPORT
myCyclesAtFrameStart = in.getLong(); myCyclesAtFrameStart = in.getLong();
myFrameWsyncCycles = in.getLong(); myFrameWsyncCycles = in.getLong();
#endif
myFrameBufferScanlines = in.getInt(); myFrameBufferScanlines = in.getInt();
myFrontBufferScanlines = in.getInt(); myFrontBufferScanlines = in.getInt();
@ -1307,7 +1314,10 @@ void TIA::updateEmulation()
void TIA::onFrameStart() void TIA::onFrameStart()
{ {
myXAtRenderingStart = 0; myXAtRenderingStart = 0;
#ifdef DEBUGGER_SUPPORT
myFrameWsyncCycles = 0; myFrameWsyncCycles = 0;
mySystem->m6532().resetTimReadCylces();
#endif
// Check for colour-loss emulation // Check for colour-loss emulation
if (myColorLossEnabled) if (myColorLossEnabled)
@ -1333,7 +1343,9 @@ void TIA::onFrameStart()
void TIA::onFrameComplete() void TIA::onFrameComplete()
{ {
mySystem->m6502().stop(); mySystem->m6502().stop();
#ifdef DEBUGGER_SUPPORT
myCyclesAtFrameStart = mySystem->cycles(); myCyclesAtFrameStart = mySystem->cycles();
#endif
if (myXAtRenderingStart > 0) if (myXAtRenderingStart > 0)
std::fill_n(myBackBuffer.begin(), myXAtRenderingStart, 0); std::fill_n(myBackBuffer.begin(), myXAtRenderingStart, 0);
@ -1355,7 +1367,9 @@ void TIA::onHalt()
{ {
mySubClock += (TIAConstants::H_CLOCKS - myHctr) % TIAConstants::H_CLOCKS; mySubClock += (TIAConstants::H_CLOCKS - myHctr) % TIAConstants::H_CLOCKS;
mySystem->incrementCycles(mySubClock / TIAConstants::CYCLE_CLOCKS); mySystem->incrementCycles(mySubClock / TIAConstants::CYCLE_CLOCKS);
myFrameWsyncCycles += mySubClock / TIAConstants::CYCLE_CLOCKS; #ifdef DEBUGGER_SUPPORT
myFrameWsyncCycles += 3 + mySubClock / TIAConstants::CYCLE_CLOCKS;
#endif
mySubClock %= TIAConstants::CYCLE_CLOCKS; mySubClock %= TIAConstants::CYCLE_CLOCKS;
} }

View File

@ -322,6 +322,7 @@ class TIA : public Device
*/ */
uInt64 cycles() const { return uInt64(mySystem->cycles()); } uInt64 cycles() const { return uInt64(mySystem->cycles()); }
#ifdef DEBUGGER_SUPPORT
/** /**
Answers the frame count from the start of the emulation. Answers the frame count from the start of the emulation.
*/ */
@ -340,6 +341,7 @@ class TIA : public Device
uInt32 frameWSyncCycles() const { uInt32 frameWSyncCycles() const {
return uInt32(myFrameWsyncCycles); return uInt32(myFrameWsyncCycles);
} }
#endif // DEBUGGER_SUPPORT
/** /**
* Get the CPU cycles since the last dump ports change. * Get the CPU cycles since the last dump ports change.
@ -560,7 +562,7 @@ class TIA : public Device
@return The access counters as comma separated string @return The access counters as comma separated string
*/ */
string getAccessCounters() const override; string getAccessCounters() const override;
#endif #endif // DEBUGGER_SUPPORT
private: private:
/** /**
@ -941,6 +943,7 @@ class TIA : public Device
std::array<uInt32, 16> myColorCounts; std::array<uInt32, 16> myColorCounts;
#ifdef DEBUGGER_SUPPORT
/** /**
* System cycles at the end of the previous frame / beginning of next frame. * System cycles at the end of the previous frame / beginning of next frame.
*/ */
@ -950,6 +953,7 @@ class TIA : public Device
* System cycles used by WSYNC during current frame. * System cycles used by WSYNC during current frame.
*/ */
uInt64 myFrameWsyncCycles{0}; uInt64 myFrameWsyncCycles{0};
#endif // DEBUGGER_SUPPORT
/** /**
* The frame manager can change during our lifetime, so we buffer those two. * The frame manager can change during our lifetime, so we buffer those two.

View File

@ -236,6 +236,8 @@ RiotMethod getRiotSpecial(char* ch)
return &RiotDebug::timWrappedOnRead; return &RiotDebug::timWrappedOnRead;
else if(BSPF::equalsIgnoreCase(ch, "_timwrapwrite")) else if(BSPF::equalsIgnoreCase(ch, "_timwrapwrite"))
return &RiotDebug::timWrappedOnWrite; return &RiotDebug::timWrappedOnWrite;
else if(BSPF::equalsIgnoreCase(ch, "_ftimreadcycles"))
return &RiotDebug::timReadCycles;
else else
return nullptr; return nullptr;
} }