mirror of https://github.com/stella-emu/stella.git
Limit the number of lines FrameManager waits for frame with large scanlines, refactoring.
This commit is contained in:
parent
a6725f2436
commit
aba48e85cf
|
@ -118,7 +118,7 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
|
||||||
myOSystem.settings().setValue("fastscbios", true);
|
myOSystem.settings().setValue("fastscbios", true);
|
||||||
mySystem->reset(true); // autodetect in reset enabled
|
mySystem->reset(true); // autodetect in reset enabled
|
||||||
myTIA->autodetectTvMode(true);
|
myTIA->autodetectTvMode(true);
|
||||||
for(int i = 0; i < 60; ++i)
|
for(int i = 0; i < 80; ++i)
|
||||||
myTIA->update();
|
myTIA->update();
|
||||||
myDisplayFormat = myTIA->tvMode() == TvMode::pal ? "PAL" : "NTSC";
|
myDisplayFormat = myTIA->tvMode() == TvMode::pal ? "PAL" : "NTSC";
|
||||||
if(myProperties.get(Display_Format) == "AUTO")
|
if(myProperties.get(Display_Format) == "AUTO")
|
||||||
|
|
|
@ -29,10 +29,11 @@ enum Metrics: uInt32 {
|
||||||
overscanNTSC = 30,
|
overscanNTSC = 30,
|
||||||
overscanPAL = 36,
|
overscanPAL = 36,
|
||||||
vsync = 3,
|
vsync = 3,
|
||||||
|
vsyncLimit = 30,
|
||||||
visibleOverscan = 20,
|
visibleOverscan = 20,
|
||||||
maxUnderscan = 10,
|
maxUnderscan = 10,
|
||||||
tvModeDetectionTolerance = 20,
|
tvModeDetectionTolerance = 20,
|
||||||
initialGarbageFrames = 10,
|
initialGarbageFrames = 20,
|
||||||
framesForModeConfirmation = 5,
|
framesForModeConfirmation = 5,
|
||||||
maxVblankViolations = 2,
|
maxVblankViolations = 2,
|
||||||
minStableVblankFrames = 1
|
minStableVblankFrames = 1
|
||||||
|
@ -71,7 +72,6 @@ void FrameManager::reset()
|
||||||
myCurrentFrameTotalLines = myCurrentFrameFinalLines = 0;
|
myCurrentFrameTotalLines = myCurrentFrameFinalLines = 0;
|
||||||
myFrameRate = 60.0;
|
myFrameRate = 60.0;
|
||||||
myLineInState = 0;
|
myLineInState = 0;
|
||||||
myMaxVisibleFrameLines = 0;
|
|
||||||
myVsync = false;
|
myVsync = false;
|
||||||
myVblank = false;
|
myVblank = false;
|
||||||
myTotalFrames = 0;
|
myTotalFrames = 0;
|
||||||
|
@ -81,6 +81,7 @@ void FrameManager::reset()
|
||||||
myVblankViolations = 0;
|
myVblankViolations = 0;
|
||||||
myStableVblankFrames = 0;
|
myStableVblankFrames = 0;
|
||||||
myVblankViolated = false;
|
myVblankViolated = false;
|
||||||
|
myVsyncLines = 0;
|
||||||
|
|
||||||
if (myVblankMode != VblankMode::fixed) myVblankMode = VblankMode::floating;
|
if (myVblankMode != VblankMode::fixed) myVblankMode = VblankMode::floating;
|
||||||
}
|
}
|
||||||
|
@ -94,7 +95,17 @@ void FrameManager::nextLine()
|
||||||
switch (myState)
|
switch (myState)
|
||||||
{
|
{
|
||||||
case State::waitForVsyncStart:
|
case State::waitForVsyncStart:
|
||||||
|
if (Int32(myLineInState) > Int32(myFrameLines - myCurrentFrameFinalLines) || !myCurrentFrameFinalLines)
|
||||||
|
myVsyncLines++;
|
||||||
|
|
||||||
|
if (myVsyncLines > Metrics::vsyncLimit) setState(State::waitForFrameStart);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case State::waitForVsyncEnd:
|
case State::waitForVsyncEnd:
|
||||||
|
if (++myVsyncLines > Metrics::vsyncLimit)
|
||||||
|
setState(State::waitForFrameStart);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::waitForFrameStart:
|
case State::waitForFrameStart:
|
||||||
|
@ -164,27 +175,6 @@ void FrameManager::nextLineInVsync()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::setYstart(uInt32 ystart)
|
|
||||||
{
|
|
||||||
if (ystart == myYstart) return;
|
|
||||||
|
|
||||||
myYstart = ystart;
|
|
||||||
|
|
||||||
myVblankMode = ystart ? VblankMode::fixed : VblankMode::floating;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt32 FrameManager::ystart() const {
|
|
||||||
return myYstart;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::setVblank(bool vblank)
|
|
||||||
{
|
|
||||||
myVblank = vblank;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameManager::setVsync(bool vsync)
|
void FrameManager::setVsync(bool vsync)
|
||||||
{
|
{
|
||||||
|
@ -220,90 +210,6 @@ void FrameManager::setVsync(bool vsync)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool FrameManager::isRendering() const
|
|
||||||
{
|
|
||||||
return myState == State::frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
TvMode FrameManager::tvMode() const
|
|
||||||
{
|
|
||||||
return myMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt32 FrameManager::height() const
|
|
||||||
{
|
|
||||||
return myFixedHeight > 0 ? myFixedHeight : (myKernelLines + Metrics::visibleOverscan);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::setFixedHeight(uInt32 height)
|
|
||||||
{
|
|
||||||
myFixedHeight = height;
|
|
||||||
|
|
||||||
(cout << myFixedHeight << "\n").flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt32 FrameManager::currentLine() const
|
|
||||||
{
|
|
||||||
return myState == State::frame ? myLineInState : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt32 FrameManager::scanlines() const
|
|
||||||
{
|
|
||||||
return myState == State::frame ? myCurrentFrameTotalLines : myCurrentFrameFinalLines;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt32 FrameManager::maxVisibleFrameLines() const
|
|
||||||
{
|
|
||||||
return myMaxVisibleFrameLines;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::setTvMode(TvMode mode)
|
|
||||||
{
|
|
||||||
if (!myAutodetectTvMode) updateTvMode(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::autodetectTvMode(bool toggle)
|
|
||||||
{
|
|
||||||
myAutodetectTvMode = toggle;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::updateTvMode(TvMode mode)
|
|
||||||
{
|
|
||||||
if (mode == myMode) return;
|
|
||||||
|
|
||||||
myMode = mode;
|
|
||||||
|
|
||||||
switch (myMode)
|
|
||||||
{
|
|
||||||
case TvMode::ntsc:
|
|
||||||
myVblankLines = Metrics::vblankNTSC;
|
|
||||||
myKernelLines = Metrics::kernelNTSC;
|
|
||||||
myOverscanLines = Metrics::overscanNTSC;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TvMode::pal:
|
|
||||||
myVblankLines = Metrics::vblankPAL;
|
|
||||||
myKernelLines = Metrics::kernelPAL;
|
|
||||||
myOverscanLines = Metrics::overscanPAL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw runtime_error("frame manager: invalid TV mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
myFrameLines = Metrics::vsync + myVblankLines + myKernelLines + myOverscanLines;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameManager::setState(FrameManager::State state)
|
void FrameManager::setState(FrameManager::State state)
|
||||||
{
|
{
|
||||||
|
@ -318,10 +224,12 @@ void FrameManager::setState(FrameManager::State state)
|
||||||
|
|
||||||
switch (myState) {
|
switch (myState) {
|
||||||
case State::waitForFrameStart:
|
case State::waitForFrameStart:
|
||||||
|
myVsyncLines = 0;
|
||||||
myVblankViolated = false;
|
myVblankViolated = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::frame:
|
case State::frame:
|
||||||
|
myVsyncLines = 0;
|
||||||
if (myOnFrameStart) myOnFrameStart();
|
if (myOnFrameStart) myOnFrameStart();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -337,15 +245,12 @@ void FrameManager::finalizeFrame(FrameManager::State state)
|
||||||
myCurrentFrameTotalLines = 0;
|
myCurrentFrameTotalLines = 0;
|
||||||
myTotalFrames++;
|
myTotalFrames++;
|
||||||
|
|
||||||
if (myTotalFrames > Metrics::initialGarbageFrames)
|
|
||||||
myMaxVisibleFrameLines = std::max(myMaxVisibleFrameLines, myLineInState);
|
|
||||||
|
|
||||||
if (myOnFrameComplete) {
|
if (myOnFrameComplete) {
|
||||||
myOnFrameComplete();
|
myOnFrameComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
||||||
(cout << "frame complete @ " << myLineInState << " (" << myCurrentFrameTotalLines << " total)" << "\n").flush();
|
(cout << "frame complete @ " << myLineInState << " (" << myCurrentFrameFinalLines << " total)" << "\n").flush();
|
||||||
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
|
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
|
||||||
|
|
||||||
setState(state);
|
setState(state);
|
||||||
|
@ -391,6 +296,103 @@ void FrameManager::updateAutodetectedTvMode()
|
||||||
myModeConfirmed = true;
|
myModeConfirmed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameManager::updateTvMode(TvMode mode)
|
||||||
|
{
|
||||||
|
if (mode == myMode) return;
|
||||||
|
|
||||||
|
myMode = mode;
|
||||||
|
|
||||||
|
switch (myMode)
|
||||||
|
{
|
||||||
|
case TvMode::ntsc:
|
||||||
|
myVblankLines = Metrics::vblankNTSC;
|
||||||
|
myKernelLines = Metrics::kernelNTSC;
|
||||||
|
myOverscanLines = Metrics::overscanNTSC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TvMode::pal:
|
||||||
|
myVblankLines = Metrics::vblankPAL;
|
||||||
|
myKernelLines = Metrics::kernelPAL;
|
||||||
|
myOverscanLines = Metrics::overscanPAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw runtime_error("frame manager: invalid TV mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
myFrameLines = Metrics::vsync + myVblankLines + myKernelLines + myOverscanLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameManager::setYstart(uInt32 ystart)
|
||||||
|
{
|
||||||
|
if (ystart == myYstart) return;
|
||||||
|
|
||||||
|
myYstart = ystart;
|
||||||
|
|
||||||
|
myVblankMode = ystart ? VblankMode::fixed : VblankMode::floating;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt32 FrameManager::ystart() const {
|
||||||
|
return myYstart;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameManager::setVblank(bool vblank)
|
||||||
|
{
|
||||||
|
myVblank = vblank;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool FrameManager::isRendering() const
|
||||||
|
{
|
||||||
|
return myState == State::frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
TvMode FrameManager::tvMode() const
|
||||||
|
{
|
||||||
|
return myMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt32 FrameManager::height() const
|
||||||
|
{
|
||||||
|
return myFixedHeight > 0 ? myFixedHeight : (myKernelLines + Metrics::visibleOverscan);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameManager::setFixedHeight(uInt32 height)
|
||||||
|
{
|
||||||
|
myFixedHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt32 FrameManager::currentLine() const
|
||||||
|
{
|
||||||
|
return myState == State::frame ? myLineInState : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
uInt32 FrameManager::scanlines() const
|
||||||
|
{
|
||||||
|
return myState == State::frame ? myCurrentFrameTotalLines : myCurrentFrameFinalLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameManager::setTvMode(TvMode mode)
|
||||||
|
{
|
||||||
|
if (!myAutodetectTvMode) updateTvMode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameManager::autodetectTvMode(bool toggle)
|
||||||
|
{
|
||||||
|
myAutodetectTvMode = toggle;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
// TODO: implement this once the class is finalized
|
// TODO: implement this once the class is finalized
|
||||||
bool FrameManager::save(Serializer& out) const
|
bool FrameManager::save(Serializer& out) const
|
||||||
|
|
|
@ -61,8 +61,6 @@ class FrameManager : public Serializable
|
||||||
|
|
||||||
uInt32 scanlines() const;
|
uInt32 scanlines() const;
|
||||||
|
|
||||||
uInt32 maxVisibleFrameLines() const;
|
|
||||||
|
|
||||||
uInt32 frameCount() const { return myTotalFrames; }
|
uInt32 frameCount() const { return myTotalFrames; }
|
||||||
|
|
||||||
float frameRate() const { return myFrameRate; }
|
float frameRate() const { return myFrameRate; }
|
||||||
|
@ -124,7 +122,7 @@ class FrameManager : public Serializable
|
||||||
uInt32 myLineInState;
|
uInt32 myLineInState;
|
||||||
uInt32 myCurrentFrameTotalLines;
|
uInt32 myCurrentFrameTotalLines;
|
||||||
uInt32 myCurrentFrameFinalLines;
|
uInt32 myCurrentFrameFinalLines;
|
||||||
uInt32 myMaxVisibleFrameLines;
|
uInt32 myVsyncLines;
|
||||||
float myFrameRate;
|
float myFrameRate;
|
||||||
|
|
||||||
uInt32 myTotalFrames;
|
uInt32 myTotalFrames;
|
||||||
|
|
|
@ -115,6 +115,7 @@ void TIA::reset()
|
||||||
myLastCycle = 0;
|
myLastCycle = 0;
|
||||||
mySubClock = 0;
|
mySubClock = 0;
|
||||||
myXDelta = 0;
|
myXDelta = 0;
|
||||||
|
myLastFrameHeight = 0;
|
||||||
|
|
||||||
myBackground.reset();
|
myBackground.reset();
|
||||||
myPlayfield.reset();
|
myPlayfield.reset();
|
||||||
|
@ -146,8 +147,6 @@ void TIA::frameReset()
|
||||||
clearBuffers();
|
clearBuffers();
|
||||||
|
|
||||||
myAutoFrameEnabled = (mySettings.getInt("framerate") <= 0);
|
myAutoFrameEnabled = (mySettings.getInt("framerate") <= 0);
|
||||||
|
|
||||||
// TODO - make use of ystart and height, maybe move to FrameManager
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -926,11 +925,13 @@ void TIA::onFrameComplete()
|
||||||
mySystem->m6502().stop();
|
mySystem->m6502().stop();
|
||||||
mySystem->resetCycles();
|
mySystem->resetCycles();
|
||||||
|
|
||||||
Int32 missingScanlines = myFrameManager.maxVisibleFrameLines() - myFrameManager.currentLine();
|
Int32 missingScanlines = myLastFrameHeight - myFrameManager.currentLine();
|
||||||
|
|
||||||
if (missingScanlines > 0)
|
if (missingScanlines > 0)
|
||||||
memset(myCurrentFrameBuffer.get() + 160 * myFrameManager.currentLine(), 0, missingScanlines * 160);
|
memset(myCurrentFrameBuffer.get() + 160 * myFrameManager.currentLine(), 0, missingScanlines * 160);
|
||||||
|
|
||||||
|
myLastFrameHeight = myFrameManager.currentLine();
|
||||||
|
|
||||||
// Recalculate framerate, attempting to auto-correct for scanline 'jumps'
|
// Recalculate framerate, attempting to auto-correct for scanline 'jumps'
|
||||||
if(myAutoFrameEnabled)
|
if(myAutoFrameEnabled)
|
||||||
myConsole.setFramerate(myFrameManager.frameRate());
|
myConsole.setFramerate(myFrameManager.frameRate());
|
||||||
|
|
|
@ -443,6 +443,7 @@ class TIA : public Device
|
||||||
// Pointer to the current and previous frame buffers
|
// Pointer to the current and previous frame buffers
|
||||||
BytePtr myCurrentFrameBuffer;
|
BytePtr myCurrentFrameBuffer;
|
||||||
BytePtr myPreviousFrameBuffer;
|
BytePtr myPreviousFrameBuffer;
|
||||||
|
uInt32 myLastFrameHeight;
|
||||||
|
|
||||||
Background myBackground;
|
Background myBackground;
|
||||||
Playfield myPlayfield;
|
Playfield myPlayfield;
|
||||||
|
|
Loading…
Reference in New Issue