diff --git a/.gitignore b/.gitignore index 8d5f232f6..c0568d40b 100644 --- a/.gitignore +++ b/.gitignore @@ -30,5 +30,4 @@ src/windows/Stella.vcxproj.user src/**/*.psess src/**/*.vspx src/**/**.pdb - - +Stella.xcscheme diff --git a/src/debugger/gui/TiaOutputWidget.cxx b/src/debugger/gui/TiaOutputWidget.cxx index ea4e42e8e..4e75a87ea 100644 --- a/src/debugger/gui/TiaOutputWidget.cxx +++ b/src/debugger/gui/TiaOutputWidget.cxx @@ -120,7 +120,7 @@ void TiaOutputWidget::handleMouseDown(int x, int y, MouseButton b, int clickCoun // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) { - uInt32 ystart = instance().console().tia().ystart(); + uInt32 startLine = instance().console().tia().startLine(); switch(cmd) { @@ -131,7 +131,7 @@ void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, in if(rmb == "scanline") { ostringstream command; - int lines = myClickY + ystart - instance().console().tia().scanlines(); + int lines = myClickY + startLine - instance().console().tia().scanlines(); if(lines < 0) lines += instance().console().tia().scanlinesLastFrame(); @@ -145,7 +145,7 @@ void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, in else if(rmb == "bp") { ostringstream command; - int scanline = myClickY + ystart; + int scanline = myClickY + startLine; command << "breakif _scan==#" << scanline; string message = instance().debugger().parser().run(command.str()); instance().frameBuffer().showMessage(message); diff --git a/src/debugger/gui/TiaZoomWidget.cxx b/src/debugger/gui/TiaZoomWidget.cxx index db5425ee4..ebc88ce27 100644 --- a/src/debugger/gui/TiaZoomWidget.cxx +++ b/src/debugger/gui/TiaZoomWidget.cxx @@ -249,13 +249,13 @@ void TiaZoomWidget::handleCommand(CommandSender* sender, int cmd, int data, int { case ContextMenu::kItemSelectedCmd: { - uInt32 ystart = instance().console().tia().ystart(); + uInt32 startLine = instance().console().tia().startLine(); const string& rmb = myMenu->getSelectedTag().toString(); if(rmb == "scanline") { ostringstream command; - int lines = myClickY / myZoomLevel + myOffY + ystart - instance().console().tia().scanlines(); + int lines = myClickY / myZoomLevel + myOffY + startLine - instance().console().tia().scanlines(); if (lines < 0) lines += instance().console().tia().scanlinesLastFrame(); @@ -269,7 +269,7 @@ void TiaZoomWidget::handleCommand(CommandSender* sender, int cmd, int data, int else if(rmb == "bp") { ostringstream command; - int scanline = myClickY / myZoomLevel + myOffY + ystart; + int scanline = myClickY / myZoomLevel + myOffY + startLine; command << "breakif _scan==#" << scanline; string message = instance().debugger().parser().run(command.str()); instance().frameBuffer().showMessage(message); diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index 449179fb8..a398b1301 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -60,7 +60,6 @@ #include "AudioSettings.hxx" #include "frame-manager/FrameManager.hxx" #include "frame-manager/FrameLayoutDetector.hxx" -#include "frame-manager/YStartDetector.hxx" #ifdef CHEATCODE_SUPPORT #include "CheatManager.hxx" @@ -71,10 +70,6 @@ #include "Console.hxx" -namespace { - constexpr uInt8 YSTART_EXTRA = 2; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Console::Console(OSystem& osystem, unique_ptr& cart, const Properties& props, AudioSettings& audioSettings) @@ -84,8 +79,6 @@ Console::Console(OSystem& osystem, unique_ptr& cart, myCart(std::move(cart)), myDisplayFormat(""), // Unknown TV format @ start myCurrentFormat(0), // Unknown format @ start, - myAutodetectedYstart(0), - myYStartAutodetected(false), myFormatAutodetected(false), myUserPaletteDefined(false), myConsoleTiming(ConsoleTiming::ntsc), @@ -151,10 +144,6 @@ Console::Console(OSystem& osystem, unique_ptr& cart, } } - if (atoi(myProperties.get(PropType::Display_VCenter).c_str()) == 0) { - autodetectYStart(); - } - myConsoleInfo.DisplayFormat = myDisplayFormat + autodetected; // Set up the correct properties used when toggling format @@ -265,49 +254,6 @@ void Console::redetectFrameLayout() save(s); autodetectFrameLayout(false); - if (myYStartAutodetected) autodetectYStart(); - - load(s); - initializeAudio(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::autodetectYStart(bool reset) -{ - // We turn off the SuperCharger progress bars, otherwise the SC BIOS - // will take over 250 frames! - // The 'fastscbios' option must be changed before the system is reset - bool fastscbios = myOSystem.settings().getBool("fastscbios"); - myOSystem.settings().setValue("fastscbios", true); - - YStartDetector ystartDetector; - ystartDetector.setLayout(myDisplayFormat == "PAL" ? FrameLayout::pal : FrameLayout::ntsc); - myTIA->setFrameManager(&ystartDetector); - - if (reset) { - mySystem->reset(true); - myRiot->update(); - } - - for (int i = 0; i < 80; i++) myTIA->update(); - - myTIA->setFrameManager(myFrameManager.get()); - - myAutodetectedYstart = ystartDetector.detectedYStart() - YSTART_EXTRA; - - // Don't forget to reset the SC progress bars again - myOSystem.settings().setValue("fastscbios", fastscbios); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::redetectYStart() -{ - Serializer s; - - myOSystem.sound().close(); - save(s); - - autodetectYStart(false); load(s); initializeAudio(); @@ -696,75 +642,57 @@ void Console::fry() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Console::changeVerticalCenter(int direction) { - uInt32 ystart = myTIA->ystart(); + Int32 vcenter = myTIA->vcenter(); - if(direction == +1) // increase YStart + if(direction == +1) // increase vcenter { - if(ystart >= TIAConstants::maxYStart) + if(vcenter >= TIAConstants::maxVcenter) { myOSystem.frameBuffer().showMessage("V-Center at minimum"); return; } - ++ystart; - myYStartAutodetected = false; + ++vcenter; } - else if(direction == -1) // decrease YStart + else if(direction == -1) // decrease vcenter { - if (ystart <= TIAConstants::minYStart) + if (vcenter <= TIAConstants::minVcenter) { myOSystem.frameBuffer().showMessage("V-Center at maximum"); return; } - --ystart; - myYStartAutodetected = false; + --vcenter; } else return; ostringstream ss; - ss << ystart; + ss << vcenter; myProperties.set(PropType::Display_VCenter, ss.str()); - if (ystart != myTIA->ystart()) myTIA->setYStart(ystart); + if (vcenter != myTIA->vcenter()) myTIA->setVcenter(vcenter); - // use vertical center instead of y-start for display - int vCenter = TIAConstants::defaultYStart - ystart; ss.str(""); - ss << "V-Center " << vCenter; + ss << "V-Center " << vcenter; myOSystem.frameBuffer().showMessage(ss.str()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::updateYStart(uInt32 ystart) +void Console::updateVcenter(Int32 vcenter) { - if (ystart > TIAConstants::maxYStart) return; + if (vcenter > TIAConstants::maxVcenter | vcenter < TIAConstants::minVcenter) return; - if (ystart == 0) { - if (myYStartAutodetected) return; - - redetectYStart(); - myYStartAutodetected = true; - ystart = myAutodetectedYstart; - } else - myYStartAutodetected = false; - - if (ystart != myTIA->ystart()) myTIA->setYStart(ystart); + if (vcenter != myTIA->vcenter()) myTIA->setVcenter(vcenter); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Console::setTIAProperties() { - // FIXME - ystart is probably disappearing soon, or at least autodetection is - uInt32 ystart = atoi(myProperties.get(PropType::Display_VCenter).c_str()); - if(ystart != 0) - ystart = BSPF::clamp(ystart, 0u, TIAConstants::maxYStart); - else { - ystart = myAutodetectedYstart; - myYStartAutodetected = true; - } + Int32 vcenter = BSPF::clamp( + static_cast(atoi(myProperties.get(PropType::Display_VCenter).c_str())), TIAConstants::minVcenter, TIAConstants::maxVcenter + ); if(myDisplayFormat == "NTSC" || myDisplayFormat == "PAL60" || myDisplayFormat == "SECAM60") @@ -778,7 +706,7 @@ void Console::setTIAProperties() myTIA->setLayout(FrameLayout::pal); } - myTIA->setYStart(ystart); + myTIA->setVcenter(vcenter); myEmulationTiming.updateFrameLayout(myTIA->frameLayout()); myEmulationTiming.updateConsoleTiming(myConsoleTiming); diff --git a/src/emucore/Console.hxx b/src/emucore/Console.hxx index b2805fdd0..6c3c86462 100644 --- a/src/emucore/Console.hxx +++ b/src/emucore/Console.hxx @@ -306,9 +306,9 @@ class Console : public Serializable, public ConsoleIO void toggleJitter() const; /** - * Update yatart and run autodetection if necessary. + * Update vcenter */ - void updateYStart(uInt32 ystart); + void updateVcenter(Int32 vcenter); private: /** @@ -316,23 +316,13 @@ class Console : public Serializable, public ConsoleIO */ void autodetectFrameLayout(bool reset = true); - /** - * Dryrun the emulation and detect ystart (the first visible scanline). - */ - void autodetectYStart(bool reset = true); - /** * Rerun frame layout autodetection */ void redetectFrameLayout(); /** - * Rerun ystart autodetection. - */ - void redetectYStart(); - - /** - Sets various properties of the TIA (YStart, Height, etc) based on + Sets various properties of the TIA (vcenter, Height, etc) based on the current display format. */ void setTIAProperties(); @@ -411,12 +401,6 @@ class Console : public Serializable, public ConsoleIO // Display format currently in use uInt32 myCurrentFormat; - // Autodetected ystart. - uInt32 myAutodetectedYstart; - - // Is ystart currently autodetected? - bool myYStartAutodetected; - // Is the TV format autodetected? bool myFormatAutodetected; diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index 4faa95c47..a562aa157 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -587,7 +587,7 @@ unique_ptr OSystem::openConsole(const FilesystemNode& romfile, string& CMDLINE_PROPS_UPDATE("rd", PropType::Console_RightDiff); CMDLINE_PROPS_UPDATE("tv", PropType::Console_TVType); CMDLINE_PROPS_UPDATE("format", PropType::Display_Format); - CMDLINE_PROPS_UPDATE("ystart", PropType::Display_VCenter); // TODO (SA): change option + CMDLINE_PROPS_UPDATE("vcenter", PropType::Display_VCenter); // TODO (SA): change option CMDLINE_PROPS_UPDATE("pp", PropType::Display_Phosphor); CMDLINE_PROPS_UPDATE("ppblend", PropType::Display_PPBlend); diff --git a/src/emucore/ProfilingRunner.cxx b/src/emucore/ProfilingRunner.cxx index 72d68ed30..f082c1269 100644 --- a/src/emucore/ProfilingRunner.cxx +++ b/src/emucore/ProfilingRunner.cxx @@ -29,7 +29,6 @@ #include "TIA.hxx" #include "ConsoleTiming.hxx" #include "FrameManager.hxx" -#include "YStartDetector.hxx" #include "FrameLayoutDetector.hxx" #include "EmulationTiming.hxx" #include "ConsoleTiming.hxx" @@ -159,20 +158,9 @@ bool ProfilingRunner::runOne(const ProfilingRun run) (cout << endl).flush(); - YStartDetector ystartDetector; - tia.setFrameManager(&ystartDetector); - system.reset(); - - (cout << "detecting ystart... ").flush(); - for (int i = 0; i < 80; i++) tia.update(); - - uInt32 yStart = ystartDetector.detectedYStart(); - (cout << yStart << endl).flush(); - FrameManager frameManager; tia.setFrameManager(&frameManager); tia.setLayout(frameLayout); - tia.setYStart(yStart); system.reset(); diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index 75b5ee38f..c53654584 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -553,7 +553,7 @@ void Settings::usage() const << " -bc Same as using both -lc and -rc\n" << " -cp Sets the 'Controller.SwapPaddles' property\n" << " -format Sets the 'Display.Format' property\n" - << " -ystart Sets the 'Display.YStart' property\n" + << " -vcenter Sets the 'Display.vcenter' property\n" << " -pp Sets the 'Display.Phosphor' property\n" << " -ppblend Sets the 'Display.PPBlend' property\n" << endl diff --git a/src/emucore/tia/TIA.hxx b/src/emucore/tia/TIA.hxx index 4bc92482b..e80c2a926 100644 --- a/src/emucore/tia/TIA.hxx +++ b/src/emucore/tia/TIA.hxx @@ -249,12 +249,13 @@ class TIA : public Device */ uInt32 width() const { return TIAConstants::H_PIXEL; } uInt32 height() const { return myFrameManager->height(); } - uInt32 ystart() const { return myFrameManager->ystart(); } + Int32 vcenter() const { return myFrameManager->vcenter(); } + uInt32 startLine() const { return myFrameManager->startLine(); } /** - Changes the current YStart property. + Changes the current vcenter property. */ - void setYStart(uInt32 ystart) { myFrameManager->setYstart(ystart); } + void setVcenter(Int32 vcenter) { myFrameManager->setVcenter(vcenter); } void setLayout(FrameLayout layout) { myFrameManager->setLayout(layout); } FrameLayout frameLayout() const { return myFrameManager->layout(); } diff --git a/src/emucore/tia/TIAConstants.hxx b/src/emucore/tia/TIAConstants.hxx index 00c488c78..1e916fa47 100644 --- a/src/emucore/tia/TIAConstants.hxx +++ b/src/emucore/tia/TIAConstants.hxx @@ -24,9 +24,8 @@ namespace TIAConstants { static constexpr uInt32 frameBufferWidth = 160; static constexpr uInt32 frameBufferHeight = 320; - static constexpr uInt32 defaultYStart = 34; // TODO: PAL-50 might need a different value here - static constexpr uInt32 minYStart = defaultYStart - 15; // limit to reasonable values - static constexpr uInt32 maxYStart = defaultYStart + 15; // limit to reasonable values + static constexpr Int32 maxVcenter = 20; // limit to reasonable values + static constexpr Int32 minVcenter = -20; // limit to reasonable values static constexpr uInt32 viewableWidth = 320; static constexpr uInt32 viewableHeight = 240; static constexpr uInt32 initialGarbageFrames = 10; diff --git a/src/emucore/tia/frame-manager/AbstractFrameManager.hxx b/src/emucore/tia/frame-manager/AbstractFrameManager.hxx index d3ea2ddf2..c827eb0cf 100644 --- a/src/emucore/tia/frame-manager/AbstractFrameManager.hxx +++ b/src/emucore/tia/frame-manager/AbstractFrameManager.hxx @@ -22,6 +22,7 @@ #include "Serializable.hxx" #include "FrameLayout.hxx" +#include "bspf.hxx" class AbstractFrameManager : public Serializable { @@ -160,14 +161,19 @@ class AbstractFrameManager : public Serializable virtual uInt32 scanlines() const { return 0; } /** - * Configure the ystart value. + * Configure the vcenter value. */ - virtual void setYstart(uInt32 ystart) {} + virtual void setVcenter(Int32 vcenter) {} /** - * The configured ystart value. + * The configured vcenter value. */ - virtual uInt32 ystart() const { return 0; } + virtual Int32 vcenter() const { return 0; } + + /** + * The corresponding start line. + */ + virtual uInt32 startLine() const { return 0; } /** * Set the frame layout. This may be a noop (on the autodetection manager). diff --git a/src/emucore/tia/frame-manager/FrameManager.cxx b/src/emucore/tia/frame-manager/FrameManager.cxx index cc0d32299..34179d864 100644 --- a/src/emucore/tia/frame-manager/FrameManager.cxx +++ b/src/emucore/tia/frame-manager/FrameManager.cxx @@ -31,7 +31,9 @@ enum Metrics: uInt32 { vsync = 3, maxLinesVsync = 50, visibleOverscan = 20, - initialGarbageFrames = TIAConstants::initialGarbageFrames + initialGarbageFrames = TIAConstants::initialGarbageFrames, + ystartNTSC = 34, + ystartPAL = 39 }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -46,9 +48,11 @@ FrameManager::FrameManager() myFrameLines(0), myHeight(0), myYStart(0), + myVcenter(0), myJitterEnabled(false) { reset(); + updateYStart(); onLayoutChange(); } @@ -98,7 +102,7 @@ void FrameManager::onNextLine() case State::frame: if (myLineInState >= myHeight) { - myLastY = ystart() + myY; // Last line drawn in this frame + myLastY = myYStart + myY; // Last line drawn in this frame setState(State::waitForVsyncStart); } break; @@ -121,10 +125,10 @@ Int32 FrameManager::missingScanlines() const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameManager::setYstart(uInt32 ystart) +void FrameManager::setVcenter(Int32 vcenter) { - myYStart = ystart; - myJitterEmulation.setYStart(ystart); + myVcenter = vcenter; + updateYStart(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -241,3 +245,9 @@ bool FrameManager::onLoad(Serializer& in) return true; } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameManager::updateYStart() { + myYStart = (layout() == FrameLayout::ntsc ? Metrics::ystartNTSC : Metrics::ystartPAL) - myVcenter; + myJitterEmulation.setYStart(myYStart); +} diff --git a/src/emucore/tia/frame-manager/FrameManager.hxx b/src/emucore/tia/frame-manager/FrameManager.hxx index d133e93e5..b737fa9b5 100644 --- a/src/emucore/tia/frame-manager/FrameManager.hxx +++ b/src/emucore/tia/frame-manager/FrameManager.hxx @@ -44,9 +44,11 @@ class FrameManager: public AbstractFrameManager { Int32 missingScanlines() const override; - void setYstart(uInt32 ystart) override; + void setVcenter(Int32 vcenter) override; - uInt32 ystart() const override { return myYStart; } + Int32 vcenter() const override { return myVcenter; } + + uInt32 startLine() const override { return myYStart; } void setLayout(FrameLayout mode) override { layout(mode); } @@ -77,6 +79,8 @@ class FrameManager: public AbstractFrameManager { void updateIsRendering(); + void updateYStart(); + private: State myState; @@ -90,6 +94,7 @@ class FrameManager: public AbstractFrameManager { uInt32 myFrameLines; uInt32 myHeight; uInt32 myYStart; + Int32 myVcenter; bool myJitterEnabled; diff --git a/src/emucore/tia/frame-manager/YStartDetector.cxx b/src/emucore/tia/frame-manager/YStartDetector.cxx deleted file mode 100644 index bf8d79ab3..000000000 --- a/src/emucore/tia/frame-manager/YStartDetector.cxx +++ /dev/null @@ -1,230 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#include "YStartDetector.hxx" -#include "TIAConstants.hxx" - -/** - * Misc. numeric constants used in the algorithm. - */ -enum Metrics: uInt32 { - // ideal world frame sizes - frameLinesNTSC = 262, - frameLinesPAL = 312, - - // the ideal vblank zone - vblankNTSC = 37, - vblankPAL = 45, - - // number of scanlines to wait for vsync to start (exceeding after the ideal frame size) and stop - waitForVsync = 50, - - // max lines underscan - maxUnderscan = 10, - - // max lines deviations from detected ystart before we switch back to floating - maxVblankViolations = 2, - - // switch to fixed mode after this number of stable frames (+1) - minStableVblankFrames = 1, - - // no transitions to fixed mode will happend during those - initialGarbageFrames = TIAConstants::initialGarbageFrames -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -YStartDetector::YStartDetector() - : myState(State::waitForVsyncStart), - myVblankMode(VblankMode::floating), - myLinesWaitingForVsyncToStart(0), - myCurrentVblankLines(0), - myLastVblankLines(0), - myVblankViolations(0), - myStableVblankFrames(0), - myVblankViolated(false) -{ - reset(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 YStartDetector::detectedYStart() const -{ - return myLastVblankLines; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void YStartDetector::onReset() -{ - myState = State::waitForVsyncStart; - myVblankMode = VblankMode::floating; - myLinesWaitingForVsyncToStart = 0; - myCurrentVblankLines = 0; - myLastVblankLines = 0; - myVblankViolations = 0; - myStableVblankFrames = 0; - myVblankViolated = false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void YStartDetector::onSetVsync() -{ - if (myVsync) - setState(State::waitForVsyncEnd); - else - setState(State::waitForFrameStart); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void YStartDetector::onNextLine() -{ - const uInt32 frameLines = layout() == FrameLayout::ntsc ? Metrics::frameLinesNTSC : Metrics::frameLinesPAL; - - switch (myState) { - case State::waitForVsyncStart: - // We start counting the number of "lines spent while waiting for vsync start" from - // the "ideal" frame size (corrected by the three scanlines spent in vsync). - if (myCurrentFrameTotalLines > frameLines - 3 || myTotalFrames == 0) - ++myLinesWaitingForVsyncToStart; - - if (myLinesWaitingForVsyncToStart > Metrics::waitForVsync) setState(State::waitForVsyncEnd); - - break; - - case State::waitForVsyncEnd: - if (++myLinesWaitingForVsyncToStart > Metrics::waitForVsync) setState(State::waitForFrameStart); - - break; - - case State::waitForFrameStart: - if (shouldTransitionToFrame()) setState(State::waitForVsyncStart); - else ++myCurrentVblankLines; - - break; - - default: - throw runtime_error("cannot happen"); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool YStartDetector::shouldTransitionToFrame() -{ - uInt32 vblankLines = layout() == FrameLayout::pal ? Metrics::vblankPAL : Metrics::vblankNTSC; - - // Are we free to transition as per vblank cycle? - bool shouldTransition = myCurrentVblankLines + 1 >= (myVblank ? vblankLines : vblankLines - Metrics::maxUnderscan); - - // Do we **actually** transition? This depends on what mode we are in. - bool transition = false; - - switch (myVblankMode) { - // Floating mode: we still are looking for a stable frame start - case VblankMode::floating: - - // Are we free to transition? - if (shouldTransition) { - // Is this same scanline in which the transition ocurred last frame? - if (myTotalFrames > Metrics::initialGarbageFrames && myCurrentVblankLines == myLastVblankLines) - // Yes? -> Increase the number of stable frames - ++myStableVblankFrames; - else - // No? -> Frame start shifted again, set the number of consecutive stable frames to zero - myStableVblankFrames = 0; - - // Save the transition point for checking on it next frame - myLastVblankLines = myCurrentVblankLines; - - // In floating mode, we transition whenever we can. - transition = true; - } - - // Transition to locked mode if we saw enough stable frames in a row. - if (myStableVblankFrames >= Metrics::minStableVblankFrames) { - myVblankMode = VblankMode::locked; - myVblankViolations = 0; - } - - break; - - // Locked mode: always transition at the same point, but check whether this is actually the - // detected transition point and revert state if applicable - case VblankMode::locked: - - // Have we reached the transition point? - if (myCurrentVblankLines == myLastVblankLines) { - - // Are we free to transition per the algorithm and didn't observe an violation before? - // (aka did the algorithm tell us to transition before reaching the actual line) - if (shouldTransition && !myVblankViolated) - // Reset the number of irregular frames (if any) - myVblankViolations = 0; - else { - // Record a violation if it wasn't recorded before - if (!myVblankViolated) ++myVblankViolations; - myVblankViolated = true; - } - - // transition - transition = true; - // The algorithm tells us to transition although we haven't reached the trip line before - } else if (shouldTransition) { - // Record a violation if it wasn't recorded before - if (!myVblankViolated) ++myVblankViolations; - myVblankViolated = true; - } - - // Revert to floating mode if there were too many irregular frames in a row - if (myVblankViolations > Metrics::maxVblankViolations) { - myVblankMode = VblankMode::floating; - myStableVblankFrames = 0; - } - - break; - - default: - throw runtime_error("cannot happen"); - } - - return transition; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void YStartDetector::setState(State state) -{ - if (state == myState) return; - - myState = state; - myLinesWaitingForVsyncToStart = 0; - - switch (state) { - case State::waitForVsyncEnd: - break; - - case State::waitForVsyncStart: - notifyFrameComplete(); - notifyFrameStart(); - break; - - case State::waitForFrameStart: - myVblankViolated = false; - myCurrentVblankLines = 0; - break; - - default: - throw new runtime_error("cannot happen"); - } -} diff --git a/src/emucore/tia/frame-manager/YStartDetector.hxx b/src/emucore/tia/frame-manager/YStartDetector.hxx deleted file mode 100644 index 7f589475c..000000000 --- a/src/emucore/tia/frame-manager/YStartDetector.hxx +++ /dev/null @@ -1,155 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#ifndef TIA_YSTART_DETECTOR -#define TIA_YSTART_DETECTOR - -#include "AbstractFrameManager.hxx" - -/** - * This frame manager detects ystart from the first line with vblank = off. - */ - -class YStartDetector: public AbstractFrameManager { - - public: - - YStartDetector(); - - public: - - /** - * Getter for the detected ystart value - */ - uInt32 detectedYStart() const; - - /** - * We require frame layout to be set from outside. - */ - void setLayout(FrameLayout layout) override { this->layout(layout); } - - protected: - - /** - * We need to track vsync changes. - */ - void onSetVsync() override; - - /** - * Reset hook. - */ - void onReset() override; - - /** - * The workhorse. - */ - void onNextLine() override; - - private: - - /** - * Our various states. - */ - enum class State { - // Wait for vsync on - waitForVsyncStart, - - // Wait for vsync off - waitForVsyncEnd, - - // Wait for the visible frame to start - waitForFrameStart - }; - - /** - * Have we settled on a frame start? - */ - enum class VblankMode { - // We have settled on a frame start and have some hysteresis before we return to floating - locked, - - // We are actively looking for the frame to start - floating - }; - - private: - - /** - * Side effects for state transitions. - */ - void setState(State state); - - /** - * Perform detection and decide whether the frame starts now. - */ - bool shouldTransitionToFrame(); - - private: - - /** - * State. - */ - State myState; - - /** - * locked / floating - */ - VblankMode myVblankMode; - - /** - * Counts the scanlines that we wait for vsync to start. - */ - uInt32 myLinesWaitingForVsyncToStart; - - /** - * The number of lines we are currently waiting for the frame to start (and vblank to end). - */ - uInt32 myCurrentVblankLines; - - /** - * The number of vblank lines on the last frame. - */ - uInt32 myLastVblankLines; - - /** - * Count "vblank violations" in fixed mode (the number of consecutive frames where ystart - * differs from the previously detected value). Once a trip point is reached, we transition - * back to floating mode. - */ - uInt32 myVblankViolations; - - /** - * The number of frames in floating mode with stable ystart. Once a trip point is reacted, - * we transition to fixed mode - */ - uInt32 myStableVblankFrames; - - /** - * Tracks deviations from the determined ystart value during a fixed mode frame in order to - * avoid double counting. - */ - bool myVblankViolated; - - private: - - YStartDetector(const YStartDetector&) = delete; - YStartDetector(YStartDetector&&) = delete; - YStartDetector& operator=(const YStartDetector&) = delete; - YStartDetector& operator=(YStartDetector&&) = delete; -}; - -#endif // TIA_YSTART_DETECTOR diff --git a/src/emucore/tia/frame-manager/module.mk b/src/emucore/tia/frame-manager/module.mk index 9bd6093c2..b4f8fdcdb 100644 --- a/src/emucore/tia/frame-manager/module.mk +++ b/src/emucore/tia/frame-manager/module.mk @@ -4,7 +4,6 @@ MODULE_OBJS := \ src/emucore/tia/frame-manager/FrameManager.o \ src/emucore/tia/frame-manager/AbstractFrameManager.o \ src/emucore/tia/frame-manager/FrameLayoutDetector.o \ - src/emucore/tia/frame-manager/YStartDetector.o \ src/emucore/tia/frame-manager/JitterEmulation.o MODULE_DIRS += \ diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index ae9e60804..ec41669ac 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -138,9 +138,9 @@ GameInfoDialog::GameInfoDialog( t = new StaticTextWidget(myTab, font, HBORDER, ypos + 1, "V-Center "); myVCenter = new SliderWidget(myTab, font, t->getRight() + 2, ypos, "", 0, kVCenterChanged, 7 * fontWidth, "px"); -// TODO (SA):check relationship of ystart and vcenter - myVCenter->setMinValue(TIAConstants::minYStart - TIAConstants::defaultYStart); - myVCenter->setMaxValue(TIAConstants::maxYStart - TIAConstants::defaultYStart); + + myVCenter->setMinValue(TIAConstants::minVcenter); + myVCenter->setMaxValue(TIAConstants::maxVcenter); myVCenter->setTickmarkIntervals(4); wid.push_back(myVCenter); @@ -458,20 +458,10 @@ void GameInfoDialog::loadEmulationProperties(const Properties& props) myPPBlend->setValue(atoi(blend.c_str())); // set vertical center - int vCenter = atoi(props.get(PropType::Display_VCenter).c_str()); - if (vCenter) - { - // convert y-start into v-center - // TODO (SA): fix this - vCenter = TIAConstants::defaultYStart - vCenter; - myVCenter->setValueLabel(vCenter); - } - else - { - myVCenter->setValueLabel("default"); - } - myVCenter->setValue(vCenter); - myVCenter->setValueUnit(vCenter ? "px" : ""); + Int32 vcenter = atoi(props.get(PropType::Display_VCenter).c_str()); + myVCenter->setValueLabel(vcenter); + myVCenter->setValue(vcenter); + myVCenter->setValueUnit(vcenter ? "px" : ""); mySound->setState(props.get(PropType::Cart_Sound) == "STEREO"); // if stereo is always enabled, disable game specific stereo setting @@ -548,11 +538,9 @@ void GameInfoDialog::saveConfig() myGameProperties.set(PropType::Display_Phosphor, myPhosphor->getState() ? "YES" : "NO"); myGameProperties.set(PropType::Display_PPBlend, myPPBlend->getValueLabel() == "Off" ? "0" : myPPBlend->getValueLabel()); - int vCenter = myVCenter->getValue(); - if (vCenter) - // convert v-center into y-start TODO (SA): fix this - vCenter = TIAConstants::defaultYStart - vCenter; - myGameProperties.set(PropType::Display_VCenter, std::to_string(vCenter)); + Int32 vcenter = myVCenter->getValue(); + + myGameProperties.set(PropType::Display_VCenter, std::to_string(vcenter)); myGameProperties.set(PropType::Cart_Sound, mySound->getState() ? "STEREO" : "MONO"); // Console properties @@ -595,7 +583,7 @@ void GameInfoDialog::saveConfig() // update 'Emulation' tab settings immediately instance().console().setFormat(myFormat->getSelected()); instance().frameBuffer().tiaSurface().enablePhosphor(myPhosphor->getState(), myPPBlend->getValue()); - instance().console().updateYStart(vCenter); + instance().console().updateVcenter(vcenter); instance().console().initializeAudio(); // update 'Console' tab settings immediately