From a83e7eb26d3e7dcdfdd8952f4fe723cafc95d5d4 Mon Sep 17 00:00:00 2001 From: Christian Speckner Date: Sun, 1 Jan 2017 22:25:56 +0100 Subject: [PATCH] Fix garbage for ROMs with varying visible frame heights: * Keep track of max frame height * Blank out any missing scanlines * Refactoring --- src/emucore/tia/FrameManager.cxx | 34 ++++++++++++++++-------- src/emucore/tia/FrameManager.hxx | 7 +++++ src/emucore/tia/TIA.cxx | 45 ++++++++++++++++++++++---------- src/emucore/tia/TIA.hxx | 4 +++ 4 files changed, 65 insertions(+), 25 deletions(-) diff --git a/src/emucore/tia/FrameManager.cxx b/src/emucore/tia/FrameManager.cxx index 5bf2ad8fb..a37b13ed0 100644 --- a/src/emucore/tia/FrameManager.cxx +++ b/src/emucore/tia/FrameManager.cxx @@ -17,6 +17,8 @@ // #define TIA_FRAMEMANAGER_DEBUG_LOG +#include + #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; } diff --git a/src/emucore/tia/FrameManager.hxx b/src/emucore/tia/FrameManager.hxx index 23585487d..c534aca84 100644 --- a/src/emucore/tia/FrameManager.hxx +++ b/src/emucore/tia/FrameManager.hxx @@ -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; diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx index ee8b1e528..2e0a297fc 100644 --- a/src/emucore/tia/TIA.cxx +++ b/src/emucore/tia/TIA.cxx @@ -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(160 * 320); - myPreviousFrameBuffer = make_ptr(160 * 320); + myCurrentFrameBuffer = make_ptr(160 * FrameManager::frameBufferHeight); + myPreviousFrameBuffer = make_ptr(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) { diff --git a/src/emucore/tia/TIA.hxx b/src/emucore/tia/TIA.hxx index 8875fadf8..7dc14e9ad 100644 --- a/src/emucore/tia/TIA.hxx +++ b/src/emucore/tia/TIA.hxx @@ -351,6 +351,10 @@ class TIA : public Device private: + void onFrameStart(); + + void onFrameComplete(); + void updateEmulation(); void cycle(uInt32 colorClocks);