Skip to content

Commit

Permalink
Limit the number of lines FrameManager waits for frame with large sca…
Browse files Browse the repository at this point in the history
…nlines, refactoring.
  • Loading branch information
DirtyHairy committed Jan 10, 2017
1 parent a6725f2 commit aba48e8
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 118 deletions.
2 changes: 1 addition & 1 deletion src/emucore/Console.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
myOSystem.settings().setValue("fastscbios", true);
mySystem->reset(true); // autodetect in reset enabled
myTIA->autodetectTvMode(true);
for(int i = 0; i < 60; ++i)
for(int i = 0; i < 80; ++i)
myTIA->update();
myDisplayFormat = myTIA->tvMode() == TvMode::pal ? "PAL" : "NTSC";
if(myProperties.get(Display_Format) == "AUTO")
Expand Down
224 changes: 113 additions & 111 deletions src/emucore/tia/FrameManager.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ enum Metrics: uInt32 {
overscanNTSC = 30,
overscanPAL = 36,
vsync = 3,
vsyncLimit = 30,
visibleOverscan = 20,
maxUnderscan = 10,
tvModeDetectionTolerance = 20,
initialGarbageFrames = 10,
initialGarbageFrames = 20,
framesForModeConfirmation = 5,
maxVblankViolations = 2,
minStableVblankFrames = 1
Expand Down Expand Up @@ -71,7 +72,6 @@ void FrameManager::reset()
myCurrentFrameTotalLines = myCurrentFrameFinalLines = 0;
myFrameRate = 60.0;
myLineInState = 0;
myMaxVisibleFrameLines = 0;
myVsync = false;
myVblank = false;
myTotalFrames = 0;
Expand All @@ -81,6 +81,7 @@ void FrameManager::reset()
myVblankViolations = 0;
myStableVblankFrames = 0;
myVblankViolated = false;
myVsyncLines = 0;

if (myVblankMode != VblankMode::fixed) myVblankMode = VblankMode::floating;
}
Expand All @@ -94,7 +95,17 @@ void FrameManager::nextLine()
switch (myState)
{
case State::waitForVsyncStart:
if (Int32(myLineInState) > Int32(myFrameLines - myCurrentFrameFinalLines) || !myCurrentFrameFinalLines)
myVsyncLines++;

if (myVsyncLines > Metrics::vsyncLimit) setState(State::waitForFrameStart);

break;

case State::waitForVsyncEnd:
if (++myVsyncLines > Metrics::vsyncLimit)
setState(State::waitForFrameStart);

break;

case State::waitForFrameStart:
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
{
Expand All @@ -318,10 +224,12 @@ void FrameManager::setState(FrameManager::State state)

switch (myState) {
case State::waitForFrameStart:
myVsyncLines = 0;
myVblankViolated = false;
break;

case State::frame:
myVsyncLines = 0;
if (myOnFrameStart) myOnFrameStart();
break;

Expand All @@ -337,15 +245,12 @@ void FrameManager::finalizeFrame(FrameManager::State state)
myCurrentFrameTotalLines = 0;
myTotalFrames++;

if (myTotalFrames > Metrics::initialGarbageFrames)
myMaxVisibleFrameLines = std::max(myMaxVisibleFrameLines, myLineInState);

if (myOnFrameComplete) {
myOnFrameComplete();
}

#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

setState(state);
Expand Down Expand Up @@ -391,6 +296,103 @@ void FrameManager::updateAutodetectedTvMode()
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
bool FrameManager::save(Serializer& out) const
Expand Down
4 changes: 1 addition & 3 deletions src/emucore/tia/FrameManager.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ class FrameManager : public Serializable

uInt32 scanlines() const;

uInt32 maxVisibleFrameLines() const;

uInt32 frameCount() const { return myTotalFrames; }

float frameRate() const { return myFrameRate; }
Expand Down Expand Up @@ -124,7 +122,7 @@ class FrameManager : public Serializable
uInt32 myLineInState;
uInt32 myCurrentFrameTotalLines;
uInt32 myCurrentFrameFinalLines;
uInt32 myMaxVisibleFrameLines;
uInt32 myVsyncLines;
float myFrameRate;

uInt32 myTotalFrames;
Expand Down
7 changes: 4 additions & 3 deletions src/emucore/tia/TIA.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ void TIA::reset()
myLastCycle = 0;
mySubClock = 0;
myXDelta = 0;
myLastFrameHeight = 0;

myBackground.reset();
myPlayfield.reset();
Expand Down Expand Up @@ -146,8 +147,6 @@ void TIA::frameReset()
clearBuffers();

myAutoFrameEnabled = (mySettings.getInt("framerate") <= 0);

// TODO - make use of ystart and height, maybe move to FrameManager
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Expand Down Expand Up @@ -926,11 +925,13 @@ void TIA::onFrameComplete()
mySystem->m6502().stop();
mySystem->resetCycles();

Int32 missingScanlines = myFrameManager.maxVisibleFrameLines() - myFrameManager.currentLine();
Int32 missingScanlines = myLastFrameHeight - myFrameManager.currentLine();

if (missingScanlines > 0)
memset(myCurrentFrameBuffer.get() + 160 * myFrameManager.currentLine(), 0, missingScanlines * 160);

myLastFrameHeight = myFrameManager.currentLine();

// Recalculate framerate, attempting to auto-correct for scanline 'jumps'
if(myAutoFrameEnabled)
myConsole.setFramerate(myFrameManager.frameRate());
Expand Down
1 change: 1 addition & 0 deletions src/emucore/tia/TIA.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ class TIA : public Device
// Pointer to the current and previous frame buffers
BytePtr myCurrentFrameBuffer;
BytePtr myPreviousFrameBuffer;
uInt32 myLastFrameHeight;

Background myBackground;
Playfield myPlayfield;
Expand Down

0 comments on commit aba48e8

Please sign in to comment.