Reworked the "Force NTSC Timings" feature to support both NTSC and PAL frame timings (#3287)

This commit is contained in:
spacepaw
2024-09-03 10:50:45 +02:00
committed by Stenzek
parent 4c51337edd
commit 63abdb7afd
12 changed files with 118 additions and 43 deletions
+6 -6
View File
@@ -4271,6 +4271,12 @@ void FullscreenUI::DrawDisplaySettingsPage()
"Display", "Scaling", Settings::DEFAULT_DISPLAY_SCALING, &Settings::ParseDisplayScaling,
&Settings::GetDisplayScalingName, &Settings::GetDisplayScalingDisplayName, DisplayScalingMode::Count);
DrawEnumSetting(
bsi, FSUI_CSTR("Force Frame Timings"),
FSUI_CSTR("Utilizes the chosen frame timing regardless of the active region."),
"GPU", "ForceFrameTimings", Settings::DEFAULT_FORCE_FRAME_TIMINGS_MODE, &Settings::ParseForceFrameTimings,
&Settings::GetForceFrameTimingsName, &Settings::GetForceFrameTimingsDisplayName, ForceFrameTimingsMode::Count);
if (is_hardware)
{
DrawToggleSetting(bsi, FSUI_CSTR("True Color Rendering"),
@@ -4310,12 +4316,6 @@ void FullscreenUI::DrawDisplaySettingsPage()
"but others will break."),
"GPU", "DisableInterlacing", true);
DrawToggleSetting(
bsi, FSUI_CSTR("Force NTSC Timings"),
FSUI_CSTR("Forces PAL games to run at NTSC timings, i.e. 60hz. Some PAL games will run at their \"normal\" "
"speeds, while others will break."),
"GPU", "ForceNTSCTimings", false);
MenuHeading(FSUI_CSTR("Advanced"));
std::optional<SmallString> strvalue = bsi->GetOptionalSmallStringValue(
+6 -6
View File
@@ -75,7 +75,7 @@ static constexpr const std::array<const char*, static_cast<u32>(GameDatabase::Tr
"DisableTextureFiltering",
"DisableSpriteTextureFiltering",
"DisableScaledDithering",
"DisableForceNTSCTimings",
"DisableForceFrameTimings",
"DisableWidescreen",
"DisablePGXP",
"DisablePGXPCulling",
@@ -105,7 +105,7 @@ static constexpr const std::array<const char*, static_cast<u32>(GameDatabase::Tr
TRANSLATE_NOOP("GameDatabase", "Disable Texture Filtering"),
TRANSLATE_NOOP("GameDatabase", "Disable Sprite Texture Filtering"),
TRANSLATE_NOOP("GameDatabase", "Disable Scaled Dithering"),
TRANSLATE_NOOP("GameDatabase", "Disable Force NTSC Timings"),
TRANSLATE_NOOP("GameDatabase", "Disable Force Frame Timings"),
TRANSLATE_NOOP("GameDatabase", "Disable Widescreen"),
TRANSLATE_NOOP("GameDatabase", "Disable PGXP"),
TRANSLATE_NOOP("GameDatabase", "Disable PGXP Culling"),
@@ -590,12 +590,12 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes
settings.gpu_widescreen_hack = false;
}
if (HasTrait(Trait::DisableForceNTSCTimings))
if (HasTrait(Trait::DisableForceFrameTimings))
{
if (display_osd_messages && settings.gpu_force_ntsc_timings)
APPEND_MESSAGE(TRANSLATE_SV("GameDatabase", "Force NTSC timings disabled."));
if (display_osd_messages && settings.gpu_force_frame_timings != ForceFrameTimingsMode::Disabled)
APPEND_MESSAGE(TRANSLATE_SV("GameDatabase", "Force frame timings disabled."));
settings.gpu_force_ntsc_timings = false;
settings.gpu_force_frame_timings = ForceFrameTimingsMode::Disabled;
}
if (HasTrait(Trait::DisablePGXP))
+1 -1
View File
@@ -40,7 +40,7 @@ enum class Trait : u32
DisableTextureFiltering,
DisableSpriteTextureFiltering,
DisableScaledDithering,
DisableForceNTSCTimings,
DisableForceFrameTimings,
DisableWidescreen,
DisablePGXP,
DisablePGXPCulling,
+22 -4
View File
@@ -88,7 +88,7 @@ GPU::~GPU()
bool GPU::Initialize()
{
m_force_progressive_scan = g_settings.gpu_disable_interlacing;
m_force_ntsc_timings = g_settings.gpu_force_ntsc_timings;
m_force_frame_timings = g_settings.gpu_force_frame_timings;
s_crtc_tick_event.Activate();
m_fifo_size = g_settings.gpu_fifo_size;
m_max_run_ahead = g_settings.gpu_max_run_ahead;
@@ -119,9 +119,9 @@ void GPU::UpdateSettings(const Settings& old_settings)
m_fifo_size = g_settings.gpu_fifo_size;
m_max_run_ahead = g_settings.gpu_max_run_ahead;
if (m_force_ntsc_timings != g_settings.gpu_force_ntsc_timings || m_console_is_pal != System::IsPALRegion())
if (m_force_frame_timings != g_settings.gpu_force_frame_timings)
{
m_force_ntsc_timings = g_settings.gpu_force_ntsc_timings;
m_force_frame_timings = g_settings.gpu_force_frame_timings;
m_console_is_pal = System::IsPALRegion();
UpdateCRTCConfig();
}
@@ -637,7 +637,7 @@ void GPU::UpdateCRTCConfig()
cs.vertical_display_start = std::min<u16>(cs.regs.Y1, cs.vertical_total);
cs.vertical_display_end = std::min<u16>(cs.regs.Y2, cs.vertical_total);
if (m_GPUSTAT.pal_mode && m_force_ntsc_timings)
if (m_GPUSTAT.pal_mode && m_force_frame_timings == ForceFrameTimingsMode::NTSC)
{
// scale to NTSC parameters
cs.horizontal_display_start =
@@ -655,6 +655,24 @@ void GPU::UpdateCRTCConfig()
cs.horizontal_total = NTSC_TICKS_PER_LINE;
cs.current_tick_in_scanline %= NTSC_TICKS_PER_LINE;
}
else if (!m_GPUSTAT.pal_mode && m_force_frame_timings == ForceFrameTimingsMode::PAL)
{
// scale to PAL parameters
cs.horizontal_display_start =
static_cast<u16>((static_cast<u32>(cs.horizontal_display_start) * PAL_TICKS_PER_LINE) / NTSC_TICKS_PER_LINE);
cs.horizontal_display_end = static_cast<u16>(
((static_cast<u32>(cs.horizontal_display_end) * PAL_TICKS_PER_LINE) + (NTSC_TICKS_PER_LINE - 1)) /
NTSC_TICKS_PER_LINE);
cs.vertical_display_start =
static_cast<u16>((static_cast<u32>(cs.vertical_display_start) * PAL_TOTAL_LINES) / NTSC_TOTAL_LINES);
cs.vertical_display_end = static_cast<u16>(
((static_cast<u32>(cs.vertical_display_end) * PAL_TOTAL_LINES) + (NTSC_TOTAL_LINES - 1)) / NTSC_TOTAL_LINES);
cs.vertical_total = PAL_TOTAL_LINES;
cs.current_scanline %= PAL_TOTAL_LINES;
cs.horizontal_total = PAL_TICKS_PER_LINE;
cs.current_tick_in_scanline %= PAL_TICKS_PER_LINE;
}
cs.horizontal_display_start =
static_cast<u16>(System::ScaleTicksToOverclock(static_cast<TickCount>(cs.horizontal_display_start)));
+1 -1
View File
@@ -505,7 +505,7 @@ protected:
bool m_set_texture_disable_mask = false;
bool m_drawing_area_changed = false;
bool m_force_progressive_scan = false;
bool m_force_ntsc_timings = false;
ForceFrameTimingsMode m_force_frame_timings = ForceFrameTimingsMode::Disabled;
struct CRTCState
{
+3 -1
View File
@@ -435,8 +435,10 @@ void ImGuiManager::DrawEnhancementsOverlay()
text.append(" TrueCol");
if (g_settings.gpu_disable_interlacing)
text.append(" ForceProg");
if (g_settings.gpu_force_ntsc_timings && System::GetRegion() == ConsoleRegion::PAL)
if (g_settings.gpu_force_frame_timings == ForceFrameTimingsMode::NTSC && System::GetRegion() == ConsoleRegion::PAL)
text.append(" PAL60");
if (g_settings.gpu_force_frame_timings == ForceFrameTimingsMode::PAL && System::GetRegion() != ConsoleRegion::PAL)
text.append(" NTSC50");
if (g_settings.gpu_texture_filter != GPUTextureFilter::Nearest)
{
if (g_settings.gpu_sprite_texture_filter != g_settings.gpu_texture_filter)
+31 -3
View File
@@ -228,7 +228,10 @@ void Settings::Load(SettingsInterface& si, SettingsInterface& controller_si)
si.GetStringValue("GPU", "WireframeMode", GetGPUWireframeModeName(DEFAULT_GPU_WIREFRAME_MODE)).c_str())
.value_or(DEFAULT_GPU_WIREFRAME_MODE);
gpu_disable_interlacing = si.GetBoolValue("GPU", "DisableInterlacing", true);
gpu_force_ntsc_timings = si.GetBoolValue("GPU", "ForceNTSCTimings", false);
gpu_force_frame_timings =
ParseForceFrameTimings(
si.GetStringValue("GPU", "ForceFrameTimings", GetForceFrameTimingsName(DEFAULT_FORCE_FRAME_TIMINGS_MODE)).c_str())
.value_or(DEFAULT_FORCE_FRAME_TIMINGS_MODE);
gpu_widescreen_hack = si.GetBoolValue("GPU", "WidescreenHack", false);
display_24bit_chroma_smoothing = si.GetBoolValue("GPU", "ChromaSmoothing24Bit", false);
gpu_pgxp_enable = si.GetBoolValue("GPU", "PGXPEnable", false);
@@ -533,7 +536,7 @@ void Settings::Save(SettingsInterface& si, bool ignore_base) const
si.SetUIntValue("GPU", "DownsampleScale", gpu_downsample_scale);
si.SetStringValue("GPU", "WireframeMode", GetGPUWireframeModeName(gpu_wireframe_mode));
si.SetBoolValue("GPU", "DisableInterlacing", gpu_disable_interlacing);
si.SetBoolValue("GPU", "ForceNTSCTimings", gpu_force_ntsc_timings);
si.SetStringValue("GPU", "ForceFrameTimings", GetForceFrameTimingsName(gpu_force_frame_timings));
si.SetBoolValue("GPU", "WidescreenHack", gpu_widescreen_hack);
si.SetBoolValue("GPU", "ChromaSmoothing24Bit", display_24bit_chroma_smoothing);
si.SetBoolValue("GPU", "PGXPEnable", gpu_pgxp_enable);
@@ -741,7 +744,7 @@ void Settings::FixIncompatibleSettings(bool display_osd_messages)
g_settings.gpu_sprite_texture_filter = GPUTextureFilter::Nearest;
g_settings.gpu_line_detect_mode = GPULineDetectMode::Disabled;
g_settings.gpu_disable_interlacing = false;
g_settings.gpu_force_ntsc_timings = false;
g_settings.gpu_force_frame_timings = ForceFrameTimingsMode::Disabled;
g_settings.gpu_widescreen_hack = false;
g_settings.gpu_pgxp_enable = false;
g_settings.display_24bit_chroma_smoothing = false;
@@ -1504,7 +1507,22 @@ const char* Settings::GetDisplayRotationDisplayName(DisplayRotation rotation)
{
return Host::TranslateToCString("Settings", s_display_rotation_display_names[static_cast<size_t>(rotation)]);
}
static constexpr const std::array s_display_force_frame_timings_names = {
"Disabled", "NTSC", "PAL"
};
std::optional<ForceFrameTimingsMode> Settings::ParseForceFrameTimings(const char* str)
{
int index = 0;
for (const char* name : s_display_force_frame_timings_names)
{
if (StringUtil::Strcasecmp(name, str) == 0)
return static_cast<ForceFrameTimingsMode>(index);
index++;
}
return std::nullopt;
}
static constexpr const std::array s_display_scaling_names = {
"Nearest", "NearestInteger", "BilinearSmooth", "BilinearSharp", "BilinearInteger",
};
@@ -1540,6 +1558,16 @@ const char* Settings::GetDisplayScalingDisplayName(DisplayScalingMode mode)
return Host::TranslateToCString("DisplayScalingMode", s_display_scaling_display_names[static_cast<int>(mode)]);
}
const char* Settings::GetForceFrameTimingsName(ForceFrameTimingsMode mode)
{
return s_display_force_frame_timings_names[static_cast<int>(mode)];
}
const char* Settings::GetForceFrameTimingsDisplayName(ForceFrameTimingsMode mode)
{
return Host::TranslateToCString("ForceFrameTimingsMode", s_display_force_frame_timings_names[static_cast<int>(mode)]);
}
static constexpr const std::array s_display_exclusive_fullscreen_mode_names = {
"Automatic",
"Disallowed",
+6 -1
View File
@@ -121,7 +121,6 @@ struct Settings
bool gpu_force_round_texcoords : 1 = false;
bool gpu_accurate_blending : 1 = false;
bool gpu_disable_interlacing : 1 = true;
bool gpu_force_ntsc_timings : 1 = false;
bool gpu_widescreen_hack : 1 = false;
bool gpu_pgxp_enable : 1 = false;
bool gpu_pgxp_culling : 1 = true;
@@ -132,6 +131,7 @@ struct Settings
bool gpu_pgxp_preserve_proj_fp : 1 = false;
bool gpu_pgxp_depth_buffer : 1 = false;
bool gpu_pgxp_disable_2d : 1 = false;
ForceFrameTimingsMode gpu_force_frame_timings = DEFAULT_FORCE_FRAME_TIMINGS_MODE;
GPUTextureFilter gpu_texture_filter = DEFAULT_GPU_TEXTURE_FILTER;
GPUTextureFilter gpu_sprite_texture_filter = DEFAULT_GPU_TEXTURE_FILTER;
GPULineDetectMode gpu_line_detect_mode = DEFAULT_GPU_LINE_DETECT_MODE;
@@ -433,6 +433,10 @@ struct Settings
static const char* GetDisplayScalingName(DisplayScalingMode mode);
static const char* GetDisplayScalingDisplayName(DisplayScalingMode mode);
static std::optional<ForceFrameTimingsMode> ParseForceFrameTimings(const char* str);
static const char* GetForceFrameTimingsName(ForceFrameTimingsMode mode);
static const char* GetForceFrameTimingsDisplayName(ForceFrameTimingsMode mode);
static std::optional<DisplayExclusiveFullscreenControl> ParseDisplayExclusiveFullscreenControl(const char* str);
static const char* GetDisplayExclusiveFullscreenControlName(DisplayExclusiveFullscreenControl mode);
static const char* GetDisplayExclusiveFullscreenControlDisplayName(DisplayExclusiveFullscreenControl mode);
@@ -491,6 +495,7 @@ struct Settings
static constexpr DisplayAlignment DEFAULT_DISPLAY_ALIGNMENT = DisplayAlignment::Center;
static constexpr DisplayRotation DEFAULT_DISPLAY_ROTATION = DisplayRotation::Normal;
static constexpr DisplayScalingMode DEFAULT_DISPLAY_SCALING = DisplayScalingMode::BilinearSmooth;
static constexpr ForceFrameTimingsMode DEFAULT_FORCE_FRAME_TIMINGS_MODE = ForceFrameTimingsMode::Disabled;
static constexpr DisplayExclusiveFullscreenControl DEFAULT_DISPLAY_EXCLUSIVE_FULLSCREEN_CONTROL =
DisplayExclusiveFullscreenControl::Automatic;
static constexpr DisplayScreenshotMode DEFAULT_DISPLAY_SCREENSHOT_MODE = DisplayScreenshotMode::ScreenResolution;
+3 -3
View File
@@ -4303,7 +4303,7 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
g_settings.gpu_sprite_texture_filter != old_settings.gpu_sprite_texture_filter ||
g_settings.gpu_line_detect_mode != old_settings.gpu_line_detect_mode ||
g_settings.gpu_disable_interlacing != old_settings.gpu_disable_interlacing ||
g_settings.gpu_force_ntsc_timings != old_settings.gpu_force_ntsc_timings ||
g_settings.gpu_force_frame_timings != old_settings.gpu_force_frame_timings ||
g_settings.gpu_downsample_mode != old_settings.gpu_downsample_mode ||
g_settings.gpu_downsample_scale != old_settings.gpu_downsample_scale ||
g_settings.gpu_wireframe_mode != old_settings.gpu_wireframe_mode ||
@@ -4530,9 +4530,9 @@ void System::WarnAboutUnsafeSettings()
TinyString(TRANSLATE_SV("System", "Instant")) :
TinyString::from_format("{}x", g_settings.cdrom_seek_speedup)));
}
if (g_settings.gpu_force_ntsc_timings)
if (g_settings.gpu_force_frame_timings != ForceFrameTimingsMode::Disabled)
{
append(ICON_FA_TV, TRANSLATE_SV("System", "Force NTSC timings is enabled. Games may run at incorrect speeds."));
append(ICON_FA_TV, TRANSLATE_SV("System", "Force frame timings is enabled. Games may run at incorrect speeds."));
}
if (!g_settings.IsUsingSoftwareRenderer())
{
+9
View File
@@ -275,3 +275,12 @@ enum class SaveStateCompressionMode : u8
Count,
};
enum class ForceFrameTimingsMode : u8
{
Disabled,
NTSC,
PAL,
Count,
};