mirror of https://github.com/stella-emu/stella.git
Fix garbage for ROMs with varying visible frame heights:
* Keep track of max frame height * Blank out any missing scanlines * Refactoring
This commit is contained in:
parent
5f5ea1f424
commit
a83e7eb26d
|
@ -17,6 +17,8 @@
|
|||
|
||||
// #define TIA_FRAMEMANAGER_DEBUG_LOG
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<uInt8[]>(160 * 320);
|
||||
myPreviousFrameBuffer = make_ptr<uInt8[]>(160 * 320);
|
||||
myCurrentFrameBuffer = make_ptr<uInt8[]>(160 * FrameManager::frameBufferHeight);
|
||||
myPreviousFrameBuffer = make_ptr<uInt8[]>(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)
|
||||
{
|
||||
|
|
|
@ -351,6 +351,10 @@ class TIA : public Device
|
|||
|
||||
private:
|
||||
|
||||
void onFrameStart();
|
||||
|
||||
void onFrameComplete();
|
||||
|
||||
void updateEmulation();
|
||||
|
||||
void cycle(uInt32 colorClocks);
|
||||
|
|
Loading…
Reference in New Issue