diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index bb3968e8c..2307b6d8f 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -57,6 +57,7 @@ #include "Version.hxx" #include "TIAConstants.hxx" #include "FrameLayout.hxx" +#include "frame-manager/FrameManager.hxx" #ifdef DEBUGGER_SUPPORT #include "Debugger.hxx" @@ -88,8 +89,11 @@ Console::Console(OSystem& osystem, unique_ptr& cart, my6502 = make_unique(myOSystem.settings()); myRiot = make_unique(*this, myOSystem.settings()); myTIA = make_unique(*this, myOSystem.sound(), myOSystem.settings()); + myFrameManager = make_unique(); mySwitches = make_unique(myEvent, myProperties); + myTIA->setFrameManager(myFrameManager.get()); + // Construct the system and components mySystem = make_unique(osystem, *my6502, *myRiot, *myTIA, *myCart); diff --git a/src/emucore/Console.hxx b/src/emucore/Console.hxx index 65855e682..f4c697257 100644 --- a/src/emucore/Console.hxx +++ b/src/emucore/Console.hxx @@ -35,6 +35,7 @@ class Debugger; #include "FrameBuffer.hxx" #include "Serializable.hxx" #include "NTSCFilter.hxx" +#include "frame-manager/AbstractFrameManager.hxx" /** Contains detailed info about a console. @@ -360,6 +361,9 @@ class Console : public Serializable // Pointer to the TIA object unique_ptr myTIA; + // The frame manager instance that is used during emulation. + unique_ptr myFrameManager; + // Pointer to the Cartridge (the debugger needs it) unique_ptr myCart; diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx index 3fec0c07c..523839d09 100644 --- a/src/emucore/tia/TIA.cxx +++ b/src/emucore/tia/TIA.cxx @@ -69,6 +69,7 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings) : myConsole(console), mySound(sound), mySettings(settings), + myFrameManager(nullptr), myPlayfield(~CollisionMask::playfield & 0x7FFF), myMissile0(~CollisionMask::missile0 & 0x7FFF), myMissile1(~CollisionMask::missile1 & 0x7FFF), @@ -78,7 +79,28 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings) mySpriteEnabledBits(0xFF), myCollisionsEnabledBits(0xFF) { - myFrameManager = new FrameManager(); + myTIAPinsDriven = mySettings.getBool("tiadriven"); + + myBackground.setTIA(this); + myPlayfield.setTIA(this); + myPlayer0.setTIA(this); + myPlayer1.setTIA(this); + myMissile0.setTIA(this); + myMissile1.setTIA(this); + myBall.setTIA(this); + + myEnableJitter = mySettings.getBool("tv.jitter"); + myJitterFactor = mySettings.getInt("tv.jitter_recovery"); + + reset(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIA::setFrameManager(AbstractFrameManager *frameManager) +{ + clearFrameManager(); + + myFrameManager = frameManager; myFrameManager->setHandlers( [this] () { @@ -92,25 +114,18 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings) } ); - myTIAPinsDriven = mySettings.getBool("tiadriven"); - - myBackground.setTIA(this); - myPlayfield.setTIA(this); - myPlayer0.setTIA(this); - myPlayer1.setTIA(this); - myMissile0.setTIA(this); - myMissile1.setTIA(this); - myBall.setTIA(this); - - myFrameManager->enableJitter(mySettings.getBool("tv.jitter")); - myFrameManager->setJitterFactor(mySettings.getInt("tv.jitter_recovery")); - - reset(); + myFrameManager->enableJitter(myEnableJitter); + myFrameManager->setJitterFactor(myJitterFactor); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TIA::~TIA() { - delete myFrameManager; +void TIA::clearFrameManager() +{ + if (!myFrameManager) return; + + myFrameManager->clearHandlers(); + + myFrameManager = nullptr; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -152,7 +167,8 @@ void TIA::reset() mySound.reset(); myDelayQueue.reset(); - myFrameManager->reset(); + + if (myFrameManager) myFrameManager->reset(); myCyclesAtFrameStart = 0; @@ -914,7 +930,9 @@ bool TIA::toggleCollisions() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool TIA::enableFixedColors(bool enable) { - int layout = myFrameManager->layout() == FrameLayout::pal ? 1 : 0; + int layout = 0; + if (myFrameManager) layout = myFrameManager->layout() == FrameLayout::pal ? 1 : 0; + myMissile0.setDebugColor(myFixedColorPalette[layout][FixedObject::M0]); myMissile1.setDebugColor(myFixedColorPalette[layout][FixedObject::M1]); myPlayer0.setDebugColor(myFixedColorPalette[layout][FixedObject::P0]); @@ -999,22 +1017,32 @@ bool TIA::toggleJitter(uInt8 mode) { switch (mode) { case 0: - myFrameManager->enableJitter(false); + myEnableJitter = false; break; case 1: - myFrameManager->enableJitter(true); + myEnableJitter = true; break; case 2: - myFrameManager->enableJitter(!myFrameManager->jitterEnabled()); + myEnableJitter = !myEnableJitter; break; default: throw runtime_error("invalid argument for toggleJitter"); } - return myFrameManager->jitterEnabled(); + if (myFrameManager) myFrameManager->enableJitter(myEnableJitter); + + return myEnableJitter; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIA::setJitterRecoveryFactor(Int32 factor) +{ + myJitterFactor = factor; + + if (myFrameManager) myFrameManager->setJitterFactor(myJitterFactor); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/tia/TIA.hxx b/src/emucore/tia/TIA.hxx index e06e81421..75a8a1803 100644 --- a/src/emucore/tia/TIA.hxx +++ b/src/emucore/tia/TIA.hxx @@ -101,9 +101,20 @@ class TIA : public Device @param settings The settings object for this TIA device */ TIA(Console& console, Sound& sound, Settings& settings); - virtual ~TIA(); + + virtual ~TIA() = default; public: + /** + * Configure the frame manager. + */ + void setFrameManager(AbstractFrameManager *frameManager); + + /** + * Clear the configured frame manager and deteach the lifecycle callbacks. + */ + void clearFrameManager(); + /** Reset device to its power-on state. */ @@ -360,7 +371,7 @@ class TIA : public Device @return Whether the mode was enabled or disabled */ bool toggleJitter(uInt8 mode = 2); - void setJitterRecoveryFactor(Int32 factor) { myFrameManager->setJitterFactor(factor); } + void setJitterRecoveryFactor(Int32 factor); /** This method should be called to update the TIA with a new scanline. @@ -731,10 +742,17 @@ class TIA : public Device bool myColorLossActive; /** - * System cycles at the end of the previous frame / beginning of next frame + * System cycles at the end of the previous frame / beginning of next frame. */ uInt64 myCyclesAtFrameStart; + /** + * The frame manager can change during our lifetime, so we buffer those two. + */ + bool myEnableJitter; + uInt8 myJitterFactor; + + #ifdef DEBUGGER_SUPPORT // The arrays containing information about every byte of TIA // indicating whether and how (RW) it is used. diff --git a/src/emucore/tia/frame-manager/AbstractFrameManager.cxx b/src/emucore/tia/frame-manager/AbstractFrameManager.cxx index 3e82cee2a..8455434da 100644 --- a/src/emucore/tia/frame-manager/AbstractFrameManager.cxx +++ b/src/emucore/tia/frame-manager/AbstractFrameManager.cxx @@ -20,9 +20,9 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AbstractFrameManager::AbstractFrameManager() : myLayout(FrameLayout::pal), - myOnFrameStart(0), - myOnFrameComplete(0), - myOnRenderingStart(0) + myOnFrameStart(nullptr), + myOnFrameComplete(nullptr), + myOnRenderingStart(nullptr) { layout(FrameLayout::ntsc); reset(); @@ -63,6 +63,12 @@ void AbstractFrameManager::setHandlers( myOnRenderingStart = renderingStartCallback; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void AbstractFrameManager::clearHandlers() +{ + myOnFrameStart = myOnFrameComplete = myOnRenderingStart = nullptr; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void AbstractFrameManager::setVblank(bool vblank) { diff --git a/src/emucore/tia/frame-manager/AbstractFrameManager.hxx b/src/emucore/tia/frame-manager/AbstractFrameManager.hxx index f0cb4f693..29f7ec7b5 100644 --- a/src/emucore/tia/frame-manager/AbstractFrameManager.hxx +++ b/src/emucore/tia/frame-manager/AbstractFrameManager.hxx @@ -44,6 +44,11 @@ class AbstractFrameManager : public Serializable callback renderingStartCallback ); + /** + * Clear the configured handler callbacks. + */ + void clearHandlers(); + /** * Reset. */ @@ -151,7 +156,7 @@ class AbstractFrameManager : public Serializable /** * Frame height. */ - virtual uInt32 height() { return 0; } + virtual uInt32 height() const { return 0; } /** * Configure a fixed frame height (the default is determined by the frame @@ -162,13 +167,13 @@ class AbstractFrameManager : public Serializable /** * The current y coordinate (valid only during rendering). */ - virtual uInt32 getY() { return 0; } + virtual uInt32 getY() const { return 0; } /** * The current number of scanlines in the current frame (including invisible * lines). */ - virtual uInt32 scanlines() { return 0; } + virtual uInt32 scanlines() const { return 0; } /** * Configure the ystart value. @@ -178,12 +183,12 @@ class AbstractFrameManager : public Serializable /** * The configured ystart value. */ - virtual uInt32 ystart() { return 0; } + virtual uInt32 ystart() const { return 0; } /** * TODO: this looks pretty weird --- does this actually work? */ - virtual bool ystartIsAuto(uInt32 line) { return false; } + virtual bool ystartIsAuto(uInt32 line) const { return false; } /** * TODO: this has to go