Finalize and start frames right after vsync -> stabilizes algorithm.

This commit is contained in:
Christian Speckner 2017-01-15 01:33:07 +01:00
parent c0aa5c83f5
commit 3303f0560a
3 changed files with 35 additions and 30 deletions

View File

@ -29,7 +29,7 @@ enum Metrics: uInt32 {
overscanNTSC = 30,
overscanPAL = 36,
vsync = 3,
maxLinesVsync = 30,
maxLinesVsync = 32,
maxLinesVsyncDuringAutodetect = 100,
visibleOverscan = 20,
maxUnderscan = 10,
@ -93,6 +93,8 @@ void FrameManager::reset()
myStableVblankFrames = 0;
myVblankViolated = false;
myVsyncLines = 0;
myY = 0;
myFramePending = false;
if (myVblankMode != VblankMode::fixed) myVblankMode = VblankMode::floating;
}
@ -100,13 +102,15 @@ void FrameManager::reset()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameManager::nextLine()
{
State previousState = myState;
myCurrentFrameTotalLines++;
myLineInState++;
switch (myState)
{
case State::waitForVsyncStart:
if (Int32(myLineInState) >= Int32(myFrameLines - myCurrentFrameFinalLines) || !myCurrentFrameFinalLines)
if ((myCurrentFrameTotalLines > myFrameLines - 3) || myTotalFrames == 0)
myVsyncLines++;
if (myVsyncLines > vsyncLimit(myAutodetectTvMode)) setState(State::waitForFrameStart);
@ -125,12 +129,14 @@ void FrameManager::nextLine()
case State::frame:
if (myLineInState >= (myFixedHeight > 0 ? myFixedHeight : (myKernelLines + Metrics::visibleOverscan)))
finalizeFrame();
setState(State::waitForVsyncStart);
break;
default:
throw runtime_error("frame manager: invalid state");
}
if (myState == State::frame && previousState == State::frame) myY++;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -215,15 +221,11 @@ void FrameManager::setVsync(bool vsync)
break;
case State::waitForVsyncEnd:
if (!myVsync)
setState(State::waitForFrameStart);
if (!myVsync) setState(State::waitForFrameStart);
break;
case State::frame:
if (myVsync) {
myCurrentFrameTotalLines++;
finalizeFrame(State::waitForVsyncEnd);
}
if (myVsync) setState(State::waitForVsyncEnd);
break;
default:
@ -245,13 +247,17 @@ void FrameManager::setState(FrameManager::State state)
switch (myState) {
case State::waitForFrameStart:
if (myFramePending) finalizeFrame();
if (myOnFrameStart) myOnFrameStart();
myFramePending = true;
myVsyncLines = 0;
myVblankViolated = false;
break;
case State::frame:
myVsyncLines = 0;
if (myOnFrameStart) myOnFrameStart();
myY = 0;
break;
default:
@ -260,22 +266,18 @@ void FrameManager::setState(FrameManager::State state)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameManager::finalizeFrame(FrameManager::State state)
void FrameManager::finalizeFrame()
{
myCurrentFrameFinalLines = myCurrentFrameTotalLines;
myCurrentFrameTotalLines = 0;
myTotalFrames++;
if (myOnFrameComplete) {
myOnFrameComplete();
}
if (myOnFrameComplete) myOnFrameComplete();
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
(cout << "frame complete @ " << myLineInState << " (" << myCurrentFrameFinalLines << " total)" << "\n").flush();
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
setState(state);
if (myAutodetectTvMode) updateAutodetectedTvMode();
myFrameRate = (myMode == TvMode::pal ? 15600.0 : 15720.0) /
@ -322,6 +324,10 @@ void FrameManager::updateTvMode(TvMode mode)
{
if (mode == myMode) return;
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
(cout << "TV mode switched to " << int(mode) << "\n").flush();
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
myMode = mode;
switch (myMode)
@ -395,12 +401,6 @@ void FrameManager::setFixedHeight(uInt32 height)
myFixedHeight = height;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameManager::currentLine() const
{
return myState == State::frame ? myLineInState : 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameManager::scanlines() const
{

View File

@ -60,7 +60,10 @@ class FrameManager : public Serializable
void setFixedHeight(uInt32 height);
uInt32 currentLine() const;
uInt32 getY() const
{
return myY;
}
uInt32 scanlines() const;
@ -111,7 +114,7 @@ class FrameManager : public Serializable
void setState(State state);
void finalizeFrame(State state = State::waitForVsyncStart);
void finalizeFrame();
void nextLineInVsync();
@ -128,6 +131,8 @@ class FrameManager : public Serializable
uInt32 myCurrentFrameFinalLines;
uInt32 myVsyncLines;
float myFrameRate;
uInt32 myY;
bool myFramePending;
uInt32 myTotalFrames;
uInt32 myFramesInMode;

View File

@ -925,12 +925,12 @@ void TIA::onFrameComplete()
mySystem->m6502().stop();
mySystem->resetCycles();
Int32 missingScanlines = myLastFrameHeight - myFrameManager.currentLine();
Int32 missingScanlines = myLastFrameHeight - myFrameManager.getY();
if (missingScanlines > 0)
memset(myCurrentFrameBuffer.get() + 160 * myFrameManager.currentLine(), 0, missingScanlines * 160);
memset(myCurrentFrameBuffer.get() + 160 * myFrameManager.getY(), 0, missingScanlines * 160);
myLastFrameHeight = myFrameManager.currentLine();
myLastFrameHeight = myFrameManager.getY();
// Recalculate framerate, attempting to auto-correct for scanline 'jumps'
if(myAutoFrameEnabled)
@ -1003,7 +1003,7 @@ void TIA::tickHblank()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::tickHframe()
{
const uInt32 y = myFrameManager.currentLine();
const uInt32 y = myFrameManager.getY();
const bool lineNotCached = myLinesSinceChange < 2 || y == 0;
const uInt32 x = myHctr - 68 + myXDelta;
@ -1027,7 +1027,7 @@ void TIA::applyRsync()
if (x > 0 && myFrameManager.isRendering()) {
myXDelta = x - 157;
memset(myCurrentFrameBuffer.get() + myFrameManager.currentLine() * 160 + x, 0, 160 - x);
memset(myCurrentFrameBuffer.get() + myFrameManager.getY() * 160 + x, 0, 160 - x);
}
myLinesSinceChange = 0;
@ -1141,7 +1141,7 @@ void TIA::renderPixel(uInt32 x, uInt32 y, bool lineNotCached)
void TIA::clearHmoveComb()
{
if (myFrameManager.isRendering() && myHstate == HState::blank)
memset(myCurrentFrameBuffer.get() + myFrameManager.currentLine() * 160,
memset(myCurrentFrameBuffer.get() + myFrameManager.getY() * 160,
myColorHBlank, 8);
}