mirror of https://github.com/stella-emu/stella.git
Refactor FrameManager to extend AbstractFrameManager.
This commit is contained in:
parent
d52562975d
commit
a400238c19
|
@ -48,7 +48,7 @@ const DebuggerState& TIADebug::getState()
|
||||||
myState.coluRegs.push_back(coluBK());
|
myState.coluRegs.push_back(coluBK());
|
||||||
|
|
||||||
// Debug Colors
|
// Debug Colors
|
||||||
int mode = myTIA.myFrameManager.layout() == FrameLayout::ntsc ? 0 : 1;
|
int mode = myTIA.frameLayout() == FrameLayout::ntsc ? 0 : 1;
|
||||||
myState.fixedCols.clear();
|
myState.fixedCols.clear();
|
||||||
myState.fixedCols.push_back(myTIA.myFixedColorPalette[mode][TIA::P0]);
|
myState.fixedCols.push_back(myTIA.myFixedColorPalette[mode][TIA::P0]);
|
||||||
myState.fixedCols.push_back(myTIA.myFixedColorPalette[mode][TIA::P1]);
|
myState.fixedCols.push_back(myTIA.myFixedColorPalette[mode][TIA::P1]);
|
||||||
|
@ -721,7 +721,7 @@ int TIADebug::scanlines() const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
int TIADebug::scanlinesLastFrame() const
|
int TIADebug::scanlinesLastFrame() const
|
||||||
{
|
{
|
||||||
return myTIA.myFrameManager.scanlinesLastFrame();
|
return myTIA.scanlinesLastFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -801,7 +801,7 @@ string TIADebug::debugColors() const
|
||||||
{
|
{
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
|
|
||||||
int mode = myTIA.myFrameManager.layout() == FrameLayout::ntsc ? 0 : 1;
|
int mode = myTIA.frameLayout() == FrameLayout::ntsc ? 0 : 1;
|
||||||
buf << " Red " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::P0])
|
buf << " Red " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::P0])
|
||||||
<< " Player 0\n"
|
<< " Player 0\n"
|
||||||
<< " Orange " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::M0])
|
<< " Orange " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::M0])
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "Paddles.hxx"
|
#include "Paddles.hxx"
|
||||||
#include "DelayQueueIteratorImpl.hxx"
|
#include "DelayQueueIteratorImpl.hxx"
|
||||||
#include "TIAConstants.hxx"
|
#include "TIAConstants.hxx"
|
||||||
|
#include "frame-manager/FrameManager.hxx"
|
||||||
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "CartDebug.hxx"
|
#include "CartDebug.hxx"
|
||||||
|
@ -77,7 +78,9 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
|
||||||
mySpriteEnabledBits(0xFF),
|
mySpriteEnabledBits(0xFF),
|
||||||
myCollisionsEnabledBits(0xFF)
|
myCollisionsEnabledBits(0xFF)
|
||||||
{
|
{
|
||||||
myFrameManager.setHandlers(
|
myFrameManager = new FrameManager();
|
||||||
|
|
||||||
|
myFrameManager->setHandlers(
|
||||||
[this] () {
|
[this] () {
|
||||||
onFrameStart();
|
onFrameStart();
|
||||||
},
|
},
|
||||||
|
@ -99,12 +102,17 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
|
||||||
myMissile1.setTIA(this);
|
myMissile1.setTIA(this);
|
||||||
myBall.setTIA(this);
|
myBall.setTIA(this);
|
||||||
|
|
||||||
myFrameManager.enableJitter(mySettings.getBool("tv.jitter"));
|
myFrameManager->enableJitter(mySettings.getBool("tv.jitter"));
|
||||||
myFrameManager.setJitterFactor(mySettings.getInt("tv.jitter_recovery"));
|
myFrameManager->setJitterFactor(mySettings.getInt("tv.jitter_recovery"));
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
TIA::~TIA() {
|
||||||
|
delete myFrameManager;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIA::reset()
|
void TIA::reset()
|
||||||
{
|
{
|
||||||
|
@ -144,7 +152,7 @@ void TIA::reset()
|
||||||
|
|
||||||
mySound.reset();
|
mySound.reset();
|
||||||
myDelayQueue.reset();
|
myDelayQueue.reset();
|
||||||
myFrameManager.reset();
|
myFrameManager->reset();
|
||||||
|
|
||||||
myCyclesAtFrameStart = 0;
|
myCyclesAtFrameStart = 0;
|
||||||
|
|
||||||
|
@ -206,7 +214,7 @@ bool TIA::save(Serializer& out) const
|
||||||
if(!mySound.save(out)) return false;
|
if(!mySound.save(out)) return false;
|
||||||
|
|
||||||
if(!myDelayQueue.save(out)) return false;
|
if(!myDelayQueue.save(out)) return false;
|
||||||
if(!myFrameManager.save(out)) return false;
|
if(!myFrameManager->save(out)) return false;
|
||||||
|
|
||||||
if(!myBackground.save(out)) return false;
|
if(!myBackground.save(out)) return false;
|
||||||
if(!myPlayfield.save(out)) return false;
|
if(!myPlayfield.save(out)) return false;
|
||||||
|
@ -277,7 +285,7 @@ bool TIA::load(Serializer& in)
|
||||||
if(!mySound.load(in)) return false;
|
if(!mySound.load(in)) return false;
|
||||||
|
|
||||||
if(!myDelayQueue.load(in)) return false;
|
if(!myDelayQueue.load(in)) return false;
|
||||||
if(!myFrameManager.load(in)) return false;
|
if(!myFrameManager->load(in)) return false;
|
||||||
|
|
||||||
if(!myBackground.load(in)) return false;
|
if(!myBackground.load(in)) return false;
|
||||||
if(!myPlayfield.load(in)) return false;
|
if(!myPlayfield.load(in)) return false;
|
||||||
|
@ -482,7 +490,7 @@ bool TIA::poke(uInt16 address, uInt8 value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VSYNC:
|
case VSYNC:
|
||||||
myFrameManager.setVsync(value & 0x02);
|
myFrameManager->setVsync(value & 0x02);
|
||||||
myShadowRegisters[address] = value;
|
myShadowRegisters[address] = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -796,7 +804,7 @@ bool TIA::enableColorLoss(bool enabled)
|
||||||
if(enabled)
|
if(enabled)
|
||||||
{
|
{
|
||||||
myColorLossEnabled = true;
|
myColorLossEnabled = true;
|
||||||
myColorLossActive = myFrameManager.scanlinesLastFrame() & 0x1;
|
myColorLossActive = myFrameManager->scanlinesLastFrame() & 0x1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -820,7 +828,7 @@ bool TIA::electronBeamPos(uInt32& x, uInt32& y) const
|
||||||
uInt8 clocks = clocksThisLine();
|
uInt8 clocks = clocksThisLine();
|
||||||
|
|
||||||
x = (clocks < 68) ? 0 : clocks - 68;
|
x = (clocks < 68) ? 0 : clocks - 68;
|
||||||
y = myFrameManager.getY();
|
y = myFrameManager->getY();
|
||||||
|
|
||||||
return isRendering();
|
return isRendering();
|
||||||
}
|
}
|
||||||
|
@ -906,7 +914,7 @@ bool TIA::toggleCollisions()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool TIA::enableFixedColors(bool enable)
|
bool TIA::enableFixedColors(bool enable)
|
||||||
{
|
{
|
||||||
int layout = myFrameManager.layout() == FrameLayout::pal ? 1 : 0;
|
int layout = myFrameManager->layout() == FrameLayout::pal ? 1 : 0;
|
||||||
myMissile0.setDebugColor(myFixedColorPalette[layout][FixedObject::M0]);
|
myMissile0.setDebugColor(myFixedColorPalette[layout][FixedObject::M0]);
|
||||||
myMissile1.setDebugColor(myFixedColorPalette[layout][FixedObject::M1]);
|
myMissile1.setDebugColor(myFixedColorPalette[layout][FixedObject::M1]);
|
||||||
myPlayer0.setDebugColor(myFixedColorPalette[layout][FixedObject::P0]);
|
myPlayer0.setDebugColor(myFixedColorPalette[layout][FixedObject::P0]);
|
||||||
|
@ -991,22 +999,22 @@ bool TIA::toggleJitter(uInt8 mode)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 0:
|
case 0:
|
||||||
myFrameManager.enableJitter(false);
|
myFrameManager->enableJitter(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
myFrameManager.enableJitter(true);
|
myFrameManager->enableJitter(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
myFrameManager.enableJitter(!myFrameManager.jitterEnabled());
|
myFrameManager->enableJitter(!myFrameManager->jitterEnabled());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw runtime_error("invalid argument for toggleJitter");
|
throw runtime_error("invalid argument for toggleJitter");
|
||||||
}
|
}
|
||||||
|
|
||||||
return myFrameManager.jitterEnabled();
|
return myFrameManager->jitterEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1081,9 +1089,9 @@ void TIA::onFrameStart()
|
||||||
{
|
{
|
||||||
// Only activate it when necessary, since changing colours in
|
// Only activate it when necessary, since changing colours in
|
||||||
// the graphical object forces the TIA cached line to be flushed
|
// the graphical object forces the TIA cached line to be flushed
|
||||||
if (myFrameManager.scanlineCountTransitioned())
|
if (myFrameManager->scanlineCountTransitioned())
|
||||||
{
|
{
|
||||||
myColorLossActive = myFrameManager.scanlinesLastFrame() & 0x1;
|
myColorLossActive = myFrameManager->scanlinesLastFrame() & 0x1;
|
||||||
|
|
||||||
myMissile0.applyColorLoss();
|
myMissile0.applyColorLoss();
|
||||||
myMissile1.applyColorLoss();
|
myMissile1.applyColorLoss();
|
||||||
|
@ -1112,13 +1120,13 @@ void TIA::onFrameComplete()
|
||||||
memset(myFramebuffer, 0, myXAtRenderingStart);
|
memset(myFramebuffer, 0, myXAtRenderingStart);
|
||||||
|
|
||||||
// Blank out any extra lines not drawn this frame
|
// Blank out any extra lines not drawn this frame
|
||||||
const uInt32 missingScanlines = myFrameManager.missingScanlines();
|
const Int32 missingScanlines = myFrameManager->missingScanlines();
|
||||||
if (missingScanlines > 0)
|
if (missingScanlines > 0)
|
||||||
memset(myFramebuffer + 160 * myFrameManager.getY(), 0, missingScanlines * 160);
|
memset(myFramebuffer + 160 * myFrameManager->getY(), 0, missingScanlines * 160);
|
||||||
|
|
||||||
// Recalculate framerate, attempting to auto-correct for scanline 'jumps'
|
// Recalculate framerate, attempting to auto-correct for scanline 'jumps'
|
||||||
if(myAutoFrameEnabled)
|
if(myAutoFrameEnabled)
|
||||||
myConsole.setFramerate(myFrameManager.frameRate());
|
myConsole.setFramerate(myFrameManager->frameRate());
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1148,7 +1156,7 @@ void TIA::cycle(uInt32 colorClocks)
|
||||||
else
|
else
|
||||||
tickHframe();
|
tickHframe();
|
||||||
|
|
||||||
if (myCollisionUpdateRequired && !myFrameManager.vblank()) updateCollision();
|
if (myCollisionUpdateRequired && !myFrameManager->vblank()) updateCollision();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++myHctr >= 228)
|
if (++myHctr >= 228)
|
||||||
|
@ -1202,7 +1210,7 @@ void TIA::tickHblank()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIA::tickHframe()
|
void TIA::tickHframe()
|
||||||
{
|
{
|
||||||
const uInt32 y = myFrameManager.getY();
|
const uInt32 y = myFrameManager->getY();
|
||||||
const uInt32 x = myHctr - 68 - myHctrDelta;
|
const uInt32 x = myHctr - 68 - myHctrDelta;
|
||||||
|
|
||||||
myCollisionUpdateRequired = true;
|
myCollisionUpdateRequired = true;
|
||||||
|
@ -1214,7 +1222,7 @@ void TIA::tickHframe()
|
||||||
myPlayer1.tick();
|
myPlayer1.tick();
|
||||||
myBall.tick();
|
myBall.tick();
|
||||||
|
|
||||||
if (myFrameManager.isRendering())
|
if (myFrameManager->isRendering())
|
||||||
renderPixel(x, y);
|
renderPixel(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1224,8 +1232,8 @@ void TIA::applyRsync()
|
||||||
const uInt32 x = myHctr > 68 ? myHctr - 68 : 0;
|
const uInt32 x = myHctr > 68 ? myHctr - 68 : 0;
|
||||||
|
|
||||||
myHctrDelta = 225 - myHctr;
|
myHctrDelta = 225 - myHctr;
|
||||||
if (myFrameManager.isRendering())
|
if (myFrameManager->isRendering())
|
||||||
memset(myFramebuffer + myFrameManager.getY() * 160 + x, 0, 160 - x);
|
memset(myFramebuffer + myFrameManager->getY() * 160 + x, 0, 160 - x);
|
||||||
|
|
||||||
myHctr = 225;
|
myHctr = 225;
|
||||||
}
|
}
|
||||||
|
@ -1244,9 +1252,9 @@ void TIA::nextLine()
|
||||||
myHstate = HState::blank;
|
myHstate = HState::blank;
|
||||||
myHctrDelta = 0;
|
myHctrDelta = 0;
|
||||||
|
|
||||||
myFrameManager.nextLine();
|
myFrameManager->nextLine();
|
||||||
|
|
||||||
if (myFrameManager.isRendering() && myFrameManager.getY() == 0) flushLineCache();
|
if (myFrameManager->isRendering() && myFrameManager->getY() == 0) flushLineCache();
|
||||||
|
|
||||||
mySystem->m6502().clearHaltRequest();
|
mySystem->m6502().clearHaltRequest();
|
||||||
}
|
}
|
||||||
|
@ -1254,9 +1262,9 @@ void TIA::nextLine()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIA::cloneLastLine()
|
void TIA::cloneLastLine()
|
||||||
{
|
{
|
||||||
const auto y = myFrameManager.getY();
|
const auto y = myFrameManager->getY();
|
||||||
|
|
||||||
if (!myFrameManager.isRendering() || y == 0) return;
|
if (!myFrameManager->isRendering() || y == 0) return;
|
||||||
|
|
||||||
uInt8* buffer = myFramebuffer;
|
uInt8* buffer = myFramebuffer;
|
||||||
|
|
||||||
|
@ -1283,7 +1291,7 @@ void TIA::renderPixel(uInt32 x, uInt32 y)
|
||||||
|
|
||||||
uInt8 color = 0;
|
uInt8 color = 0;
|
||||||
|
|
||||||
if (!myFrameManager.vblank())
|
if (!myFrameManager->vblank())
|
||||||
{
|
{
|
||||||
switch (myPriority)
|
switch (myPriority)
|
||||||
{
|
{
|
||||||
|
@ -1356,8 +1364,8 @@ void TIA::flushLineCache()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIA::clearHmoveComb()
|
void TIA::clearHmoveComb()
|
||||||
{
|
{
|
||||||
if (myFrameManager.isRendering() && myHstate == HState::blank)
|
if (myFrameManager->isRendering() && myHstate == HState::blank)
|
||||||
memset(myFramebuffer + myFrameManager.getY() * 160, myColorHBlank, 8);
|
memset(myFramebuffer + myFrameManager->getY() * 160, myColorHBlank, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1370,7 +1378,7 @@ void TIA::delayedWrite(uInt8 address, uInt8 value)
|
||||||
{
|
{
|
||||||
case VBLANK:
|
case VBLANK:
|
||||||
flushLineCache();
|
flushLineCache();
|
||||||
myFrameManager.setVblank(value & 0x02);
|
myFrameManager->setVblank(value & 0x02);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HMOVE:
|
case HMOVE:
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include "TIAConstants.hxx"
|
#include "TIAConstants.hxx"
|
||||||
#include "DelayQueue.hxx"
|
#include "DelayQueue.hxx"
|
||||||
#include "DelayQueueIterator.hxx"
|
#include "DelayQueueIterator.hxx"
|
||||||
#include "frame-manager/FrameManager.hxx"
|
#include "frame-manager/AbstractFrameManager.hxx"
|
||||||
#include "FrameLayout.hxx"
|
#include "FrameLayout.hxx"
|
||||||
#include "Background.hxx"
|
#include "Background.hxx"
|
||||||
#include "Playfield.hxx"
|
#include "Playfield.hxx"
|
||||||
|
@ -101,7 +101,7 @@ class TIA : public Device
|
||||||
@param settings The settings object for this TIA device
|
@param settings The settings object for this TIA device
|
||||||
*/
|
*/
|
||||||
TIA(Console& console, Sound& sound, Settings& settings);
|
TIA(Console& console, Sound& sound, Settings& settings);
|
||||||
virtual ~TIA() = default;
|
virtual ~TIA();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -193,21 +193,21 @@ class TIA : public Device
|
||||||
Answers dimensional info about the framebuffer.
|
Answers dimensional info about the framebuffer.
|
||||||
*/
|
*/
|
||||||
uInt32 width() const { return 160; }
|
uInt32 width() const { return 160; }
|
||||||
uInt32 height() const { return myFrameManager.height(); }
|
uInt32 height() const { return myFrameManager->height(); }
|
||||||
uInt32 ystart() const { return myFrameManager.ystart(); }
|
uInt32 ystart() const { return myFrameManager->ystart(); }
|
||||||
bool ystartIsAuto(uInt32 line) const { return myFrameManager.ystartIsAuto(line); }
|
bool ystartIsAuto(uInt32 line) const { return myFrameManager->ystartIsAuto(line); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Changes the current Height/YStart properties.
|
Changes the current Height/YStart properties.
|
||||||
Note that calls to these method(s) must be eventually followed by
|
Note that calls to these method(s) must be eventually followed by
|
||||||
::frameReset() for the changes to take effect.
|
::frameReset() for the changes to take effect.
|
||||||
*/
|
*/
|
||||||
void setHeight(uInt32 height) { myFrameManager.setFixedHeight(height); }
|
void setHeight(uInt32 height) { myFrameManager->setFixedHeight(height); }
|
||||||
void setYStart(uInt32 ystart) { myFrameManager.setYstart(ystart); }
|
void setYStart(uInt32 ystart) { myFrameManager->setYstart(ystart); }
|
||||||
|
|
||||||
void autodetectLayout(bool toggle) { myFrameManager.autodetectLayout(toggle); }
|
void autodetectLayout(bool toggle) { myFrameManager->autodetectLayout(toggle); }
|
||||||
void setLayout(FrameLayout layout) { myFrameManager.setLayout(layout); }
|
void setLayout(FrameLayout layout) { myFrameManager->setLayout(layout); }
|
||||||
FrameLayout frameLayout() const { return myFrameManager.layout(); }
|
FrameLayout frameLayout() const { return myFrameManager->layout(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers the timing of the console currently in use.
|
Answers the timing of the console currently in use.
|
||||||
|
@ -250,7 +250,7 @@ class TIA : public Device
|
||||||
|
|
||||||
@return The total number of scanlines generated
|
@return The total number of scanlines generated
|
||||||
*/
|
*/
|
||||||
uInt32 scanlines() const { return myFrameManager.scanlines(); }
|
uInt32 scanlines() const { return myFrameManager->scanlines(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers the total number of scanlines the TIA generated in the
|
Answers the total number of scanlines the TIA generated in the
|
||||||
|
@ -258,7 +258,7 @@ class TIA : public Device
|
||||||
|
|
||||||
@return The total number of scanlines generated in the last frame.
|
@return The total number of scanlines generated in the last frame.
|
||||||
*/
|
*/
|
||||||
uInt32 scanlinesLastFrame() const { return myFrameManager.scanlinesLastFrame(); }
|
uInt32 scanlinesLastFrame() const { return myFrameManager->scanlinesLastFrame(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers the total system cycles from the start of the emulation.
|
Answers the total system cycles from the start of the emulation.
|
||||||
|
@ -268,7 +268,7 @@ class TIA : public Device
|
||||||
/**
|
/**
|
||||||
Answers the frame count from the start of the emulation.
|
Answers the frame count from the start of the emulation.
|
||||||
*/
|
*/
|
||||||
uInt32 frameCount() const { return myFrameManager.frameCount(); }
|
uInt32 frameCount() const { return myFrameManager->frameCount(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers the system cycles from the start of the current frame.
|
Answers the system cycles from the start of the current frame.
|
||||||
|
@ -283,7 +283,7 @@ class TIA : public Device
|
||||||
|
|
||||||
@return If the frame is in rendering mode
|
@return If the frame is in rendering mode
|
||||||
*/
|
*/
|
||||||
bool isRendering() const { return myFrameManager.isRendering(); }
|
bool isRendering() const { return myFrameManager->isRendering(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers the current position of the virtual 'electron beam' used
|
Answers the current position of the virtual 'electron beam' used
|
||||||
|
@ -360,7 +360,7 @@ class TIA : public Device
|
||||||
@return Whether the mode was enabled or disabled
|
@return Whether the mode was enabled or disabled
|
||||||
*/
|
*/
|
||||||
bool toggleJitter(uInt8 mode = 2);
|
bool toggleJitter(uInt8 mode = 2);
|
||||||
void setJitterRecoveryFactor(Int32 factor) { myFrameManager.setJitterFactor(factor); }
|
void setJitterRecoveryFactor(Int32 factor) { myFrameManager->setJitterFactor(factor); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method should be called to update the TIA with a new scanline.
|
This method should be called to update the TIA with a new scanline.
|
||||||
|
@ -593,7 +593,7 @@ class TIA : public Device
|
||||||
* The frame manager is responsible for detecting frame boundaries and the visible
|
* The frame manager is responsible for detecting frame boundaries and the visible
|
||||||
* region of each frame.
|
* region of each frame.
|
||||||
*/
|
*/
|
||||||
FrameManager myFrameManager;
|
AbstractFrameManager *myFrameManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The various TIA objects.
|
* The various TIA objects.
|
||||||
|
|
|
@ -18,8 +18,13 @@
|
||||||
#include "AbstractFrameManager.hxx"
|
#include "AbstractFrameManager.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
AbstractFrameManager::AbstractFrameManager()
|
AbstractFrameManager::AbstractFrameManager() :
|
||||||
|
myLayout(FrameLayout::pal),
|
||||||
|
myOnFrameStart(0),
|
||||||
|
myOnFrameComplete(0),
|
||||||
|
myOnRenderingStart(0)
|
||||||
{
|
{
|
||||||
|
layout(FrameLayout::ntsc);
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,11 +38,8 @@ void AbstractFrameManager::reset()
|
||||||
myCurrentFrameFinalLines = 0;
|
myCurrentFrameFinalLines = 0;
|
||||||
myPreviousFrameFinalLines = 0;
|
myPreviousFrameFinalLines = 0;
|
||||||
myTotalFrames = 0;
|
myTotalFrames = 0;
|
||||||
myLayout = FrameLayout::ntsc;
|
|
||||||
myFrameRate = 0;
|
myFrameRate = 0;
|
||||||
myOnFrameComplete = 0;
|
myFrameRate = 60.0;
|
||||||
myOnFrameStart = 0;
|
|
||||||
myOnRenderingStart = 0;
|
|
||||||
|
|
||||||
onReset();
|
onReset();
|
||||||
}
|
}
|
||||||
|
@ -96,6 +98,9 @@ void AbstractFrameManager::notifyFrameComplete()
|
||||||
myTotalFrames++;
|
myTotalFrames++;
|
||||||
|
|
||||||
if (myOnFrameComplete) myOnFrameComplete();
|
if (myOnFrameComplete) myOnFrameComplete();
|
||||||
|
|
||||||
|
myFrameRate = (layout() == FrameLayout::pal ? 15600.0 : 15720.0) /
|
||||||
|
myCurrentFrameFinalLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -104,6 +109,16 @@ void AbstractFrameManager::notifyRenderingStart()
|
||||||
if (myOnRenderingStart) myOnRenderingStart();
|
if (myOnRenderingStart) myOnRenderingStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void AbstractFrameManager::layout(FrameLayout layout)
|
||||||
|
{
|
||||||
|
if (layout == myLayout) return;
|
||||||
|
|
||||||
|
myLayout = layout;
|
||||||
|
|
||||||
|
onLayoutChange();
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool AbstractFrameManager::save(Serializer& out) const
|
bool AbstractFrameManager::save(Serializer& out) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,6 +67,10 @@ class AbstractFrameManager : public Serializable
|
||||||
|
|
||||||
float frameRate() const { return myFrameRate; }
|
float frameRate() const { return myFrameRate; }
|
||||||
|
|
||||||
|
bool save(Serializer& out) const override;
|
||||||
|
|
||||||
|
bool load(Serializer& in) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void setJitterFactor(uInt8 factor) {}
|
virtual void setJitterFactor(uInt8 factor) {}
|
||||||
|
@ -75,10 +79,6 @@ class AbstractFrameManager : public Serializable
|
||||||
|
|
||||||
virtual void enableJitter(bool enabled) {};
|
virtual void enableJitter(bool enabled) {};
|
||||||
|
|
||||||
bool save(Serializer& out) const override;
|
|
||||||
|
|
||||||
bool load(Serializer& in) override;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual uInt32 height() const = 0;
|
virtual uInt32 height() const = 0;
|
||||||
|
@ -89,11 +89,11 @@ class AbstractFrameManager : public Serializable
|
||||||
|
|
||||||
virtual uInt32 scanlines() const = 0;
|
virtual uInt32 scanlines() const = 0;
|
||||||
|
|
||||||
virtual uInt32 missingScanlines() const = 0;
|
virtual Int32 missingScanlines() const = 0;
|
||||||
|
|
||||||
virtual void setYstart(uInt32 ystart) = 0;
|
virtual void setYstart(uInt32 ystart) = 0;
|
||||||
|
|
||||||
virtual uInt32 ystart() = 0;
|
virtual uInt32 ystart() const = 0;
|
||||||
|
|
||||||
// TODO: this looks pretty weird --- does this actually work?
|
// TODO: this looks pretty weird --- does this actually work?
|
||||||
virtual bool ystartIsAuto(uInt32 line) const = 0;
|
virtual bool ystartIsAuto(uInt32 line) const = 0;
|
||||||
|
@ -101,6 +101,7 @@ class AbstractFrameManager : public Serializable
|
||||||
// TODO: this has to go
|
// TODO: this has to go
|
||||||
virtual void autodetectLayout(bool toggle) = 0;
|
virtual void autodetectLayout(bool toggle) = 0;
|
||||||
|
|
||||||
|
// TODO: this collides with layout(...). Refactor after all is done.
|
||||||
virtual void setLayout(FrameLayout mode) = 0;
|
virtual void setLayout(FrameLayout mode) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -113,6 +114,8 @@ class AbstractFrameManager : public Serializable
|
||||||
|
|
||||||
virtual void onReset() {}
|
virtual void onReset() {}
|
||||||
|
|
||||||
|
virtual void onLayoutChange() {}
|
||||||
|
|
||||||
virtual bool onSave(Serializer& out) const { throw runtime_error("cannot be serialized"); }
|
virtual bool onSave(Serializer& out) const { throw runtime_error("cannot be serialized"); }
|
||||||
|
|
||||||
virtual bool onLoad(Serializer& in) { throw runtime_error("cannot be serialized"); }
|
virtual bool onLoad(Serializer& in) { throw runtime_error("cannot be serialized"); }
|
||||||
|
@ -125,6 +128,8 @@ class AbstractFrameManager : public Serializable
|
||||||
|
|
||||||
void notifyRenderingStart();
|
void notifyRenderingStart();
|
||||||
|
|
||||||
|
void layout(FrameLayout layout);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
bool myIsRendering;
|
bool myIsRendering;
|
||||||
|
@ -141,12 +146,12 @@ class AbstractFrameManager : public Serializable
|
||||||
|
|
||||||
uInt32 myTotalFrames;
|
uInt32 myTotalFrames;
|
||||||
|
|
||||||
FrameLayout myLayout;
|
|
||||||
|
|
||||||
float myFrameRate;
|
float myFrameRate;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
FrameLayout myLayout;
|
||||||
|
|
||||||
callback myOnFrameStart;
|
callback myOnFrameStart;
|
||||||
callback myOnFrameComplete;
|
callback myOnFrameComplete;
|
||||||
callback myOnRenderingStart;
|
callback myOnRenderingStart;
|
||||||
|
|
|
@ -50,39 +50,19 @@ inline static uInt32 vsyncLimit(bool autodetect) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FrameManager::FrameManager()
|
FrameManager::FrameManager() :
|
||||||
: myLayout(FrameLayout::pal),
|
myHeight(0)
|
||||||
myAutodetectLayout(true),
|
|
||||||
myHeight(0),
|
|
||||||
myFixedHeight(0),
|
|
||||||
myJitterEnabled(false)
|
|
||||||
{
|
{
|
||||||
updateLayout(FrameLayout::ntsc);
|
onLayoutChange();
|
||||||
reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameManager::setHandlers(
|
void FrameManager::onReset()
|
||||||
FrameManager::callback frameStartCallback,
|
|
||||||
FrameManager::callback frameCompleteCallback,
|
|
||||||
FrameManager::callback renderingStartCallback
|
|
||||||
)
|
|
||||||
{
|
|
||||||
myOnFrameStart = frameStartCallback;
|
|
||||||
myOnFrameComplete = frameCompleteCallback;
|
|
||||||
myOnRenderingStart = renderingStartCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameManager::reset()
|
|
||||||
{
|
{
|
||||||
myVblankManager.reset();
|
myVblankManager.reset();
|
||||||
|
|
||||||
myState = State::waitForVsyncStart;
|
myState = State::waitForVsyncStart;
|
||||||
myCurrentFrameTotalLines = myCurrentFrameFinalLines = 0;
|
|
||||||
myFrameRate = 60.0;
|
|
||||||
myLineInState = 0;
|
myLineInState = 0;
|
||||||
myVsync = false;
|
|
||||||
myTotalFrames = 0;
|
myTotalFrames = 0;
|
||||||
myFramesInMode = 0;
|
myFramesInMode = 0;
|
||||||
myModeConfirmed = false;
|
myModeConfirmed = false;
|
||||||
|
@ -98,11 +78,9 @@ void FrameManager::reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameManager::nextLine()
|
void FrameManager::onNextLine()
|
||||||
{
|
{
|
||||||
State previousState = myState;
|
State previousState = myState;
|
||||||
|
|
||||||
myCurrentFrameTotalLines++;
|
|
||||||
myLineInState++;
|
myLineInState++;
|
||||||
|
|
||||||
switch (myState)
|
switch (myState)
|
||||||
|
@ -142,25 +120,22 @@ void FrameManager::nextLine()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt32 FrameManager::missingScanlines() const
|
Int32 FrameManager::missingScanlines() const
|
||||||
{
|
{
|
||||||
if (myLastY == ystart() + myY)
|
if (myLastY == ystart() + myY)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else {
|
||||||
return myHeight - myY;
|
return myHeight - myY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameManager::setVsync(bool vsync)
|
void FrameManager::onSetVsync()
|
||||||
{
|
{
|
||||||
if (vsync == myVsync) return;
|
|
||||||
|
|
||||||
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
||||||
(cout << "vsync " << myVsync << " -> " << vsync << ": state " << int(myState) << " @ " << myLineInState << "\n").flush();
|
(cout << "vsync " << !myVsync << " -> " << myVsync << ": state " << int(myState) << " @ " << myLineInState << "\n").flush();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
myVsync = vsync;
|
|
||||||
|
|
||||||
switch (myState)
|
switch (myState)
|
||||||
{
|
{
|
||||||
case State::waitForVsyncStart:
|
case State::waitForVsyncStart:
|
||||||
|
@ -200,6 +175,8 @@ void FrameManager::setState(FrameManager::State state)
|
||||||
myStableFrames >= Metrics::minStableFrames ||
|
myStableFrames >= Metrics::minStableFrames ||
|
||||||
myStabilizationFrames >= Metrics::maxStabilizationFrames;
|
myStabilizationFrames >= Metrics::maxStabilizationFrames;
|
||||||
|
|
||||||
|
updateIsRendering();
|
||||||
|
|
||||||
myStabilizationFrames++;
|
myStabilizationFrames++;
|
||||||
|
|
||||||
if (myVblankManager.isStable())
|
if (myVblankManager.isStable())
|
||||||
|
@ -209,7 +186,7 @@ void FrameManager::setState(FrameManager::State state)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myFramePending) finalizeFrame();
|
if (myFramePending) finalizeFrame();
|
||||||
if (myOnFrameStart) myOnFrameStart();
|
notifyFrameStart();
|
||||||
|
|
||||||
myVblankManager.start();
|
myVblankManager.start();
|
||||||
myFramePending = true;
|
myFramePending = true;
|
||||||
|
@ -218,7 +195,7 @@ void FrameManager::setState(FrameManager::State state)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::frame:
|
case State::frame:
|
||||||
if (myOnRenderingStart) myOnRenderingStart();
|
notifyRenderingStart();
|
||||||
myVsyncLines = 0;
|
myVsyncLines = 0;
|
||||||
myY = 0;
|
myY = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -226,6 +203,8 @@ void FrameManager::setState(FrameManager::State state)
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateIsRendering();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -246,21 +225,13 @@ void FrameManager::finalizeFrame()
|
||||||
else myStableFrameHeightCountdown = 0;
|
else myStableFrameHeightCountdown = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
myPreviousFrameFinalLines = myCurrentFrameFinalLines;
|
notifyFrameComplete();
|
||||||
myCurrentFrameFinalLines = myCurrentFrameTotalLines;
|
|
||||||
myCurrentFrameTotalLines = 0;
|
|
||||||
myTotalFrames++;
|
|
||||||
|
|
||||||
if (myOnFrameComplete) myOnFrameComplete();
|
|
||||||
|
|
||||||
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
||||||
(cout << "frame complete @ " << myLineInState << " (" << myCurrentFrameFinalLines << " total)" << "\n").flush();
|
(cout << "frame complete @ " << myLineInState << " (" << myCurrentFrameFinalLines << " total)" << "\n").flush();
|
||||||
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
|
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
|
||||||
|
|
||||||
if (myAutodetectLayout) updateAutodetectedLayout();
|
if (myAutodetectLayout) updateAutodetectedLayout();
|
||||||
|
|
||||||
myFrameRate = (myLayout == FrameLayout::pal ? 15600.0 : 15720.0) /
|
|
||||||
myCurrentFrameFinalLines;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -282,26 +253,26 @@ void FrameManager::updateAutodetectedLayout()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FrameLayout oldLayout = myLayout;
|
const FrameLayout oldLayout = layout();
|
||||||
|
|
||||||
const uInt32
|
const uInt32
|
||||||
deltaNTSC = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesNTSC)),
|
deltaNTSC = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesNTSC)),
|
||||||
deltaPAL = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesPAL));
|
deltaPAL = abs(Int32(myCurrentFrameFinalLines) - Int32(frameLinesPAL));
|
||||||
|
|
||||||
if (std::min(deltaNTSC, deltaPAL) <= Metrics::tvModeDetectionTolerance)
|
if (std::min(deltaNTSC, deltaPAL) <= Metrics::tvModeDetectionTolerance)
|
||||||
updateLayout(deltaNTSC <= deltaPAL ? FrameLayout::ntsc : FrameLayout::pal);
|
layout(deltaNTSC <= deltaPAL ? FrameLayout::ntsc : FrameLayout::pal);
|
||||||
else if (!myModeConfirmed) {
|
else if (!myModeConfirmed) {
|
||||||
if (
|
if (
|
||||||
(myCurrentFrameFinalLines < frameLinesPAL) &&
|
(myCurrentFrameFinalLines < frameLinesPAL) &&
|
||||||
(myCurrentFrameFinalLines > frameLinesNTSC) &&
|
(myCurrentFrameFinalLines > frameLinesNTSC) &&
|
||||||
(myCurrentFrameFinalLines % 2)
|
(myCurrentFrameFinalLines % 2)
|
||||||
)
|
)
|
||||||
updateLayout(FrameLayout::ntsc);
|
layout(FrameLayout::ntsc);
|
||||||
else
|
else
|
||||||
updateLayout(deltaNTSC <= deltaPAL ? FrameLayout::ntsc : FrameLayout::pal);
|
layout(deltaNTSC <= deltaPAL ? FrameLayout::ntsc : FrameLayout::pal);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldLayout == myLayout)
|
if (oldLayout == layout())
|
||||||
myFramesInMode++;
|
myFramesInMode++;
|
||||||
else
|
else
|
||||||
myFramesInMode = 0;
|
myFramesInMode = 0;
|
||||||
|
@ -311,17 +282,13 @@ void FrameManager::updateAutodetectedLayout()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameManager::updateLayout(FrameLayout layout)
|
void FrameManager::onLayoutChange()
|
||||||
{
|
{
|
||||||
if (layout == myLayout) return;
|
|
||||||
|
|
||||||
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
||||||
(cout << "TV mode switched to " << int(layout) << "\n").flush();
|
(cout << "TV mode switched to " << int(layout()) << "\n").flush();
|
||||||
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
|
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
|
||||||
|
|
||||||
myLayout = layout;
|
switch (layout())
|
||||||
|
|
||||||
switch (myLayout)
|
|
||||||
{
|
{
|
||||||
case FrameLayout::ntsc:
|
case FrameLayout::ntsc:
|
||||||
myVblankLines = Metrics::vblankNTSC;
|
myVblankLines = Metrics::vblankNTSC;
|
||||||
|
@ -347,18 +314,18 @@ void FrameManager::updateLayout(FrameLayout layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameManager::setVblank(bool vblank)
|
void FrameManager::onSetVblank()
|
||||||
{
|
{
|
||||||
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
#ifdef TIA_FRAMEMANAGER_DEBUG_LOG
|
||||||
(cout << "vblank change " << myVblankManager.vblank() << " -> " << vblank << "@" << myLineInState << "\n").flush();
|
(cout << "vblank change " << !myVblank << " -> " << myVblank << "@" << myLineInState << "\n").flush();
|
||||||
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
|
#endif // TIA_FRAMEMANAGER_DEBUG_LOG
|
||||||
|
|
||||||
if (myState == State::waitForFrameStart) {
|
if (myState == State::waitForFrameStart) {
|
||||||
if (myVblankManager.setVblankDuringVblank(vblank, myTotalFrames <= Metrics::initialGarbageFrames)) {
|
if (myVblankManager.setVblankDuringVblank(myVblank, myTotalFrames <= Metrics::initialGarbageFrames)) {
|
||||||
setState(State::frame);
|
setState(State::frame);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
myVblankManager.setVblank(vblank);
|
myVblankManager.setVblank(myVblank);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -377,106 +344,76 @@ void FrameManager::enableJitter(bool enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameManager::save(Serializer& out) const
|
void FrameManager::updateIsRendering() {
|
||||||
|
myIsRendering = myState == State::frame && myHasStabilized;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool FrameManager::onSave(Serializer& out) const
|
||||||
{
|
{
|
||||||
try
|
if (!myVblankManager.save(out)) return false;
|
||||||
{
|
|
||||||
out.putString(name());
|
|
||||||
|
|
||||||
if (!myVblankManager.save(out)) return false;
|
out.putBool(myAutodetectLayout);
|
||||||
|
out.putInt(uInt32(myState));
|
||||||
|
out.putInt(myLineInState);
|
||||||
|
out.putInt(myVsyncLines);
|
||||||
|
out.putInt(myY);
|
||||||
|
out.putInt(myLastY);
|
||||||
|
out.putBool(myFramePending);
|
||||||
|
|
||||||
out.putInt(uInt32(myLayout));
|
out.putInt(myFramesInMode);
|
||||||
out.putBool(myAutodetectLayout);
|
out.putBool(myModeConfirmed);
|
||||||
out.putInt(uInt32(myState));
|
|
||||||
out.putInt(myLineInState);
|
|
||||||
out.putInt(myCurrentFrameTotalLines);
|
|
||||||
out.putInt(myCurrentFrameFinalLines);
|
|
||||||
out.putInt(myPreviousFrameFinalLines);
|
|
||||||
out.putInt(myVsyncLines);
|
|
||||||
out.putDouble(myFrameRate);
|
|
||||||
out.putInt(myY); out.putInt(myLastY);
|
|
||||||
out.putBool(myFramePending);
|
|
||||||
|
|
||||||
out.putInt(myTotalFrames);
|
out.putInt(myStableFrames);
|
||||||
out.putInt(myFramesInMode);
|
out.putInt(myStabilizationFrames);
|
||||||
out.putBool(myModeConfirmed);
|
out.putBool(myHasStabilized);
|
||||||
|
|
||||||
out.putInt(myStableFrames);
|
out.putInt(myVblankLines);
|
||||||
out.putInt(myStabilizationFrames);
|
out.putInt(myKernelLines);
|
||||||
out.putBool(myHasStabilized);
|
out.putInt(myOverscanLines);
|
||||||
|
out.putInt(myFrameLines);
|
||||||
|
out.putInt(myHeight);
|
||||||
|
out.putInt(myFixedHeight);
|
||||||
|
|
||||||
out.putBool(myVsync);
|
out.putBool(myJitterEnabled);
|
||||||
|
|
||||||
out.putInt(myVblankLines);
|
out.putInt(myStableFrameLines);
|
||||||
out.putInt(myKernelLines);
|
out.putInt(myStableFrameHeightCountdown);
|
||||||
out.putInt(myOverscanLines);
|
|
||||||
out.putInt(myFrameLines);
|
|
||||||
out.putInt(myHeight);
|
|
||||||
out.putInt(myFixedHeight);
|
|
||||||
|
|
||||||
out.putBool(myJitterEnabled);
|
|
||||||
|
|
||||||
out.putInt(myStableFrameLines);
|
|
||||||
out.putInt(myStableFrameHeightCountdown);
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: TIA_FrameManager::save" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameManager::load(Serializer& in)
|
bool FrameManager::onLoad(Serializer& in)
|
||||||
{
|
{
|
||||||
try
|
if (!myVblankManager.load(in)) return false;
|
||||||
{
|
|
||||||
if(in.getString() != name())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!myVblankManager.load(in)) return false;
|
myAutodetectLayout = in.getBool();
|
||||||
|
myState = State(in.getInt());
|
||||||
|
myLineInState = in.getInt();
|
||||||
|
myVsyncLines = in.getInt();
|
||||||
|
myY = in.getInt();
|
||||||
|
myLastY = in.getInt();
|
||||||
|
myFramePending = in.getBool();
|
||||||
|
|
||||||
myLayout = FrameLayout(in.getInt());
|
myFramesInMode = in.getInt();
|
||||||
myAutodetectLayout = in.getBool();
|
myModeConfirmed = in.getBool();
|
||||||
myState = State(in.getInt());
|
|
||||||
myLineInState = in.getInt();
|
|
||||||
myCurrentFrameTotalLines = in.getInt();
|
|
||||||
myCurrentFrameFinalLines = in.getInt();
|
|
||||||
myPreviousFrameFinalLines = in.getInt();
|
|
||||||
myVsyncLines = in.getInt();
|
|
||||||
myFrameRate = float(in.getDouble());
|
|
||||||
myY = in.getInt(); myLastY = in.getInt();
|
|
||||||
myFramePending = in.getBool();
|
|
||||||
|
|
||||||
myTotalFrames = in.getInt();
|
myStableFrames = in.getInt();
|
||||||
myFramesInMode = in.getInt();
|
myStabilizationFrames = in.getInt();
|
||||||
myModeConfirmed = in.getBool();
|
myHasStabilized = in.getBool();
|
||||||
|
|
||||||
myStableFrames = in.getInt();
|
myVblankLines = in.getInt();
|
||||||
myStabilizationFrames = in.getInt();
|
myKernelLines = in.getInt();
|
||||||
myHasStabilized = in.getBool();
|
myOverscanLines = in.getInt();
|
||||||
|
myFrameLines = in.getInt();
|
||||||
|
myHeight = in.getInt();
|
||||||
|
myFixedHeight = in.getInt();
|
||||||
|
|
||||||
myVsync = in.getBool();
|
myJitterEnabled = in.getBool();
|
||||||
|
|
||||||
myVblankLines = in.getInt();
|
myStableFrameLines = in.getInt();
|
||||||
myKernelLines = in.getInt();
|
myStableFrameHeightCountdown = in.getInt();
|
||||||
myOverscanLines = in.getInt();
|
|
||||||
myFrameLines = in.getInt();
|
|
||||||
myHeight = in.getInt();
|
|
||||||
myFixedHeight = in.getInt();
|
|
||||||
|
|
||||||
myJitterEnabled = in.getBool();
|
|
||||||
|
|
||||||
myStableFrameLines = in.getInt();
|
|
||||||
myStableFrameHeightCountdown = in.getInt();
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: TIA_FrameManager::load" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,88 +18,60 @@
|
||||||
#ifndef TIA_FRAME_MANAGER
|
#ifndef TIA_FRAME_MANAGER
|
||||||
#define TIA_FRAME_MANAGER
|
#define TIA_FRAME_MANAGER
|
||||||
|
|
||||||
#include <functional>
|
#include "AbstractFrameManager.hxx"
|
||||||
|
|
||||||
#include "VblankManager.hxx"
|
#include "VblankManager.hxx"
|
||||||
#include "Serializable.hxx"
|
|
||||||
#include "FrameLayout.hxx"
|
|
||||||
#include "TIAConstants.hxx"
|
#include "TIAConstants.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
|
||||||
class FrameManager : public Serializable
|
class FrameManager: public AbstractFrameManager {
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
using callback = std::function<void()>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FrameManager();
|
FrameManager();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void setHandlers(
|
void setJitterFactor(uInt8 factor) override { myVblankManager.setJitterFactor(factor); }
|
||||||
callback frameStartCallback,
|
|
||||||
callback frameCompletionCallback,
|
|
||||||
callback renderingStartCallback
|
|
||||||
);
|
|
||||||
|
|
||||||
void reset();
|
bool jitterEnabled() const override { return myJitterEnabled; }
|
||||||
|
|
||||||
void nextLine();
|
void enableJitter(bool enabled) override;
|
||||||
|
|
||||||
void setVblank(bool vblank);
|
uInt32 height() const override { return myHeight; };
|
||||||
|
|
||||||
void setVsync(bool vsync);
|
void setFixedHeight(uInt32 height) override;
|
||||||
|
|
||||||
bool isRendering() const { return myState == State::frame && myHasStabilized; }
|
uInt32 getY() const override { return myY; }
|
||||||
|
|
||||||
FrameLayout layout() const { return myLayout; }
|
uInt32 scanlines() const override { return myCurrentFrameTotalLines; }
|
||||||
|
|
||||||
bool vblank() const { return myVblankManager.vblank(); }
|
Int32 missingScanlines() const override;
|
||||||
|
|
||||||
bool vsync() const { return myVsync; }
|
void setYstart(uInt32 ystart) override { myVblankManager.setYstart(ystart); }
|
||||||
|
|
||||||
uInt32 height() const { return myHeight; }
|
uInt32 ystart() const override { return myVblankManager.ystart(); }
|
||||||
|
|
||||||
void setFixedHeight(uInt32 height);
|
bool ystartIsAuto(uInt32 line) const override { return myVblankManager.ystartIsAuto(line); };
|
||||||
|
|
||||||
uInt32 getY() const { return myY; }
|
void autodetectLayout(bool toggle) override { myAutodetectLayout = toggle; }
|
||||||
|
|
||||||
uInt32 scanlines() const { return myCurrentFrameTotalLines; }
|
void setLayout(FrameLayout mode) override { if (!myAutodetectLayout) layout(mode); }
|
||||||
|
|
||||||
uInt32 scanlinesLastFrame() const { return myCurrentFrameFinalLines; }
|
void onSetVblank() override;
|
||||||
|
|
||||||
uInt32 missingScanlines() const;
|
void onSetVsync() override;
|
||||||
|
|
||||||
bool scanlineCountTransitioned() const {
|
void onNextLine() override;
|
||||||
return (myPreviousFrameFinalLines & 0x1) != (myCurrentFrameFinalLines & 0x1);
|
|
||||||
}
|
|
||||||
|
|
||||||
uInt32 frameCount() const { return myTotalFrames; }
|
void onReset() override;
|
||||||
|
|
||||||
float frameRate() const { return myFrameRate; }
|
void onLayoutChange() override;
|
||||||
|
|
||||||
void setYstart(uInt32 ystart) { myVblankManager.setYstart(ystart); }
|
bool onSave(Serializer& out) const override;
|
||||||
|
|
||||||
uInt32 ystart() const { return myVblankManager.ystart(); }
|
bool onLoad(Serializer& in) override;
|
||||||
bool ystartIsAuto(uInt32 line) const { return myVblankManager.ystartIsAuto(line); }
|
|
||||||
|
|
||||||
void autodetectLayout(bool toggle) { myAutodetectLayout = toggle; }
|
|
||||||
|
|
||||||
void setLayout(FrameLayout mode) { if (!myAutodetectLayout) updateLayout(mode); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
Serializable methods (see that class for more information).
|
|
||||||
*/
|
|
||||||
bool save(Serializer& out) const override;
|
|
||||||
bool load(Serializer& in) override;
|
|
||||||
string name() const override { return "TIA_FrameManager"; }
|
string name() const override { return "TIA_FrameManager"; }
|
||||||
|
|
||||||
void setJitterFactor(uInt8 factor) { myVblankManager.setJitterFactor(factor); }
|
|
||||||
bool jitterEnabled() const { return myJitterEnabled; }
|
|
||||||
void enableJitter(bool enabled);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
|
@ -109,17 +81,8 @@ class FrameManager : public Serializable
|
||||||
frame
|
frame
|
||||||
};
|
};
|
||||||
|
|
||||||
enum VblankMode {
|
|
||||||
locked,
|
|
||||||
floating,
|
|
||||||
final,
|
|
||||||
fixed
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void updateLayout(FrameLayout mode);
|
|
||||||
|
|
||||||
void updateAutodetectedLayout();
|
void updateAutodetectedLayout();
|
||||||
|
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
|
@ -130,27 +93,19 @@ class FrameManager : public Serializable
|
||||||
|
|
||||||
void handleJitter(Int32 scanlineDifference);
|
void handleJitter(Int32 scanlineDifference);
|
||||||
|
|
||||||
private:
|
void updateIsRendering();
|
||||||
|
|
||||||
callback myOnFrameStart;
|
private:
|
||||||
callback myOnFrameComplete;
|
|
||||||
callback myOnRenderingStart;
|
|
||||||
|
|
||||||
VblankManager myVblankManager;
|
VblankManager myVblankManager;
|
||||||
|
|
||||||
FrameLayout myLayout;
|
|
||||||
bool myAutodetectLayout;
|
bool myAutodetectLayout;
|
||||||
State myState;
|
State myState;
|
||||||
uInt32 myLineInState;
|
uInt32 myLineInState;
|
||||||
uInt32 myCurrentFrameTotalLines;
|
|
||||||
uInt32 myCurrentFrameFinalLines;
|
|
||||||
uInt32 myPreviousFrameFinalLines;
|
|
||||||
uInt32 myVsyncLines;
|
uInt32 myVsyncLines;
|
||||||
float myFrameRate;
|
|
||||||
uInt32 myY, myLastY;
|
uInt32 myY, myLastY;
|
||||||
bool myFramePending;
|
bool myFramePending;
|
||||||
|
|
||||||
uInt32 myTotalFrames;
|
|
||||||
uInt32 myFramesInMode;
|
uInt32 myFramesInMode;
|
||||||
bool myModeConfirmed;
|
bool myModeConfirmed;
|
||||||
|
|
||||||
|
@ -158,8 +113,6 @@ class FrameManager : public Serializable
|
||||||
uInt32 myStabilizationFrames;
|
uInt32 myStabilizationFrames;
|
||||||
bool myHasStabilized;
|
bool myHasStabilized;
|
||||||
|
|
||||||
bool myVsync;
|
|
||||||
|
|
||||||
uInt32 myVblankLines;
|
uInt32 myVblankLines;
|
||||||
uInt32 myKernelLines;
|
uInt32 myKernelLines;
|
||||||
uInt32 myOverscanLines;
|
uInt32 myOverscanLines;
|
||||||
|
@ -173,6 +126,7 @@ class FrameManager : public Serializable
|
||||||
uInt8 myStableFrameHeightCountdown;
|
uInt8 myStableFrameHeightCountdown;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
FrameManager(const FrameManager&) = delete;
|
FrameManager(const FrameManager&) = delete;
|
||||||
FrameManager(FrameManager&&) = delete;
|
FrameManager(FrameManager&&) = delete;
|
||||||
FrameManager& operator=(const FrameManager&) = delete;
|
FrameManager& operator=(const FrameManager&) = delete;
|
||||||
|
|
Loading…
Reference in New Issue