diff --git a/Changes.txt b/Changes.txt index 295b15b79..4565a97fe 100644 --- a/Changes.txt +++ b/Changes.txt @@ -12,6 +12,19 @@ Release History =========================================================================== +6.5.2 to 6.5.3 (XXX, 2021) + + * Improved support of multiple monitors with different resolutions. + + * Improved analog input reading (Paddles, Keyboards...). + + * Fixed QuadTari handling for controller types other than Joysticks. + + * Fixed immediate disassembling when switching options in debugger. + +-Have fun! + + 6.5.1 to 6.5.2 (February 25, 2021) * Fixed broken Driving Controller support for Stelladaptor/2600-daptor @@ -23,8 +36,6 @@ * Added CPU usage stats to ARM cart classes debug widgets. --Have fun! - 6.5 to 6.5.1 (January 24, 2021) diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index 29f73a705..ceb48daab 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -91,7 +91,7 @@ Debugger::~Debugger() void Debugger::initialize() { mySize = myOSystem.settings().getSize("dbg.res"); - const Common::Size& d = myOSystem.frameBuffer().desktopSize(); + const Common::Size& d = myOSystem.frameBuffer().desktopSize(BufferType::Debugger); // The debugger dialog is resizable, within certain bounds // We check those bounds now diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index 750ecc517..14137b0ff 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -77,47 +77,45 @@ void FrameBuffer::initialize() myBackend = MediaFactory::createVideoBackend(myOSystem); // Get desktop resolution and supported renderers - vector windowedDisplays; - myBackend->queryHardware(myFullscreenDisplays, windowedDisplays, myRenderers); - uInt32 query_w = windowedDisplays[0].w, query_h = windowedDisplays[0].h; + myBackend->queryHardware(myFullscreenDisplays, myWindowedDisplays, myRenderers); - // Check the 'maxres' setting, which is an undocumented developer feature - // that specifies the desktop size (not normally set) - const Common::Size& s = myOSystem.settings().getSize("maxres"); - if(s.valid()) + int numDisplays = int(myWindowedDisplays.size()); + + for(int display = 0; display < numDisplays; ++display) { - query_w = s.w; - query_h = s.h; - } - // Various parts of the codebase assume a minimum screen size - myAbsDesktopSize.w = std::max(query_w, FBMinimum::Width); - myAbsDesktopSize.h = std::max(query_h, FBMinimum::Height); - myDesktopSize = myAbsDesktopSize; + uInt32 query_w = myWindowedDisplays[display].w, query_h = myWindowedDisplays[display].h; - // Check for HiDPI mode (is it activated, and can we use it?) - myHiDPIAllowed = ((myAbsDesktopSize.w / 2) >= FBMinimum::Width) && - ((myAbsDesktopSize.h / 2) >= FBMinimum::Height); - myHiDPIEnabled = myHiDPIAllowed && myOSystem.settings().getBool("hidpi"); + // Check the 'maxres' setting, which is an undocumented developer feature + // that specifies the desktop size (not normally set) + const Common::Size& s = myOSystem.settings().getSize("maxres"); + if(s.valid()) + { + query_w = s.w; + query_h = s.h; + } + // Various parts of the codebase assume a minimum screen size + Common::Size size(std::max(query_w, FBMinimum::Width), std::max(query_h, FBMinimum::Height)); + myAbsDesktopSize.push_back(size); - // In HiDPI mode, the desktop resolution is essentially halved - // Later, the output is scaled and rendered in 2x mode - if(hidpiEnabled()) - { - myDesktopSize.w = myAbsDesktopSize.w / hidpiScaleFactor(); - myDesktopSize.h = myAbsDesktopSize.h / hidpiScaleFactor(); + // Check for HiDPI mode (is it activated, and can we use it?) + myHiDPIAllowed.push_back(((myAbsDesktopSize[display].w / 2) >= FBMinimum::Width) && + ((myAbsDesktopSize[display].h / 2) >= FBMinimum::Height)); + myHiDPIEnabled.push_back(myHiDPIAllowed.back() && myOSystem.settings().getBool("hidpi")); + + // In HiDPI mode, the desktop resolution is essentially halved + // Later, the output is scaled and rendered in 2x mode + if(myHiDPIEnabled.back()) + { + size.w = myAbsDesktopSize[display].w / hidpiScaleFactor(); + size.h = myAbsDesktopSize[display].h / hidpiScaleFactor(); + } + myDesktopSize.push_back(size); } #ifdef GUI_SUPPORT setupFonts(); #endif - // Determine possible TIA windowed zoom levels - myTIAMaxZoom = maxWindowZoom(TIAConstants::viewableWidth, - TIAConstants::viewableHeight); - float currentTIAZoom = myOSystem.settings().getFloat("tia.zoom"); - myOSystem.settings().setValue("tia.zoom", - BSPF::clampw(currentTIAZoom, supportedTIAMinZoom(), myTIAMaxZoom)); - setUIPalette(); myGrabMouse = myOSystem.settings().getBool("grabmouse"); @@ -126,6 +124,20 @@ void FrameBuffer::initialize() myTIASurface = make_unique(myOSystem); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const int FrameBuffer::displayId(BufferType bufferType) const +{ + const int maxDisplay = int(myWindowedDisplays.size()) - 1; + int display; + + if(bufferType == myBufferType) + display = myBackend->getCurrentDisplayIndex(); + else + display = myOSystem.settings().getInt(getDisplayKey(bufferType)); + + return std::min(std::max(0, display), maxDisplay); +} + #ifdef GUI_SUPPORT // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FrameBuffer::setupFonts() @@ -218,6 +230,10 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type, ++myInitializedCount; myBackend->setTitle(title); + // Always save, maybe only the mode of the window has changed + saveCurrentWindowPosition(); + myBufferType = type; + // In HiDPI mode, all created displays must be scaled appropriately if(honourHiDPI && hidpiEnabled()) { @@ -235,22 +251,32 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type, // If the WINDOWED_SUPPORT macro is defined, we treat the system as the // former type; if not, as the latter type + int display = displayId(); #ifdef WINDOWED_SUPPORT // We assume that a desktop of at least minimum acceptable size means that // we're running on a 'large' system, and the window size requirements // can be relaxed // Otherwise, we treat the system as if WINDOWED_SUPPORT is not defined - if(myDesktopSize.w < FBMinimum::Width && myDesktopSize.h < FBMinimum::Height && - size > myDesktopSize) + if(myDesktopSize[display].w < FBMinimum::Width && + myDesktopSize[display].h < FBMinimum::Height && + size > myDesktopSize[display]) return FBInitStatus::FailTooLarge; #else // Make sure this mode is even possible // We only really need to worry about it in non-windowed environments, // where requesting a window that's too large will probably cause a crash - if(size > myDesktopSize) + if(size > myDesktopSize[display]) return FBInitStatus::FailTooLarge; #endif + if(myBufferType == BufferType::Emulator) + { + // Determine possible TIA windowed zoom levels + float currentTIAZoom = myOSystem.settings().getFloat("tia.zoom"); + myOSystem.settings().setValue("tia.zoom", + BSPF::clampw(currentTIAZoom, supportedTIAMinZoom(), supportedTIAMaxZoom())); + } + #ifdef GUI_SUPPORT // TODO: put message stuff in its own class // Erase any messages from a previous run myMsg.enabled = false; @@ -282,10 +308,6 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type, // appropriate for the requested image size myVidModeHandler.setImageSize(size); - // Always save, maybe only the mode of the window has changed - saveCurrentWindowPosition(); - myBufferType = type; - // Initialize video subsystem string pre_about = myBackend->about(); FBInitStatus status = applyVideoMode(); @@ -979,10 +1001,13 @@ void FrameBuffer::stateChanged(EventHandlerState state) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string FrameBuffer::getDisplayKey() const +string FrameBuffer::getDisplayKey(BufferType bufferType) const { + if(bufferType == BufferType::None) + bufferType = myBufferType; + // save current window's display and position - switch(myBufferType) + switch(bufferType) { case BufferType::Launcher: return "launcherdisplay"; @@ -1192,7 +1217,7 @@ void FrameBuffer::switchVideoMode(int direction) else if(direction == -1) zoom -= ZOOM_STEPS; // Make sure the level is within the allowable desktop size - zoom = BSPF::clampw(zoom, supportedTIAMinZoom(), myTIAMaxZoom); + zoom = BSPF::clampw(zoom, supportedTIAMinZoom(), supportedTIAMaxZoom()); myOSystem.settings().setValue("tia.zoom", zoom); } else @@ -1213,7 +1238,7 @@ void FrameBuffer::switchVideoMode(int direction) showTextMessage(myActiveVidMode.description); else showGaugeMessage("Zoom", myActiveVidMode.description, myActiveVidMode.zoom, - supportedTIAMinZoom(), myTIAMaxZoom); + supportedTIAMinZoom(), supportedTIAMaxZoom()); } } @@ -1222,13 +1247,12 @@ FBInitStatus FrameBuffer::applyVideoMode() { // Update display size, in case windowed/fullscreen mode has changed const Settings& s = myOSystem.settings(); + int display = displayId(); + if(s.getBool("fullscreen")) - { - Int32 fsIndex = std::max(myBackend->getCurrentDisplayIndex(), 0); - myVidModeHandler.setDisplaySize(myFullscreenDisplays[fsIndex], fsIndex); - } + myVidModeHandler.setDisplaySize(myFullscreenDisplays[display], display); else - myVidModeHandler.setDisplaySize(myAbsDesktopSize); + myVidModeHandler.setDisplaySize(myAbsDesktopSize[display]); const bool inTIAMode = myOSystem.eventHandler().inTIAMode(); @@ -1279,16 +1303,18 @@ FBInitStatus FrameBuffer::applyVideoMode() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -float FrameBuffer::maxWindowZoom(uInt32 baseWidth, uInt32 baseHeight) const +float FrameBuffer::maxWindowZoom() const { + int display = displayId(BufferType::Emulator); float multiplier = 1; + for(;;) { // Figure out the zoomed size of the window - uInt32 width = baseWidth * multiplier; - uInt32 height = baseHeight * multiplier; + uInt32 width = TIAConstants::viewableWidth * multiplier; + uInt32 height = TIAConstants::viewableHeight * multiplier; - if((width > myAbsDesktopSize.w) || (height > myAbsDesktopSize.h)) + if((width > myAbsDesktopSize[display].w) || (height > myAbsDesktopSize[display].h)) break; multiplier += ZOOM_STEPS; diff --git a/src/emucore/FrameBuffer.hxx b/src/emucore/FrameBuffer.hxx index 90dfafe22..2e7c6b438 100644 --- a/src/emucore/FrameBuffer.hxx +++ b/src/emucore/FrameBuffer.hxx @@ -194,9 +194,11 @@ class FrameBuffer const Common::Rect& screenRect() const { return myActiveVidMode.screenR; } /** - Returns the current dimensions of the users' desktop. + Returns the dimensions of the mode specific users' desktop. */ - const Common::Size& desktopSize() const { return myDesktopSize; } + const Common::Size& desktopSize(BufferType bufferType) const { + return myDesktopSize[displayId(bufferType)]; + } /** Get the supported renderers for the video hardware. @@ -210,7 +212,7 @@ class FrameBuffer for the framebuffer. */ float supportedTIAMinZoom() const { return myTIAMinZoom * hidpiScaleFactor(); } - float supportedTIAMaxZoom() const { return myTIAMaxZoom; } + float supportedTIAMaxZoom() const { return maxWindowZoom(); } /** Get the TIA surface associated with the framebuffer. @@ -281,14 +283,14 @@ class FrameBuffer Answer whether hidpi mode is allowed. In this mode, all FBSurfaces are scaled to 2x normal size. */ - bool hidpiAllowed() const { return myHiDPIAllowed; } + bool hidpiAllowed() const { return myHiDPIAllowed[displayId()]; } /** Answer whether hidpi mode is enabled. In this mode, all FBSurfaces are scaled to 2x normal size. */ - bool hidpiEnabled() const { return myHiDPIEnabled; } - uInt32 hidpiScaleFactor() const { return myHiDPIEnabled ? 2 : 1; } + bool hidpiEnabled() const { return myHiDPIEnabled[displayId()]; } + uInt32 hidpiScaleFactor() const { return myHiDPIEnabled[displayId()] ? 2 : 1; } /** This method should be called to save the current settings of all @@ -381,7 +383,7 @@ class FrameBuffer current window. */ string getPositionKey() const; - string getDisplayKey() const; + string getDisplayKey(BufferType bufferType = BufferType::None) const; void saveCurrentWindowPosition() const; /** @@ -418,6 +420,12 @@ class FrameBuffer */ void drawFrameStats(float framesPerSecond); + + /** + Get the display used for the current mode. + */ + const int displayId(BufferType bufferType = BufferType::None) const; + /** Build an applicable video mode based on the current settings in effect, whether TIA mode is active, etc. Then tell the backend @@ -431,7 +439,7 @@ class FrameBuffer Calculate the maximum level by which the base window can be zoomed and still fit in the desktop screen. */ - float maxWindowZoom(uInt32 baseWidth, uInt32 baseHeight) const; + float maxWindowZoom() const; /** Enables/disables fullscreen mode. @@ -461,16 +469,19 @@ class FrameBuffer // Maximum dimensions of the desktop area // Note that this takes 'hidpi' mode into account, so in some cases // it will be less than the absolute desktop size - Common::Size myDesktopSize; + vector myDesktopSize; // Maximum absolute dimensions of the desktop area - Common::Size myAbsDesktopSize; + vector myAbsDesktopSize; // The resolution of the attached displays in fullscreen mode // The primary display is typically the first in the array // Windowed modes use myDesktopSize directly vector myFullscreenDisplays; + // The resolution of the attached displays in windowed mode + vector myWindowedDisplays; + // Supported renderers VariantList myRenderers; @@ -523,13 +534,11 @@ class FrameBuffer uInt32 myLastScanlines{0}; bool myGrabMouse{false}; - bool myHiDPIAllowed{false}; - bool myHiDPIEnabled{false}; + vector myHiDPIAllowed{false}; + vector myHiDPIEnabled{false}; // Minimum TIA zoom level that can be used for this framebuffer float myTIAMinZoom{2.F}; - // Maximum TIA zoom level that can be used for this framebuffer - float myTIAMaxZoom{1.F}; // Maximum message width [chars] static constexpr int MESSAGE_WIDTH = 56; diff --git a/src/gui/DeveloperDialog.cxx b/src/gui/DeveloperDialog.cxx index 3d7068490..fd5c33154 100644 --- a/src/gui/DeveloperDialog.cxx +++ b/src/gui/DeveloperDialog.cxx @@ -567,7 +567,7 @@ void DeveloperDialog::addDebuggerTab(const GUI::Font& font) VGAP = Dialog::vGap(); VariantList items; int xpos, ypos, pwidth; - const Common::Size& ds = instance().frameBuffer().desktopSize(); + const Common::Size& ds = instance().frameBuffer().desktopSize(BufferType::Debugger); xpos = HBORDER; ypos = VBORDER; @@ -1071,8 +1071,10 @@ void DeveloperDialog::setDefaults() case 4: // Debugger options { #ifdef DEBUGGER_SUPPORT - uInt32 w = std::min(instance().frameBuffer().desktopSize().w, uInt32(DebuggerDialog::kMediumFontMinW)); - uInt32 h = std::min(instance().frameBuffer().desktopSize().h, uInt32(DebuggerDialog::kMediumFontMinH)); + const Common::Size& size = instance().frameBuffer().desktopSize(BufferType::Debugger); + + uInt32 w = std::min(size.w, uInt32(DebuggerDialog::kMediumFontMinW)); + uInt32 h = std::min(size.h, uInt32(DebuggerDialog::kMediumFontMinH)); myDebuggerWidthSlider->setValue(w); myDebuggerHeightSlider->setValue(h); myDebuggerFontSize->setSelected("medium"); @@ -1548,8 +1550,9 @@ void DeveloperDialog::handleFontSize() minW = DebuggerDialog::kLargeFontMinW; minH = DebuggerDialog::kLargeFontMinH; } - minW = std::min(instance().frameBuffer().desktopSize().w, minW); - minH = std::min(instance().frameBuffer().desktopSize().h, minH); + const Common::Size& size = instance().frameBuffer().desktopSize(BufferType::Debugger); + minW = std::min(size.w, minW); + minH = std::min(size.h, minH); myDebuggerWidthSlider->setMinValue(minW); if(minW > uInt32(myDebuggerWidthSlider->getValue())) diff --git a/src/gui/Launcher.cxx b/src/gui/Launcher.cxx index 90d5c2309..befb08d72 100644 --- a/src/gui/Launcher.cxx +++ b/src/gui/Launcher.cxx @@ -30,7 +30,7 @@ Launcher::Launcher(OSystem& osystem) : DialogContainer(osystem), mySize{myOSystem.settings().getSize("launcherres")} { - const Common::Size& d = myOSystem.frameBuffer().desktopSize(); + const Common::Size& d = myOSystem.frameBuffer().desktopSize(BufferType::Launcher); double overscan = 1 - myOSystem.settings().getInt("tia.fs_overscan") / 100.0; // The launcher dialog is resizable, within certain bounds diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 5f00fccc2..0525606b8 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -57,7 +57,7 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, int lwidth, pwidth, bwidth; WidgetArray wid; VariantList items; - const Common::Size& ds = instance().frameBuffer().desktopSize(); + const Common::Size& ds = instance().frameBuffer().desktopSize(BufferType::Launcher); // Set real dimensions setSize(64 * fontWidth + HBORDER * 2, @@ -326,12 +326,13 @@ void UIDialog::loadConfig() // Launcher size const Common::Size& ls = settings.getSize("launcherres"); + const Common::Size& ds = instance().frameBuffer().desktopSize(BufferType::Launcher); uInt32 w = ls.w, h = ls.h; w = std::max(w, FBMinimum::Width); h = std::max(h, FBMinimum::Height); - w = std::min(w, instance().frameBuffer().desktopSize().w); - h = std::min(h, instance().frameBuffer().desktopSize().h); + w = std::min(w, ds.w); + h = std::min(h, ds.h); myLauncherWidthSlider->setValue(w); myLauncherHeightSlider->setValue(h); @@ -501,9 +502,11 @@ void UIDialog::setDefaults() case 1: // Launcher options { FilesystemNode node("~"); + const Common::Size& size = instance().frameBuffer().desktopSize(BufferType::Launcher); + myRomPath->setText(node.getShortPath()); - uInt32 w = std::min(instance().frameBuffer().desktopSize().w, 900); - uInt32 h = std::min(instance().frameBuffer().desktopSize().h, 600); + uInt32 w = std::min(size.w, 900); + uInt32 h = std::min(size.h, 600); myLauncherWidthSlider->setValue(w); myLauncherHeightSlider->setValue(h); myLauncherFontPopup->setSelected("medium", ""); @@ -612,7 +615,7 @@ void UIDialog::handleLauncherSize() FontDesc fd = instance().frameBuffer().getFontDesc(myDialogFontPopup->getSelectedTag().toString()); int w = std::max(FBMinimum::Width, FBMinimum::Width * fd.maxwidth / GUI::stellaMediumDesc.maxwidth); int h = std::max(FBMinimum::Height, FBMinimum::Height * fd.height / GUI::stellaMediumDesc.height); - const Common::Size& ds = instance().frameBuffer().desktopSize(); + const Common::Size& ds = instance().frameBuffer().desktopSize(BufferType::Launcher); myLauncherWidthSlider->setMinValue(w); if(myLauncherWidthSlider->getValue() < myLauncherWidthSlider->getMinValue())