mirror of https://github.com/stella-emu/stella.git
started working on emulating VBLANK during VSYNC
This commit is contained in:
parent
0933f1ae66
commit
56a82682d5
|
@ -583,7 +583,6 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
updateDumpPorts(value);
|
updateDumpPorts(value);
|
||||||
|
|
||||||
myDelayQueue.push(VBLANK, value, Delay::vblank);
|
myDelayQueue.push(VBLANK, value, Delay::vblank);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUDV0:
|
case AUDV0:
|
||||||
|
@ -1936,7 +1935,7 @@ void TIA::delayedWrite(uInt8 address, uInt8 value)
|
||||||
{
|
{
|
||||||
case VBLANK:
|
case VBLANK:
|
||||||
flushLineCache();
|
flushLineCache();
|
||||||
myFrameManager->setVblank(value & 0x02);
|
myFrameManager->setVblank(value & 0x02, mySystem->cycles());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HMOVE:
|
case HMOVE:
|
||||||
|
|
|
@ -62,13 +62,13 @@ void AbstractFrameManager::clearHandlers()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void AbstractFrameManager::setVblank(bool vblank)
|
void AbstractFrameManager::setVblank(bool vblank, uInt64 cycles)
|
||||||
{
|
{
|
||||||
if (vblank == myVblank) return;
|
if (vblank == myVblank) return;
|
||||||
|
|
||||||
myVblank = vblank;
|
myVblank = vblank;
|
||||||
|
|
||||||
onSetVblank();
|
onSetVblank(cycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -63,7 +63,7 @@ class AbstractFrameManager : public Serializable
|
||||||
/**
|
/**
|
||||||
* Called by TIA on VBLANK writes.
|
* Called by TIA on VBLANK writes.
|
||||||
*/
|
*/
|
||||||
void setVblank(bool vblank);
|
void setVblank(bool vblank, uInt64 cycles);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by TIA on VSYNC writes.
|
* Called by TIA on VSYNC writes.
|
||||||
|
@ -218,7 +218,7 @@ class AbstractFrameManager : public Serializable
|
||||||
/**
|
/**
|
||||||
* Called if vblank changes.
|
* Called if vblank changes.
|
||||||
*/
|
*/
|
||||||
virtual void onSetVblank() {}
|
virtual void onSetVblank(uInt64 cycles) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called if vsync changes.
|
* Called if vsync changes.
|
||||||
|
|
|
@ -34,7 +34,7 @@ void FrameManager::onReset()
|
||||||
myState = State::waitForVsyncStart;
|
myState = State::waitForVsyncStart;
|
||||||
myLineInState = 0;
|
myLineInState = 0;
|
||||||
myTotalFrames = 0;
|
myTotalFrames = 0;
|
||||||
myVsyncLines = 0;
|
myVsyncLineCount = 0;
|
||||||
myY = 0;
|
myY = 0;
|
||||||
|
|
||||||
myJitterEmulation.reset();
|
myJitterEmulation.reset();
|
||||||
|
@ -50,14 +50,19 @@ void FrameManager::onNextLine()
|
||||||
{
|
{
|
||||||
case State::waitForVsyncStart:
|
case State::waitForVsyncStart:
|
||||||
if ((myCurrentFrameTotalLines > myFrameLines - 3) || myTotalFrames == 0)
|
if ((myCurrentFrameTotalLines > myFrameLines - 3) || myTotalFrames == 0)
|
||||||
++myVsyncLines;
|
{
|
||||||
|
if (myVblank)
|
||||||
|
++myVsyncLineCount;
|
||||||
|
}
|
||||||
|
|
||||||
if (myVsyncLines > Metrics::maxLinesVsync) setState(State::waitForFrameStart);
|
if (myVsyncLineCount > Metrics::maxLinesVsync) setState(State::waitForFrameStart);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::waitForVsyncEnd:
|
case State::waitForVsyncEnd:
|
||||||
if (++myVsyncLines > Metrics::maxLinesVsync)
|
if (myVblank)
|
||||||
|
++myVsyncLineCount;
|
||||||
|
if (myVsyncLineCount > Metrics::maxLinesVsync)
|
||||||
setState(State::waitForFrameStart);
|
setState(State::waitForFrameStart);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -112,16 +117,38 @@ void FrameManager::setAdjustVSize(Int32 adjustVSize)
|
||||||
recalculateMetrics();
|
recalculateMetrics();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameManager::onSetVblank(uInt64 cycles)
|
||||||
|
{
|
||||||
|
if (myState == State::waitForVsyncEnd)
|
||||||
|
if (myVblank) // VBLANK switched on
|
||||||
|
{
|
||||||
|
myVblankStart = cycles;
|
||||||
|
cerr << ", VBLANK ON " << cycles;
|
||||||
|
}
|
||||||
|
else // VBLANK switched off
|
||||||
|
{
|
||||||
|
myVblankCycles += cycles - myVblankStart;
|
||||||
|
cerr << ", VBLANK OFF " << cycles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameManager::onSetVsync(uInt64 cycles)
|
void FrameManager::onSetVsync(uInt64 cycles)
|
||||||
{
|
{
|
||||||
if (myState == State::waitForVsyncEnd) {
|
if (myState == State::waitForVsyncEnd) {
|
||||||
myVsyncEnd = cycles;
|
myVsyncEnd = cycles;
|
||||||
|
if(myVblankStart != INT64_MAX)
|
||||||
|
myVblankCycles += cycles - myVblankStart;
|
||||||
setState(State::waitForFrameStart);
|
setState(State::waitForFrameStart);
|
||||||
|
cerr << ", VSYNC waitForVsyncEnd " << cycles << " \n";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
myVsyncStart = cycles;
|
myVsyncStart = cycles;
|
||||||
|
myVblankStart = myVblank ? cycles : INT64_MAX;
|
||||||
|
myVblankCycles = 0;
|
||||||
setState(State::waitForVsyncEnd);
|
setState(State::waitForVsyncEnd);
|
||||||
|
cerr << ", VSYNC waitForFrameStart " << cycles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,15 +166,15 @@ void FrameManager::setState(FrameManager::State state)
|
||||||
|
|
||||||
if (myTotalFrames > Metrics::initialGarbageFrames)
|
if (myTotalFrames > Metrics::initialGarbageFrames)
|
||||||
myJitterEmulation.frameComplete(myCurrentFrameFinalLines,
|
myJitterEmulation.frameComplete(myCurrentFrameFinalLines,
|
||||||
static_cast<Int32>(myVsyncEnd - myVsyncStart));
|
static_cast<Int32>(myVsyncEnd - myVsyncStart), static_cast<Int32>(myVblankCycles));
|
||||||
|
|
||||||
notifyFrameStart();
|
notifyFrameStart();
|
||||||
|
|
||||||
myVsyncLines = 0;
|
myVsyncLineCount = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::frame:
|
case State::frame:
|
||||||
myVsyncLines = 0;
|
myVsyncLineCount = 0;
|
||||||
myY = 0;
|
myY = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -176,7 +203,7 @@ bool FrameManager::onSave(Serializer& out) const
|
||||||
|
|
||||||
out.putInt(static_cast<uInt32>(myState));
|
out.putInt(static_cast<uInt32>(myState));
|
||||||
out.putInt(myLineInState);
|
out.putInt(myLineInState);
|
||||||
out.putInt(myVsyncLines);
|
out.putInt(myVsyncLineCount);
|
||||||
out.putInt(myY);
|
out.putInt(myY);
|
||||||
out.putInt(myLastY);
|
out.putInt(myLastY);
|
||||||
|
|
||||||
|
@ -200,7 +227,7 @@ bool FrameManager::onLoad(Serializer& in)
|
||||||
|
|
||||||
myState = static_cast<State>(in.getInt());
|
myState = static_cast<State>(in.getInt());
|
||||||
myLineInState = in.getInt();
|
myLineInState = in.getInt();
|
||||||
myVsyncLines = in.getInt();
|
myVsyncLineCount = in.getInt();
|
||||||
myY = in.getInt();
|
myY = in.getInt();
|
||||||
myLastY = in.getInt();
|
myLastY = in.getInt();
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,8 @@ class FrameManager: public AbstractFrameManager {
|
||||||
|
|
||||||
void setLayout(FrameLayout mode) override { layout(mode); }
|
void setLayout(FrameLayout mode) override { layout(mode); }
|
||||||
|
|
||||||
|
void onSetVblank(uInt64 cycles) override;
|
||||||
|
|
||||||
void onSetVsync(uInt64 cycles) override;
|
void onSetVsync(uInt64 cycles) override;
|
||||||
|
|
||||||
void onNextLine() override;
|
void onNextLine() override;
|
||||||
|
@ -116,7 +118,7 @@ class FrameManager: public AbstractFrameManager {
|
||||||
|
|
||||||
State myState{State::waitForVsyncStart};
|
State myState{State::waitForVsyncStart};
|
||||||
uInt32 myLineInState{0};
|
uInt32 myLineInState{0};
|
||||||
uInt32 myVsyncLines{0};
|
uInt32 myVsyncLineCount{0};
|
||||||
uInt32 myY{0}, myLastY{0};
|
uInt32 myY{0}, myLastY{0};
|
||||||
|
|
||||||
uInt32 myVblankLines{0};
|
uInt32 myVblankLines{0};
|
||||||
|
@ -129,6 +131,8 @@ class FrameManager: public AbstractFrameManager {
|
||||||
|
|
||||||
uInt64 myVsyncStart{0};
|
uInt64 myVsyncStart{0};
|
||||||
uInt64 myVsyncEnd{0};
|
uInt64 myVsyncEnd{0};
|
||||||
|
uInt64 myVblankStart{0};
|
||||||
|
uInt64 myVblankCycles{0};
|
||||||
bool myJitterEnabled{false};
|
bool myJitterEnabled{false};
|
||||||
|
|
||||||
JitterEmulation myJitterEmulation;
|
JitterEmulation myJitterEmulation;
|
||||||
|
|
|
@ -54,13 +54,16 @@ void JitterEmulation::setSensitivity(Int32 sensitivity)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void JitterEmulation::frameComplete(Int32 scanlineCount, Int32 vsyncCycles)
|
void JitterEmulation::frameComplete(Int32 scanlineCount, Int32 vsyncCycles, Int32 vblankCycles)
|
||||||
{
|
{
|
||||||
//#ifdef DEBUG_BUILD
|
//#ifdef DEBUG_BUILD
|
||||||
// const int vsyncLines = round((vsyncCycles - 2) / 76.0);
|
// const int vsyncLines = round((vsyncCycles - 2) / 76.0);
|
||||||
// cerr << "TV jitter " << myJitter << " - " << scanlineCount << ", " << vsyncCycles << ", " << vsyncLines << '\n';
|
// cerr << "TV jitter " << myJitter << " - " << scanlineCount << ", " << vsyncCycles << ", " << vsyncLines << '\n';
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
|
if (mySensitivity >= 6)
|
||||||
|
vsyncCycles = std::min(vsyncCycles, vblankCycles);
|
||||||
|
|
||||||
// Check if current frame size is stable compared to previous frame
|
// Check if current frame size is stable compared to previous frame
|
||||||
const bool scanlinesStable = scanlineCount == myLastFrameScanlines;
|
const bool scanlinesStable = scanlineCount == myLastFrameScanlines;
|
||||||
const bool vsyncCyclesStable = vsyncCycles >= myVsyncCycles;
|
const bool vsyncCyclesStable = vsyncCycles >= myVsyncCycles;
|
||||||
|
|
|
@ -48,7 +48,7 @@ class JitterEmulation : public Serializable
|
||||||
void setRecovery(Int32 recoveryFactor) { myJitterRecovery = recoveryFactor; }
|
void setRecovery(Int32 recoveryFactor) { myJitterRecovery = recoveryFactor; }
|
||||||
void setYStart(Int32 ystart) { myYStart = ystart; }
|
void setYStart(Int32 ystart) { myYStart = ystart; }
|
||||||
|
|
||||||
void frameComplete(Int32 scanlineCount, Int32 vsyncCycles);
|
void frameComplete(Int32 scanlineCount, Int32 vsyncCycles, Int32 vblankCycles);
|
||||||
Int32 jitter() const { return myJitter; }
|
Int32 jitter() const { return myJitter; }
|
||||||
|
|
||||||
bool vsyncCorrect() const { return myVsyncCorrect; }
|
bool vsyncCorrect() const { return myVsyncCorrect; }
|
||||||
|
|
Loading…
Reference in New Issue