Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qt/Patches: Bring back the global WS/NI toggle, but make it clearer in the UI #12117

Merged
merged 3 commits into from
Dec 29, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 71 additions & 8 deletions pcsx2-qt/Settings/GamePatchSettingsWidget.cpp
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
#include <algorithm>

GamePatchDetailsWidget::GamePatchDetailsWidget(std::string name, const std::string& author,
const std::string& description, bool enabled, SettingsWindow* dialog, QWidget* parent)
const std::string& description, bool tristate, Qt::CheckState checkState, SettingsWindow* dialog, QWidget* parent)
: QWidget(parent)
, m_dialog(dialog)
, m_name(name)
@@ -30,7 +30,8 @@ GamePatchDetailsWidget::GamePatchDetailsWidget(std::string name, const std::stri
.arg(description.empty() ? tr("No description provided.") : QString::fromStdString(description)));

pxAssert(dialog->getSettingsInterface());
m_ui.enabled->setChecked(enabled);
m_ui.enabled->setTristate(tristate);
m_ui.enabled->setCheckState(checkState);
connect(m_ui.enabled, &QCheckBox::checkStateChanged, this, &GamePatchDetailsWidget::onEnabledStateChanged);
}

@@ -40,9 +41,25 @@ void GamePatchDetailsWidget::onEnabledStateChanged(int state)
{
SettingsInterface* si = m_dialog->getSettingsInterface();
if (state == Qt::Checked)
si->AddToStringList("Patches", "Enable", m_name.c_str());
{
si->AddToStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY, m_name.c_str());
si->RemoveFromStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_DISABLE_CONFIG_KEY, m_name.c_str());
}
else
si->RemoveFromStringList("Patches", "Enable", m_name.c_str());
{
si->RemoveFromStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY, m_name.c_str());
if (m_ui.enabled->isTristate())
{
if (state == Qt::Unchecked)
{
si->AddToStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_DISABLE_CONFIG_KEY, m_name.c_str());
}
else
{
si->RemoveFromStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_DISABLE_CONFIG_KEY, m_name.c_str());
}
}
}

si->Save();
g_emu_thread->reloadGameSettings();
@@ -56,6 +73,8 @@ GamePatchSettingsWidget::GamePatchSettingsWidget(SettingsWindow* dialog, QWidget
m_ui.scrollArea->setFrameShadow(QFrame::Sunken);

setUnlabeledPatchesWarningVisibility(false);
setGlobalWsPatchNoteVisibility(false);
setGlobalNiPatchNoteVisibility(false);

SettingsInterface* sif = m_dialog->getSettingsInterface();
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.allCRCsCheckbox, "EmuCore", "ShowPatchesForAllCRCs", false);
@@ -88,14 +107,22 @@ void GamePatchSettingsWidget::disableAllPatches()

void GamePatchSettingsWidget::reloadList()
{
const SettingsInterface* si = m_dialog->getSettingsInterface();
// Patches shouldn't have any unlabelled patch groups, because they're new.
u32 number_of_unlabeled_patches = 0;
bool showAllCRCS = m_ui.allCRCsCheckbox->isChecked();
std::vector<Patch::PatchInfo> patches = Patch::GetPatchInfo(m_dialog->getSerial(), m_dialog->getDiscCRC(), false, showAllCRCS, &number_of_unlabeled_patches);
std::vector<std::string> enabled_list =
m_dialog->getSettingsInterface()->GetStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY);
si->GetStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY);
std::vector<std::string> disabled_list =
si->GetStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_DISABLE_CONFIG_KEY);

const bool ws_patches_enabled_globally = m_dialog->getEffectiveBoolValue("EmuCore", "EnableWideScreenPatches", false);
const bool ni_patches_enabled_globally = m_dialog->getEffectiveBoolValue("EmuCore", "EnableNoInterlacingPatches", false);

setUnlabeledPatchesWarningVisibility(number_of_unlabeled_patches > 0);
setGlobalWsPatchNoteVisibility(ws_patches_enabled_globally);
setGlobalNiPatchNoteVisibility(ni_patches_enabled_globally);
delete m_ui.scrollArea->takeWidget();

QWidget* container = new QWidget(m_ui.scrollArea);
@@ -106,7 +133,7 @@ void GamePatchSettingsWidget::reloadList()
{
bool first = true;

for (Patch::PatchInfo& pi : patches)
for (const Patch::PatchInfo& pi : patches)
{
if (!first)
{
@@ -120,9 +147,35 @@ void GamePatchSettingsWidget::reloadList()
first = false;
}

const bool enabled = (std::find(enabled_list.begin(), enabled_list.end(), pi.name) != enabled_list.end());
const bool is_on_enable_list = std::find(enabled_list.begin(), enabled_list.end(), pi.name) != enabled_list.end();
const bool is_on_disable_list = std::find(disabled_list.begin(), disabled_list.end(), pi.name) != disabled_list.end();
const bool globally_toggleable_option = Patch::IsGloballyToggleablePatch(pi);

Qt::CheckState check_state;
if (!globally_toggleable_option)
{
// Normal patches
check_state = is_on_enable_list && !is_on_disable_list ? Qt::CheckState::Checked : Qt::CheckState::Unchecked;
}
else
{
// WS/NI patches
if (is_on_disable_list)
{
check_state = Qt::CheckState::Unchecked;
}
else if (is_on_enable_list)
{
check_state = Qt::CheckState::Checked;
}
else
{
check_state = Qt::CheckState::PartiallyChecked;
}
}

GamePatchDetailsWidget* it =
new GamePatchDetailsWidget(std::move(pi.name), pi.author, pi.description, enabled, m_dialog, container);
new GamePatchDetailsWidget(std::move(pi.name), pi.author, pi.description, globally_toggleable_option, check_state, m_dialog, container);
layout->addWidget(it);
}
}
@@ -141,3 +194,13 @@ void GamePatchSettingsWidget::setUnlabeledPatchesWarningVisibility(bool visible)
{
m_ui.unlabeledPatchWarning->setVisible(visible);
}

void GamePatchSettingsWidget::setGlobalWsPatchNoteVisibility(bool visible)
{
m_ui.globalWsPatchState->setVisible(visible);
}

void GamePatchSettingsWidget::setGlobalNiPatchNoteVisibility(bool visible)
{
m_ui.globalNiPatchState->setVisible(visible);
}
4 changes: 3 additions & 1 deletion pcsx2-qt/Settings/GamePatchSettingsWidget.h
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ class GamePatchDetailsWidget : public QWidget
Q_OBJECT

public:
GamePatchDetailsWidget(std::string name, const std::string& author, const std::string& description, bool enabled,
GamePatchDetailsWidget(std::string name, const std::string& author, const std::string& description, bool tristate, Qt::CheckState checkState,
SettingsWindow* dialog, QWidget* parent);
~GamePatchDetailsWidget();

@@ -50,6 +50,8 @@ private Q_SLOTS:
private:
void reloadList();
void setUnlabeledPatchesWarningVisibility(bool visible);
void setGlobalWsPatchNoteVisibility(bool visible);
void setGlobalNiPatchNoteVisibility(bool visible);

Ui::GamePatchSettingsWidget m_ui;
SettingsWindow* m_dialog;
23 changes: 23 additions & 0 deletions pcsx2-qt/Settings/GamePatchSettingsWidget.ui
Original file line number Diff line number Diff line change
@@ -38,6 +38,29 @@
<property name="text">
<string>Any patches bundled with PCSX2 for this game will be disabled since you have unlabeled patches loaded.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="globalWsPatchState">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Widescreen patches are currently &lt;span style=&quot; font-weight:600;&quot;&gt;ENABLED&lt;/span&gt; globally.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="globalNiPatchState">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;No-Interlacing patches are currently &lt;span style=&quot; font-weight:600;&quot;&gt;ENABLED&lt;/span&gt; globally.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
74 changes: 61 additions & 13 deletions pcsx2-qt/Settings/GraphicsSettingsWidget.cpp
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@
#include <QtWidgets/QMessageBox>

#include "pcsx2/Host.h"
#include "pcsx2/Patch.h"
#include "pcsx2/GS/GS.h"
#include "pcsx2/GS/GSCapture.h"
#include "pcsx2/GS/GSUtil.h"
@@ -88,6 +89,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.interlacing, "EmuCore/GS", "deinterlace_mode", DEFAULT_INTERLACE_MODE);
SettingWidgetBinder::BindWidgetToIntSetting(
sif, m_ui.bilinearFiltering, "EmuCore/GS", "linear_present_mode", static_cast<int>(GSPostBilinearMode::BilinearSmooth));
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.widescreenPatches, "EmuCore", "EnableWideScreenPatches", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.noInterlacingPatches, "EmuCore", "EnableNoInterlacingPatches", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.integerScaling, "EmuCore/GS", "IntegerScaling", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.PCRTCOffsets, "EmuCore/GS", "pcrtc_offsets", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.PCRTCOverscan, "EmuCore/GS", "pcrtc_overscan", false);
@@ -319,22 +322,61 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
}
#endif

// Prompt user to get rid of widescreen/no-interlace config from the ini if the user has enabled them before.
if ((m_dialog->getBoolValue("EmuCore", "EnableWideScreenPatches", false) == true ||
m_dialog->getBoolValue("EmuCore", "EnableWideScreenPatches", false) == true) &&
!m_dialog->containsSettingValue("UI", "UserHasDeniedWSPatchWarning"))
// Get rid of widescreen/no-interlace checkboxes from per-game settings, and migrate them to Patches if necessary.
if (m_dialog->isPerGameSettings())
{
if (QMessageBox::question(QtUtils::GetRootWidget(this), tr("Remove Unsupported Settings"),
tr("You previously had the <strong>Enable Widescreen Patches</strong> or <strong>Enable No-Interlacing Patches</strong> options enabled.<br><br>"
"We no longer provide these options, instead <strong>you should go to the \"Patches\" section on the per-game settings, and explicitly enable the patches that you want.</strong><br><br>"
"Do you want to remove these options from your configuration now?"),
QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
SettingsInterface* si = m_dialog->getSettingsInterface();
bool needs_save = false;

if (si->ContainsValue("EmuCore", "EnableWideScreenPatches"))
{
m_dialog->removeSettingValue("EmuCore", "EnableWideScreenPatches");
m_dialog->removeSettingValue("EmuCore", "EnableNoInterlacingPatches");
const bool ws_enabled = si->GetBoolValue("EmuCore", "EnableWideScreenPatches");
si->DeleteValue("EmuCore", "EnableWideScreenPatches");

const char* WS_PATCH_NAME = "Widescreen 16:9";
if (ws_enabled)
{
si->AddToStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY, WS_PATCH_NAME);
si->RemoveFromStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_DISABLE_CONFIG_KEY, WS_PATCH_NAME);
}
else
{
si->AddToStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_DISABLE_CONFIG_KEY, WS_PATCH_NAME);
si->RemoveFromStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY, WS_PATCH_NAME);
}
needs_save = true;
}
else
m_dialog->setBoolSettingValue("UI", "UserHasDeniedWSPatchWarning", true);

if (si->ContainsValue("EmuCore", "EnableNoInterlacingPatches"))
{
const bool ni_enabled = si->GetBoolValue("EmuCore", "EnableNoInterlacingPatches");
si->DeleteValue("EmuCore", "EnableNoInterlacingPatches");

const char* NI_PATCH_NAME = "No-Interlacing";
if (ni_enabled)
{
si->AddToStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY, NI_PATCH_NAME);
si->RemoveFromStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_DISABLE_CONFIG_KEY, NI_PATCH_NAME);
}
else
{
si->AddToStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_DISABLE_CONFIG_KEY, NI_PATCH_NAME);
si->RemoveFromStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY, NI_PATCH_NAME);
}
needs_save = true;
}

if (needs_save)
{
m_dialog->saveAndReloadGameSettings();
}

m_ui.displayGridLayout->removeWidget(m_ui.widescreenPatches);
m_ui.displayGridLayout->removeWidget(m_ui.noInterlacingPatches);
m_ui.widescreenPatches->deleteLater();
m_ui.noInterlacingPatches->deleteLater();
m_ui.widescreenPatches = nullptr;
m_ui.noInterlacingPatches = nullptr;
}

// Hide advanced options by default.
@@ -427,6 +469,12 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*

// Display tab
{
dialog->registerWidgetHelp(m_ui.widescreenPatches, tr("Enable Widescreen Patches"), tr("Unchecked"),
tr("Automatically loads and applies widescreen patches on game start. Can cause issues."));

dialog->registerWidgetHelp(m_ui.noInterlacingPatches, tr("Enable No-Interlacing Patches"), tr("Unchecked"),
tr("Automatically loads and applies no-interlacing patches on game start. Can cause issues."));

dialog->registerWidgetHelp(m_ui.DisableInterlaceOffset, tr("Disable Interlace Offset"), tr("Unchecked"),
tr("Disables interlacing offset which may reduce blurring in some situations."));

34 changes: 24 additions & 10 deletions pcsx2-qt/Settings/GraphicsSettingsWidget.ui
Original file line number Diff line number Diff line change
@@ -404,28 +404,28 @@
</item>
<item row="8" column="0" colspan="2">
<layout class="QGridLayout" name="displayGridLayout">
<item row="0" column="1">
<item row="1" column="1">
<widget class="QCheckBox" name="integerScaling">
<property name="text">
<string>Integer Scaling</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="PCRTCOverscan">
<item row="0" column="0">
<widget class="QCheckBox" name="widescreenPatches">
<property name="text">
<string>Show Overscan</string>
<string>Apply Widescreen Patches</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="PCRTCOffsets">
<item row="0" column="1">
<widget class="QCheckBox" name="noInterlacingPatches">
<property name="text">
<string>Screen Offsets</string>
<string>Apply No-Interlacing Patches</string>
</property>
</widget>
</item>
<item row="0" column="0">
<item row="1" column="0">
<widget class="QCheckBox" name="PCRTCAntiBlur">
<property name="text">
<string>Anti-Blur</string>
@@ -435,13 +435,27 @@
</property>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="1">
<widget class="QCheckBox" name="DisableInterlaceOffset">
<property name="text">
<string>Disable Interlace Offset</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="PCRTCOffsets">
<property name="text">
<string>Screen Offsets</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="PCRTCOverscan">
<property name="text">
<string>Show Overscan</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@@ -2111,7 +2125,7 @@
</widget>
</item>
<item row="10" column="0" colspan="2">
<layout class="QGridLayout" name="advancedOptionsGrid">
<layout class="QGridLayout" name="gridLayout_9">
<item row="2" column="0">
<widget class="QCheckBox" name="disableMailboxPresentation">
<property name="text">
2 changes: 2 additions & 0 deletions pcsx2/Config.h
Original file line number Diff line number Diff line change
@@ -1268,6 +1268,8 @@ struct Pcsx2Config
EnablePatches : 1, // enables patch detection and application
EnableCheats : 1, // enables cheat detection and application
EnablePINE : 1, // enables inter-process communication
EnableWideScreenPatches : 1,
EnableNoInterlacingPatches : 1,
EnableFastBoot : 1,
EnableFastBootFastForward : 1,
EnableThreadPinning : 1,
9 changes: 9 additions & 0 deletions pcsx2/ImGui/FullscreenUI.cpp
Original file line number Diff line number Diff line change
@@ -3705,6 +3705,15 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
"EmuCore/GS", "StretchY", 100, 10, 300, FSUI_CSTR("%d%%"));
DrawIntRectSetting(bsi, FSUI_CSTR("Crop"), FSUI_CSTR("Crops the image, while respecting aspect ratio."), "EmuCore/GS", "CropLeft", 0,
"CropTop", 0, "CropRight", 0, "CropBottom", 0, 0, 720, 1, FSUI_CSTR("%dpx"));

if (!IsEditingGameSettings(bsi))
{
DrawToggleSetting(bsi, FSUI_CSTR("Enable Widescreen Patches"), FSUI_CSTR("Enables loading widescreen patches from pnach files."),
"EmuCore", "EnableWideScreenPatches", false);
DrawToggleSetting(bsi, FSUI_CSTR("Enable No-Interlacing Patches"),
FSUI_CSTR("Enables loading no-interlacing patches from pnach files."), "EmuCore", "EnableNoInterlacingPatches", false);
}

DrawIntListSetting(bsi, FSUI_CSTR("Bilinear Upscaling"), FSUI_CSTR("Smooths out the image when upscaling the console to the screen."),
"EmuCore/GS", "linear_present_mode", static_cast<int>(GSPostBilinearMode::BilinearSharp), s_bilinear_present_options,
std::size(s_bilinear_present_options), true);
Loading