Support custom and match display aspect ratios
This commit is contained in:
parent
48bc152a63
commit
256f272768
|
@ -45,6 +45,7 @@
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="settings_display_aspect_ratio_names">
|
<string-array name="settings_display_aspect_ratio_names">
|
||||||
<item>Auto (Nativo del juego)</item>
|
<item>Auto (Nativo del juego)</item>
|
||||||
|
<item>Auto (Match Display)</item>
|
||||||
<item>4:3</item>
|
<item>4:3</item>
|
||||||
<item>16:9</item>
|
<item>16:9</item>
|
||||||
<item>16:10</item>
|
<item>16:10</item>
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="settings_display_aspect_ratio_names">
|
<string-array name="settings_display_aspect_ratio_names">
|
||||||
<item>Auto (Game Native)</item>
|
<item>Auto (Game Native)</item>
|
||||||
|
<item>Auto (Match Display)</item>
|
||||||
<item>4:3</item>
|
<item>4:3</item>
|
||||||
<item>16:9</item>
|
<item>16:9</item>
|
||||||
<item>16:10</item>
|
<item>16:10</item>
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="settings_display_aspect_ratio_names">
|
<string-array name="settings_display_aspect_ratio_names">
|
||||||
<item>Auto (Game Native)</item>
|
<item>Auto (Game Native)</item>
|
||||||
|
<item>Auto (Match Display)</item>
|
||||||
<item>4:3</item>
|
<item>4:3</item>
|
||||||
<item>16:9</item>
|
<item>16:9</item>
|
||||||
<item>16:10</item>
|
<item>16:10</item>
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="settings_display_aspect_ratio_names">
|
<string-array name="settings_display_aspect_ratio_names">
|
||||||
<item>Auto (Nativo)</item>
|
<item>Auto (Nativo)</item>
|
||||||
|
<item>Auto (Match Display)</item>
|
||||||
<item>4:3</item>
|
<item>4:3</item>
|
||||||
<item>16:9</item>
|
<item>16:9</item>
|
||||||
<item>16:10</item>
|
<item>16:10</item>
|
||||||
|
|
|
@ -44,8 +44,9 @@
|
||||||
<item>Все границы</item>
|
<item>Все границы</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="settings_display_aspect_ratio_names">
|
<string-array name="settings_display_aspect_ratio_names">
|
||||||
<item>Автонастройка (нативное игре)</item>
|
<item>Автонастройка (нативное игре)</item>
|
||||||
<item>4:3</item>
|
<item>Auto (Match Display)</item>
|
||||||
|
<item>4:3</item>
|
||||||
<item>16:9</item>
|
<item>16:9</item>
|
||||||
<item>16:10</item>
|
<item>16:10</item>
|
||||||
<item>19:9</item>
|
<item>19:9</item>
|
||||||
|
|
|
@ -89,6 +89,7 @@
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="settings_display_aspect_ratio_names">
|
<string-array name="settings_display_aspect_ratio_names">
|
||||||
<item>Auto (Game Native)</item>
|
<item>Auto (Game Native)</item>
|
||||||
|
<item>Auto (Match Display)</item>
|
||||||
<item>4:3</item>
|
<item>4:3</item>
|
||||||
<item>16:9</item>
|
<item>16:9</item>
|
||||||
<item>16:10</item>
|
<item>16:10</item>
|
||||||
|
@ -105,6 +106,7 @@
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="settings_display_aspect_ratio_values">
|
<string-array name="settings_display_aspect_ratio_values">
|
||||||
<item>Auto (Game Native)</item>
|
<item>Auto (Game Native)</item>
|
||||||
|
<item>Auto (Match Window)</item>
|
||||||
<item>4:3</item>
|
<item>4:3</item>
|
||||||
<item>16:9</item>
|
<item>16:9</item>
|
||||||
<item>16:10</item>
|
<item>16:10</item>
|
||||||
|
|
|
@ -492,7 +492,7 @@ float GPU::GetDisplayAspectRatio() const
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return Settings::GetDisplayAspectRatioValue(g_settings.display_aspect_ratio);
|
return g_settings.GetDisplayAspectRatioValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
251
src/core/gte.cpp
251
src/core/gte.cpp
|
@ -3,10 +3,13 @@
|
||||||
#include "common/bitutils.h"
|
#include "common/bitutils.h"
|
||||||
#include "common/state_wrapper.h"
|
#include "common/state_wrapper.h"
|
||||||
#include "cpu_core.h"
|
#include "cpu_core.h"
|
||||||
|
#include "host_display.h"
|
||||||
|
#include "host_interface.h"
|
||||||
#include "pgxp.h"
|
#include "pgxp.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
namespace GTE {
|
namespace GTE {
|
||||||
|
|
||||||
|
@ -19,6 +22,11 @@ static constexpr s32 IR0_MAX_VALUE = 0x1000;
|
||||||
static constexpr s32 IR123_MIN_VALUE = -(INT64_C(1) << 15);
|
static constexpr s32 IR123_MIN_VALUE = -(INT64_C(1) << 15);
|
||||||
static constexpr s32 IR123_MAX_VALUE = (INT64_C(1) << 15) - 1;
|
static constexpr s32 IR123_MAX_VALUE = (INT64_C(1) << 15) - 1;
|
||||||
|
|
||||||
|
static DisplayAspectRatio s_aspect_ratio = DisplayAspectRatio::R4_3;
|
||||||
|
static u32 s_custom_aspect_ratio_numerator;
|
||||||
|
static u32 s_custom_aspect_ratio_denominator;
|
||||||
|
static float s_custom_aspect_ratio_f;
|
||||||
|
|
||||||
#define REGS CPU::g_state.gte_regs
|
#define REGS CPU::g_state.gte_regs
|
||||||
|
|
||||||
ALWAYS_INLINE static u32 CountLeadingBits(u32 value)
|
ALWAYS_INLINE static u32 CountLeadingBits(u32 value)
|
||||||
|
@ -148,6 +156,7 @@ ALWAYS_INLINE static u32 TruncateRGB(s32 value)
|
||||||
|
|
||||||
void Initialize()
|
void Initialize()
|
||||||
{
|
{
|
||||||
|
UpdateAspectRatio();
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,6 +171,55 @@ bool DoState(StateWrapper& sw)
|
||||||
return !sw.HasError();
|
return !sw.HasError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateAspectRatio()
|
||||||
|
{
|
||||||
|
if (!g_settings.gpu_widescreen_hack)
|
||||||
|
{
|
||||||
|
s_aspect_ratio = DisplayAspectRatio::R4_3;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_aspect_ratio = g_settings.display_aspect_ratio;
|
||||||
|
|
||||||
|
u32 num, denom;
|
||||||
|
switch (s_aspect_ratio)
|
||||||
|
{
|
||||||
|
case DisplayAspectRatio::MatchWindow:
|
||||||
|
{
|
||||||
|
const HostDisplay* display = g_host_interface->GetDisplay();
|
||||||
|
if (!display)
|
||||||
|
{
|
||||||
|
s_aspect_ratio = DisplayAspectRatio::R4_3;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
num = display->GetWindowWidth();
|
||||||
|
denom = display->GetWindowHeight();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DisplayAspectRatio::Custom:
|
||||||
|
{
|
||||||
|
num = g_settings.display_aspect_ratio_custom_numerator;
|
||||||
|
denom = g_settings.display_aspect_ratio_custom_denominator;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (4 / 3) / (num / denom) => gcd((4 * denom) / (3 * num))
|
||||||
|
const u32 x = 4u * denom;
|
||||||
|
const u32 y = 3u * num;
|
||||||
|
const u32 gcd = std::gcd(x, y);
|
||||||
|
|
||||||
|
s_custom_aspect_ratio_numerator = x / gcd;
|
||||||
|
s_custom_aspect_ratio_denominator = y / gcd;
|
||||||
|
|
||||||
|
s_custom_aspect_ratio_f = static_cast<float>((4.0 / 3.0) / (static_cast<double>(num) / static_cast<double>(denom)));
|
||||||
|
}
|
||||||
|
|
||||||
u32 ReadRegister(u32 index)
|
u32 ReadRegister(u32 index)
|
||||||
{
|
{
|
||||||
DebugAssert(index < countof(REGS.r32));
|
DebugAssert(index < countof(REGS.r32));
|
||||||
|
@ -614,66 +672,65 @@ static void RTPS(const s16 V[3], u8 shift, bool lm, bool last)
|
||||||
const s64 result = static_cast<s64>(ZeroExtend64(UNRDivide(REGS.H, REGS.SZ3)));
|
const s64 result = static_cast<s64>(ZeroExtend64(UNRDivide(REGS.H, REGS.SZ3)));
|
||||||
|
|
||||||
s64 Sx;
|
s64 Sx;
|
||||||
if (g_settings.gpu_widescreen_hack)
|
switch (s_aspect_ratio)
|
||||||
{
|
{
|
||||||
const DisplayAspectRatio ar = g_settings.display_aspect_ratio;
|
case DisplayAspectRatio::R16_9:
|
||||||
switch (ar)
|
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(3)) / s64(4)) + s64(REGS.OFX));
|
||||||
{
|
break;
|
||||||
case DisplayAspectRatio::R16_9:
|
|
||||||
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(3)) / s64(4)) + s64(REGS.OFX));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DisplayAspectRatio::R16_10:
|
case DisplayAspectRatio::R16_10:
|
||||||
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(5)) / s64(6)) + s64(REGS.OFX));
|
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(5)) / s64(6)) + s64(REGS.OFX));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R19_9:
|
case DisplayAspectRatio::R19_9:
|
||||||
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(12)) / s64(19)) + s64(REGS.OFX));
|
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(12)) / s64(19)) + s64(REGS.OFX));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R20_9:
|
case DisplayAspectRatio::R20_9:
|
||||||
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(3)) / s64(5)) + s64(REGS.OFX));
|
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(3)) / s64(5)) + s64(REGS.OFX));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R21_9:
|
case DisplayAspectRatio::R21_9:
|
||||||
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(9)) / s64(16)) + s64(REGS.OFX));
|
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(9)) / s64(16)) + s64(REGS.OFX));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R32_9:
|
case DisplayAspectRatio::R32_9:
|
||||||
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(3)) / s64(8)) + s64(REGS.OFX));
|
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(3)) / s64(8)) + s64(REGS.OFX));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R8_7:
|
case DisplayAspectRatio::R8_7:
|
||||||
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(7)) / s64(6)) + s64(REGS.OFX));
|
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(7)) / s64(6)) + s64(REGS.OFX));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R5_4:
|
case DisplayAspectRatio::R5_4:
|
||||||
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(16)) / s64(15)) + s64(REGS.OFX));
|
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(16)) / s64(15)) + s64(REGS.OFX));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R3_2:
|
case DisplayAspectRatio::R3_2:
|
||||||
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(8)) / s64(9)) + s64(REGS.OFX));
|
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(8)) / s64(9)) + s64(REGS.OFX));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R2_1:
|
case DisplayAspectRatio::R2_1:
|
||||||
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(2)) / s64(3)) + s64(REGS.OFX));
|
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(2)) / s64(3)) + s64(REGS.OFX));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R1_1:
|
case DisplayAspectRatio::R1_1:
|
||||||
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(7)) / s64(6)) + s64(REGS.OFX));
|
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(7)) / s64(6)) + s64(REGS.OFX));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::Auto:
|
case DisplayAspectRatio::Custom:
|
||||||
case DisplayAspectRatio::R4_3:
|
case DisplayAspectRatio::MatchWindow:
|
||||||
case DisplayAspectRatio::PAR1_1:
|
Sx = ((((s64(result) * s64(REGS.IR1)) * s64(s_custom_aspect_ratio_numerator)) /
|
||||||
default:
|
s64(s_custom_aspect_ratio_denominator)) +
|
||||||
Sx = (s64(result) * s64(REGS.IR1) + s64(REGS.OFX));
|
s64(REGS.OFX));
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
case DisplayAspectRatio::Auto:
|
||||||
else
|
case DisplayAspectRatio::R4_3:
|
||||||
{
|
case DisplayAspectRatio::PAR1_1:
|
||||||
Sx = (s64(result) * s64(REGS.IR1) + s64(REGS.OFX));
|
default:
|
||||||
|
Sx = (s64(result) * s64(REGS.IR1) + s64(REGS.OFX));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const s64 Sy = s64(result) * s64(REGS.IR2) + s64(REGS.OFY);
|
const s64 Sy = s64(result) * s64(REGS.IR2) + s64(REGS.OFY);
|
||||||
|
@ -713,70 +770,68 @@ static void RTPS(const s16 V[3], u8 shift, bool lm, bool last)
|
||||||
const float precise_h_div_sz = float(REGS.H) / precise_z;
|
const float precise_h_div_sz = float(REGS.H) / precise_z;
|
||||||
const float fofx = float(REGS.OFX) / float(1 << 16);
|
const float fofx = float(REGS.OFX) / float(1 << 16);
|
||||||
const float fofy = float(REGS.OFY) / float(1 << 16);
|
const float fofy = float(REGS.OFY) / float(1 << 16);
|
||||||
float precise_x;
|
float precise_x = precise_ir1 * precise_h_div_sz;
|
||||||
if (g_settings.gpu_widescreen_hack)
|
|
||||||
|
switch (s_aspect_ratio)
|
||||||
{
|
{
|
||||||
precise_x = precise_ir1 * precise_h_div_sz;
|
case DisplayAspectRatio::R16_9:
|
||||||
const DisplayAspectRatio ar = g_settings.display_aspect_ratio;
|
precise_x = (precise_x * 3.0f) / 4.0f;
|
||||||
switch (ar)
|
break;
|
||||||
{
|
|
||||||
case DisplayAspectRatio::R16_9:
|
|
||||||
precise_x = (precise_x * 3.0f) / 4.0f;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DisplayAspectRatio::R16_10:
|
case DisplayAspectRatio::R16_10:
|
||||||
precise_x = (precise_x * 5.0f) / 6.0f;
|
precise_x = (precise_x * 5.0f) / 6.0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R19_9:
|
case DisplayAspectRatio::R19_9:
|
||||||
precise_x = (precise_x * 12.0f) / 19.0f;
|
precise_x = (precise_x * 12.0f) / 19.0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R20_9:
|
case DisplayAspectRatio::R20_9:
|
||||||
precise_x = (precise_x * 3.0f) / 5.0f;
|
precise_x = (precise_x * 3.0f) / 5.0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R21_9:
|
case DisplayAspectRatio::R21_9:
|
||||||
precise_x = (precise_x * 9.0f) / 16.0f;
|
precise_x = (precise_x * 9.0f) / 16.0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R32_9:
|
case DisplayAspectRatio::R32_9:
|
||||||
precise_x = (precise_x * 3.0f) / 8.0f;
|
precise_x = (precise_x * 3.0f) / 8.0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R8_7:
|
case DisplayAspectRatio::R8_7:
|
||||||
precise_x = (precise_x * 7.0f) / 6.0f;
|
precise_x = (precise_x * 7.0f) / 6.0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R5_4:
|
case DisplayAspectRatio::R5_4:
|
||||||
precise_x = (precise_x * 16.0f) / 15.0f;
|
precise_x = (precise_x * 16.0f) / 15.0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R3_2:
|
case DisplayAspectRatio::R3_2:
|
||||||
precise_x = (precise_x * 8.0f) / 9.0f;
|
precise_x = (precise_x * 8.0f) / 9.0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R2_1:
|
case DisplayAspectRatio::R2_1:
|
||||||
precise_x = (precise_x * 2.0f) / 3.0f;
|
precise_x = (precise_x * 2.0f) / 3.0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::R1_1:
|
case DisplayAspectRatio::R1_1:
|
||||||
precise_x = (precise_x * 7.0f) / 6.0f;
|
precise_x = (precise_x * 7.0f) / 6.0f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisplayAspectRatio::Auto:
|
case DisplayAspectRatio::MatchWindow:
|
||||||
case DisplayAspectRatio::R4_3:
|
case DisplayAspectRatio::Custom:
|
||||||
case DisplayAspectRatio::PAR1_1:
|
precise_x = precise_x * s_custom_aspect_ratio_f;
|
||||||
default:
|
break;
|
||||||
break;
|
|
||||||
}
|
case DisplayAspectRatio::Auto:
|
||||||
precise_x += fofx;
|
case DisplayAspectRatio::R4_3:
|
||||||
}
|
case DisplayAspectRatio::PAR1_1:
|
||||||
else
|
default:
|
||||||
{
|
break;
|
||||||
precise_x = fofx + (precise_ir1 * precise_h_div_sz);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
precise_x += fofx;
|
||||||
|
|
||||||
float precise_y = fofy + (precise_ir2 * precise_h_div_sz);
|
float precise_y = fofy + (precise_ir2 * precise_h_div_sz);
|
||||||
|
|
||||||
precise_x = std::clamp<float>(precise_x, -1024.0f, 1023.0f);
|
precise_x = std::clamp<float>(precise_x, -1024.0f, 1023.0f);
|
||||||
|
|
|
@ -8,6 +8,7 @@ namespace GTE {
|
||||||
void Initialize();
|
void Initialize();
|
||||||
void Reset();
|
void Reset();
|
||||||
bool DoState(StateWrapper& sw);
|
bool DoState(StateWrapper& sw);
|
||||||
|
void UpdateAspectRatio();
|
||||||
|
|
||||||
// control registers are offset by +32
|
// control registers are offset by +32
|
||||||
u32 ReadRegister(u32 index);
|
u32 ReadRegister(u32 index);
|
||||||
|
|
|
@ -533,6 +533,8 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si)
|
||||||
si.SetIntValue("Display", "LineEndOffset", 0);
|
si.SetIntValue("Display", "LineEndOffset", 0);
|
||||||
si.SetStringValue("Display", "AspectRatio",
|
si.SetStringValue("Display", "AspectRatio",
|
||||||
Settings::GetDisplayAspectRatioName(Settings::DEFAULT_DISPLAY_ASPECT_RATIO));
|
Settings::GetDisplayAspectRatioName(Settings::DEFAULT_DISPLAY_ASPECT_RATIO));
|
||||||
|
si.SetIntValue("Display", "CustomAspectRatioNumerator", 4);
|
||||||
|
si.GetIntValue("Display", "CustomAspectRatioDenominator", 3);
|
||||||
si.SetBoolValue("Display", "Force4_3For24Bit", false);
|
si.SetBoolValue("Display", "Force4_3For24Bit", false);
|
||||||
si.SetBoolValue("Display", "LinearFiltering", true);
|
si.SetBoolValue("Display", "LinearFiltering", true);
|
||||||
si.SetBoolValue("Display", "IntegerScaling", false);
|
si.SetBoolValue("Display", "IntegerScaling", false);
|
||||||
|
@ -803,6 +805,14 @@ void HostInterface::CheckForSettingsChanges(const Settings& old_settings)
|
||||||
g_gpu->UpdateSettings();
|
g_gpu->UpdateSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_settings.display_aspect_ratio != old_settings.display_aspect_ratio ||
|
||||||
|
(g_settings.display_aspect_ratio == DisplayAspectRatio::Custom &&
|
||||||
|
(g_settings.display_aspect_ratio_custom_numerator != old_settings.display_aspect_ratio_custom_numerator ||
|
||||||
|
g_settings.display_aspect_ratio_custom_denominator != old_settings.display_aspect_ratio_custom_denominator)))
|
||||||
|
{
|
||||||
|
GTE::UpdateAspectRatio();
|
||||||
|
}
|
||||||
|
|
||||||
if (g_settings.gpu_pgxp_enable != old_settings.gpu_pgxp_enable ||
|
if (g_settings.gpu_pgxp_enable != old_settings.gpu_pgxp_enable ||
|
||||||
(g_settings.gpu_pgxp_enable && (g_settings.gpu_pgxp_culling != old_settings.gpu_pgxp_culling ||
|
(g_settings.gpu_pgxp_enable && (g_settings.gpu_pgxp_culling != old_settings.gpu_pgxp_culling ||
|
||||||
g_settings.gpu_pgxp_cpu != old_settings.gpu_pgxp_cpu)))
|
g_settings.gpu_pgxp_cpu != old_settings.gpu_pgxp_cpu)))
|
||||||
|
@ -899,6 +909,15 @@ void HostInterface::SetUserDirectoryToProgramDirectory()
|
||||||
m_user_directory = program_directory;
|
m_user_directory = program_directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HostInterface::OnHostDisplayResized()
|
||||||
|
{
|
||||||
|
if (System::IsValid())
|
||||||
|
{
|
||||||
|
if (g_settings.display_aspect_ratio == DisplayAspectRatio::MatchWindow)
|
||||||
|
GTE::UpdateAspectRatio();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string HostInterface::GetUserDirectoryRelativePath(const char* format, ...) const
|
std::string HostInterface::GetUserDirectoryRelativePath(const char* format, ...) const
|
||||||
{
|
{
|
||||||
std::va_list ap;
|
std::va_list ap;
|
||||||
|
|
|
@ -183,6 +183,9 @@ protected:
|
||||||
/// Enables "relative" mouse mode, locking the cursor position and returning relative coordinates.
|
/// Enables "relative" mouse mode, locking the cursor position and returning relative coordinates.
|
||||||
virtual void SetMouseMode(bool relative, bool hide_cursor);
|
virtual void SetMouseMode(bool relative, bool hide_cursor);
|
||||||
|
|
||||||
|
/// Call when host display size changes, use with "match display" aspect ratio setting.
|
||||||
|
virtual void OnHostDisplayResized();
|
||||||
|
|
||||||
/// Sets the user directory to the program directory, i.e. "portable mode".
|
/// Sets the user directory to the program directory, i.e. "portable mode".
|
||||||
void SetUserDirectoryToProgramDirectory();
|
void SetUserDirectoryToProgramDirectory();
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "common/file_system.h"
|
#include "common/file_system.h"
|
||||||
#include "common/make_array.h"
|
#include "common/make_array.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
#include "host_display.h"
|
||||||
#include "host_interface.h"
|
#include "host_interface.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
@ -222,6 +223,10 @@ void Settings::Load(SettingsInterface& si)
|
||||||
ParseDisplayAspectRatio(
|
ParseDisplayAspectRatio(
|
||||||
si.GetStringValue("Display", "AspectRatio", GetDisplayAspectRatioName(DEFAULT_DISPLAY_ASPECT_RATIO)).c_str())
|
si.GetStringValue("Display", "AspectRatio", GetDisplayAspectRatioName(DEFAULT_DISPLAY_ASPECT_RATIO)).c_str())
|
||||||
.value_or(DEFAULT_DISPLAY_ASPECT_RATIO);
|
.value_or(DEFAULT_DISPLAY_ASPECT_RATIO);
|
||||||
|
display_aspect_ratio_custom_numerator = static_cast<u16>(
|
||||||
|
std::clamp<int>(si.GetIntValue("Display", "CustomAspectRatioNumerator", 4), 1, std::numeric_limits<u16>::max()));
|
||||||
|
display_aspect_ratio_custom_denominator = static_cast<u16>(
|
||||||
|
std::clamp<int>(si.GetIntValue("Display", "CustomAspectRatioDenominator", 3), 1, std::numeric_limits<u16>::max()));
|
||||||
display_force_4_3_for_24bit = si.GetBoolValue("Display", "Force4_3For24Bit", false);
|
display_force_4_3_for_24bit = si.GetBoolValue("Display", "Force4_3For24Bit", false);
|
||||||
display_active_start_offset = static_cast<s16>(si.GetIntValue("Display", "ActiveStartOffset", 0));
|
display_active_start_offset = static_cast<s16>(si.GetIntValue("Display", "ActiveStartOffset", 0));
|
||||||
display_active_end_offset = static_cast<s16>(si.GetIntValue("Display", "ActiveEndOffset", 0));
|
display_active_end_offset = static_cast<s16>(si.GetIntValue("Display", "ActiveEndOffset", 0));
|
||||||
|
@ -395,6 +400,8 @@ void Settings::Save(SettingsInterface& si) const
|
||||||
si.SetIntValue("Display", "LineEndOffset", display_line_end_offset);
|
si.SetIntValue("Display", "LineEndOffset", display_line_end_offset);
|
||||||
si.SetBoolValue("Display", "Force4_3For24Bit", display_force_4_3_for_24bit);
|
si.SetBoolValue("Display", "Force4_3For24Bit", display_force_4_3_for_24bit);
|
||||||
si.SetStringValue("Display", "AspectRatio", GetDisplayAspectRatioName(display_aspect_ratio));
|
si.SetStringValue("Display", "AspectRatio", GetDisplayAspectRatioName(display_aspect_ratio));
|
||||||
|
si.SetIntValue("Display", "CustomAspectRatioNumerator", display_aspect_ratio_custom_numerator);
|
||||||
|
si.GetIntValue("Display", "CustomAspectRatioDenominator", display_aspect_ratio_custom_denominator);
|
||||||
si.SetBoolValue("Display", "LinearFiltering", display_linear_filtering);
|
si.SetBoolValue("Display", "LinearFiltering", display_linear_filtering);
|
||||||
si.SetBoolValue("Display", "IntegerScaling", display_integer_scaling);
|
si.SetBoolValue("Display", "IntegerScaling", display_integer_scaling);
|
||||||
si.SetBoolValue("Display", "Stretch", display_stretch);
|
si.SetBoolValue("Display", "Stretch", display_stretch);
|
||||||
|
@ -767,12 +774,12 @@ const char* Settings::GetDisplayCropModeDisplayName(DisplayCropMode crop_mode)
|
||||||
return s_display_crop_mode_display_names[static_cast<int>(crop_mode)];
|
return s_display_crop_mode_display_names[static_cast<int>(crop_mode)];
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::array<const char*, 14> s_display_aspect_ratio_names = {
|
static std::array<const char*, 16> s_display_aspect_ratio_names = {
|
||||||
{TRANSLATABLE("DisplayAspectRatio", "Auto (Game Native)"), "4:3", "16:9", "16:10", "19:9", "20:9", "21:9", "32:9",
|
{TRANSLATABLE("DisplayAspectRatio", "Auto (Game Native)"), "Auto (Match Window)", "Custom", "4:3", "16:9", "16:10",
|
||||||
"8:7", "5:4", "3:2", "2:1 (VRAM 1:1)", "1:1", "PAR 1:1"}};
|
"19:9", "20:9", "21:9", "32:9", "8:7", "5:4", "3:2", "2:1 (VRAM 1:1)", "1:1", "PAR 1:1"}};
|
||||||
static constexpr std::array<float, 14> s_display_aspect_ratio_values = {
|
static constexpr std::array<float, 16> s_display_aspect_ratio_values = {
|
||||||
{-1.0f, 4.0f / 3.0f, 16.0f / 9.0f, 16.0f / 10.0f, 19.0f / 9.0f, 20.0f / 9.0f, 64.0f / 27.0f, 32.0f / 9.0f,
|
{-1.0f, -1.0f, -1.0f, 4.0f / 3.0f, 16.0f / 9.0f, 16.0f / 10.0f, 19.0f / 9.0f, 20.0f / 9.0f, 64.0f / 27.0f,
|
||||||
8.0f / 7.0f, 5.0f / 4.0f, 3.0f / 2.0f, 2.0f / 1.0f, 1.0f, -1.0f}};
|
32.0f / 9.0f, 8.0f / 7.0f, 5.0f / 4.0f, 3.0f / 2.0f, 2.0f / 1.0f, 1.0f, -1.0f}};
|
||||||
|
|
||||||
std::optional<DisplayAspectRatio> Settings::ParseDisplayAspectRatio(const char* str)
|
std::optional<DisplayAspectRatio> Settings::ParseDisplayAspectRatio(const char* str)
|
||||||
{
|
{
|
||||||
|
@ -793,9 +800,32 @@ const char* Settings::GetDisplayAspectRatioName(DisplayAspectRatio ar)
|
||||||
return s_display_aspect_ratio_names[static_cast<int>(ar)];
|
return s_display_aspect_ratio_names[static_cast<int>(ar)];
|
||||||
}
|
}
|
||||||
|
|
||||||
float Settings::GetDisplayAspectRatioValue(DisplayAspectRatio ar)
|
float Settings::GetDisplayAspectRatioValue() const
|
||||||
{
|
{
|
||||||
return s_display_aspect_ratio_values[static_cast<int>(ar)];
|
switch (display_aspect_ratio)
|
||||||
|
{
|
||||||
|
case DisplayAspectRatio::MatchWindow:
|
||||||
|
{
|
||||||
|
const HostDisplay* display = g_host_interface->GetDisplay();
|
||||||
|
if (!display)
|
||||||
|
return s_display_aspect_ratio_values[static_cast<int>(DEFAULT_DISPLAY_ASPECT_RATIO)];
|
||||||
|
|
||||||
|
const u32 width = display->GetWindowWidth();
|
||||||
|
const u32 height = display->GetWindowHeight() - display->GetDisplayTopMargin();
|
||||||
|
return static_cast<float>(width) / static_cast<float>(height);
|
||||||
|
}
|
||||||
|
|
||||||
|
case DisplayAspectRatio::Custom:
|
||||||
|
{
|
||||||
|
return static_cast<float>(display_aspect_ratio_custom_numerator) /
|
||||||
|
static_cast<float>(display_aspect_ratio_custom_denominator);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return s_display_aspect_ratio_values[static_cast<int>(display_aspect_ratio)];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::array<const char*, 3> s_audio_backend_names = {{
|
static std::array<const char*, 3> s_audio_backend_names = {{
|
||||||
|
|
|
@ -127,6 +127,8 @@ struct Settings
|
||||||
bool gpu_pgxp_depth_buffer = false;
|
bool gpu_pgxp_depth_buffer = false;
|
||||||
DisplayCropMode display_crop_mode = DisplayCropMode::None;
|
DisplayCropMode display_crop_mode = DisplayCropMode::None;
|
||||||
DisplayAspectRatio display_aspect_ratio = DisplayAspectRatio::Auto;
|
DisplayAspectRatio display_aspect_ratio = DisplayAspectRatio::Auto;
|
||||||
|
u16 display_aspect_ratio_custom_numerator = 0;
|
||||||
|
u16 display_aspect_ratio_custom_denominator = 0;
|
||||||
s16 display_active_start_offset = 0;
|
s16 display_active_start_offset = 0;
|
||||||
s16 display_active_end_offset = 0;
|
s16 display_active_end_offset = 0;
|
||||||
s8 display_line_start_offset = 0;
|
s8 display_line_start_offset = 0;
|
||||||
|
@ -256,6 +258,8 @@ struct Settings
|
||||||
return audio_output_muted ? 0 : (fast_forwarding ? audio_fast_forward_volume : audio_output_volume);
|
return audio_output_muted ? 0 : (fast_forwarding ? audio_fast_forward_volume : audio_output_volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float GetDisplayAspectRatioValue() const;
|
||||||
|
|
||||||
bool HasAnyPerGameMemoryCards() const;
|
bool HasAnyPerGameMemoryCards() const;
|
||||||
|
|
||||||
static void CPUOverclockPercentToFraction(u32 percent, u32* numerator, u32* denominator);
|
static void CPUOverclockPercentToFraction(u32 percent, u32* numerator, u32* denominator);
|
||||||
|
@ -316,7 +320,6 @@ struct Settings
|
||||||
|
|
||||||
static std::optional<DisplayAspectRatio> ParseDisplayAspectRatio(const char* str);
|
static std::optional<DisplayAspectRatio> ParseDisplayAspectRatio(const char* str);
|
||||||
static const char* GetDisplayAspectRatioName(DisplayAspectRatio ar);
|
static const char* GetDisplayAspectRatioName(DisplayAspectRatio ar);
|
||||||
static float GetDisplayAspectRatioValue(DisplayAspectRatio ar);
|
|
||||||
|
|
||||||
static std::optional<AudioBackend> ParseAudioBackend(const char* str);
|
static std::optional<AudioBackend> ParseAudioBackend(const char* str);
|
||||||
static const char* GetAudioBackendName(AudioBackend backend);
|
static const char* GetAudioBackendName(AudioBackend backend);
|
||||||
|
|
|
@ -94,6 +94,8 @@ enum class DisplayCropMode : u8
|
||||||
enum class DisplayAspectRatio : u8
|
enum class DisplayAspectRatio : u8
|
||||||
{
|
{
|
||||||
Auto,
|
Auto,
|
||||||
|
MatchWindow,
|
||||||
|
Custom,
|
||||||
R4_3,
|
R4_3,
|
||||||
R16_9,
|
R16_9,
|
||||||
R16_10,
|
R16_10,
|
||||||
|
|
|
@ -25,6 +25,10 @@ DisplaySettingsWidget::DisplaySettingsWidget(QtHostInterface* host_interface, QW
|
||||||
SettingWidgetBinder::BindWidgetToEnumSetting(m_host_interface, m_ui.displayAspectRatio, "Display", "AspectRatio",
|
SettingWidgetBinder::BindWidgetToEnumSetting(m_host_interface, m_ui.displayAspectRatio, "Display", "AspectRatio",
|
||||||
&Settings::ParseDisplayAspectRatio, &Settings::GetDisplayAspectRatioName,
|
&Settings::ParseDisplayAspectRatio, &Settings::GetDisplayAspectRatioName,
|
||||||
Settings::DEFAULT_DISPLAY_ASPECT_RATIO);
|
Settings::DEFAULT_DISPLAY_ASPECT_RATIO);
|
||||||
|
SettingWidgetBinder::BindWidgetToIntSetting(m_host_interface, m_ui.customAspectRatioNumerator, "Display",
|
||||||
|
"CustomAspectRatioNumerator", 1);
|
||||||
|
SettingWidgetBinder::BindWidgetToIntSetting(m_host_interface, m_ui.customAspectRatioDenominator, "Display",
|
||||||
|
"CustomAspectRatioDenominator", 1);
|
||||||
SettingWidgetBinder::BindWidgetToEnumSetting(m_host_interface, m_ui.displayCropMode, "Display", "CropMode",
|
SettingWidgetBinder::BindWidgetToEnumSetting(m_host_interface, m_ui.displayCropMode, "Display", "CropMode",
|
||||||
&Settings::ParseDisplayCropMode, &Settings::GetDisplayCropModeName,
|
&Settings::ParseDisplayCropMode, &Settings::GetDisplayCropModeName,
|
||||||
Settings::DEFAULT_DISPLAY_CROP_MODE);
|
Settings::DEFAULT_DISPLAY_CROP_MODE);
|
||||||
|
@ -59,10 +63,13 @@ DisplaySettingsWidget::DisplaySettingsWidget(QtHostInterface* host_interface, QW
|
||||||
&DisplaySettingsWidget::onGPUAdapterIndexChanged);
|
&DisplaySettingsWidget::onGPUAdapterIndexChanged);
|
||||||
connect(m_ui.fullscreenMode, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
connect(m_ui.fullscreenMode, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||||
&DisplaySettingsWidget::onGPUFullscreenModeIndexChanged);
|
&DisplaySettingsWidget::onGPUFullscreenModeIndexChanged);
|
||||||
|
connect(m_ui.displayAspectRatio, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||||
|
&DisplaySettingsWidget::onAspectRatioChanged);
|
||||||
connect(m_ui.displayIntegerScaling, &QCheckBox::stateChanged, this,
|
connect(m_ui.displayIntegerScaling, &QCheckBox::stateChanged, this,
|
||||||
&DisplaySettingsWidget::onIntegerFilteringChanged);
|
&DisplaySettingsWidget::onIntegerFilteringChanged);
|
||||||
populateGPUAdaptersAndResolutions();
|
populateGPUAdaptersAndResolutions();
|
||||||
onIntegerFilteringChanged();
|
onIntegerFilteringChanged();
|
||||||
|
onAspectRatioChanged();
|
||||||
|
|
||||||
dialog->registerWidgetHelp(
|
dialog->registerWidgetHelp(
|
||||||
m_ui.renderer, tr("Renderer"),
|
m_ui.renderer, tr("Renderer"),
|
||||||
|
@ -283,3 +290,13 @@ void DisplaySettingsWidget::onIntegerFilteringChanged()
|
||||||
m_ui.displayLinearFiltering->setEnabled(!m_ui.displayIntegerScaling->isChecked());
|
m_ui.displayLinearFiltering->setEnabled(!m_ui.displayIntegerScaling->isChecked());
|
||||||
m_ui.displayStretch->setEnabled(!m_ui.displayIntegerScaling->isChecked());
|
m_ui.displayStretch->setEnabled(!m_ui.displayIntegerScaling->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisplaySettingsWidget::onAspectRatioChanged()
|
||||||
|
{
|
||||||
|
const bool is_custom =
|
||||||
|
static_cast<DisplayAspectRatio>(m_ui.displayAspectRatio->currentIndex()) == DisplayAspectRatio::Custom;
|
||||||
|
|
||||||
|
m_ui.customAspectRatioNumerator->setVisible(is_custom);
|
||||||
|
m_ui.customAspectRatioDenominator->setVisible(is_custom);
|
||||||
|
m_ui.customAspectRatioSeparator->setVisible(is_custom);
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ private Q_SLOTS:
|
||||||
void onGPUAdapterIndexChanged();
|
void onGPUAdapterIndexChanged();
|
||||||
void onGPUFullscreenModeIndexChanged();
|
void onGPUFullscreenModeIndexChanged();
|
||||||
void onIntegerFilteringChanged();
|
void onIntegerFilteringChanged();
|
||||||
|
void onAspectRatioChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupAdditionalUi();
|
void setupAdditionalUi();
|
||||||
|
|
|
@ -111,7 +111,38 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QComboBox" name="displayAspectRatio"/>
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0,0,0">
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="displayAspectRatio"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="customAspectRatioNumerator">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>9999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="customAspectRatioSeparator">
|
||||||
|
<property name="text">
|
||||||
|
<string>:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="customAspectRatioDenominator">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>9999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
|
|
|
@ -575,6 +575,8 @@ void CommonHostInterface::OnHostDisplayResized()
|
||||||
const u32 new_height = m_display ? m_display->GetWindowHeight() : 0;
|
const u32 new_height = m_display ? m_display->GetWindowHeight() : 0;
|
||||||
const float new_scale = m_display ? m_display->GetWindowScale() : 1.0f;
|
const float new_scale = m_display ? m_display->GetWindowScale() : 1.0f;
|
||||||
|
|
||||||
|
HostInterface::OnHostDisplayResized();
|
||||||
|
|
||||||
ImGui::GetIO().DisplaySize.x = static_cast<float>(new_width);
|
ImGui::GetIO().DisplaySize.x = static_cast<float>(new_width);
|
||||||
ImGui::GetIO().DisplaySize.y = static_cast<float>(new_height);
|
ImGui::GetIO().DisplaySize.y = static_cast<float>(new_height);
|
||||||
|
|
||||||
|
|
|
@ -412,13 +412,13 @@ protected:
|
||||||
void UpdateSpeedLimiterState();
|
void UpdateSpeedLimiterState();
|
||||||
|
|
||||||
void RecreateSystem() override;
|
void RecreateSystem() override;
|
||||||
|
void OnHostDisplayResized() override;
|
||||||
|
|
||||||
void ApplyGameSettings(bool display_osd_messages);
|
void ApplyGameSettings(bool display_osd_messages);
|
||||||
void ApplyControllerCompatibilitySettings(u64 controller_mask, bool display_osd_messages);
|
void ApplyControllerCompatibilitySettings(u64 controller_mask, bool display_osd_messages);
|
||||||
|
|
||||||
bool CreateHostDisplayResources();
|
bool CreateHostDisplayResources();
|
||||||
void ReleaseHostDisplayResources();
|
void ReleaseHostDisplayResources();
|
||||||
void OnHostDisplayResized();
|
|
||||||
|
|
||||||
virtual void DrawImGuiWindows();
|
virtual void DrawImGuiWindows();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue