summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2021-01-06 01:52:15 +0100
committerGitHub <noreply@github.com>2021-01-06 01:52:15 +0100
commit4cdcbb6ab28596653635ab91b1ccd0332629925a (patch)
treeeb431b7b8e243064ae5cd0c5a2f16249da8353e3 /Source/Core
parent0b1db65aa155c65942ac6674b541fbf8aafc83d0 (diff)
parentf4c579e720013065ebe5257aa40d713e354bcfce (diff)
Merge pull request #9308 from smurf3tte/re23_patch
Patches for Resident Evil 2/3 audio issues
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/PatchEngine.cpp15
-rw-r--r--Source/Core/Core/PatchEngine.h2
-rw-r--r--Source/Core/DolphinQt/Config/NewPatchDialog.cpp168
-rw-r--r--Source/Core/DolphinQt/Config/NewPatchDialog.h8
-rw-r--r--Source/Core/DolphinQt/Config/PatchesWidget.cpp15
5 files changed, 135 insertions, 73 deletions
diff --git a/Source/Core/Core/PatchEngine.cpp b/Source/Core/Core/PatchEngine.cpp
index 4f4daafcd7..a3b13c14d3 100644
--- a/Source/Core/Core/PatchEngine.cpp
+++ b/Source/Core/Core/PatchEngine.cpp
@@ -90,6 +90,11 @@ void LoadPatchSection(const std::string& section, std::vector<Patch>& patches, I
bool success = true;
success &= TryParse(items[0], &pE.address);
success &= TryParse(items[2], &pE.value);
+ if (items.size() >= 4)
+ {
+ success &= TryParse(items[3], &pE.comparand);
+ pE.conditional = true;
+ }
const auto iter =
std::find(s_patch_type_strings.begin(), s_patch_type_strings.end(), items[1]);
@@ -184,16 +189,20 @@ static void ApplyPatches(const std::vector<Patch>& patches)
{
u32 addr = entry.address;
u32 value = entry.value;
+ u32 comparand = entry.comparand;
switch (entry.type)
{
case PatchType::Patch8Bit:
- PowerPC::HostWrite_U8(static_cast<u8>(value), addr);
+ if (!entry.conditional || PowerPC::HostRead_U8(addr) == static_cast<u8>(comparand))
+ PowerPC::HostWrite_U8(static_cast<u8>(value), addr);
break;
case PatchType::Patch16Bit:
- PowerPC::HostWrite_U16(static_cast<u16>(value), addr);
+ if (!entry.conditional || PowerPC::HostRead_U16(addr) == static_cast<u16>(comparand))
+ PowerPC::HostWrite_U16(static_cast<u16>(value), addr);
break;
case PatchType::Patch32Bit:
- PowerPC::HostWrite_U32(value, addr);
+ if (!entry.conditional || PowerPC::HostRead_U32(addr) == comparand)
+ PowerPC::HostWrite_U32(value, addr);
break;
default:
// unknown patchtype
diff --git a/Source/Core/Core/PatchEngine.h b/Source/Core/Core/PatchEngine.h
index a496f04936..490fb2e646 100644
--- a/Source/Core/Core/PatchEngine.h
+++ b/Source/Core/Core/PatchEngine.h
@@ -27,6 +27,8 @@ struct PatchEntry
PatchType type = PatchType::Patch8Bit;
u32 address = 0;
u32 value = 0;
+ u32 comparand = 0;
+ bool conditional = false;
};
struct Patch
diff --git a/Source/Core/DolphinQt/Config/NewPatchDialog.cpp b/Source/Core/DolphinQt/Config/NewPatchDialog.cpp
index b0f45afc49..6f06899639 100644
--- a/Source/Core/DolphinQt/Config/NewPatchDialog.cpp
+++ b/Source/Core/DolphinQt/Config/NewPatchDialog.cpp
@@ -4,6 +4,7 @@
#include "DolphinQt/Config/NewPatchDialog.h"
+#include <QCheckBox>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QGroupBox>
@@ -17,6 +18,23 @@
#include "Core/PatchEngine.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
+struct NewPatchEntry
+{
+ NewPatchEntry() = default;
+
+ // These entries share the lifetime of their associated text widgets, and because they are
+ // captured by pointer by various edit handlers, they should not copied or moved.
+ NewPatchEntry(const NewPatchEntry&) = delete;
+ NewPatchEntry& operator=(const NewPatchEntry&) = delete;
+ NewPatchEntry(NewPatchEntry&&) = delete;
+ NewPatchEntry& operator=(NewPatchEntry&&) = delete;
+
+ QLineEdit* address = nullptr;
+ QLineEdit* value = nullptr;
+ QLineEdit* comparand = nullptr;
+ PatchEngine::PatchEntry entry;
+};
+
NewPatchDialog::NewPatchDialog(QWidget* parent, PatchEngine::Patch& patch)
: QDialog(parent), m_patch(patch)
{
@@ -38,6 +56,8 @@ NewPatchDialog::NewPatchDialog(QWidget* parent, PatchEngine::Patch& patch)
}
}
+NewPatchDialog::~NewPatchDialog() = default;
+
void NewPatchDialog::CreateWidgets()
{
m_name_edit = new QLineEdit;
@@ -79,26 +99,29 @@ void NewPatchDialog::ConnectWidgets()
void NewPatchDialog::AddEntry()
{
- m_patch.entries.emplace_back();
-
- m_entry_layout->addWidget(CreateEntry(m_patch.entries[m_patch.entries.size() - 1]));
+ m_entry_layout->addWidget(CreateEntry({}));
}
-static bool PatchEq(const PatchEngine::PatchEntry& a, const PatchEngine::PatchEntry& b)
+static u32 OnTextEdited(QLineEdit* edit, const QString& text)
{
- if (a.address != b.address)
- return false;
+ bool okay = false;
+ u32 value = text.toUInt(&okay, 16);
+
+ QFont font;
+ QPalette palette;
+
+ font.setBold(!okay);
- if (a.type != b.type)
- return false;
+ if (!okay)
+ palette.setColor(QPalette::Text, Qt::red);
- if (a.value != b.value)
- return false;
+ edit->setFont(font);
+ edit->setPalette(palette);
- return true;
+ return value;
}
-QGroupBox* NewPatchDialog::CreateEntry(PatchEngine::PatchEntry& entry)
+QGroupBox* NewPatchDialog::CreateEntry(const PatchEngine::PatchEntry& entry)
{
QGroupBox* box = new QGroupBox();
@@ -115,95 +138,90 @@ QGroupBox* NewPatchDialog::CreateEntry(PatchEngine::PatchEntry& entry)
type_layout->addWidget(dword);
type->setLayout(type_layout);
- auto* offset = new QLineEdit;
+ auto* address = new QLineEdit;
auto* value = new QLineEdit;
+ auto* comparand = new QLineEdit;
- m_edits.push_back(offset);
- m_edits.push_back(value);
+ auto* new_entry = m_entries.emplace_back(std::make_unique<NewPatchEntry>()).get();
+ new_entry->address = address;
+ new_entry->value = value;
+ new_entry->comparand = comparand;
+ new_entry->entry = entry;
+
+ auto* conditional = new QCheckBox(tr("Conditional"));
+ auto* comparand_label = new QLabel(tr("Comparand:"));
auto* layout = new QGridLayout;
layout->addWidget(type, 0, 0, 1, -1);
- layout->addWidget(new QLabel(tr("Offset:")), 1, 0);
- layout->addWidget(offset, 1, 1);
+ layout->addWidget(new QLabel(tr("Address:")), 1, 0);
+ layout->addWidget(address, 1, 1);
layout->addWidget(new QLabel(tr("Value:")), 2, 0);
layout->addWidget(value, 2, 1);
- layout->addWidget(remove, 3, 0, 1, -1);
+ layout->addWidget(conditional, 3, 0, 1, -1);
+ layout->addWidget(comparand_label, 4, 0);
+ layout->addWidget(comparand, 4, 1);
+ layout->addWidget(remove, 5, 0, 1, -1);
box->setLayout(layout);
- connect(offset, qOverload<const QString&>(&QLineEdit::textEdited),
- [&entry, offset](const QString& text) {
- bool okay = true;
- entry.address = text.toUInt(&okay, 16);
-
- QFont font;
- QPalette palette;
-
- font.setBold(!okay);
-
- if (!okay)
- palette.setColor(QPalette::Text, Qt::red);
-
- offset->setFont(font);
- offset->setPalette(palette);
+ connect(address, qOverload<const QString&>(&QLineEdit::textEdited),
+ [new_entry](const QString& text) {
+ new_entry->entry.address = OnTextEdited(new_entry->address, text);
});
connect(value, qOverload<const QString&>(&QLineEdit::textEdited),
- [&entry, value](const QString& text) {
- bool okay;
- entry.value = text.toUInt(&okay, 16);
-
- QFont font;
- QPalette palette;
-
- font.setBold(!okay);
-
- if (!okay)
- palette.setColor(QPalette::Text, Qt::red);
+ [new_entry](const QString& text) {
+ new_entry->entry.value = OnTextEdited(new_entry->value, text);
+ });
- value->setFont(font);
- value->setPalette(palette);
+ connect(comparand, qOverload<const QString&>(&QLineEdit::textEdited),
+ [new_entry](const QString& text) {
+ new_entry->entry.comparand = OnTextEdited(new_entry->comparand, text);
});
- connect(remove, &QPushButton::clicked, [this, box, offset, value, entry] {
- if (m_patch.entries.size() > 1)
+ connect(remove, &QPushButton::clicked, [this, box, new_entry] {
+ if (m_entries.size() > 1)
{
box->setVisible(false);
m_entry_layout->removeWidget(box);
box->deleteLater();
- m_patch.entries.erase(
- std::find_if(m_patch.entries.begin(), m_patch.entries.end(),
- [entry](const PatchEngine::PatchEntry& e) { return PatchEq(e, entry); }));
-
- const auto it =
- std::remove_if(m_edits.begin(), m_edits.end(), [offset, value](QLineEdit* line_edit) {
- return line_edit == offset || line_edit == value;
- });
- m_edits.erase(it, m_edits.end());
+ m_entries.erase(std::find_if(m_entries.begin(), m_entries.end(),
+ [new_entry](const auto& e) { return e.get() == new_entry; }));
}
});
- connect(byte, &QRadioButton::toggled, [&entry](bool checked) {
+ connect(byte, &QRadioButton::toggled, [new_entry](bool checked) {
if (checked)
- entry.type = PatchEngine::PatchType::Patch8Bit;
+ new_entry->entry.type = PatchEngine::PatchType::Patch8Bit;
});
- connect(word, &QRadioButton::toggled, [&entry](bool checked) {
+ connect(word, &QRadioButton::toggled, [new_entry](bool checked) {
if (checked)
- entry.type = PatchEngine::PatchType::Patch16Bit;
+ new_entry->entry.type = PatchEngine::PatchType::Patch16Bit;
});
- connect(dword, &QRadioButton::toggled, [&entry](bool checked) {
+ connect(dword, &QRadioButton::toggled, [new_entry](bool checked) {
if (checked)
- entry.type = PatchEngine::PatchType::Patch32Bit;
+ new_entry->entry.type = PatchEngine::PatchType::Patch32Bit;
});
byte->setChecked(entry.type == PatchEngine::PatchType::Patch8Bit);
word->setChecked(entry.type == PatchEngine::PatchType::Patch16Bit);
dword->setChecked(entry.type == PatchEngine::PatchType::Patch32Bit);
- offset->setText(QStringLiteral("%1").arg(entry.address, 8, 16, QLatin1Char('0')));
+ connect(conditional, &QCheckBox::toggled, [new_entry, comparand_label, comparand](bool checked) {
+ new_entry->entry.conditional = checked;
+ comparand_label->setVisible(checked);
+ comparand->setVisible(checked);
+ });
+
+ conditional->setChecked(entry.conditional);
+ comparand_label->setVisible(entry.conditional);
+ comparand->setVisible(entry.conditional);
+
+ address->setText(QStringLiteral("%1").arg(entry.address, 8, 16, QLatin1Char('0')));
value->setText(QStringLiteral("%1").arg(entry.value, 8, 16, QLatin1Char('0')));
+ comparand->setText(QStringLiteral("%1").arg(entry.comparand, 8, 16, QLatin1Char('0')));
return box;
}
@@ -218,11 +236,22 @@ void NewPatchDialog::accept()
bool valid = true;
- for (const auto* edit : m_edits)
+ for (const auto& entry : m_entries)
{
- edit->text().toUInt(&valid, 16);
+ entry->address->text().toUInt(&valid, 16);
+ if (!valid)
+ break;
+
+ entry->value->text().toUInt(&valid, 16);
if (!valid)
break;
+
+ if (entry->entry.conditional)
+ {
+ entry->comparand->text().toUInt(&valid, 16);
+ if (!valid)
+ break;
+ }
}
if (!valid)
@@ -233,5 +262,12 @@ void NewPatchDialog::accept()
return;
}
+ m_patch.entries.clear();
+
+ for (const auto& entry : m_entries)
+ {
+ m_patch.entries.emplace_back(entry->entry);
+ }
+
QDialog::accept();
}
diff --git a/Source/Core/DolphinQt/Config/NewPatchDialog.h b/Source/Core/DolphinQt/Config/NewPatchDialog.h
index d77005cc1d..ff9d09feea 100644
--- a/Source/Core/DolphinQt/Config/NewPatchDialog.h
+++ b/Source/Core/DolphinQt/Config/NewPatchDialog.h
@@ -4,6 +4,7 @@
#pragma once
+#include <memory>
#include <vector>
#include <QDialog>
@@ -21,10 +22,13 @@ class QLineEdit;
class QVBoxLayout;
class QPushButton;
+struct NewPatchEntry;
+
class NewPatchDialog : public QDialog
{
public:
explicit NewPatchDialog(QWidget* parent, PatchEngine::Patch& patch);
+ ~NewPatchDialog() override;
private:
void CreateWidgets();
@@ -33,7 +37,7 @@ private:
void accept() override;
- QGroupBox* CreateEntry(PatchEngine::PatchEntry& entry);
+ QGroupBox* CreateEntry(const PatchEngine::PatchEntry& entry);
QLineEdit* m_name_edit;
QWidget* m_entry_widget;
@@ -41,7 +45,7 @@ private:
QPushButton* m_add_button;
QDialogButtonBox* m_button_box;
- std::vector<QLineEdit*> m_edits;
+ std::vector<std::unique_ptr<NewPatchEntry>> m_entries;
PatchEngine::Patch& m_patch;
};
diff --git a/Source/Core/DolphinQt/Config/PatchesWidget.cpp b/Source/Core/DolphinQt/Config/PatchesWidget.cpp
index 43dd4a415e..8628f1997a 100644
--- a/Source/Core/DolphinQt/Config/PatchesWidget.cpp
+++ b/Source/Core/DolphinQt/Config/PatchesWidget.cpp
@@ -8,6 +8,8 @@
#include <QListWidget>
#include <QPushButton>
+#include <fmt/format.h>
+
#include "Common/FileUtil.h"
#include "Common/IniFile.h"
#include "Common/StringUtil.h"
@@ -143,8 +145,17 @@ void PatchesWidget::SavePatches()
for (const auto& entry : patch.entries)
{
- lines.emplace_back(StringFromFormat("0x%08X:%s:0x%08X", entry.address,
- PatchEngine::PatchTypeAsString(entry.type), entry.value));
+ if (!entry.conditional)
+ {
+ lines.emplace_back(fmt::format("0x{:08X}:{}:0x{:08X}", entry.address,
+ PatchEngine::PatchTypeAsString(entry.type), entry.value));
+ }
+ else
+ {
+ lines.emplace_back(fmt::format("0x{:08X}:{}:0x{:08X}:0x{:08X}", entry.address,
+ PatchEngine::PatchTypeAsString(entry.type), entry.value,
+ entry.comparand));
+ }
}
}