Reimplement jitter; fixes #11.

This commit is contained in:
Christian Speckner 2017-05-09 00:10:14 +02:00
parent 1cb83f4a68
commit 362f7c2888
6 changed files with 93 additions and 12 deletions

View File

@ -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(...)
{

View File

@ -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;

View File

@ -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();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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();

View File

@ -17,20 +17,25 @@
// #define TIA_VBLANK_MANAGER_DEBUG_LOG
#include <algorithm>
#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<Int32>(jitter, Metrics::maxJitter);
if (myMode == VblankMode::final) jitter = std::max<Int32>(jitter, -myLastVblankLines);
if (myMode == VblankMode::fixed) jitter = std::max<Int32>(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<Int32>(myYstart + std::min<Int32>(myJitter, Metrics::maxJitter), 0);
break;
case VblankMode::final:
transition = myCurrentLine >= myLastVblankLines;
transition = (Int32)myCurrentLine >=
std::max<Int32>(myLastVblankLines + std::min<Int32>(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(...)

View File

@ -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: