diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index 70ad0bf27..852e6f7d4 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -696,11 +696,13 @@ void Console::setTIAProperties() { // Assume we've got ~262 scanlines (NTSC-like format) myTIA->setLayout(FrameLayout::ntsc); + myTIA->setAdjustScanlines(myOSystem.settings().getInt("tia.adjustscanlines.ntsc")); } else { // Assume we've got ~312 scanlines (PAL-like format) myTIA->setLayout(FrameLayout::pal); + myTIA->setAdjustScanlines(myOSystem.settings().getInt("tia.adjustscanlines.pal")); } myTIA->setVcenter(vcenter); diff --git a/src/emucore/Console.hxx b/src/emucore/Console.hxx index 872725979..ee13cea41 100644 --- a/src/emucore/Console.hxx +++ b/src/emucore/Console.hxx @@ -311,6 +311,12 @@ class Console : public Serializable, public ConsoleIO */ void updateVcenter(Int32 vcenter); + /** + Set up various properties of the TIA (vcenter, Height, etc) based on + the current display format. + */ + void setTIAProperties(); + private: /** * Dry-run the emulation and detect the frame layout (PAL / NTSC). @@ -322,12 +328,6 @@ class Console : public Serializable, public ConsoleIO */ void redetectFrameLayout(); - /** - Sets various properties of the TIA (vcenter, Height, etc) based on - the current display format. - */ - void setTIAProperties(); - /** Create the audio queue */ diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index 40ca11f1c..d5fae0e02 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -932,14 +932,6 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight) uInt32 minZoom = supportedTIAMinZoom(); myTIAMaxZoom = maxZoomForScreen(baseWidth, baseHeight, myAbsDesktopSize.w, myAbsDesktopSize.h); - - #if 0 // FIXME - does this apply any longer?? - // Aspect ratio - uInt32 aspect = myOSystem.settings().getInt( - myOSystem.console().tia().frameLayout() == FrameLayout::ntsc ? - "tia.aspectn" : "tia.aspectp"); - #endif - // Determine all zoom levels for(float zoom = minZoom; zoom <= myTIAMaxZoom; zoom += ZOOM_STEPS) { diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index a42af17b9..d6a566766 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -50,8 +50,8 @@ Settings::Settings() // TIA specific options setPermanent("tia.zoom", "3"); setPermanent("tia.inter", "false"); - setPermanent("tia.aspectn", "100"); - setPermanent("tia.aspectp", "100"); + setPermanent("tia.adjustscanlines.ntsc", "0"); + setPermanent("tia.adjustscanlines.pal", "0"); setPermanent("fullscreen", "false"); setPermanent("tia.fs_stretch", "false"); setPermanent("tia.fs_overscan", "0"); @@ -255,10 +255,10 @@ void Settings::validate() f = getFloat("speed"); if (f <= 0) setValue("speed", "1.0"); - i = getInt("tia.aspectn"); - if(i < 80 || i > 120) setValue("tia.aspectn", "90"); - i = getInt("tia.aspectp"); - if(i < 80 || i > 120) setValue("tia.aspectp", "100"); + i = getInt("tia.adjustscanlines.ntsc"); + if(i < -25 || i > 25) setValue("tia.adjustscanlines.ntsc", "90"); + i = getInt("tia.adjustscanlines.pal"); + if(i < -25 || i > 25) setValue("tia.adjustscanlines.pal", "100"); s = getString("tia.dbgcolors"); sort(s.begin(), s.end()); @@ -410,10 +410,8 @@ void Settings::usage() const << " for TIA image\n" << " -tia.inter <1|0> Enable interpolated (smooth) scaling for TIA\n" << " image\n" - << " -tia.aspectn Scale TIA width by the given percentage in NTS\n" - << " mode\n" - << " -tia.aspectp Scale TIA width by the given percentage in PAL\n" - << " mode\n" + << " -tia.adjustscanlines.ntsc Adjust the visible number if TIA scanlines on NTSC\n" + << " -tia.adjustscanlines.pal Adjust the visible number if TIA scanlines on PAL\n" << " -tia.fs_stretch <1|0> Stretch TIA image to fill fullscreen mode\n" << " -tia.fs_overscan <0-10> Add overscan to TIA image in fill fullscreen mode\n" << " -tia.dbgcolors Debug colors to use for each object (see manual\n" diff --git a/src/emucore/TIASurface.cxx b/src/emucore/TIASurface.cxx index 74cdc2efa..17b75197d 100644 --- a/src/emucore/TIASurface.cxx +++ b/src/emucore/TIASurface.cxx @@ -219,9 +219,15 @@ void TIASurface::enableNTSC(bool enable) { myFilter = Filter(enable ? uInt8(myFilter) | 0x10 : uInt8(myFilter) & 0x01); - // Normal vs NTSC mode uses different source widths - myTiaSurface->setSrcSize(enable ? AtariNTSC::outWidth(TIAConstants::frameBufferWidth) - : TIAConstants::frameBufferWidth, myTIA->height()); + uInt32 surfaceWidth = enable ? + AtariNTSC::outWidth(TIAConstants::frameBufferWidth) : TIAConstants::frameBufferWidth; + + if (surfaceWidth != myTiaSurface->srcRect().w() || myTIA->height() != myTiaSurface->srcRect().h()) { + myTiaSurface->setSrcSize(surfaceWidth, myTIA->height()); + + myTiaSurface->invalidate(); + myTIA->clearFrameBuffer(); + } mySLineSurface->setSrcSize(1, 2 * myTIA->height()); diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx index f713f0586..60608b765 100644 --- a/src/emucore/tia/TIA.cxx +++ b/src/emucore/tia/TIA.cxx @@ -899,6 +899,13 @@ void TIA::renderToFrameBuffer() myFrameBufferScanlines = myFrontBufferScanlines; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIA::clearFrameBuffer() +{ + myFramebuffer.fill(0); + myFrontBuffer.fill(0); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TIA::update(uInt64 maxCycles) { diff --git a/src/emucore/tia/TIA.hxx b/src/emucore/tia/TIA.hxx index 0f6336128..a25a942d1 100644 --- a/src/emucore/tia/TIA.hxx +++ b/src/emucore/tia/TIA.hxx @@ -244,6 +244,8 @@ class TIA : public Device */ uInt8* frameBuffer() { return myFramebuffer.data(); } + void clearFrameBuffer(); + /** Answers dimensional info about the framebuffer. */ @@ -260,6 +262,9 @@ class TIA : public Device void setLayout(FrameLayout layout) { myFrameManager->setLayout(layout); } FrameLayout frameLayout() const { return myFrameManager->layout(); } + void setAdjustScanlines(Int32 adjustScanlines) { myFrameManager->setAdjustScanlines(adjustScanlines); } + Int32 adjustScanlines() const { return myFrameManager->adjustScanlines(); } + /** Enables/disables color-loss for PAL modes only. diff --git a/src/emucore/tia/frame-manager/AbstractFrameManager.hxx b/src/emucore/tia/frame-manager/AbstractFrameManager.hxx index 5f11fd39c..a4b285a3e 100644 --- a/src/emucore/tia/frame-manager/AbstractFrameManager.hxx +++ b/src/emucore/tia/frame-manager/AbstractFrameManager.hxx @@ -170,6 +170,10 @@ class AbstractFrameManager : public Serializable */ virtual Int32 vcenter() const { return 0; } + virtual void setAdjustScanlines(Int32 adjustScanlines) {} + + virtual Int32 adjustScanlines() const { return 0; } + /** * The corresponding start line. */ diff --git a/src/emucore/tia/frame-manager/FrameManager.cxx b/src/emucore/tia/frame-manager/FrameManager.cxx index 4aa2a2bbc..55d94115c 100644 --- a/src/emucore/tia/frame-manager/FrameManager.cxx +++ b/src/emucore/tia/frame-manager/FrameManager.cxx @@ -24,13 +24,12 @@ enum Metrics: uInt32 { vblankNTSC = 37, vblankPAL = 45, - kernelNTSC = 192, - kernelPAL = 228, - overscanNTSC = 30, - overscanPAL = 36, vsync = 3, + frameSizeNTSC = 262, + frameSizePAL = 312, + baseHeightNTSC = 240, + baseHeightPAL = 288, maxLinesVsync = 50, - visibleOverscan = 20, initialGarbageFrames = TIAConstants::initialGarbageFrames, ystartNTSC = 34, ystartPAL = 39 @@ -40,8 +39,7 @@ enum Metrics: uInt32 { FrameManager::FrameManager() { reset(); - updateYStart(); - onLayoutChange(); + recalculateMetrics(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -118,7 +116,14 @@ void FrameManager::setVcenter(Int32 vcenter) if (vcenter < TIAConstants::minVcenter || vcenter > TIAConstants::maxVcenter) return; myVcenter = vcenter; - updateYStart(); + recalculateMetrics(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameManager::setAdjustScanlines(Int32 adjustScanlines) +{ + myAdjustScanlines = adjustScanlines; + recalculateMetrics(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -163,26 +168,7 @@ void FrameManager::setState(FrameManager::State state) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FrameManager::onLayoutChange() { - switch (layout()) - { - case FrameLayout::ntsc: - myVblankLines = Metrics::vblankNTSC; - myKernelLines = Metrics::kernelNTSC; - myOverscanLines = Metrics::overscanNTSC; - break; - - case FrameLayout::pal: - myVblankLines = Metrics::vblankPAL; - myKernelLines = Metrics::kernelPAL; - myOverscanLines = Metrics::overscanPAL; - break; - - default: - throw runtime_error("frame manager: invalid TV mode"); - } - - myFrameLines = Metrics::vsync + myVblankLines + myKernelLines + myOverscanLines; - myHeight = myKernelLines + Metrics::visibleOverscan; + recalculateMetrics(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -202,8 +188,6 @@ bool FrameManager::onSave(Serializer& out) const out.putInt(myLastY); out.putInt(myVblankLines); - out.putInt(myKernelLines); - out.putInt(myOverscanLines); out.putInt(myFrameLines); out.putInt(myHeight); out.putInt(myYStart); @@ -225,8 +209,6 @@ bool FrameManager::onLoad(Serializer& in) myLastY = in.getInt(); myVblankLines = in.getInt(); - myKernelLines = in.getInt(); - myOverscanLines = in.getInt(); myFrameLines = in.getInt(); myHeight = in.getInt(); myYStart = in.getInt(); @@ -237,7 +219,32 @@ bool FrameManager::onLoad(Serializer& in) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameManager::updateYStart() { - myYStart = (layout() == FrameLayout::ntsc ? Metrics::ystartNTSC : Metrics::ystartPAL) - myVcenter; +void FrameManager::recalculateMetrics() { + Int32 ystartBase; + Int32 baseHeight; + + switch (layout()) + { + case FrameLayout::ntsc: + myVblankLines = Metrics::vblankNTSC; + myFrameLines = Metrics::frameSizeNTSC; + ystartBase = Metrics::ystartNTSC; + baseHeight = Metrics::baseHeightNTSC; + break; + + case FrameLayout::pal: + myVblankLines = Metrics::vblankPAL; + myFrameLines = Metrics::frameSizePAL; + ystartBase = Metrics::ystartPAL; + baseHeight = Metrics::baseHeightPAL; + break; + + default: + throw runtime_error("frame manager: invalid TV mode"); + } + + myHeight = BSPF::clamp(baseHeight + myAdjustScanlines * 2, 0, myFrameLines); + myYStart = BSPF::clamp(ystartBase + (baseHeight - static_cast(myHeight)) / 2 + myVcenter, 0, myFrameLines); + myJitterEmulation.setYStart(myYStart); } diff --git a/src/emucore/tia/frame-manager/FrameManager.hxx b/src/emucore/tia/frame-manager/FrameManager.hxx index 2f47d5ccc..a876298f5 100644 --- a/src/emucore/tia/frame-manager/FrameManager.hxx +++ b/src/emucore/tia/frame-manager/FrameManager.hxx @@ -48,6 +48,10 @@ class FrameManager: public AbstractFrameManager { Int32 vcenter() const override { return myVcenter; } + void setAdjustScanlines(Int32 adjustScanlines) override; + + Int32 adjustScanlines() const override { return myAdjustScanlines; } + uInt32 startLine() const override { return myYStart; } void setLayout(FrameLayout mode) override { layout(mode); } @@ -79,7 +83,7 @@ class FrameManager: public AbstractFrameManager { void updateIsRendering(); - void updateYStart(); + void recalculateMetrics(); private: @@ -89,12 +93,11 @@ class FrameManager: public AbstractFrameManager { uInt32 myY{0}, myLastY{0}; uInt32 myVblankLines{0}; - uInt32 myKernelLines{0}; - uInt32 myOverscanLines{0}; uInt32 myFrameLines{0}; uInt32 myHeight{0}; uInt32 myYStart{0}; Int32 myVcenter{0}; + Int32 myAdjustScanlines{0}; bool myJitterEnabled{false}; diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx index 33a8028be..493c1a39a 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -86,7 +86,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, fontWidth = font.getMaxCharWidth(), buttonHeight = font.getLineHeight() + 4; int xpos, ypos, tabID; - int lwidth = font.getStringWidth("TIA Palette "), + int lwidth = font.getStringWidth("NTSC scanlines adjust "), pwidth = font.getStringWidth("XXXXxXXXX"), swidth = font.getMaxCharWidth() * 10 - 2; @@ -94,7 +94,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, VariantList items; // Set real dimensions - setSize(55 * fontWidth + HBORDER * 2, 14 * (lineHeight + VGAP) + 14 + _th, max_w, max_h); + setSize(65 * fontWidth + HBORDER * 2, 14 * (lineHeight + VGAP) + 14 + _th, max_w, max_h); // The tab widget xpos = 2; ypos = 4; @@ -136,23 +136,23 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, ypos += lineHeight + VGAP; // Aspect ratio (NTSC mode) - myNAspectRatio = + myAdjustScanlinesNTSC = new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, - "NTSC aspect ", lwidth, 0, - fontWidth * 4, "%"); - myNAspectRatio->setMinValue(80); myNAspectRatio->setMaxValue(120); - myNAspectRatio->setTickmarkIntervals(2); - wid.push_back(myNAspectRatio); + "NTSC scanlines adjust ", lwidth, 0, + fontWidth * 4, ""); + myAdjustScanlinesNTSC->setMinValue(-25); myAdjustScanlinesNTSC->setMaxValue(25); + myAdjustScanlinesNTSC->setTickmarkIntervals(2); + wid.push_back(myAdjustScanlinesNTSC); ypos += lineHeight + VGAP; // Aspect ratio (PAL mode) - myPAspectRatio = + myAdjustScanlinesPAL = new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, - "PAL aspect ", lwidth, 0, - fontWidth * 4, "%"); - myPAspectRatio->setMinValue(80); myPAspectRatio->setMaxValue(120); - myPAspectRatio->setTickmarkIntervals(2); - wid.push_back(myPAspectRatio); + "PAL scanlines adjust ", lwidth, 0, + fontWidth * 4, ""); + myAdjustScanlinesPAL->setMinValue(-25); myAdjustScanlinesPAL->setMaxValue(25); + myAdjustScanlinesPAL->setTickmarkIntervals(2); + wid.push_back(myAdjustScanlinesPAL); ypos += lineHeight + VGAP; // Speed @@ -353,8 +353,8 @@ void VideoDialog::loadConfig() myTIAInterpolate->setState(instance().settings().getBool("tia.inter")); // Aspect ratio setting (NTSC and PAL) - myNAspectRatio->setValue(instance().settings().getInt("tia.aspectn")); - myPAspectRatio->setValue(instance().settings().getInt("tia.aspectp")); + myAdjustScanlinesNTSC->setValue(instance().settings().getInt("tia.adjustscanlines.ntsc")); + myAdjustScanlinesPAL->setValue(instance().settings().getInt("tia.adjustscanlines.pal")); // Emulation speed int speed = mapSpeed(instance().settings().getFloat("speed")); @@ -426,8 +426,8 @@ void VideoDialog::saveConfig() instance().settings().setValue("tia.inter", myTIAInterpolate->getState()); // Aspect ratio setting (NTSC and PAL) - instance().settings().setValue("tia.aspectn", myNAspectRatio->getValueLabel()); - instance().settings().setValue("tia.aspectp", myPAspectRatio->getValueLabel()); + instance().settings().setValue("tia.adjustscanlines.ntsc", myAdjustScanlinesNTSC->getValueLabel()); + instance().settings().setValue("tia.adjustscanlines.pal", myAdjustScanlinesPAL->getValueLabel()); // Speed int speedup = mySpeed->getValue(); @@ -487,6 +487,8 @@ void VideoDialog::saveConfig() // TV scanline intensity instance().settings().setValue("tv.scanlines", myTVScanIntense->getValueLabel()); + instance().console().setTIAProperties(); + // Finally, issue a complete framebuffer re-initialization... instance().createFrameBuffer(); @@ -505,8 +507,8 @@ void VideoDialog::setDefaults() myTIAZoom->setValue(300); myTIAPalette->setSelected("standard", ""); myTIAInterpolate->setState(false); - myNAspectRatio->setValue(91); - myPAspectRatio->setValue(109); + myAdjustScanlinesNTSC->setValue(0); + myAdjustScanlinesPAL->setValue(0); mySpeed->setValue(0); myFullscreen->setState(false); diff --git a/src/gui/VideoDialog.hxx b/src/gui/VideoDialog.hxx index aa56e37bf..4d3ce582a 100644 --- a/src/gui/VideoDialog.hxx +++ b/src/gui/VideoDialog.hxx @@ -58,8 +58,8 @@ class VideoDialog : public Dialog SliderWidget* myTIAZoom{nullptr}; PopUpWidget* myTIAPalette{nullptr}; CheckboxWidget* myTIAInterpolate{nullptr}; - SliderWidget* myNAspectRatio{nullptr}; - SliderWidget* myPAspectRatio{nullptr}; + SliderWidget* myAdjustScanlinesNTSC{nullptr}; + SliderWidget* myAdjustScanlinesPAL{nullptr}; SliderWidget* mySpeed{nullptr}; CheckboxWidget* myFullscreen{nullptr}; diff --git a/src/libretro/StellaLIBRETRO.cxx b/src/libretro/StellaLIBRETRO.cxx index 1c1478087..d599619f3 100644 --- a/src/libretro/StellaLIBRETRO.cxx +++ b/src/libretro/StellaLIBRETRO.cxx @@ -90,8 +90,8 @@ bool StellaLIBRETRO::create(bool logging) settings.setValue("tia.zoom", 1); settings.setValue("tia.inter", false); - settings.setValue("tia.aspectn", 100); - settings.setValue("tia.aspectp", 100); + settings.setValue("tia.adjustscanlines.ntsc", 0); + settings.setValue("tia.adjustscanlines.ntsc", 0); //fastscbios // Fast loading of Supercharger BIOS