Fix garbage for ROMs with varying visible frame heights:

* Keep track of max frame height
  * Blank out any missing scanlines
  * Refactoring
This commit is contained in:
Christian Speckner 2017-01-01 22:25:56 +01:00
parent 5f5ea1f424
commit a83e7eb26d
4 changed files with 65 additions and 25 deletions

View File

@ -17,6 +17,8 @@
// #define TIA_FRAMEMANAGER_DEBUG_LOG
#include <algorithm>
#include "FrameManager.hxx"
enum Metrics: uInt32 {
@ -65,6 +67,7 @@ void FrameManager::reset()
myCurrentFrameTotalLines = myCurrentFrameFinalLines = 0;
myFrameRate = 60.0;
myLineInState = 0;
myMaxVisibleFrameLines = 0;
myVsync = false;
myVblank = false;
myTotalFrames = 0;
@ -141,14 +144,15 @@ void FrameManager::nextLineInVsync()
}
setState(State::frame);
} else if (shouldTransition){
if (!myVblankViolated) myVblankViolations++;
myVblankViolated = true;
}
} else if (shouldTransition){
if (!myVblankViolated) myVblankViolations++;
myVblankViolated = true;
}
if (myVblankViolations > Metrics::maxVblankViolations)
myVblankMode = VblankMode::floating;
if (myVblankViolations > Metrics::maxVblankViolations)
myVblankMode = VblankMode::floating;
break;
}
}
@ -221,6 +225,12 @@ uInt32 FrameManager::scanlines() const
return myState == State::frame ? myLineInState : myCurrentFrameFinalLines;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameManager::maxVisibleFrameLines() const
{
return myMaxVisibleFrameLines;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameManager::setTvMode(TvMode mode)
{
@ -278,6 +288,13 @@ void FrameManager::setState(FrameManager::State state)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameManager::finalizeFrame(FrameManager::State state)
{
myCurrentFrameFinalLines = myCurrentFrameTotalLines;
myCurrentFrameTotalLines = 0;
myTotalFrames++;
if (myTotalFrames > Metrics::initialGarbageFrames)
myMaxVisibleFrameLines = std::max(myMaxVisibleFrameLines, myLineInState);
if (myOnFrameComplete) {
myOnFrameComplete();
}
@ -286,12 +303,7 @@ void FrameManager::finalizeFrame(FrameManager::State state)
(cout << "frame complete @ " << myLineInState << " (" << myCurrentFrameTotalLines << " total)" << "\n").flush();
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
myCurrentFrameFinalLines = myCurrentFrameTotalLines;
myCurrentFrameTotalLines = 0;
setState(state);
myTotalFrames++;
if (myTotalFrames <= Metrics::initialGarbageFrames) {
return;
}

View File

@ -59,6 +59,8 @@ class FrameManager : public Serializable
uInt32 scanlines() const;
uInt32 maxVisibleFrameLines() const;
uInt32 frameCount() const { return myTotalFrames; }
float frameRate() const { return myFrameRate; }
@ -70,6 +72,10 @@ class FrameManager : public Serializable
bool load(Serializer& in) override;
string name() const override { return "TIA_FrameManager"; }
public:
static constexpr uInt32 frameBufferHeight = 320;
private:
enum State {
@ -104,6 +110,7 @@ class FrameManager : public Serializable
uInt32 myLineInState;
uInt32 myCurrentFrameTotalLines;
uInt32 myCurrentFrameFinalLines;
uInt32 myMaxVisibleFrameLines;
float myFrameRate;
uInt32 myTotalFrames;

View File

@ -83,23 +83,15 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
{
myFrameManager.setHandlers(
[this] () {
myCurrentFrameBuffer.swap(myPreviousFrameBuffer);
for (uInt8 i = 0; i < 4; i++)
updatePaddle(i);
onFrameStart();
},
[this] () {
mySystem->m6502().stop();
mySystem->resetCycles();
// Recalculate framerate, attempting to auto-correct for scanline 'jumps'
if(myAutoFrameEnabled)
myConsole.setFramerate(myFrameManager.frameRate());
onFrameComplete();
}
);
myCurrentFrameBuffer = make_ptr<uInt8[]>(160 * 320);
myPreviousFrameBuffer = make_ptr<uInt8[]>(160 * 320);
myCurrentFrameBuffer = make_ptr<uInt8[]>(160 * FrameManager::frameBufferHeight);
myPreviousFrameBuffer = make_ptr<uInt8[]>(160 * FrameManager::frameBufferHeight);
myTIAPinsDriven = mySettings.getBool("tiadriven");
@ -193,8 +185,8 @@ void TIA::installDelegate(System& system, Device& device)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::clearBuffers()
{
memset(myCurrentFrameBuffer.get(), 0, 160 * 320);
memset(myPreviousFrameBuffer.get(), 0, 160 * 320);
memset(myCurrentFrameBuffer.get(), 0, 160 * FrameManager::frameBufferHeight);
memset(myPreviousFrameBuffer.get(), 0, 160 * FrameManager::frameBufferHeight);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -906,6 +898,31 @@ void TIA::updateEmulation()
cycle(cyclesToRun);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::onFrameStart()
{
myCurrentFrameBuffer.swap(myPreviousFrameBuffer);
for (uInt8 i = 0; i < 4; i++)
updatePaddle(i);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::onFrameComplete()
{
mySystem->m6502().stop();
mySystem->resetCycles();
Int32 missingScanlines = myFrameManager.maxVisibleFrameLines() - myFrameManager.currentLine();
if (missingScanlines > 0)
memset(myCurrentFrameBuffer.get() + 160 * myFrameManager.currentLine(), 0, missingScanlines * 160);
// Recalculate framerate, attempting to auto-correct for scanline 'jumps'
if(myAutoFrameEnabled)
myConsole.setFramerate(myFrameManager.frameRate());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::cycle(uInt32 colorClocks)
{

View File

@ -351,6 +351,10 @@ class TIA : public Device
private:
void onFrameStart();
void onFrameComplete();
void updateEmulation();
void cycle(uInt32 colorClocks);