mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-10-07 07:43:36 +00:00
Merge pull request #9308 from smurf3tte/re23_patch
Patches for Resident Evil 2/3 audio issues
This commit is contained in:
commit
4cdcbb6ab2
16
Data/Sys/GameSettings/GHAE08.ini
Normal file
16
Data/Sys/GameSettings/GHAE08.ini
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# GHAE08 - Resident Evil 2
|
||||||
|
|
||||||
|
[OnFrame]
|
||||||
|
# Work around a game bug that causes background sounds to be zeroed during load.
|
||||||
|
# The bug was masked on real hardware by dcache. This patch fully fixes the bug
|
||||||
|
# and should also work on real hardware. Dolphin doesn't emulate dcache because
|
||||||
|
# the performance hit would be huge.
|
||||||
|
$Fix audio issues
|
||||||
|
# main.dol
|
||||||
|
0x800339E4:dword:0x60000000
|
||||||
|
# leon.rel
|
||||||
|
0x8055ACBC:dword:0x60000000:0x4BAA8445
|
||||||
|
# claire.rel
|
||||||
|
0x8055AB54:dword:0x60000000:0x4BAA85AD
|
||||||
|
[OnFrame_Enabled]
|
||||||
|
$Fix audio issues
|
16
Data/Sys/GameSettings/GHAJ08.ini
Normal file
16
Data/Sys/GameSettings/GHAJ08.ini
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# GHAJ08 - Biohazard 2
|
||||||
|
|
||||||
|
[OnFrame]
|
||||||
|
# Work around a game bug that causes background sounds to be zeroed during load.
|
||||||
|
# The bug was masked on real hardware by dcache. This patch fully fixes the bug
|
||||||
|
# and should also work on real hardware. Dolphin doesn't emulate dcache because
|
||||||
|
# the performance hit would be huge.
|
||||||
|
$Fix audio issues
|
||||||
|
# main.dol
|
||||||
|
0x80065FFC:dword:0x60000000
|
||||||
|
# leon.rel
|
||||||
|
0x805C5CC4:dword:0x60000000:0x4BA3D43D
|
||||||
|
# claire.rel
|
||||||
|
0x805C5BFC:dword:0x60000000:0x4BA3D505
|
||||||
|
[OnFrame_Enabled]
|
||||||
|
$Fix audio issues
|
32
Data/Sys/GameSettings/GHAP08.ini
Normal file
32
Data/Sys/GameSettings/GHAP08.ini
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# GHAP08 - Resident Evil 2
|
||||||
|
|
||||||
|
[OnFrame]
|
||||||
|
# Work around a game bug that causes background sounds to be zeroed during load.
|
||||||
|
# The bug was masked on real hardware by dcache. This patch fully fixes the bug
|
||||||
|
# and should also work on real hardware. Dolphin doesn't emulate dcache because
|
||||||
|
# the performance hit would be huge.
|
||||||
|
$Fix audio issues
|
||||||
|
# main.dol
|
||||||
|
0x80033D60:dword:0x60000000
|
||||||
|
# leon.rel
|
||||||
|
0x8055C5F8:dword:0x60000000:0x4BAA6B09
|
||||||
|
# claire.rel
|
||||||
|
0x8055C490:dword:0x60000000:0x4BAA6C71
|
||||||
|
# leon_g.rel
|
||||||
|
0x8055C3B8:dword:0x60000000:0x4BAA6D49
|
||||||
|
# claire_g.rel
|
||||||
|
0x8055C328:dword:0x60000000:0x4BAA6DD9
|
||||||
|
# leon_f.rel
|
||||||
|
0x8055D188:dword:0x60000000:0x4BAA5F79
|
||||||
|
# claire_f.rel
|
||||||
|
0x8055D068:dword:0x60000000:0x4BAA6099
|
||||||
|
# leon_s.rel
|
||||||
|
0x8055D100:dword:0x60000000:0x4BAA6001
|
||||||
|
# claire_s.rel
|
||||||
|
0x8055D064:dword:0x60000000:0x4BAA609D
|
||||||
|
# leon_i.rel
|
||||||
|
0x8055CFDC:dword:0x60000000:0x4BAA6125
|
||||||
|
# claire_i.rel
|
||||||
|
0x8055CEBC:dword:0x60000000:0x4BAA6245
|
||||||
|
[OnFrame_Enabled]
|
||||||
|
$Fix audio issues
|
12
Data/Sys/GameSettings/GLEE08.ini
Normal file
12
Data/Sys/GameSettings/GLEE08.ini
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# GLEE08 - Resident Evil 3: Nemesis
|
||||||
|
|
||||||
|
[OnFrame]
|
||||||
|
# Work around a game bug that causes background sounds to be zeroed during load.
|
||||||
|
# The bug was masked on real hardware by dcache. This patch fully fixes the bug
|
||||||
|
# and should also work on real hardware. Dolphin doesn't emulate dcache because
|
||||||
|
# the performance hit would be huge.
|
||||||
|
$Fix audio issues
|
||||||
|
# main.dol
|
||||||
|
0x80150E94:dword:0x60000000
|
||||||
|
[OnFrame_Enabled]
|
||||||
|
$Fix audio issues
|
12
Data/Sys/GameSettings/GLEJ08.ini
Normal file
12
Data/Sys/GameSettings/GLEJ08.ini
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# GLEJ08 - BioHazard 3: Last Escape
|
||||||
|
|
||||||
|
[OnFrame]
|
||||||
|
# Work around a game bug that causes background sounds to be zeroed during load.
|
||||||
|
# The bug was masked on real hardware by dcache. This patch fully fixes the bug
|
||||||
|
# and should also work on real hardware. Dolphin doesn't emulate dcache because
|
||||||
|
# the performance hit would be huge.
|
||||||
|
$Fix audio issues
|
||||||
|
# main.dol
|
||||||
|
0x8015110C:dword:0x60000000
|
||||||
|
[OnFrame_Enabled]
|
||||||
|
$Fix audio issues
|
20
Data/Sys/GameSettings/GLEP08.ini
Normal file
20
Data/Sys/GameSettings/GLEP08.ini
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# GLEP08 - Resident Evil 3: Nemesis
|
||||||
|
|
||||||
|
[OnFrame]
|
||||||
|
# Work around a game bug that causes background sounds to be zeroed during load.
|
||||||
|
# The bug was masked on real hardware by dcache. This patch fully fixes the bug
|
||||||
|
# and should also work on real hardware. Dolphin doesn't emulate dcache because
|
||||||
|
# the performance hit would be huge.
|
||||||
|
$Fix audio issues
|
||||||
|
# eng.rel
|
||||||
|
0x8058C174:dword:0x60000000:0x4BA76F8D
|
||||||
|
# ger.rel
|
||||||
|
0x8058CE40:dword:0x60000000:0x4BA762C1
|
||||||
|
# fra.rel
|
||||||
|
0x8058D03C:dword:0x60000000:0x4BA760C5
|
||||||
|
# spa.rel
|
||||||
|
0x8058D024:dword:0x60000000:0x4BA760DD
|
||||||
|
# ita.rel
|
||||||
|
0x8058CEA4:dword:0x60000000:0x4BA7625D
|
||||||
|
[OnFrame_Enabled]
|
||||||
|
$Fix audio issues
|
@ -90,6 +90,11 @@ void LoadPatchSection(const std::string& section, std::vector<Patch>& patches, I
|
|||||||
bool success = true;
|
bool success = true;
|
||||||
success &= TryParse(items[0], &pE.address);
|
success &= TryParse(items[0], &pE.address);
|
||||||
success &= TryParse(items[2], &pE.value);
|
success &= TryParse(items[2], &pE.value);
|
||||||
|
if (items.size() >= 4)
|
||||||
|
{
|
||||||
|
success &= TryParse(items[3], &pE.comparand);
|
||||||
|
pE.conditional = true;
|
||||||
|
}
|
||||||
|
|
||||||
const auto iter =
|
const auto iter =
|
||||||
std::find(s_patch_type_strings.begin(), s_patch_type_strings.end(), items[1]);
|
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 addr = entry.address;
|
||||||
u32 value = entry.value;
|
u32 value = entry.value;
|
||||||
|
u32 comparand = entry.comparand;
|
||||||
switch (entry.type)
|
switch (entry.type)
|
||||||
{
|
{
|
||||||
case PatchType::Patch8Bit:
|
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;
|
break;
|
||||||
case PatchType::Patch16Bit:
|
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;
|
break;
|
||||||
case PatchType::Patch32Bit:
|
case PatchType::Patch32Bit:
|
||||||
PowerPC::HostWrite_U32(value, addr);
|
if (!entry.conditional || PowerPC::HostRead_U32(addr) == comparand)
|
||||||
|
PowerPC::HostWrite_U32(value, addr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// unknown patchtype
|
// unknown patchtype
|
||||||
|
@ -27,6 +27,8 @@ struct PatchEntry
|
|||||||
PatchType type = PatchType::Patch8Bit;
|
PatchType type = PatchType::Patch8Bit;
|
||||||
u32 address = 0;
|
u32 address = 0;
|
||||||
u32 value = 0;
|
u32 value = 0;
|
||||||
|
u32 comparand = 0;
|
||||||
|
bool conditional = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Patch
|
struct Patch
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "DolphinQt/Config/NewPatchDialog.h"
|
#include "DolphinQt/Config/NewPatchDialog.h"
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
@ -17,6 +18,23 @@
|
|||||||
#include "Core/PatchEngine.h"
|
#include "Core/PatchEngine.h"
|
||||||
#include "DolphinQt/QtUtils/ModalMessageBox.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)
|
NewPatchDialog::NewPatchDialog(QWidget* parent, PatchEngine::Patch& patch)
|
||||||
: QDialog(parent), m_patch(patch)
|
: QDialog(parent), m_patch(patch)
|
||||||
{
|
{
|
||||||
@ -38,6 +56,8 @@ NewPatchDialog::NewPatchDialog(QWidget* parent, PatchEngine::Patch& patch)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NewPatchDialog::~NewPatchDialog() = default;
|
||||||
|
|
||||||
void NewPatchDialog::CreateWidgets()
|
void NewPatchDialog::CreateWidgets()
|
||||||
{
|
{
|
||||||
m_name_edit = new QLineEdit;
|
m_name_edit = new QLineEdit;
|
||||||
@ -79,26 +99,29 @@ void NewPatchDialog::ConnectWidgets()
|
|||||||
|
|
||||||
void NewPatchDialog::AddEntry()
|
void NewPatchDialog::AddEntry()
|
||||||
{
|
{
|
||||||
m_patch.entries.emplace_back();
|
m_entry_layout->addWidget(CreateEntry({}));
|
||||||
|
|
||||||
m_entry_layout->addWidget(CreateEntry(m_patch.entries[m_patch.entries.size() - 1]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool PatchEq(const PatchEngine::PatchEntry& a, const PatchEngine::PatchEntry& b)
|
static u32 OnTextEdited(QLineEdit* edit, const QString& text)
|
||||||
{
|
{
|
||||||
if (a.address != b.address)
|
bool okay = false;
|
||||||
return false;
|
u32 value = text.toUInt(&okay, 16);
|
||||||
|
|
||||||
if (a.type != b.type)
|
QFont font;
|
||||||
return false;
|
QPalette palette;
|
||||||
|
|
||||||
if (a.value != b.value)
|
font.setBold(!okay);
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
if (!okay)
|
||||||
|
palette.setColor(QPalette::Text, Qt::red);
|
||||||
|
|
||||||
|
edit->setFont(font);
|
||||||
|
edit->setPalette(palette);
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
QGroupBox* NewPatchDialog::CreateEntry(PatchEngine::PatchEntry& entry)
|
QGroupBox* NewPatchDialog::CreateEntry(const PatchEngine::PatchEntry& entry)
|
||||||
{
|
{
|
||||||
QGroupBox* box = new QGroupBox();
|
QGroupBox* box = new QGroupBox();
|
||||||
|
|
||||||
@ -115,95 +138,90 @@ QGroupBox* NewPatchDialog::CreateEntry(PatchEngine::PatchEntry& entry)
|
|||||||
type_layout->addWidget(dword);
|
type_layout->addWidget(dword);
|
||||||
type->setLayout(type_layout);
|
type->setLayout(type_layout);
|
||||||
|
|
||||||
auto* offset = new QLineEdit;
|
auto* address = new QLineEdit;
|
||||||
auto* value = new QLineEdit;
|
auto* value = new QLineEdit;
|
||||||
|
auto* comparand = new QLineEdit;
|
||||||
|
|
||||||
m_edits.push_back(offset);
|
auto* new_entry = m_entries.emplace_back(std::make_unique<NewPatchEntry>()).get();
|
||||||
m_edits.push_back(value);
|
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;
|
auto* layout = new QGridLayout;
|
||||||
layout->addWidget(type, 0, 0, 1, -1);
|
layout->addWidget(type, 0, 0, 1, -1);
|
||||||
layout->addWidget(new QLabel(tr("Offset:")), 1, 0);
|
layout->addWidget(new QLabel(tr("Address:")), 1, 0);
|
||||||
layout->addWidget(offset, 1, 1);
|
layout->addWidget(address, 1, 1);
|
||||||
layout->addWidget(new QLabel(tr("Value:")), 2, 0);
|
layout->addWidget(new QLabel(tr("Value:")), 2, 0);
|
||||||
layout->addWidget(value, 2, 1);
|
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);
|
box->setLayout(layout);
|
||||||
|
|
||||||
connect(offset, qOverload<const QString&>(&QLineEdit::textEdited),
|
connect(address, qOverload<const QString&>(&QLineEdit::textEdited),
|
||||||
[&entry, offset](const QString& text) {
|
[new_entry](const QString& text) {
|
||||||
bool okay = true;
|
new_entry->entry.address = OnTextEdited(new_entry->address, text);
|
||||||
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(value, qOverload<const QString&>(&QLineEdit::textEdited),
|
connect(value, qOverload<const QString&>(&QLineEdit::textEdited),
|
||||||
[&entry, value](const QString& text) {
|
[new_entry](const QString& text) {
|
||||||
bool okay;
|
new_entry->entry.value = OnTextEdited(new_entry->value, text);
|
||||||
entry.value = text.toUInt(&okay, 16);
|
|
||||||
|
|
||||||
QFont font;
|
|
||||||
QPalette palette;
|
|
||||||
|
|
||||||
font.setBold(!okay);
|
|
||||||
|
|
||||||
if (!okay)
|
|
||||||
palette.setColor(QPalette::Text, Qt::red);
|
|
||||||
|
|
||||||
value->setFont(font);
|
|
||||||
value->setPalette(palette);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(remove, &QPushButton::clicked, [this, box, offset, value, entry] {
|
connect(comparand, qOverload<const QString&>(&QLineEdit::textEdited),
|
||||||
if (m_patch.entries.size() > 1)
|
[new_entry](const QString& text) {
|
||||||
|
new_entry->entry.comparand = OnTextEdited(new_entry->comparand, text);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(remove, &QPushButton::clicked, [this, box, new_entry] {
|
||||||
|
if (m_entries.size() > 1)
|
||||||
{
|
{
|
||||||
box->setVisible(false);
|
box->setVisible(false);
|
||||||
m_entry_layout->removeWidget(box);
|
m_entry_layout->removeWidget(box);
|
||||||
box->deleteLater();
|
box->deleteLater();
|
||||||
|
|
||||||
m_patch.entries.erase(
|
m_entries.erase(std::find_if(m_entries.begin(), m_entries.end(),
|
||||||
std::find_if(m_patch.entries.begin(), m_patch.entries.end(),
|
[new_entry](const auto& e) { return e.get() == new_entry; }));
|
||||||
[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());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(byte, &QRadioButton::toggled, [&entry](bool checked) {
|
connect(byte, &QRadioButton::toggled, [new_entry](bool checked) {
|
||||||
if (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)
|
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)
|
if (checked)
|
||||||
entry.type = PatchEngine::PatchType::Patch32Bit;
|
new_entry->entry.type = PatchEngine::PatchType::Patch32Bit;
|
||||||
});
|
});
|
||||||
|
|
||||||
byte->setChecked(entry.type == PatchEngine::PatchType::Patch8Bit);
|
byte->setChecked(entry.type == PatchEngine::PatchType::Patch8Bit);
|
||||||
word->setChecked(entry.type == PatchEngine::PatchType::Patch16Bit);
|
word->setChecked(entry.type == PatchEngine::PatchType::Patch16Bit);
|
||||||
dword->setChecked(entry.type == PatchEngine::PatchType::Patch32Bit);
|
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')));
|
value->setText(QStringLiteral("%1").arg(entry.value, 8, 16, QLatin1Char('0')));
|
||||||
|
comparand->setText(QStringLiteral("%1").arg(entry.comparand, 8, 16, QLatin1Char('0')));
|
||||||
|
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
@ -218,11 +236,22 @@ void NewPatchDialog::accept()
|
|||||||
|
|
||||||
bool valid = true;
|
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)
|
if (!valid)
|
||||||
break;
|
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)
|
if (!valid)
|
||||||
@ -233,5 +262,12 @@ void NewPatchDialog::accept()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_patch.entries.clear();
|
||||||
|
|
||||||
|
for (const auto& entry : m_entries)
|
||||||
|
{
|
||||||
|
m_patch.entries.emplace_back(entry->entry);
|
||||||
|
}
|
||||||
|
|
||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
@ -21,10 +22,13 @@ class QLineEdit;
|
|||||||
class QVBoxLayout;
|
class QVBoxLayout;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
|
|
||||||
|
struct NewPatchEntry;
|
||||||
|
|
||||||
class NewPatchDialog : public QDialog
|
class NewPatchDialog : public QDialog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit NewPatchDialog(QWidget* parent, PatchEngine::Patch& patch);
|
explicit NewPatchDialog(QWidget* parent, PatchEngine::Patch& patch);
|
||||||
|
~NewPatchDialog() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CreateWidgets();
|
void CreateWidgets();
|
||||||
@ -33,7 +37,7 @@ private:
|
|||||||
|
|
||||||
void accept() override;
|
void accept() override;
|
||||||
|
|
||||||
QGroupBox* CreateEntry(PatchEngine::PatchEntry& entry);
|
QGroupBox* CreateEntry(const PatchEngine::PatchEntry& entry);
|
||||||
|
|
||||||
QLineEdit* m_name_edit;
|
QLineEdit* m_name_edit;
|
||||||
QWidget* m_entry_widget;
|
QWidget* m_entry_widget;
|
||||||
@ -41,7 +45,7 @@ private:
|
|||||||
QPushButton* m_add_button;
|
QPushButton* m_add_button;
|
||||||
QDialogButtonBox* m_button_box;
|
QDialogButtonBox* m_button_box;
|
||||||
|
|
||||||
std::vector<QLineEdit*> m_edits;
|
std::vector<std::unique_ptr<NewPatchEntry>> m_entries;
|
||||||
|
|
||||||
PatchEngine::Patch& m_patch;
|
PatchEngine::Patch& m_patch;
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "Common/FileUtil.h"
|
#include "Common/FileUtil.h"
|
||||||
#include "Common/IniFile.h"
|
#include "Common/IniFile.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
@ -143,8 +145,17 @@ void PatchesWidget::SavePatches()
|
|||||||
|
|
||||||
for (const auto& entry : patch.entries)
|
for (const auto& entry : patch.entries)
|
||||||
{
|
{
|
||||||
lines.emplace_back(StringFromFormat("0x%08X:%s:0x%08X", entry.address,
|
if (!entry.conditional)
|
||||||
PatchEngine::PatchTypeAsString(entry.type), entry.value));
|
{
|
||||||
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user