From 362f7c2888e18f7d52ae0481c8ad67bf5c192d70 Mon Sep 17 00:00:00 2001 From: Christian Speckner Date: Tue, 9 May 2017 00:10:14 +0200 Subject: [PATCH] Reimplement jitter; fixes #11. --- src/emucore/tia/FrameManager.cxx | 25 +++++++++++++++++++- src/emucore/tia/FrameManager.hxx | 8 +++++++ src/emucore/tia/TIA.cxx | 26 ++++++++++++++++----- src/emucore/tia/TIA.hxx | 2 +- src/emucore/tia/VblankManager.cxx | 38 +++++++++++++++++++++++++++---- src/emucore/tia/VblankManager.hxx | 6 +++++ 6 files changed, 93 insertions(+), 12 deletions(-) diff --git a/src/emucore/tia/FrameManager.cxx b/src/emucore/tia/FrameManager.cxx index 61a632ead..a1c3f4b66 100644 --- a/src/emucore/tia/FrameManager.cxx +++ b/src/emucore/tia/FrameManager.cxx @@ -57,7 +57,8 @@ FrameManager::FrameManager() : myLayout(FrameLayout::pal), myAutodetectLayout(true), myHeight(0), - myFixedHeight(0) + myFixedHeight(0), + myJitterEnabled(false) { updateLayout(FrameLayout::ntsc); reset(); @@ -210,6 +211,8 @@ void FrameManager::setState(FrameManager::State state) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FrameManager::finalizeFrame() { + handleJitter(myCurrentFrameTotalLines - myCurrentFrameFinalLines); + myCurrentFrameFinalLines = myCurrentFrameTotalLines; myCurrentFrameTotalLines = 0; myTotalFrames++; @@ -226,6 +229,14 @@ void FrameManager::finalizeFrame() myCurrentFrameFinalLines; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameManager::handleJitter(Int32 scanlineDifference) +{ + if (scanlineDifference == 0 || !myJitterEnabled || myTotalFrames < Metrics::initialGarbageFrames) return; + + myVblankManager.setJitter(scanlineDifference); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FrameManager::updateAutodetectedLayout() { @@ -315,6 +326,14 @@ void FrameManager::setFixedHeight(uInt32 height) myHeight = myFixedHeight > 0 ? myFixedHeight : (myKernelLines + Metrics::visibleOverscan); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameManager::enableJitter(bool enabled) +{ + myJitterEnabled = enabled; + + if (!enabled) myVblankManager.setJitter(0); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool FrameManager::save(Serializer& out) const { @@ -347,6 +366,8 @@ bool FrameManager::save(Serializer& out) const out.putInt(myFrameLines); out.putInt(myHeight); out.putInt(myFixedHeight); + + out.putBool(myJitterEnabled); } catch(...) { @@ -390,6 +411,8 @@ bool FrameManager::load(Serializer& in) myFrameLines = in.getInt(); myHeight = in.getInt(); myFixedHeight = in.getInt(); + + myJitterEnabled = in.getBool(); } catch(...) { diff --git a/src/emucore/tia/FrameManager.hxx b/src/emucore/tia/FrameManager.hxx index ee6022457..659446c81 100644 --- a/src/emucore/tia/FrameManager.hxx +++ b/src/emucore/tia/FrameManager.hxx @@ -89,6 +89,10 @@ class FrameManager : public Serializable bool load(Serializer& in) override; string name() const override { return "TIA_FrameManager"; } + void setJitterFactor(uInt8 factor) { myVblankManager.setJitterFactor(factor); } + bool jitterEnabled() const { return myJitterEnabled; } + void enableJitter(bool enabled); + public: static constexpr uInt32 frameBufferHeight = 320; static constexpr uInt32 minYStart = 1, maxYStart = 64; @@ -122,6 +126,8 @@ class FrameManager : public Serializable void nextLineInVsync(); + void handleJitter(Int32 scanlineDifference); + private: callback myOnFrameStart; @@ -153,6 +159,8 @@ class FrameManager : public Serializable uInt32 myHeight; uInt32 myFixedHeight; + bool myJitterEnabled; + private: FrameManager(const FrameManager&) = delete; FrameManager(FrameManager&&) = delete; diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx index 47c96fc70..8786897c3 100644 --- a/src/emucore/tia/TIA.cxx +++ b/src/emucore/tia/TIA.cxx @@ -98,6 +98,9 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings) myMissile1.setTIA(this); myBall.setTIA(this); + myFrameManager.enableJitter(mySettings.getBool("tv.jitter")); + myFrameManager.setJitterFactor(mySettings.getInt("tv.jitter_recovery")); + reset(); } @@ -896,13 +899,24 @@ bool TIA::driveUnusedPinsRandom(uInt8 mode) // TODO: stub bool TIA::toggleJitter(uInt8 mode) { - return false; -} + switch (mode) { + case 0: + myFrameManager.enableJitter(false); + break; -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// TODO: stub -void TIA::setJitterRecoveryFactor(Int32 f) -{ + case 1: + myFrameManager.enableJitter(true); + break; + + case 2: + myFrameManager.enableJitter(!myFrameManager.jitterEnabled()); + break; + + default: + throw runtime_error("invalid argument for toggleJitter"); + } + + return myFrameManager.jitterEnabled(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/tia/TIA.hxx b/src/emucore/tia/TIA.hxx index 4227dcd28..57c2ae6e1 100644 --- a/src/emucore/tia/TIA.hxx +++ b/src/emucore/tia/TIA.hxx @@ -294,7 +294,7 @@ class TIA : public Device @return Whether the mode was enabled or disabled */ bool toggleJitter(uInt8 mode = 2); - void setJitterRecoveryFactor(Int32 f); + void setJitterRecoveryFactor(Int32 factor) { myFrameManager.setJitterFactor(factor); } // Clear both internal TIA buffers to black (palette color 0) void clearBuffers(); diff --git a/src/emucore/tia/VblankManager.cxx b/src/emucore/tia/VblankManager.cxx index 2f372e5ba..b0a92e106 100644 --- a/src/emucore/tia/VblankManager.cxx +++ b/src/emucore/tia/VblankManager.cxx @@ -17,20 +17,25 @@ // #define TIA_VBLANK_MANAGER_DEBUG_LOG +#include + #include "VblankManager.hxx" enum Metrics: uInt32 { maxUnderscan = 10, maxVblankViolations = 2, minStableVblankFrames = 1, - framesUntilFinal = 30 + framesUntilFinal = 30, + maxJitter = 50 }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VblankManager::VblankManager() : myVblankLines(0), myYstart(0), - myMode(VblankMode::floating) + myMode(VblankMode::floating), + myJitter(0), + myJitterFactor(2) { reset(); } @@ -45,10 +50,24 @@ void VblankManager::reset() myVblankViolated = false; myLastVblankLines = 0; myIsRunning = false; + myJitter = 0; if (myMode != VblankMode::fixed) setVblankMode(VblankMode::floating); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VblankManager::setJitter(Int32 jitter) { + jitter = std::min(jitter, Metrics::maxJitter); + + if (myMode == VblankMode::final) jitter = std::max(jitter, -myLastVblankLines); + if (myMode == VblankMode::fixed) jitter = std::max(jitter, -myYstart); + + if (jitter > 0) jitter += myJitterFactor; + if (jitter < 0) jitter -= myJitterFactor; + + if (abs(jitter) > abs(myJitter)) myJitter = jitter; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void VblankManager::start() { @@ -58,6 +77,9 @@ void VblankManager::start() if (myMode == VblankMode::locked && ++myFramesInLockedMode > Metrics::framesUntilFinal) setVblankMode(VblankMode::final); + + if (myJitter > 0) myJitter = std::max(myJitter - myJitterFactor, 0); + if (myJitter < 0) myJitter = std::min(myJitter + myJitterFactor, 0); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -156,11 +178,13 @@ bool VblankManager::shouldTransition(bool isGarbageFrame) break; case VblankMode::fixed: - transition = myCurrentLine >= myYstart; + transition = (Int32)myCurrentLine >= + std::max(myYstart + std::min(myJitter, Metrics::maxJitter), 0); break; case VblankMode::final: - transition = myCurrentLine >= myLastVblankLines; + transition = (Int32)myCurrentLine >= + std::max(myLastVblankLines + std::min(myJitter, Metrics::maxJitter), 0); break; } @@ -203,6 +227,9 @@ bool VblankManager::save(Serializer& out) const out.putBool(myVblankViolated); out.putByte(myFramesInLockedMode); + out.putInt(myJitter); + out.putByte(myJitterFactor); + out.putBool(myIsRunning); } catch(...) @@ -234,6 +261,9 @@ bool VblankManager::load(Serializer& in) myVblankViolated = in.getBool(); myFramesInLockedMode = in.getByte(); + myJitter = in.getInt(); + myJitterFactor = in.getByte(); + myIsRunning = in.getBool(); } catch(...) diff --git a/src/emucore/tia/VblankManager.hxx b/src/emucore/tia/VblankManager.hxx index bb0ffdd9d..1a8ead5a8 100644 --- a/src/emucore/tia/VblankManager.hxx +++ b/src/emucore/tia/VblankManager.hxx @@ -49,6 +49,9 @@ class VblankManager : public Serializable uInt32 currentLine() const { return myCurrentLine; }; + void setJitter(Int32 jitter); + void setJitterFactor(uInt8 jitterFactor) { myJitterFactor = jitterFactor; } + /** Serializable methods (see that class for more information). */ @@ -85,6 +88,9 @@ class VblankManager : public Serializable bool myVblankViolated; uInt8 myFramesInLockedMode; + Int32 myJitter; + uInt8 myJitterFactor; + bool myIsRunning; private: