From 7af270aa5998d365ceb7b947c0fd91470906cca2 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Thu, 6 Jul 2017 18:29:12 +1000 Subject: [PATCH] Update to v103r09 release. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit byuu says: Changelog: - gba/apu: fixed wave RAM nibble ordering (fixes audio in Castlevania, PocketNES) - emulator: restructured video information to just a single videoResolution() → VideoResolution function - returns "projected size" (between 160x144 and 320x240) - "internal buffer size" (up to 1280x480) - returns aspect correction multiplier that is to be applied to the width field - the value could be < 1.0 to handle systems with taller pixels; although higan doesn't emulate such a system - tomoko: all calculations for scaling and overscan masking are done by the GUI now - tomoko: aspect correction can be enabled in either windowed or fullscreen mode separately; moved to Video settings panel - tomoko: video scaling multipliers (against 320x240) can now me modified from the default (2,3,4) via the configuration file - use this as a really barebones way of supporting high DPI monitors; although the GUI elements won't scale nicely - if you set a value less than two, or greater than your resolution divided by 320x240, it's your own fault when things blow up. I'm not babysitting anyone with advanced config-file only options. - tomoko: added new adaptive windowed mode - when enabled, the window will shrink to eliminate any black borders when loading a game or changing video settings. The window will not reposition itself. - tomoko: added new adaptive fullscreen mode - when enabled, the integral scaling will be disabled for fullscreen mode, forcing the video to fill at least one direction of the video monitor completely. I expect we will be bikeshedding for the next month on how to describe the new video options, where they should appear in the GUI, changes people want, etc ... but suffice to say, I'm happy with the functionality, so I don't intend to make changes to -what- things do, but I will entertain better ways to name things. --- higan/emulator/emulator.hpp | 2 +- higan/emulator/interface.hpp | 12 ++- higan/fc/interface/interface.cpp | 17 +--- higan/fc/interface/interface.hpp | 4 +- higan/gb/interface/interface.cpp | 11 +-- higan/gb/interface/interface.hpp | 3 +- higan/gba/apu/wave.cpp | 8 +- higan/gba/interface/interface.cpp | 13 +-- higan/gba/interface/interface.hpp | 3 +- higan/md/interface/interface.cpp | 19 +--- higan/md/interface/interface.hpp | 4 +- higan/ms/interface/game-gear.cpp | 11 +-- higan/ms/interface/interface.hpp | 7 +- higan/ms/interface/master-system.cpp | 17 +--- higan/pce/interface/interface.cpp | 18 +--- higan/pce/interface/interface.hpp | 4 +- higan/sfc/interface/interface.cpp | 19 +--- higan/sfc/interface/interface.hpp | 4 +- .../configuration/configuration.cpp | 12 ++- .../presentation/presentation.cpp | 92 +++++++++++-------- .../presentation/presentation.hpp | 2 - higan/target-tomoko/program/interface.cpp | 11 ++- higan/target-tomoko/settings/settings.hpp | 17 +++- higan/target-tomoko/settings/video.cpp | 17 ++++ higan/ws/interface/interface.cpp | 13 +-- higan/ws/interface/interface.hpp | 3 +- 26 files changed, 146 insertions(+), 197 deletions(-) diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 04cc680e..fa27d877 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "103.08"; + static const string Version = "103.09"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/emulator/interface.hpp b/higan/emulator/interface.hpp index 51d69d2c..17645885 100644 --- a/higan/emulator/interface.hpp +++ b/higan/emulator/interface.hpp @@ -43,10 +43,14 @@ struct Interface { virtual auto title() -> string = 0; //video information - struct VideoSize { uint width, height; }; - virtual auto videoResolution() -> VideoSize = 0; - virtual auto videoSize(uint width, uint height, bool aspectCorrection, uint cropWidth = 0, uint cropHeight = 0) -> VideoSize = 0; - virtual auto videoCrop(const uint32*& data, uint& width, uint& height, uint cropWidth, uint cropHeight) -> void {} + struct VideoResolution { + uint width; + uint height; + uint internalWidth; + uint internalHeight; + double aspectCorrection; + }; + virtual auto videoResolution() -> VideoResolution = 0; virtual auto videoColors() -> uint32 = 0; virtual auto videoColor(uint32 color) -> uint64 = 0; diff --git a/higan/fc/interface/interface.cpp b/higan/fc/interface/interface.cpp index 20fc4683..7af4e9a5 100644 --- a/higan/fc/interface/interface.cpp +++ b/higan/fc/interface/interface.cpp @@ -44,21 +44,8 @@ auto Interface::title() -> string { return cartridge.title(); } -auto Interface::videoResolution() -> VideoSize { - return {256, 240}; -} - -auto Interface::videoSize(uint width, uint height, bool aspectCorrection, uint cropHorizontal, uint cropVertical) -> VideoSize { - double widthDivider = (256 - cropHorizontal * 2) * (aspectCorrection ? 8.0 / 7.0 : 1.0); - double heightDivider = (240 - cropVertical * 2); - uint multiplier = min(width / widthDivider, height / heightDivider); - return {uint(widthDivider * multiplier), uint(heightDivider * multiplier)}; -} - -auto Interface::videoCrop(const uint32*& data, uint& width, uint& height, uint cropHorizontal, uint cropVertical) -> void { - data += cropVertical * 256 + cropHorizontal; - width -= cropHorizontal * 2; - height -= cropVertical * 2; +auto Interface::videoResolution() -> VideoResolution { + return {256, 240, 256, 240, 8.0 / 7.0}; } auto Interface::videoColors() -> uint32 { diff --git a/higan/fc/interface/interface.hpp b/higan/fc/interface/interface.hpp index 08df5b9f..3ce8110e 100644 --- a/higan/fc/interface/interface.hpp +++ b/higan/fc/interface/interface.hpp @@ -26,9 +26,7 @@ struct Interface : Emulator::Interface { auto manifest() -> string override; auto title() -> string override; - auto videoResolution() -> VideoSize override; - auto videoSize(uint width, uint height, bool aspectCorrection, uint cropHorizontal, uint cropVertical) -> VideoSize override; - auto videoCrop(const uint32*& data, uint& width, uint& height, uint cropHorizontal, uint cropVertical) -> void override; + auto videoResolution() -> VideoResolution override; auto videoColors() -> uint32 override; auto videoColor(uint32 color) -> uint64 override; diff --git a/higan/gb/interface/interface.cpp b/higan/gb/interface/interface.cpp index 864a3c0b..8a85971b 100644 --- a/higan/gb/interface/interface.cpp +++ b/higan/gb/interface/interface.cpp @@ -33,15 +33,8 @@ auto Interface::title() -> string { return cartridge.title(); } -auto Interface::videoResolution() -> VideoSize { - return {160, 144}; -} - -auto Interface::videoSize(uint width, uint height, bool, uint, uint) -> VideoSize { - double widthDivider = 160; - double heightDivider = 144; - uint multiplier = min(width / widthDivider, height / heightDivider); - return {uint(widthDivider * multiplier), uint(heightDivider * multiplier)}; +auto Interface::videoResolution() -> VideoResolution { + return {160, 144, 160, 144, 1.0}; } auto Interface::loaded() -> bool { diff --git a/higan/gb/interface/interface.hpp b/higan/gb/interface/interface.hpp index 6a243ef6..9da3820e 100644 --- a/higan/gb/interface/interface.hpp +++ b/higan/gb/interface/interface.hpp @@ -23,8 +23,7 @@ struct Interface : Emulator::Interface { auto manifest() -> string override; auto title() -> string override; - auto videoResolution() -> VideoSize override; - auto videoSize(uint width, uint height, bool, uint, uint) -> VideoSize override; + auto videoResolution() -> VideoResolution override; auto loaded() -> bool override; auto sha256() -> string override; diff --git a/higan/gba/apu/wave.cpp b/higan/gba/apu/wave.cpp index ebfcb223..070cd88c 100644 --- a/higan/gba/apu/wave.cpp +++ b/higan/gba/apu/wave.cpp @@ -66,14 +66,14 @@ auto APU::Wave::write(uint addr, uint8 byte) -> void { auto APU::Wave::readram(uint addr) const -> uint8 { uint8 byte = 0; - byte |= pattern[!bank << 5 | addr << 1 | 0] << 0; - byte |= pattern[!bank << 5 | addr << 1 | 1] << 4; + byte |= pattern[!bank << 5 | addr << 1 | 0] << 4; + byte |= pattern[!bank << 5 | addr << 1 | 1] << 0; return byte; } auto APU::Wave::writeram(uint addr, uint8 byte) -> void { - pattern[!bank << 5 | addr << 1 | 0] = byte >> 0; - pattern[!bank << 5 | addr << 1 | 1] = byte >> 4; + pattern[!bank << 5 | addr << 1 | 0] = byte >> 4; + pattern[!bank << 5 | addr << 1 | 1] = byte >> 0; } auto APU::Wave::power() -> void { diff --git a/higan/gba/interface/interface.cpp b/higan/gba/interface/interface.cpp index 2debeb74..504c1ad3 100644 --- a/higan/gba/interface/interface.cpp +++ b/higan/gba/interface/interface.cpp @@ -39,21 +39,14 @@ auto Interface::title() -> string { return cartridge.title(); } -auto Interface::videoResolution() -> VideoSize { +auto Interface::videoResolution() -> VideoResolution { if(!settings.rotateLeft) { - return {240, 160}; + return {240, 160, 240, 160, 1.0}; } else { - return {160, 240}; + return {160, 240, 160, 240, 1.0}; } } -auto Interface::videoSize(uint width, uint height, bool, uint, uint) -> VideoSize { - double widthDivider = videoResolution().width; - double heightDivider = videoResolution().height; - uint multiplier = min(width / widthDivider, height / heightDivider); - return {uint(widthDivider * multiplier), uint(heightDivider * multiplier)}; -} - auto Interface::videoColors() -> uint32 { return 1 << 15; } diff --git a/higan/gba/interface/interface.hpp b/higan/gba/interface/interface.hpp index ab18d920..ca85e284 100644 --- a/higan/gba/interface/interface.hpp +++ b/higan/gba/interface/interface.hpp @@ -23,8 +23,7 @@ struct Interface : Emulator::Interface { auto manifest() -> string override; auto title() -> string override; - auto videoResolution() -> VideoSize override; - auto videoSize(uint width, uint height, bool, uint, uint) -> VideoSize override; + auto videoResolution() -> VideoResolution override; auto videoColors() -> uint32 override; auto videoColor(uint32 color) -> uint64 override; diff --git a/higan/md/interface/interface.cpp b/higan/md/interface/interface.cpp index 9896c208..5ed75279 100644 --- a/higan/md/interface/interface.cpp +++ b/higan/md/interface/interface.cpp @@ -52,23 +52,8 @@ auto Interface::title() -> string { return cartridge.title(); } -auto Interface::videoResolution() -> VideoSize { - return {1280, 480}; -} - -auto Interface::videoSize(uint width, uint height, bool aspectCorrection, uint cropHorizontal, uint cropVertical) -> VideoSize { - double widthDivider = (320 - cropHorizontal * 2); - double heightDivider = (240 - cropVertical * 2); - uint multiplier = min(width / widthDivider, height / heightDivider); - return {uint(widthDivider * multiplier), uint(heightDivider * multiplier)}; -} - -auto Interface::videoCrop(const uint32*& data, uint& width, uint& height, uint cropHorizontal, uint cropVertical) -> void { - cropHorizontal *= 4; - cropVertical *= 2; - data += cropVertical * 1280 + cropHorizontal; - width -= cropHorizontal * 2; - height -= cropVertical * 2; +auto Interface::videoResolution() -> VideoResolution { + return {320, 240, 1280, 480, 1.0}; } auto Interface::videoColors() -> uint32 { diff --git a/higan/md/interface/interface.hpp b/higan/md/interface/interface.hpp index 3dc386fb..664af71a 100644 --- a/higan/md/interface/interface.hpp +++ b/higan/md/interface/interface.hpp @@ -26,9 +26,7 @@ struct Interface : Emulator::Interface { auto manifest() -> string override; auto title() -> string override; - auto videoResolution() -> VideoSize override; - auto videoSize(uint width, uint height, bool aspectCorrection, uint cropHorizontal, uint cropVertical) -> VideoSize override; - auto videoCrop(const uint32*& data, uint& width, uint& height, uint cropHorizontal, uint cropVertical) -> void override; + auto videoResolution() -> VideoResolution override; auto videoColors() -> uint32 override; auto videoColor(uint32 color) -> uint64 override; diff --git a/higan/ms/interface/game-gear.cpp b/higan/ms/interface/game-gear.cpp index c452f259..fdb2a01d 100644 --- a/higan/ms/interface/game-gear.cpp +++ b/higan/ms/interface/game-gear.cpp @@ -21,15 +21,8 @@ GameGearInterface::GameGearInterface() { ports.append(move(hardware)); } -auto GameGearInterface::videoResolution() -> VideoSize { - return {160, 144}; -} - -auto GameGearInterface::videoSize(uint width, uint height, bool, uint, uint) -> VideoSize { - double widthDivider = 160; - double heightDivider = 144; - uint multiplier = min(width / widthDivider, height / heightDivider); - return {uint(widthDivider * multiplier), uint(heightDivider * multiplier)}; +auto GameGearInterface::videoResolution() -> VideoResolution { + return {160, 144, 160, 144, 1.0}; } auto GameGearInterface::videoColors() -> uint32 { diff --git a/higan/ms/interface/interface.hpp b/higan/ms/interface/interface.hpp index 30d9ac24..998cfc0f 100644 --- a/higan/ms/interface/interface.hpp +++ b/higan/ms/interface/interface.hpp @@ -50,9 +50,7 @@ struct MasterSystemInterface : Interface { MasterSystemInterface(); - auto videoResolution() -> VideoSize override; - auto videoSize(uint width, uint height, bool aspectCorrection, uint cropWidth, uint cropHeight) -> VideoSize override; - auto videoCrop(const uint32*& data, uint& width, uint& height, uint cropWidth, uint cropHeight) -> void override; + auto videoResolution() -> VideoResolution override; auto videoColors() -> uint32 override; auto videoColor(uint32 color) -> uint64 override; @@ -66,8 +64,7 @@ struct GameGearInterface : Interface { GameGearInterface(); - auto videoResolution() -> VideoSize override; - auto videoSize(uint width, uint height, bool, uint, uint) -> VideoSize override; + auto videoResolution() -> VideoResolution override; auto videoColors() -> uint32 override; auto videoColor(uint32 color) -> uint64 override; diff --git a/higan/ms/interface/master-system.cpp b/higan/ms/interface/master-system.cpp index 001ace55..6b0529a0 100644 --- a/higan/ms/interface/master-system.cpp +++ b/higan/ms/interface/master-system.cpp @@ -36,21 +36,8 @@ MasterSystemInterface::MasterSystemInterface() { ports.append(move(controllerPort2)); } -auto MasterSystemInterface::videoResolution() -> VideoSize { - return {256, 240}; -} - -auto MasterSystemInterface::videoSize(uint width, uint height, bool aspectCorrection, uint cropHorizontal, uint cropVertical) -> VideoSize { - double widthDivider = (256 - cropHorizontal * 2) * (aspectCorrection ? 8.0 / 7.0 : 1.0); - double heightDivider = (240 - cropVertical * 2); - uint multiplier = min(width / widthDivider, height / heightDivider); - return {uint(widthDivider * multiplier), uint(heightDivider * multiplier)}; -} - -auto MasterSystemInterface::videoCrop(const uint32*& data, uint& width, uint& height, uint cropHorizontal, uint cropVertical) -> void { - data += cropVertical * 256 + cropHorizontal; - width -= cropHorizontal * 2; - height -= cropVertical * 2; +auto MasterSystemInterface::videoResolution() -> VideoResolution { + return {256, 240, 256, 240, 8.0 / 7.0}; } auto MasterSystemInterface::videoColors() -> uint32 { diff --git a/higan/pce/interface/interface.cpp b/higan/pce/interface/interface.cpp index 080fbbe8..5de84f22 100644 --- a/higan/pce/interface/interface.cpp +++ b/higan/pce/interface/interface.cpp @@ -39,22 +39,8 @@ auto Interface::title() -> string { return cartridge.title(); } -auto Interface::videoResolution() -> VideoSize { - return {1120, 240}; -} - -auto Interface::videoSize(uint width, uint height, bool aspectCorrection, uint cropHorizontal, uint cropVertical) -> VideoSize { - double widthDivider = (280 - cropHorizontal * 2) * (aspectCorrection ? 8.0 / 7.0 : 1.0); - double heightDivider = (240 - cropVertical * 2); - uint multiplier = min(width / widthDivider, height / heightDivider); - return {uint(widthDivider * multiplier), uint(heightDivider * multiplier)}; -} - -auto Interface::videoCrop(const uint32*& data, uint& width, uint& height, uint cropHorizontal, uint cropVertical) -> void { - cropHorizontal *= 4; - data += cropVertical * 1120 + cropHorizontal; - width -= cropHorizontal * 2; - height -= cropVertical * 2; +auto Interface::videoResolution() -> VideoResolution { + return {280, 240, 1120, 240, 8.0 / 7.0}; } auto Interface::videoColors() -> uint32 { diff --git a/higan/pce/interface/interface.hpp b/higan/pce/interface/interface.hpp index 441900c4..103838ef 100644 --- a/higan/pce/interface/interface.hpp +++ b/higan/pce/interface/interface.hpp @@ -23,9 +23,7 @@ struct Interface : Emulator::Interface { auto manifest() -> string override; auto title() -> string override; - auto videoResolution() -> VideoSize override; - auto videoSize(uint width, uint height, bool aspectCorrection, uint cropHorizontal, uint cropVertical) -> VideoSize override; - auto videoCrop(const uint32*& data, uint& width, uint& height, uint cropHorizontal, uint cropVertical) -> void override; + auto videoResolution() -> VideoResolution override; auto videoColors() -> uint32 override; auto videoColor(uint32 color) -> uint64 override; diff --git a/higan/sfc/interface/interface.cpp b/higan/sfc/interface/interface.cpp index 4452efaa..a9585dc1 100644 --- a/higan/sfc/interface/interface.cpp +++ b/higan/sfc/interface/interface.cpp @@ -118,23 +118,8 @@ auto Interface::title() -> string { return cartridge.title(); } -auto Interface::videoResolution() -> VideoSize { - return {512, 480}; -} - -auto Interface::videoSize(uint width, uint height, bool aspectCorrection, uint cropHorizontal, uint cropVertical) -> VideoSize { - double widthDivider = (256 - cropHorizontal * 2) * (aspectCorrection ? 8.0 / 7.0 : 1.0); - double heightDivider = (240 - cropVertical * 2); - uint multiplier = min(width / widthDivider, height / heightDivider); - return {uint(widthDivider * multiplier), uint(heightDivider * multiplier)}; -} - -auto Interface::videoCrop(const uint32*& data, uint& width, uint& height, uint cropHorizontal, uint cropVertical) -> void { - cropHorizontal *= 2; - cropVertical *= 2; - data += cropVertical * 512 + cropHorizontal; - width -= cropHorizontal * 2; - height -= cropVertical * 2; +auto Interface::videoResolution() -> VideoResolution { + return {256, 240, 512, 480, 8.0 / 7.0}; } auto Interface::videoColors() -> uint32 { diff --git a/higan/sfc/interface/interface.hpp b/higan/sfc/interface/interface.hpp index 1a8f3358..7502a9bf 100644 --- a/higan/sfc/interface/interface.hpp +++ b/higan/sfc/interface/interface.hpp @@ -38,9 +38,7 @@ struct Interface : Emulator::Interface { auto manifest() -> string override; auto title() -> string override; - auto videoResolution() -> VideoSize override; - auto videoSize(uint width, uint height, bool aspectCorrection, uint cropWidth, uint cropHeight) -> VideoSize override; - auto videoCrop(const uint32*& data, uint& width, uint& height, uint cropWidth, uint cropHeight) -> void override; + auto videoResolution() -> VideoResolution override; auto videoColors() -> uint32 override; auto videoColor(uint32 color) -> uint64 override; diff --git a/higan/target-tomoko/configuration/configuration.cpp b/higan/target-tomoko/configuration/configuration.cpp index 980d82a8..9c4e2c06 100644 --- a/higan/target-tomoko/configuration/configuration.cpp +++ b/higan/target-tomoko/configuration/configuration.cpp @@ -16,8 +16,6 @@ Settings::Settings() { set("Video/Driver", ruby::Video::optimalDriver()); set("Video/Synchronize", false); - set("Video/Scale", "Small"); - set("Video/AspectCorrection", true); set("Video/Shader", "Blur"); set("Video/BlurEmulation", true); set("Video/ColorEmulation", true); @@ -31,6 +29,16 @@ Settings::Settings() { set("Video/Overscan/Horizontal", 8); set("Video/Overscan/Vertical", 8); + set("Video/Windowed/AspectCorrection", true); + set("Video/Windowed/Adaptive", false); + set("Video/Windowed/Multiplier", "Small"); + set("Video/Windowed/Multiplier/Small", 2); + set("Video/Windowed/Multiplier/Medium", 3); + set("Video/Windowed/Multiplier/Large", 4); + + set("Video/Fullscreen/AspectCorrection", true); + set("Video/Fullscreen/Adaptive", false); + set("Audio/Driver", ruby::Audio::optimalDriver()); set("Audio/Device", ""); set("Audio/Exclusive", false); diff --git a/higan/target-tomoko/presentation/presentation.cpp b/higan/target-tomoko/presentation/presentation.cpp index 1b50a159..5b97dafa 100644 --- a/higan/target-tomoko/presentation/presentation.cpp +++ b/higan/target-tomoko/presentation/presentation.cpp @@ -47,23 +47,19 @@ Presentation::Presentation() { settingsMenu.setText("Settings"); videoScaleMenu.setText("Video Scale"); - if(settings["Video/Scale"].text() == "Small") videoScaleSmall.setChecked(); - if(settings["Video/Scale"].text() == "Medium") videoScaleMedium.setChecked(); - if(settings["Video/Scale"].text() == "Large") videoScaleLarge.setChecked(); + if(settings["Video/Windowed/Multiplier"].text() == "Small") videoScaleSmall.setChecked(); + if(settings["Video/Windowed/Multiplier"].text() == "Medium") videoScaleMedium.setChecked(); + if(settings["Video/Windowed/Multiplier"].text() == "Large") videoScaleLarge.setChecked(); videoScaleSmall.setText("Small").onActivate([&] { - settings["Video/Scale"].setValue("Small"); + settings["Video/Windowed/Multiplier"].setValue("Small"); resizeViewport(); }); videoScaleMedium.setText("Medium").onActivate([&] { - settings["Video/Scale"].setValue("Medium"); + settings["Video/Windowed/Multiplier"].setValue("Medium"); resizeViewport(); }); videoScaleLarge.setText("Large").onActivate([&] { - settings["Video/Scale"].setValue("Large"); - resizeViewport(); - }); - aspectCorrection.setText("Aspect Correction").setChecked(settings["Video/AspectCorrection"].boolean()).onToggle([&] { - settings["Video/AspectCorrection"].setValue(aspectCorrection.checked()); + settings["Video/Windowed/Multiplier"].setValue("Large"); resizeViewport(); }); videoEmulationMenu.setText("Video Emulation"); @@ -243,35 +239,59 @@ auto Presentation::resizeViewport() -> void { //clear video area before resizing to avoid seeing distorted video momentarily clearViewport(); - uint scale = 2; - if(settings["Video/Scale"].text() == "Small" ) scale = 2; - if(settings["Video/Scale"].text() == "Medium") scale = 3; - if(settings["Video/Scale"].text() == "Large" ) scale = 4; - - uint windowWidth = 0, windowHeight = 0; - bool aspectCorrection = true; - if(!fullScreen()) { - windowWidth = 320 * scale; - windowHeight = 240 * scale; - aspectCorrection = settings["Video/AspectCorrection"].boolean(); - } else { - windowWidth = geometry().width(); - windowHeight = geometry().height(); - } - if(!fullScreen()) setSize({windowWidth, windowHeight}); - - if(!emulator) { - viewport.setGeometry({0, 0, windowWidth, windowHeight}); - } else { - uint overscanWidth = 0, overscanHeight = 0; + double emulatorWidth = 320; + double emulatorHeight = 240; + double aspectCorrection = 1.0; + if(emulator) { + auto resolution = emulator->videoResolution(); + emulatorWidth = resolution.width; + emulatorHeight = resolution.height; + aspectCorrection = resolution.aspectCorrection; if(emulator->information.overscan && settings["Video/Overscan/Mask"].boolean()) { - overscanWidth = settings["Video/Overscan/Horizontal"].natural(); - overscanHeight = settings["Video/Overscan/Vertical" ].natural(); + uint overscanHorizontal = settings["Video/Overscan/Horizontal"].natural(); + uint overscanVertical = settings["Video/Overscan/Vertical"].natural(); + emulatorWidth -= overscanHorizontal * 2; + emulatorHeight -= overscanVertical * 2; + } + } + + if(!fullScreen()) { + if(settings["Video/Windowed/AspectCorrection"].boolean()) emulatorWidth *= aspectCorrection; + uint viewportMultiplier = 2; + if(settings["Video/Windowed/Multiplier"].text() == "Small") viewportMultiplier = settings["Video/Windowed/Multiplier/Small"].natural(); + if(settings["Video/Windowed/Multiplier"].text() == "Medium") viewportMultiplier = settings["Video/Windowed/Multiplier/Medium"].natural(); + if(settings["Video/Windowed/Multiplier"].text() == "Large") viewportMultiplier = settings["Video/Windowed/Multiplier/Large"].natural(); + uint viewportWidth = 320 * viewportMultiplier; + uint viewportHeight = 240 * viewportMultiplier; + uint multiplier = min(viewportWidth / emulatorWidth, viewportHeight / emulatorHeight); + if(!settings["Video/Windowed/Adaptive"].boolean()) { + emulatorWidth *= multiplier; + emulatorHeight *= multiplier; + setSize({viewportWidth, viewportHeight}); + viewport.setGeometry({ + (viewportWidth - emulatorWidth) / 2, (viewportHeight - emulatorHeight) / 2, + emulatorWidth, emulatorHeight + }); + } else { + setSize({emulatorWidth * multiplier, emulatorHeight * multiplier}); + viewport.setGeometry({0, 0, emulatorWidth * multiplier, emulatorHeight * multiplier}); + } + } else { + if(settings["Video/Fullscreen/AspectCorrection"].boolean()) emulatorWidth *= aspectCorrection; + uint viewportWidth = geometry().width(); + uint viewportHeight = geometry().height(); + if(!settings["Video/Fullscreen/Adaptive"].boolean()) { + uint multiplier = min(viewportWidth / emulatorWidth, viewportHeight / emulatorHeight); + emulatorWidth *= multiplier; + emulatorHeight *= multiplier; + } else { + double multiplier = min(viewportWidth / emulatorWidth, viewportHeight / emulatorHeight); + emulatorWidth *= multiplier; + emulatorHeight *= multiplier; } - auto videoSize = emulator->videoSize(windowWidth, windowHeight, aspectCorrection, overscanWidth, overscanHeight); viewport.setGeometry({ - (windowWidth - videoSize.width) / 2, (windowHeight - videoSize.height) / 2, - videoSize.width, videoSize.height + (viewportWidth - emulatorWidth) / 2, (viewportHeight - emulatorHeight) / 2, + emulatorWidth, emulatorHeight }); } diff --git a/higan/target-tomoko/presentation/presentation.hpp b/higan/target-tomoko/presentation/presentation.hpp index abea4ccb..c80fd9b9 100644 --- a/higan/target-tomoko/presentation/presentation.hpp +++ b/higan/target-tomoko/presentation/presentation.hpp @@ -31,8 +31,6 @@ struct Presentation : Window { MenuRadioItem videoScaleMedium{&videoScaleMenu}; MenuRadioItem videoScaleLarge{&videoScaleMenu}; Group videoScales{&videoScaleSmall, &videoScaleMedium, &videoScaleLarge}; - MenuSeparator videoScaleSeparator{&videoScaleMenu}; - MenuCheckItem aspectCorrection{&videoScaleMenu}; Menu videoEmulationMenu{&settingsMenu}; MenuCheckItem blurEmulation{&videoEmulationMenu}; MenuCheckItem colorEmulation{&videoEmulationMenu}; diff --git a/higan/target-tomoko/program/interface.cpp b/higan/target-tomoko/program/interface.cpp index 5c08e3e0..b1a4af62 100644 --- a/higan/target-tomoko/program/interface.cpp +++ b/higan/target-tomoko/program/interface.cpp @@ -56,9 +56,14 @@ auto Program::videoRefresh(const uint32* data, uint pitch, uint width, uint heig pitch >>= 2; if(emulator->information.overscan && settings["Video/Overscan/Mask"].boolean()) { - uint horizontal = settings["Video/Overscan/Horizontal"].natural(); - uint vertical = settings["Video/Overscan/Vertical"].natural(); - emulator->videoCrop(data, width, height, horizontal, vertical); + uint overscanHorizontal = settings["Video/Overscan/Horizontal"].natural(); + uint overscanVertical = settings["Video/Overscan/Vertical"].natural(); + auto resolution = emulator->videoResolution(); + overscanHorizontal *= resolution.internalWidth / resolution.width; + overscanVertical *= resolution.internalHeight / resolution.height; + data += overscanVertical * pitch + overscanHorizontal; + width -= overscanHorizontal * 2; + height -= overscanVertical * 2; } if(video->lock(output, length, width, height)) { diff --git a/higan/target-tomoko/settings/settings.hpp b/higan/target-tomoko/settings/settings.hpp index 351ad696..673358cd 100644 --- a/higan/target-tomoko/settings/settings.hpp +++ b/higan/target-tomoko/settings/settings.hpp @@ -2,7 +2,7 @@ struct VideoSettings : TabFrameItem { VideoSettings(TabFrame*); VerticalLayout layout{this}; - Label colorAdjustmentLabel{&layout, Size{~0, 0}}; + Label colorAdjustmentLabel{&layout, Size{~0, 0}, 2}; HorizontalLayout saturationLayout{&layout, Size{~0, 0}}; Label saturationLabel{&saturationLayout, Size{80, 0}}; Label saturationValue{&saturationLayout, Size{50, 0}}; @@ -15,7 +15,7 @@ struct VideoSettings : TabFrameItem { Label luminanceLabel{&luminanceLayout, Size{80, 0}}; Label luminanceValue{&luminanceLayout, Size{50, 0}}; HorizontalSlider luminanceSlider{&luminanceLayout, Size{~0, 0}}; - Label overscanMaskLabel{&layout, Size{~0, 0}}; + Label overscanMaskLabel{&layout, Size{~0, 0}, 2}; HorizontalLayout horizontalMaskLayout{&layout, Size{~0, 0}}; Label horizontalMaskLabel{&horizontalMaskLayout, Size{80, 0}}; Label horizontalMaskValue{&horizontalMaskLayout, Size{50, 0}}; @@ -24,16 +24,25 @@ struct VideoSettings : TabFrameItem { Label verticalMaskLabel{&verticalMaskLayout, Size{80, 0}}; Label verticalMaskValue{&verticalMaskLayout, Size{50, 0}}; HorizontalSlider verticalMaskSlider{&verticalMaskLayout, Size{~0, 0}}; + Label windowedModeLabel{&layout, Size{~0, 0}, 2}; + HorizontalLayout windowedModeLayout{&layout, Size{~0, 0}}; + CheckLabel windowedModeAspectCorrection{&windowedModeLayout, Size{0, 0}}; + CheckLabel windowedModeAdaptive{&windowedModeLayout, Size{0, 0}}; + Label fullscreenModeLabel{&layout, Size{~0, 0}, 2}; + HorizontalLayout fullscreenModeLayout{&layout, Size{~0, 0}}; + CheckLabel fullscreenModeAspectCorrection{&fullscreenModeLayout, Size{0, 0}}; + CheckLabel fullscreenModeAdaptive{&fullscreenModeLayout, Size{0, 0}}; auto updateColor() -> void; auto updateOverscan() -> void; + auto updateViewport() -> void; }; struct AudioSettings : TabFrameItem { AudioSettings(TabFrame*); VerticalLayout layout{this}; - Label driverLabel{&layout, Size{~0, 0}}; + Label driverLabel{&layout, Size{~0, 0}, 2}; HorizontalLayout controlLayout{&layout, Size{~0, 0}}; Label latencyLabel{&controlLayout, Size{0, 0}}; ComboButton latencyCombo{&controlLayout, Size{~0, 0}}; @@ -42,7 +51,7 @@ struct AudioSettings : TabFrameItem { Label resamplerLabel{&controlLayout, Size{0, 0}}; ComboButton resamplerCombo{&controlLayout, Size{~0, 0}}; CheckLabel exclusiveMode{&layout, Size{~0, 0}}; - Label effectsLabel{&layout, Size{~0, 0}}; + Label effectsLabel{&layout, Size{~0, 0}, 2}; HorizontalLayout volumeLayout{&layout, Size{~0, 0}}; Label volumeLabel{&volumeLayout, Size{80, 0}}; Label volumeValue{&volumeLayout, Size{50, 0}}; diff --git a/higan/target-tomoko/settings/video.cpp b/higan/target-tomoko/settings/video.cpp index a86eafc2..772d7f33 100644 --- a/higan/target-tomoko/settings/video.cpp +++ b/higan/target-tomoko/settings/video.cpp @@ -23,8 +23,17 @@ VideoSettings::VideoSettings(TabFrame* parent) : TabFrameItem(parent) { verticalMaskValue.setAlignment(0.5); verticalMaskSlider.setLength(25).setPosition(settings["Video/Overscan/Vertical"].natural()).onChange([&] { updateOverscan(); }); + windowedModeLabel.setFont(Font().setBold()).setText("Windowed Mode"); + windowedModeAspectCorrection.setText("Correct aspect ratio").setChecked(settings["Video/Windowed/AspectCorrection"].boolean()).onToggle([&] { updateViewport(); }); + windowedModeAdaptive.setText("Resize window to viewport").setChecked(settings["Video/Windowed/Adaptive"].boolean()).onToggle([&] { updateViewport(); }); + + fullscreenModeLabel.setFont(Font().setBold()).setText("Fullscreen Mode"); + fullscreenModeAspectCorrection.setText("Correct aspect ratio").setChecked(settings["Video/Fullscreen/AspectCorrection"].boolean()).onToggle([&] { updateViewport(); }); + fullscreenModeAdaptive.setText("Resize viewport to window").setChecked(settings["Video/Fullscreen/Adaptive"].boolean()).onToggle([&] { updateViewport(); }); + updateColor(); updateOverscan(); + updateViewport(); } auto VideoSettings::updateColor() -> void { @@ -44,3 +53,11 @@ auto VideoSettings::updateOverscan() -> void { verticalMaskValue.setText({verticalMaskSlider.position()}); presentation->resizeViewport(); } + +auto VideoSettings::updateViewport() -> void { + settings["Video/Windowed/AspectCorrection"].setValue(windowedModeAspectCorrection.checked()); + settings["Video/Windowed/Adaptive"].setValue(windowedModeAdaptive.checked()); + settings["Video/Fullscreen/AspectCorrection"].setValue(fullscreenModeAspectCorrection.checked()); + settings["Video/Fullscreen/Adaptive"].setValue(fullscreenModeAdaptive.checked()); + presentation->resizeViewport(); +} diff --git a/higan/ws/interface/interface.cpp b/higan/ws/interface/interface.cpp index f9c5af66..78bfbd9c 100644 --- a/higan/ws/interface/interface.cpp +++ b/higan/ws/interface/interface.cpp @@ -35,21 +35,14 @@ auto Interface::title() -> string { return cartridge.information.title; } -auto Interface::videoResolution() -> VideoSize { +auto Interface::videoResolution() -> VideoResolution { if(!settings.rotateLeft) { - return {224, 144}; + return {224, 144, 224, 144, 1.0}; } else { - return {144, 224}; + return {144, 224, 144, 224, 1.0}; } } -auto Interface::videoSize(uint width, uint height, bool, uint, uint) -> VideoSize { - double widthDivider = videoResolution().width; - double heightDivider = videoResolution().height; - uint multiplier = min(width / widthDivider, height / heightDivider); - return {uint(widthDivider * multiplier), uint(heightDivider * multiplier)}; -} - auto Interface::loaded() -> bool { return system.loaded(); } diff --git a/higan/ws/interface/interface.hpp b/higan/ws/interface/interface.hpp index e1ba60d8..05893b02 100644 --- a/higan/ws/interface/interface.hpp +++ b/higan/ws/interface/interface.hpp @@ -22,8 +22,7 @@ struct Interface : Emulator::Interface { auto manifest() -> string override; auto title() -> string override; - auto videoResolution() -> VideoSize override; - auto videoSize(uint width, uint height, bool, uint, uint) -> VideoSize override; + auto videoResolution() -> VideoResolution override; auto loaded() -> bool override; auto sha256() -> string override;