diff options
| author | Léo Lam <leo@leolam.fr> | 2021-01-06 01:52:15 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-01-06 01:52:15 +0100 |
| commit | 4cdcbb6ab28596653635ab91b1ccd0332629925a (patch) | |
| tree | eb431b7b8e243064ae5cd0c5a2f16249da8353e3 /Source/Core | |
| parent | 0b1db65aa155c65942ac6674b541fbf8aafc83d0 (diff) | |
| parent | f4c579e720013065ebe5257aa40d713e354bcfce (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.cpp | 15 | ||||
| -rw-r--r-- | Source/Core/Core/PatchEngine.h | 2 | ||||
| -rw-r--r-- | Source/Core/DolphinQt/Config/NewPatchDialog.cpp | 168 | ||||
| -rw-r--r-- | Source/Core/DolphinQt/Config/NewPatchDialog.h | 8 | ||||
| -rw-r--r-- | Source/Core/DolphinQt/Config/PatchesWidget.cpp | 15 |
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)); + } } } |
