Support for optional 8:7 PAR instead of 4:3 AR

This commit is contained in:
Marat Tanalin 2020-09-13 04:23:29 +03:00
parent f7d82b8732
commit dcdfafdbee
9 changed files with 88 additions and 30 deletions

View file

@ -18,6 +18,10 @@ static constexpr double defaultAspectX = 4.0,
defaultAspectY = 3.0,
defaultAspect = defaultAspectX / defaultAspectY;
static constexpr double par = 8.0 / 7.0,
parAspect = par * origWidth / origHeight,
parOverAspect = par * origWidth / origOverHeight;
auto getWidth(bool aspectCorrection) -> uint32_t {
return aspectCorrection ? std::round(origHeight * defaultAspect) : origWidth;
}
@ -34,6 +38,10 @@ auto getAspectY(bool showOverscan) -> double {
return showOverscan ? defaultAspectY * overscanRatio : defaultAspectY;
}
auto getParAspect(bool showOverscan) -> double {
return showOverscan ? parOverAspect : parAspect;
}
auto getHeightForPar1(uint32_t width, uint32_t height) -> uint32_t {
return (height == origHeight || height == origOverHeight)
? (width == origWidth ? origHeight : origDoubleHeight)
@ -42,10 +50,13 @@ auto getHeightForPar1(uint32_t width, uint32_t height) -> uint32_t {
auto calculateScaledSizeScale(
uint32_t areaWidth, uint32_t areaHeight,
bool aspectCorrection, bool showOverscan
bool aspectCorrection, bool showOverscan,
bool parInsteadOfAr
) -> is::Size
{
double aspect = aspectCorrection ? defaultAspect : (double)origWidth / origHeight;
double aspect = aspectCorrection
? (parInsteadOfAr ? parAspect : defaultAspect)
: (double)origWidth / origHeight;
if (showOverscan) {
aspect /= overscanRatio;
@ -76,42 +87,68 @@ auto calculateScaledSizeScale(
auto calculateScaledSizeCenter(
uint32_t areaWidth, uint32_t areaHeight,
uint32_t imageWidth, uint32_t imageHeight,
bool aspectCorrection, bool showOverscan
bool aspectCorrection, bool showOverscan,
bool parInsteadOfAr
) -> is::Size
{
return aspectCorrection
? is::calculateSizeCorrectedPerfectY(
areaWidth, areaHeight,
imageHeight,
defaultAspectX, getAspectY(showOverscan)
)
: is::calculateSize(
if (!aspectCorrection) {
return is::calculateSize(
areaWidth, areaHeight,
imageWidth, getHeightForPar1(imageWidth, imageHeight)
);
}
double aspectX, aspectY;
if (parInsteadOfAr) {
aspectX = getParAspect(showOverscan);
aspectY = 1.0;
}
else {
aspectX = defaultAspectX;
aspectY = getAspectY(showOverscan);
}
return is::calculateSizeCorrectedPerfectY(
areaWidth, areaHeight,
imageHeight,
aspectX, aspectY
);
}
auto calculateScaledSizePerfect(
uint32_t areaWidth, uint32_t areaHeight,
uint32_t imageWidth, uint32_t imageHeight,
bool aspectCorrection, bool showOverscan
bool aspectCorrection, bool showOverscan,
bool parInsteadOfAr
) -> is::Size
{
if (aspectCorrection) {
return is::calculateSizeCorrected(
areaWidth, areaHeight,
imageWidth, imageHeight,
defaultAspectX, getAspectY(showOverscan)
if (!aspectCorrection) {
uint32_t imageHeightForPar1 = getHeightForPar1(imageWidth, imageHeight);
uint32_t imageOverHeightForPar1 = imageHeightForPar1 == origHeight ? origOverHeight : origDoubleOverHeight;
return is::calculateSize(
areaWidth, areaHeight,
imageWidth,
showOverscan ? imageOverHeightForPar1 : imageHeightForPar1
);
}
uint32_t imageHeightForPar1 = getHeightForPar1(imageWidth, imageHeight);
uint32_t imageOverHeightForPar1 = imageHeightForPar1 == origHeight ? origOverHeight : origDoubleOverHeight;
double aspectX, aspectY;
return is::calculateSize(
areaWidth, areaHeight,
imageWidth,
showOverscan ? imageOverHeightForPar1 : imageHeightForPar1
if (parInsteadOfAr) {
aspectX = getParAspect(showOverscan);
aspectY = 1.0;
}
else {
aspectX = defaultAspectX;
aspectY = getAspectY(showOverscan);
}
return is::calculateSizeCorrected(
areaWidth, areaHeight,
imageWidth, imageHeight,
aspectX, aspectY
);
};

View file

@ -3,7 +3,6 @@
#pragma once
#include <cstdint>
#include <utility>
#include "integer-scaling/IntegerScaling.h"
@ -17,24 +16,28 @@ auto getWidth(bool aspectCorrection, uint32_t width) -> uint32_t;
auto getHeight(bool showOverscan, uint32_t height) -> uint32_t;
auto getAspectY(bool showOverscan) -> double;
auto getParAspect(bool showOverscan) -> double;
auto getHeightForPar1(uint32_t width, uint32_t height) -> uint32_t;
auto calculateScaledSizeScale(
uint32_t areaWidth, uint32_t areaHeight,
bool aspectCorrection, bool showOverscan
bool aspectCorrection, bool showOverscan,
bool parInsteadOfAr
) -> is::Size;
auto calculateScaledSizeCenter(
uint32_t areaWidth, uint32_t areaHeight,
uint32_t imageWidth, uint32_t imageHeight,
bool aspectCorrection, bool showOverscan
bool aspectCorrection, bool showOverscan,
bool parInsteadOfAr
) -> is::Size;
auto calculateScaledSizePerfect(
uint32_t areaWidth, uint32_t areaHeight,
uint32_t imageWidth, uint32_t imageHeight,
bool aspectCorrection, bool showOverscan
bool aspectCorrection, bool showOverscan,
bool parInsteadOfAr
) -> is::Size;
} // namespace bsnesMt::scaling

View file

@ -53,6 +53,7 @@ Menu.Settings.Output.PixelPerfect = "Pixel-Perfect"
Menu.Settings.Output.Scale = "Scale"
Menu.Settings.Output.Stretch = "Stretch"
Menu.Settings.Output.AspectRatioCorrection = "Aspect-Ratio Correction"
Menu.Settings.Output.parInsteadOfAr = "8:7 PAR instead of 4:3 AR"
Menu.Settings.Output.ShowOverscanArea = "Show Overscan Area"
Menu.Settings.Output.scalingInfo = "Scaling Info in Status Bar"
Menu.Settings.Output.HiresBlurEmulation = "Hires Blur Emulation"

View file

@ -53,6 +53,7 @@ Menu.Settings.Output.PixelPerfect = "Целочисленное масштаби
Menu.Settings.Output.Scale = "Масштабирование с сохранением пропорций"
Menu.Settings.Output.Stretch = "Растяжение без сохранения пропорций"
Menu.Settings.Output.AspectRatioCorrection = "Коррекция соотношения сторон"
Menu.Settings.Output.parInsteadOfAr = "PAR 8:7 вместо AR 4:3"
Menu.Settings.Output.ShowOverscanArea = "Показать область «overscan»"
Menu.Settings.Output.scalingInfo = "Информация о масштабировании в строке состояния"
Menu.Settings.Output.HiresBlurEmulation = "Эмуляция размытия в режиме высокого разрешения"

View file

@ -105,6 +105,15 @@ auto Presentation::create() -> void {
//resizeWindow(); // Commented-out by MT.
});
/* MT. */
parInsteadOfAr.setText(bmt::get("Menu.Settings.Output.parInsteadOfAr").data())
.setChecked(settings.video.parInsteadOfAr)
.onToggle([&] {
settings.video.parInsteadOfAr = parInsteadOfAr.checked();
video.clear(); // MT.
});
/* /MT. */
showOverscanArea.setText(bmt::get("Menu.Settings.Output.ShowOverscanArea").data())
.setChecked(settings.video.overscan)
.onToggle([&] {

View file

@ -50,6 +50,7 @@ struct Presentation : Window {
Group outputGroup{&centerViewport, &perfectViewport, &scaleViewport, &stretchViewport}; // `&perfectViewport,` added by MT.
MenuSeparator outputSeparator{&outputMenu};
MenuCheckItem aspectCorrection{&outputMenu};
MenuCheckItem parInsteadOfAr{&outputMenu};
MenuCheckItem showOverscanArea{&outputMenu};
MenuCheckItem scalingInfo{&outputMenu}; // MT.
MenuCheckItem blurEmulation{&outputMenu};

View file

@ -35,13 +35,15 @@ auto Program::viewportSize(uint& scaledWidth, uint& scaledHeight, uint width, ui
}
bool aspectCorrection = settings.video.aspectCorrection,
showOverscan = settings.video.overscan;
showOverscan = settings.video.overscan,
parInsteadOfAr = settings.video.parInsteadOfAr;
if (outputSetting == "Pixel-Perfect") {
auto scaledSize = bmi::calculateScaledSizePerfect(
areaWidth, areaHeight,
width, height,
aspectCorrection, showOverscan
aspectCorrection, showOverscan,
parInsteadOfAr
);
scaledWidth = scaledSize.width;
@ -51,7 +53,8 @@ auto Program::viewportSize(uint& scaledWidth, uint& scaledHeight, uint width, ui
auto scaledSize = bmi::calculateScaledSizeCenter(
areaWidth, areaHeight,
width, height,
aspectCorrection, showOverscan
aspectCorrection, showOverscan,
parInsteadOfAr
);
scaledWidth = scaledSize.width;
@ -60,7 +63,8 @@ auto Program::viewportSize(uint& scaledWidth, uint& scaledHeight, uint width, ui
else if (outputSetting == "Scale") {
auto scaledSize = bmi::calculateScaledSizeScale(
areaWidth, areaHeight,
aspectCorrection, showOverscan
aspectCorrection, showOverscan,
parInsteadOfAr
);
scaledWidth = scaledSize.width;

View file

@ -73,6 +73,7 @@ auto Settings::process(bool load) -> void {
bind(text, "Video/Output", video.output);
bind(natural, "Video/Multiplier", video.multiplier);
bind(boolean, "Video/AspectCorrection", video.aspectCorrection);
bind(boolean, "Video/ParInsteadOfAr", video.parInsteadOfAr); // MT.
bind(boolean, "Video/Overscan", video.overscan);
bind(boolean, "Video/ScalingInfo", video.scalingInfo); // MT.
bind(boolean, "Video/Blur", video.blur);

View file

@ -25,6 +25,7 @@ struct Settings : Markup::Node {
string output = "Pixel-Perfect"; // Changed from "Scale" by MT.
uint multiplier = 2;
bool aspectCorrection = true;
bool parInsteadOfAr = false; // MT.
bool overscan = false;
bool scalingInfo = false; // MT.
bool blur = false;