From 022b2fc013534ce5271b01124a0db0dae68d2df6 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 21 Jul 2024 16:04:05 +1000 Subject: [PATCH] Qt: Disable incompatible settings in game properties --- src/duckstation-qt/consolesettingswidget.cpp | 13 +++- src/duckstation-qt/consolesettingswidget.ui | 2 +- src/duckstation-qt/graphicssettingswidget.cpp | 69 ++++++++++++++----- src/duckstation-qt/settingswindow.cpp | 8 ++- src/duckstation-qt/settingswindow.h | 4 ++ src/duckstation-qt/settingwidgetbinder.h | 35 ++++++++++ 6 files changed, 111 insertions(+), 20 deletions(-) diff --git a/src/duckstation-qt/consolesettingswidget.cpp b/src/duckstation-qt/consolesettingswidget.cpp index 104cd2fb6..19ac11cfd 100644 --- a/src/duckstation-qt/consolesettingswidget.cpp +++ b/src/duckstation-qt/consolesettingswidget.cpp @@ -1,12 +1,16 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "consolesettingswidget.h" -#include "core/system.h" #include "qtutils.h" #include "settingswindow.h" #include "settingwidgetbinder.h" + +#include "core/game_database.h" +#include "core/system.h" + #include "util/cd_image.h" + #include #include @@ -122,6 +126,11 @@ ConsoleSettingsWidget::ConsoleSettingsWidget(SettingsWindow* dialog, QWidget* pa &ConsoleSettingsWidget::onEnableCPUClockSpeedControlChecked); connect(m_ui.cpuClockSpeed, &QSlider::valueChanged, this, &ConsoleSettingsWidget::onCPUClockSpeedValueChanged); + SettingWidgetBinder::SetAvailability(m_ui.cpuExecutionModeLabel, + !m_dialog->hasGameTrait(GameDatabase::Trait::ForceInterpreter)); + SettingWidgetBinder::SetAvailability(m_ui.cpuExecutionMode, + !m_dialog->hasGameTrait(GameDatabase::Trait::ForceInterpreter)); + calculateCPUClockValue(); } diff --git a/src/duckstation-qt/consolesettingswidget.ui b/src/duckstation-qt/consolesettingswidget.ui index b62e582f7..80a118961 100644 --- a/src/duckstation-qt/consolesettingswidget.ui +++ b/src/duckstation-qt/consolesettingswidget.ui @@ -74,7 +74,7 @@ - + Execution Mode: diff --git a/src/duckstation-qt/graphicssettingswidget.cpp b/src/duckstation-qt/graphicssettingswidget.cpp index 09606ba38..c4ecb5932 100644 --- a/src/duckstation-qt/graphicssettingswidget.cpp +++ b/src/duckstation-qt/graphicssettingswidget.cpp @@ -2,12 +2,14 @@ // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #include "graphicssettingswidget.h" -#include "core/gpu.h" -#include "core/settings.h" #include "qtutils.h" #include "settingswindow.h" #include "settingwidgetbinder.h" +#include "core/game_database.h" +#include "core/gpu.h" +#include "core/settings.h" + #include static QVariant GetMSAAModeValue(uint multisamples, bool ssaa) @@ -90,6 +92,21 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* connect(m_ui.trueColor, &QCheckBox::checkStateChanged, this, &GraphicsSettingsWidget::onTrueColorChanged); connect(m_ui.pgxpEnable, &QCheckBox::checkStateChanged, this, &GraphicsSettingsWidget::updatePGXPSettingsEnabled); + SettingWidgetBinder::SetAvailability(m_ui.renderer, + !m_dialog->hasGameTrait(GameDatabase::Trait::ForceSoftwareRenderer)); + SettingWidgetBinder::SetAvailability(m_ui.resolutionScale, + !m_dialog->hasGameTrait(GameDatabase::Trait::DisableUpscaling)); + SettingWidgetBinder::SetAvailability(m_ui.textureFiltering, + !m_dialog->hasGameTrait(GameDatabase::Trait::DisableTextureFiltering)); + SettingWidgetBinder::SetAvailability(m_ui.trueColor, !m_dialog->hasGameTrait(GameDatabase::Trait::DisableTrueColor)); + SettingWidgetBinder::SetAvailability(m_ui.pgxpEnable, !m_dialog->hasGameTrait(GameDatabase::Trait::DisablePGXP)); + SettingWidgetBinder::SetAvailability(m_ui.disableInterlacing, + !m_dialog->hasGameTrait(GameDatabase::Trait::ForceInterlacing)); + SettingWidgetBinder::SetAvailability(m_ui.widescreenHack, + !m_dialog->hasGameTrait(GameDatabase::Trait::DisableWidescreen)); + SettingWidgetBinder::SetAvailability(m_ui.forceNTSCTimings, + !m_dialog->hasGameTrait(GameDatabase::Trait::DisableForceNTSCTimings)); + // Advanced Tab SettingWidgetBinder::BindWidgetToEnumSetting( @@ -122,6 +139,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.forceRoundedTexcoords, "GPU", "ForceRoundTextureCoordinates", false); + SettingWidgetBinder::SetAvailability(m_ui.scaledDithering, + !m_dialog->hasGameTrait(GameDatabase::Trait::DisableScaledDithering)); + // PGXP Tab SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.pgxpGeometryTolerance, "GPU", "PGXPTolerance", -1.0f); @@ -141,6 +161,15 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* connect(m_ui.pgxpDepthBuffer, &QCheckBox::checkStateChanged, this, &GraphicsSettingsWidget::updatePGXPSettingsEnabled); + SettingWidgetBinder::SetAvailability(m_ui.pgxpTextureCorrection, + !m_dialog->hasGameTrait(GameDatabase::Trait::DisablePGXPTextureCorrection)); + SettingWidgetBinder::SetAvailability(m_ui.pgxpColorCorrection, + !m_dialog->hasGameTrait(GameDatabase::Trait::DisablePGXPColorCorrection)); + SettingWidgetBinder::SetAvailability(m_ui.pgxpCulling, + !m_dialog->hasGameTrait(GameDatabase::Trait::DisablePGXPCulling)); + SettingWidgetBinder::SetAvailability(m_ui.pgxpPreserveProjPrecision, + !m_dialog->hasGameTrait(GameDatabase::Trait::DisablePGXPPreserveProjFP)); + // OSD Tab SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.osdScale, "Display", "OSDScale", 100); @@ -619,24 +648,26 @@ void GraphicsSettingsWidget::updateRendererDependentOptions() const RenderAPI render_api = Settings::GetRenderAPIForRenderer(renderer); const bool is_hardware = (renderer != GPURenderer::Software); - m_ui.resolutionScale->setEnabled(is_hardware); - m_ui.resolutionScaleLabel->setEnabled(is_hardware); + m_ui.resolutionScale->setEnabled(is_hardware && !m_dialog->hasGameTrait(GameDatabase::Trait::DisableUpscaling)); + m_ui.resolutionScaleLabel->setEnabled(is_hardware && !m_dialog->hasGameTrait(GameDatabase::Trait::DisableUpscaling)); m_ui.msaaMode->setEnabled(is_hardware); m_ui.msaaModeLabel->setEnabled(is_hardware); - m_ui.textureFiltering->setEnabled(is_hardware); - m_ui.textureFilteringLabel->setEnabled(is_hardware); + m_ui.textureFiltering->setEnabled(is_hardware && + !m_dialog->hasGameTrait(GameDatabase::Trait::DisableTextureFiltering)); + m_ui.textureFilteringLabel->setEnabled(is_hardware && + !m_dialog->hasGameTrait(GameDatabase::Trait::DisableTextureFiltering)); m_ui.gpuDownsampleLabel->setEnabled(is_hardware); m_ui.gpuDownsampleMode->setEnabled(is_hardware); m_ui.gpuDownsampleScale->setEnabled(is_hardware); - m_ui.trueColor->setEnabled(is_hardware); - m_ui.pgxpEnable->setEnabled(is_hardware); + m_ui.trueColor->setEnabled(is_hardware && !m_dialog->hasGameTrait(GameDatabase::Trait::DisableTrueColor)); + m_ui.pgxpEnable->setEnabled(is_hardware && !m_dialog->hasGameTrait(GameDatabase::Trait::DisablePGXP)); m_ui.gpuLineDetectMode->setEnabled(is_hardware); m_ui.gpuLineDetectModeLabel->setEnabled(is_hardware); m_ui.gpuWireframeMode->setEnabled(is_hardware); m_ui.gpuWireframeModeLabel->setEnabled(is_hardware); m_ui.debanding->setEnabled(is_hardware); - m_ui.scaledDithering->setEnabled(is_hardware); + m_ui.scaledDithering->setEnabled(is_hardware && !m_dialog->hasGameTrait(GameDatabase::Trait::DisableScaledDithering)); m_ui.useSoftwareRendererForReadbacks->setEnabled(is_hardware); m_ui.tabs->setTabEnabled(TAB_INDEX_TEXTURE_REPLACEMENTS, is_hardware); @@ -712,6 +743,7 @@ void GraphicsSettingsWidget::populateGPUAdaptersAndResolutions(RenderAPI render_ SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.fullscreenMode, "GPU", "FullscreenMode"); } + if (!m_dialog->hasGameTrait(GameDatabase::Trait::DisableUpscaling)) { m_ui.resolutionScale->disconnect(); m_ui.resolutionScale->clear(); @@ -790,16 +822,20 @@ void GraphicsSettingsWidget::populateGPUAdaptersAndResolutions(RenderAPI render_ void GraphicsSettingsWidget::updatePGXPSettingsEnabled() { - const bool enabled = (effectiveRendererIsHardware() && m_dialog->getEffectiveBoolValue("GPU", "PGXPEnable", false)); + const bool enabled = (effectiveRendererIsHardware() && m_dialog->getEffectiveBoolValue("GPU", "PGXPEnable", false) && + !m_dialog->hasGameTrait(GameDatabase::Trait::DisablePGXP)); const bool tc_enabled = (enabled && m_dialog->getEffectiveBoolValue("GPU", "PGXPTextureCorrection", true)); const bool depth_enabled = (enabled && m_dialog->getEffectiveBoolValue("GPU", "PGXPDepthBuffer", false)); m_ui.tabs->setTabEnabled(TAB_INDEX_PGXP, enabled); m_ui.pgxpTab->setEnabled(enabled); - m_ui.pgxpCulling->setEnabled(enabled); - m_ui.pgxpTextureCorrection->setEnabled(enabled); - m_ui.pgxpColorCorrection->setEnabled(tc_enabled); - m_ui.pgxpDepthBuffer->setEnabled(enabled); - m_ui.pgxpPreserveProjPrecision->setEnabled(enabled); + m_ui.pgxpCulling->setEnabled(enabled && !m_dialog->hasGameTrait(GameDatabase::Trait::DisablePGXPCulling)); + m_ui.pgxpTextureCorrection->setEnabled(enabled && + !m_dialog->hasGameTrait(GameDatabase::Trait::DisablePGXPTextureCorrection)); + m_ui.pgxpColorCorrection->setEnabled(tc_enabled && + !m_dialog->hasGameTrait(GameDatabase::Trait::DisablePGXPColorCorrection)); + m_ui.pgxpDepthBuffer->setEnabled(enabled && !m_dialog->hasGameTrait(GameDatabase::Trait::DisablePGXPDepthBuffer)); + m_ui.pgxpPreserveProjPrecision->setEnabled(enabled && + !m_dialog->hasGameTrait(GameDatabase::Trait::DisablePGXPPreserveProjFP)); m_ui.pgxpCPU->setEnabled(enabled); m_ui.pgxpVertexCache->setEnabled(enabled); m_ui.pgxpGeometryTolerance->setEnabled(enabled); @@ -843,7 +879,8 @@ void GraphicsSettingsWidget::onTrueColorChanged() { const int resolution_scale = m_dialog->getEffectiveIntValue("GPU", "ResolutionScale", 1); const bool true_color = m_dialog->getEffectiveBoolValue("GPU", "TrueColor", false); - const bool allow_scaled_dithering = (resolution_scale != 1 && !true_color); + const bool allow_scaled_dithering = + (resolution_scale != 1 && !true_color && !m_dialog->hasGameTrait(GameDatabase::Trait::DisableScaledDithering)); const bool allow_debanding = true_color; m_ui.scaledDithering->setEnabled(allow_scaled_dithering); m_ui.debanding->setEnabled(allow_debanding); diff --git a/src/duckstation-qt/settingswindow.cpp b/src/duckstation-qt/settingswindow.cpp index f1bef85ec..73b066ca5 100644 --- a/src/duckstation-qt/settingswindow.cpp +++ b/src/duckstation-qt/settingswindow.cpp @@ -48,7 +48,7 @@ SettingsWindow::SettingsWindow() : QWidget() SettingsWindow::SettingsWindow(const std::string& path, const std::string& serial, DiscRegion region, const GameDatabase::Entry* entry, std::unique_ptr sif) - : QWidget(), m_sif(std::move(sif)) + : QWidget(), m_sif(std::move(sif)), m_database_entry(entry) { m_ui.setupUi(this); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); @@ -611,6 +611,12 @@ void SettingsWindow::saveAndReloadGameSettings() g_emu_thread->reloadGameSettings(false); } +bool SettingsWindow::hasGameTrait(GameDatabase::Trait trait) +{ + return (m_database_entry && m_database_entry->HasTrait(trait) && + m_sif->GetBoolValue("Main", "ApplyCompatibilitySettings", true)); +} + void SettingsWindow::openGamePropertiesDialog(const std::string& path, const std::string& title, const std::string& serial, DiscRegion region) { diff --git a/src/duckstation-qt/settingswindow.h b/src/duckstation-qt/settingswindow.h index a5e63c58e..e3aa5d8f7 100644 --- a/src/duckstation-qt/settingswindow.h +++ b/src/duckstation-qt/settingswindow.h @@ -18,6 +18,7 @@ class QWheelEvent; enum class DiscRegion : u8; namespace GameDatabase { +enum class Trait : u32; struct Entry; } @@ -91,6 +92,8 @@ public: void removeSettingValue(const char* section, const char* key); void saveAndReloadGameSettings(); + bool hasGameTrait(GameDatabase::Trait trait); + Q_SIGNALS: void settingsResetToDefaults(); @@ -123,6 +126,7 @@ private: Ui::SettingsWindow m_ui; std::unique_ptr m_sif; + const GameDatabase::Entry* m_database_entry = nullptr; InterfaceSettingsWidget* m_general_settings = nullptr; BIOSSettingsWidget* m_bios_settings = nullptr; diff --git a/src/duckstation-qt/settingwidgetbinder.h b/src/duckstation-qt/settingwidgetbinder.h index 63908578c..b16062da6 100644 --- a/src/duckstation-qt/settingwidgetbinder.h +++ b/src/duckstation-qt/settingwidgetbinder.h @@ -1283,4 +1283,39 @@ static inline void BindWidgetToFolderSetting(SettingsInterface* sif, QLineEdit* widget->connect(widget, &QLineEdit::editingFinished, widget, std::move(value_changed)); } + +template +static inline void SetAvailability(WidgetType* widget, bool available) +{ + if (available) + return; + + widget->disconnect(); + + if constexpr (std::is_same_v) + { + widget->clear(); + widget->addItem(qApp->translate("SettingWidgetBinder", "Incompatible with this game.")); + } + else if constexpr (std::is_same_v) + { + widget->setText(qApp->translate("SettingWidgetBinder", "Incompatible with this game.")); + } + else if constexpr (std::is_same_v) + { + widget->setText(widget->text() + qApp->translate("SettingWidgetBinder", " [incompatible]")); + widget->setCheckState(Qt::Unchecked); + } + else if constexpr (std::is_same_v) + { + widget->setTickPosition(0); + } + else if constexpr (std::is_same_v || std::is_same_v) + { + widget->setValue(0); + } + + widget->setEnabled(false); +} + } // namespace SettingWidgetBinder