From 4192f5c6042e63674b48c86eb0b19695260fc550 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Tue, 14 May 2019 22:44:48 +0200 Subject: [PATCH] implement emulation fullscreen overscan --- src/emucore/FrameBuffer.cxx | 34 ++++++++++++++++------------ src/emucore/FrameBuffer.hxx | 2 +- src/emucore/Settings.cxx | 4 +++- src/gui/VideoDialog.cxx | 45 ++++++++++++++++++++++++++++++++++--- src/gui/VideoDialog.hxx | 5 +++++ 5 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index 600f6b183..b61d1a508 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -137,10 +137,11 @@ bool FrameBuffer::initialize() #endif // Determine possible TIA windowed zoom levels + double overscan = 1 - myOSystem.settings().getInt("tia.fs_overscan") / 100.0; uInt32 minZoom = 2 * hidpiScaleFactor(); uInt32 maxZoom = maxWindowSizeForScreen( TIAConstants::viewableWidth, TIAConstants::viewableHeight, - myAbsDesktopSize.w, myAbsDesktopSize.h); + myAbsDesktopSize.w * overscan, myAbsDesktopSize.h * overscan); for(uInt32 zoom = minZoom; zoom <= maxZoom; ++zoom) { ostringstream desc; @@ -874,6 +875,7 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight) EventHandlerState state = myOSystem.eventHandler().state(); bool tiaMode = (state != EventHandlerState::DEBUGGER && state != EventHandlerState::LAUNCHER); + double overscan = 1 - myOSystem.settings().getInt("tia.fs_overscan") / 100.0; // TIA mode allows zooming at integral factors in windowed modes, // and also non-integral factors in fullscreen mode @@ -882,7 +884,7 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight) // TIA windowed modes uInt32 minZoom = 2 * hidpiScaleFactor(); uInt32 maxZoom = maxWindowSizeForScreen(baseWidth, baseHeight, - myAbsDesktopSize.w, myAbsDesktopSize.h); + myAbsDesktopSize.w * overscan, myAbsDesktopSize.h * overscan); #if 0 // FIXME - does this apply any longer?? // Aspect ratio @@ -898,7 +900,7 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight) desc << "Zoom " << zoom << "x"; VideoMode mode(baseWidth*zoom, baseHeight*zoom, baseWidth*zoom, baseHeight*zoom, - VideoMode::Stretch::Fill, desc.str(), zoom); + VideoMode::Stretch::Fill, overscan, desc.str(), zoom); myWindowedModeList.add(mode); } @@ -906,19 +908,19 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight) for(uInt32 i = 0; i < myFullscreenDisplays.size(); ++i) { maxZoom = maxWindowSizeForScreen(baseWidth, baseHeight, - myFullscreenDisplays[i].w, myFullscreenDisplays[i].h); + myFullscreenDisplays[i].w * overscan, myFullscreenDisplays[i].h * overscan); // Add both normal aspect and filled modes // It's easier to define them both now, and simply switch between // them when necessary VideoMode mode1(baseWidth*maxZoom, baseHeight*maxZoom, myFullscreenDisplays[i].w, myFullscreenDisplays[i].h, - VideoMode::Stretch::Preserve, + VideoMode::Stretch::Preserve, overscan, "Preserve aspect, no stretch", maxZoom, i); myFullscreenModeLists[i].add(mode1); VideoMode mode2(baseWidth*maxZoom, baseHeight*maxZoom, myFullscreenDisplays[i].w, myFullscreenDisplays[i].h, - VideoMode::Stretch::Fill, + VideoMode::Stretch::Fill, overscan, "Ignore aspect, full stretch", maxZoom, i); myFullscreenModeLists[i].add(mode2); } @@ -932,8 +934,9 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight) for(uInt32 i = 0; i < myFullscreenDisplays.size(); ++i) { myFullscreenModeLists[i].add( - VideoMode(baseWidth, baseHeight, myFullscreenDisplays[i].w, myFullscreenDisplays[i].h, - VideoMode::Stretch::None, "", 1, i) + VideoMode(baseWidth, baseHeight, + myFullscreenDisplays[i].w, myFullscreenDisplays[i].h, + VideoMode::Stretch::None, 1.0, "", 1, i) ); } } @@ -988,7 +991,7 @@ FrameBuffer::VideoMode::VideoMode() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FrameBuffer::VideoMode::VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, - Stretch smode, const string& desc, + Stretch smode, double overscan, const string& desc, uInt32 zoomLevel, Int32 fsindex) : stretch(smode), description(desc), @@ -1011,6 +1014,7 @@ FrameBuffer::VideoMode::VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, if(fsIndex != -1) { + //double overscan = 1 - myOSystem.settings().getInt("tia.fs_overscan") / 100.0; switch(stretch) { case Stretch::Preserve: @@ -1025,19 +1029,21 @@ FrameBuffer::VideoMode::VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, else stretchFactor = float(screen.h) / ih; - iw = uInt32(stretchFactor * iw); - ih = uInt32(stretchFactor * ih); + iw = uInt32(stretchFactor * iw) * overscan; + ih = uInt32(stretchFactor * ih) * overscan; break; } case Stretch::Fill: // Scale to all available space - iw = screen.w; - ih = screen.h; + iw = screen.w * overscan; + ih = screen.h * overscan; break; case Stretch::None: - // Don't do any scaling at all + // Don't do any scaling at all, but obey overscan + iw = std::min(iw, screen.w) * overscan; + ih = std::min(ih, screen.h) * overscan; break; } } diff --git a/src/emucore/FrameBuffer.hxx b/src/emucore/FrameBuffer.hxx index a14aca188..965bc445b 100644 --- a/src/emucore/FrameBuffer.hxx +++ b/src/emucore/FrameBuffer.hxx @@ -67,7 +67,7 @@ class FrameBuffer Int32 fsIndex; VideoMode(); - VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, Stretch smode, + VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, Stretch smode, double overscan = 1.0, const string& desc = "", uInt32 zoomLevel = 1, Int32 fsindex = -1); friend ostream& operator<<(ostream& os, const VideoMode& vm) diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index e3116080f..af85bcc49 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -37,7 +37,6 @@ Settings::Settings() setPermanent("video", ""); setPermanent("speed", "1.0"); setPermanent("vsync", "true"); - setPermanent("fullscreen", "false"); setPermanent("center", "false"); setPermanent("palette", "standard"); setPermanent("uimessages", "true"); @@ -47,7 +46,9 @@ Settings::Settings() setPermanent("tia.inter", "false"); setPermanent("tia.aspectn", "100"); setPermanent("tia.aspectp", "100"); + setPermanent("fullscreen", "false"); setPermanent("tia.fs_stretch", "false"); + setPermanent("tia.fs_overscan", "0"); setPermanent("tia.dbgcolors", "roygpb"); // TV filtering options @@ -393,6 +394,7 @@ void Settings::usage() const << " -tia.aspectp Scale TIA width by the given percentage in PAL\n" << " mode\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" << " for description)\n" << endl diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx index 5598e55d0..e2f9edc58 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -180,7 +180,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, ypos = VBORDER; // Fullscreen - myFullscreen = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fullscreen"); + myFullscreen = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fullscreen", kFullScreenChanged); wid.push_back(myFullscreen); ypos += lineHeight + VGAP; @@ -191,8 +191,16 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, ypos += lineHeight + VGAP;*/ // FS stretch - myUseStretch = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fullscreen stretch"); + myUseStretch = new CheckboxWidget(myTab, font, xpos + INDENT, ypos + 1, "Stretch"); wid.push_back(myUseStretch); + ypos += lineHeight + VGAP; + + // FS overscan + myUseOverscan = new SliderWidget(myTab, font, xpos + INDENT, ypos - 1, swidth, lineHeight, + "Overscan", font.getStringWidth("Overscan "), kOverscanChanged, fontWidth * 3, "%"); + myUseOverscan->setMinValue(0); myUseOverscan->setMaxValue(10); + myUseOverscan->setTickmarkInterval(2); + wid.push_back(myUseOverscan); ypos += (lineHeight + VGAP) * 2; // Skip progress load bars for SuperCharger ROMs @@ -359,9 +367,10 @@ void VideoDialog::loadConfig() myFullscreen->setState(instance().settings().getBool("fullscreen")); /*string mode = instance().settings().getString("fullscreenmode"); myFullScreenMode->setSelected(mode);*/ - // Fullscreen stretch setting myUseStretch->setState(instance().settings().getBool("tia.fs_stretch")); + // Fullscreen overscan setting + myUseOverscan->setValue(instance().settings().getInt("tia.fs_overscan")); // Use sync to vertical blank myUseVSync->setState(instance().settings().getBool("vsync")); @@ -433,6 +442,8 @@ void VideoDialog::saveConfig() myFullScreenMode->getSelectedTag().toString());*/ // Fullscreen stretch setting instance().settings().setValue("tia.fs_stretch", myUseStretch->getState()); + // Fullscreen overscan + instance().settings().setValue("tia.fs_overscan", myUseOverscan->getValueLabel()); // Use sync to vertical blank instance().settings().setValue("vsync", myUseVSync->getState()); @@ -570,6 +581,26 @@ void VideoDialog::loadTVAdjustables(NTSCFilter::Preset preset) myTVGamma->setValue(adj.gamma); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoDialog::handleFullScreenChange() +{ + bool enable = myFullscreen->getState(); + myUseStretch->setEnabled(enable); + myUseOverscan->setEnabled(enable); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoDialog::handleOverscanChange() +{ + if (myUseOverscan->getValue() == 0) + { + myUseOverscan->setValueLabel("Off"); + myUseOverscan->setValueUnit(""); + } + else + myUseOverscan->setValueUnit("%"); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void VideoDialog::handlePhosphorChange() { @@ -595,6 +626,14 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd, mySpeed->setValueLabel(formatSpeed(mySpeed->getValue())); break; + case kFullScreenChanged: + handleFullScreenChange(); + break; + + case kOverscanChanged: + handleOverscanChange(); + break; + case kTVModeChanged: handleTVModeChange(NTSCFilter::Preset(myTVMode->getSelectedTag().toInt())); break; diff --git a/src/gui/VideoDialog.hxx b/src/gui/VideoDialog.hxx index be05d89ab..f141f9aaf 100644 --- a/src/gui/VideoDialog.hxx +++ b/src/gui/VideoDialog.hxx @@ -45,6 +45,8 @@ class VideoDialog : public Dialog void handleTVModeChange(NTSCFilter::Preset); void loadTVAdjustables(NTSCFilter::Preset preset); + void handleFullScreenChange(); + void handleOverscanChange(); void handlePhosphorChange(); void handleCommand(CommandSender* sender, int cmd, int data, int id) override; @@ -63,6 +65,7 @@ class VideoDialog : public Dialog CheckboxWidget* myFullscreen; //PopUpWidget* myFullScreenMode; CheckboxWidget* myUseStretch; + SliderWidget* myUseOverscan; CheckboxWidget* myUseVSync; CheckboxWidget* myUIMessages; CheckboxWidget* myCenter; @@ -99,6 +102,8 @@ class VideoDialog : public Dialog enum { kSpeedupChanged = 'VDSp', + kFullScreenChanged = 'VDFs', + kOverscanChanged = 'VDOv', kTVModeChanged = 'VDtv', kCloneCompositeCmd = 'CLcp',