mirror of https://github.com/stella-emu/stella.git
Reimplement jitter; fixes #11.
This commit is contained in:
parent
1cb83f4a68
commit
362f7c2888
|
@ -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(...)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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(...)
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue