mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-26 21:35:28 +00:00
Merge pull request #6843 from lioncash/patch
PatchEngine: Minor changes
This commit is contained in:
commit
07b57c7ac6
@ -9,6 +9,8 @@
|
|||||||
#include "Core/PatchEngine.h"
|
#include "Core/PatchEngine.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <iterator>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -26,14 +28,19 @@
|
|||||||
|
|
||||||
namespace PatchEngine
|
namespace PatchEngine
|
||||||
{
|
{
|
||||||
const char* PatchTypeStrings[] = {
|
constexpr std::array<const char*, 3> s_patch_type_strings{{
|
||||||
"byte",
|
"byte",
|
||||||
"word",
|
"word",
|
||||||
"dword",
|
"dword",
|
||||||
};
|
}};
|
||||||
|
|
||||||
static std::vector<Patch> onFrame;
|
static std::vector<Patch> s_on_frame;
|
||||||
static std::map<u32, int> speedHacks;
|
static std::map<u32, int> s_speed_hacks;
|
||||||
|
|
||||||
|
const char* PatchTypeAsString(PatchType type)
|
||||||
|
{
|
||||||
|
return s_patch_type_strings.at(static_cast<int>(type));
|
||||||
|
}
|
||||||
|
|
||||||
void LoadPatchSection(const std::string& section, std::vector<Patch>& patches, IniFile& globalIni,
|
void LoadPatchSection(const std::string& section, std::vector<Patch>& patches, IniFile& globalIni,
|
||||||
IniFile& localIni)
|
IniFile& localIni)
|
||||||
@ -97,8 +104,10 @@ void LoadPatchSection(const std::string& section, std::vector<Patch>& patches, I
|
|||||||
success &= TryParse(items[0], &pE.address);
|
success &= TryParse(items[0], &pE.address);
|
||||||
success &= TryParse(items[2], &pE.value);
|
success &= TryParse(items[2], &pE.value);
|
||||||
|
|
||||||
pE.type = PatchType(std::find(PatchTypeStrings, PatchTypeStrings + 3, items[1]) -
|
const auto iter =
|
||||||
PatchTypeStrings);
|
std::find(s_patch_type_strings.begin(), s_patch_type_strings.end(), items[1]);
|
||||||
|
pE.type = PatchType(std::distance(s_patch_type_strings.begin(), iter));
|
||||||
|
|
||||||
success &= (pE.type != (PatchType)3);
|
success &= (pE.type != (PatchType)3);
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
@ -132,7 +141,7 @@ static void LoadSpeedhacks(const std::string& section, IniFile& ini)
|
|||||||
success &= TryParse(value, &cycles);
|
success &= TryParse(value, &cycles);
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
speedHacks[address] = (int)cycles;
|
s_speed_hacks[address] = static_cast<int>(cycles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,11 +149,11 @@ static void LoadSpeedhacks(const std::string& section, IniFile& ini)
|
|||||||
|
|
||||||
int GetSpeedhackCycles(const u32 addr)
|
int GetSpeedhackCycles(const u32 addr)
|
||||||
{
|
{
|
||||||
std::map<u32, int>::const_iterator iter = speedHacks.find(addr);
|
const auto iter = s_speed_hacks.find(addr);
|
||||||
if (iter == speedHacks.end())
|
if (iter == s_speed_hacks.end())
|
||||||
return 0;
|
return 0;
|
||||||
else
|
|
||||||
return iter->second;
|
return iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadPatches()
|
void LoadPatches()
|
||||||
@ -153,7 +162,7 @@ void LoadPatches()
|
|||||||
IniFile globalIni = SConfig::GetInstance().LoadDefaultGameIni();
|
IniFile globalIni = SConfig::GetInstance().LoadDefaultGameIni();
|
||||||
IniFile localIni = SConfig::GetInstance().LoadLocalGameIni();
|
IniFile localIni = SConfig::GetInstance().LoadLocalGameIni();
|
||||||
|
|
||||||
LoadPatchSection("OnFrame", onFrame, globalIni, localIni);
|
LoadPatchSection("OnFrame", s_on_frame, globalIni, localIni);
|
||||||
ActionReplay::LoadAndApplyCodes(globalIni, localIni);
|
ActionReplay::LoadAndApplyCodes(globalIni, localIni);
|
||||||
|
|
||||||
Gecko::SetActiveCodes(Gecko::LoadCodes(globalIni, localIni));
|
Gecko::SetActiveCodes(Gecko::LoadCodes(globalIni, localIni));
|
||||||
@ -173,13 +182,13 @@ static void ApplyPatches(const std::vector<Patch>& patches)
|
|||||||
u32 value = entry.value;
|
u32 value = entry.value;
|
||||||
switch (entry.type)
|
switch (entry.type)
|
||||||
{
|
{
|
||||||
case PATCH_8BIT:
|
case PatchType::Patch8Bit:
|
||||||
PowerPC::HostWrite_U8((u8)value, addr);
|
PowerPC::HostWrite_U8(static_cast<u8>(value), addr);
|
||||||
break;
|
break;
|
||||||
case PATCH_16BIT:
|
case PatchType::Patch16Bit:
|
||||||
PowerPC::HostWrite_U16((u16)value, addr);
|
PowerPC::HostWrite_U16(static_cast<u16>(value), addr);
|
||||||
break;
|
break;
|
||||||
case PATCH_32BIT:
|
case PatchType::Patch32Bit:
|
||||||
PowerPC::HostWrite_U32(value, addr);
|
PowerPC::HostWrite_U32(value, addr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -229,7 +238,7 @@ bool ApplyFramePatches()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplyPatches(onFrame);
|
ApplyPatches(s_on_frame);
|
||||||
|
|
||||||
// Run the Gecko code handler
|
// Run the Gecko code handler
|
||||||
Gecko::RunCodeHandler();
|
Gecko::RunCodeHandler();
|
||||||
@ -240,8 +249,8 @@ bool ApplyFramePatches()
|
|||||||
|
|
||||||
void Shutdown()
|
void Shutdown()
|
||||||
{
|
{
|
||||||
onFrame.clear();
|
s_on_frame.clear();
|
||||||
speedHacks.clear();
|
s_speed_hacks.clear();
|
||||||
ActionReplay::ApplyCodes({});
|
ActionReplay::ApplyCodes({});
|
||||||
Gecko::Shutdown();
|
Gecko::Shutdown();
|
||||||
}
|
}
|
||||||
|
@ -13,32 +13,32 @@ class IniFile;
|
|||||||
|
|
||||||
namespace PatchEngine
|
namespace PatchEngine
|
||||||
{
|
{
|
||||||
enum PatchType
|
enum class PatchType
|
||||||
{
|
{
|
||||||
PATCH_8BIT,
|
Patch8Bit,
|
||||||
PATCH_16BIT,
|
Patch16Bit,
|
||||||
PATCH_32BIT,
|
Patch32Bit,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const char* PatchTypeStrings[];
|
|
||||||
|
|
||||||
struct PatchEntry
|
struct PatchEntry
|
||||||
{
|
{
|
||||||
PatchEntry() {}
|
PatchEntry() = default;
|
||||||
PatchEntry(PatchType _t, u32 _addr, u32 _value) : type(_t), address(_addr), value(_value) {}
|
PatchEntry(PatchType t, u32 addr, u32 value_) : type(t), address(addr), value(value_) {}
|
||||||
PatchType type;
|
PatchType type = PatchType::Patch8Bit;
|
||||||
u32 address;
|
u32 address = 0;
|
||||||
u32 value;
|
u32 value = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Patch
|
struct Patch
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<PatchEntry> entries;
|
std::vector<PatchEntry> entries;
|
||||||
bool active;
|
bool active = false;
|
||||||
bool user_defined; // False if this code is shipped with Dolphin.
|
bool user_defined = false; // False if this code is shipped with Dolphin.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char* PatchTypeAsString(PatchType type);
|
||||||
|
|
||||||
int GetSpeedhackCycles(const u32 addr);
|
int GetSpeedhackCycles(const u32 addr);
|
||||||
void LoadPatchSection(const std::string& section, std::vector<Patch>& patches, IniFile& globalIni,
|
void LoadPatchSection(const std::string& section, std::vector<Patch>& patches, IniFile& globalIni,
|
||||||
IniFile& localIni);
|
IniFile& localIni);
|
||||||
@ -52,15 +52,15 @@ inline int GetPatchTypeCharLength(PatchType type)
|
|||||||
int size = 8;
|
int size = 8;
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case PatchEngine::PATCH_8BIT:
|
case PatchType::Patch8Bit:
|
||||||
size = 2;
|
size = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PatchEngine::PATCH_16BIT:
|
case PatchType::Patch16Bit:
|
||||||
size = 4;
|
size = 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PatchEngine::PATCH_32BIT:
|
case PatchType::Patch32Bit:
|
||||||
size = 8;
|
size = 8;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -77,11 +77,7 @@ void NewPatchDialog::ConnectWidgets()
|
|||||||
|
|
||||||
void NewPatchDialog::AddEntry()
|
void NewPatchDialog::AddEntry()
|
||||||
{
|
{
|
||||||
PatchEngine::PatchEntry entry;
|
m_patch.entries.emplace_back();
|
||||||
entry.type = PatchEngine::PATCH_8BIT;
|
|
||||||
entry.address = entry.value = 0;
|
|
||||||
|
|
||||||
m_patch.entries.push_back(entry);
|
|
||||||
|
|
||||||
m_entry_layout->addWidget(CreateEntry(static_cast<int>(m_patch.entries.size() - 1)));
|
m_entry_layout->addWidget(CreateEntry(static_cast<int>(m_patch.entries.size() - 1)));
|
||||||
}
|
}
|
||||||
@ -163,24 +159,24 @@ QGroupBox* NewPatchDialog::CreateEntry(int index)
|
|||||||
|
|
||||||
connect(byte, &QRadioButton::toggled, [this, index](bool checked) {
|
connect(byte, &QRadioButton::toggled, [this, index](bool checked) {
|
||||||
if (checked)
|
if (checked)
|
||||||
m_patch.entries[index].type = PatchEngine::PATCH_8BIT;
|
m_patch.entries[index].type = PatchEngine::PatchType::Patch8Bit;
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(word, &QRadioButton::toggled, [this, index](bool checked) {
|
connect(word, &QRadioButton::toggled, [this, index](bool checked) {
|
||||||
if (checked)
|
if (checked)
|
||||||
m_patch.entries[index].type = PatchEngine::PATCH_16BIT;
|
m_patch.entries[index].type = PatchEngine::PatchType::Patch16Bit;
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(dword, &QRadioButton::toggled, [this, index](bool checked) {
|
connect(dword, &QRadioButton::toggled, [this, index](bool checked) {
|
||||||
if (checked)
|
if (checked)
|
||||||
m_patch.entries[index].type = PatchEngine::PATCH_32BIT;
|
m_patch.entries[index].type = PatchEngine::PatchType::Patch32Bit;
|
||||||
});
|
});
|
||||||
|
|
||||||
auto entry_type = m_patch.entries[index].type;
|
auto entry_type = m_patch.entries[index].type;
|
||||||
|
|
||||||
byte->setChecked(entry_type == PatchEngine::PATCH_8BIT);
|
byte->setChecked(entry_type == PatchEngine::PatchType::Patch8Bit);
|
||||||
word->setChecked(entry_type == PatchEngine::PATCH_16BIT);
|
word->setChecked(entry_type == PatchEngine::PatchType::Patch16Bit);
|
||||||
dword->setChecked(entry_type == PatchEngine::PATCH_32BIT);
|
dword->setChecked(entry_type == PatchEngine::PatchType::Patch32Bit);
|
||||||
|
|
||||||
offset->setText(
|
offset->setText(
|
||||||
QStringLiteral("%1").arg(m_patch.entries[index].address, 10, 16, QLatin1Char('0')));
|
QStringLiteral("%1").arg(m_patch.entries[index].address, 10, 16, QLatin1Char('0')));
|
||||||
|
@ -138,7 +138,7 @@ void PatchesWidget::SavePatches()
|
|||||||
for (const auto& entry : patch.entries)
|
for (const auto& entry : patch.entries)
|
||||||
{
|
{
|
||||||
lines.push_back(StringFromFormat("0x%08X:%s:0x%08X", entry.address,
|
lines.push_back(StringFromFormat("0x%08X:%s:0x%08X", entry.address,
|
||||||
PatchEngine::PatchTypeStrings[entry.type], entry.value));
|
PatchEngine::PatchTypeAsString(entry.type), entry.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -755,9 +755,10 @@ void CISOProperties::PatchList_Save()
|
|||||||
lines.push_back("$" + p.name);
|
lines.push_back("$" + p.name);
|
||||||
for (const PatchEngine::PatchEntry& entry : p.entries)
|
for (const PatchEngine::PatchEntry& entry : p.entries)
|
||||||
{
|
{
|
||||||
std::string temp = StringFromFormat("0x%08X:%s:0x%08X", entry.address,
|
std::string temp =
|
||||||
PatchEngine::PatchTypeStrings[entry.type], entry.value);
|
StringFromFormat("0x%08X:%s:0x%08X", entry.address,
|
||||||
lines.push_back(temp);
|
PatchEngine::PatchTypeAsString(entry.type), entry.value);
|
||||||
|
lines.push_back(std::move(temp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++index;
|
++index;
|
||||||
|
@ -42,7 +42,7 @@ void CPatchAddEdit::CreateGUIControls(int _selection)
|
|||||||
if (_selection == -1)
|
if (_selection == -1)
|
||||||
{
|
{
|
||||||
tempEntries.clear();
|
tempEntries.clear();
|
||||||
tempEntries.emplace_back(PatchEngine::PATCH_8BIT, 0x00000000, 0x00000000);
|
tempEntries.emplace_back();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -68,11 +68,14 @@ void CPatchAddEdit::CreateGUIControls(int _selection)
|
|||||||
EntrySelection->SetRange(0, (int)tempEntries.size() - 1);
|
EntrySelection->SetRange(0, (int)tempEntries.size() - 1);
|
||||||
EntrySelection->SetValue((int)tempEntries.size() - 1);
|
EntrySelection->SetValue((int)tempEntries.size() - 1);
|
||||||
|
|
||||||
wxArrayString wxArrayStringFor_EditPatchType;
|
wxArrayString patch_types;
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
wxArrayStringFor_EditPatchType.Add(StrToWxStr(PatchEngine::PatchTypeStrings[i]));
|
{
|
||||||
EditPatchType = new wxRadioBox(this, wxID_ANY, _("Type"), wxDefaultPosition, wxDefaultSize,
|
patch_types.Add(
|
||||||
wxArrayStringFor_EditPatchType, 3, wxRA_SPECIFY_COLS);
|
StrToWxStr(PatchEngine::PatchTypeAsString(static_cast<PatchEngine::PatchType>(i))));
|
||||||
|
}
|
||||||
|
EditPatchType =
|
||||||
|
new wxRadioBox(this, wxID_ANY, _("Type"), wxDefaultPosition, wxDefaultSize, patch_types);
|
||||||
EditPatchType->SetSelection((int)tempEntries.at(0).type);
|
EditPatchType->SetSelection((int)tempEntries.at(0).type);
|
||||||
|
|
||||||
wxStaticText* EditPatchValueText = new wxStaticText(this, wxID_ANY, _("Value:"));
|
wxStaticText* EditPatchValueText = new wxStaticText(this, wxID_ANY, _("Value:"));
|
||||||
@ -165,7 +168,7 @@ void CPatchAddEdit::AddEntry(wxCommandEvent& event)
|
|||||||
if (!UpdateTempEntryData(itCurEntry))
|
if (!UpdateTempEntryData(itCurEntry))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PatchEngine::PatchEntry peEmptyEntry(PatchEngine::PATCH_8BIT, 0x00000000, 0x00000000);
|
PatchEngine::PatchEntry peEmptyEntry;
|
||||||
++itCurEntry;
|
++itCurEntry;
|
||||||
currentItem++;
|
currentItem++;
|
||||||
itCurEntry = tempEntries.insert(itCurEntry, peEmptyEntry);
|
itCurEntry = tempEntries.insert(itCurEntry, peEmptyEntry);
|
||||||
@ -206,7 +209,7 @@ void CPatchAddEdit::UpdateEntryCtrls(PatchEngine::PatchEntry pE)
|
|||||||
sbEntry->GetStaticBox()->SetLabel(
|
sbEntry->GetStaticBox()->SetLabel(
|
||||||
wxString::Format(_("Entry %d/%d"), currentItem, (int)tempEntries.size()));
|
wxString::Format(_("Entry %d/%d"), currentItem, (int)tempEntries.size()));
|
||||||
EditPatchOffset->SetValue(wxString::Format("%08X", pE.address));
|
EditPatchOffset->SetValue(wxString::Format("%08X", pE.address));
|
||||||
EditPatchType->SetSelection(pE.type);
|
EditPatchType->SetSelection(static_cast<int>(pE.type));
|
||||||
EditPatchValue->SetValue(
|
EditPatchValue->SetValue(
|
||||||
wxString::Format("%0*X", PatchEngine::GetPatchTypeCharLength(pE.type), pE.value));
|
wxString::Format("%0*X", PatchEngine::GetPatchTypeCharLength(pE.type), pE.value));
|
||||||
}
|
}
|
||||||
@ -217,19 +220,19 @@ bool CPatchAddEdit::UpdateTempEntryData(std::vector<PatchEngine::PatchEntry>::it
|
|||||||
bool parsed_ok = true;
|
bool parsed_ok = true;
|
||||||
|
|
||||||
if (EditPatchOffset->GetValue().ToULong(&value, 16))
|
if (EditPatchOffset->GetValue().ToULong(&value, 16))
|
||||||
(*iterEntry).address = value;
|
iterEntry->address = value;
|
||||||
else
|
else
|
||||||
parsed_ok = false;
|
parsed_ok = false;
|
||||||
|
|
||||||
PatchEngine::PatchType tempType = (*iterEntry).type =
|
const auto tempType = iterEntry->type =
|
||||||
(PatchEngine::PatchType)EditPatchType->GetSelection();
|
static_cast<PatchEngine::PatchType>(EditPatchType->GetSelection());
|
||||||
|
|
||||||
if (EditPatchValue->GetValue().ToULong(&value, 16))
|
if (EditPatchValue->GetValue().ToULong(&value, 16))
|
||||||
{
|
{
|
||||||
(*iterEntry).value = value;
|
iterEntry->value = value;
|
||||||
if (tempType == PatchEngine::PATCH_8BIT && value > 0xff)
|
if (tempType == PatchEngine::PatchType::Patch8Bit && value > 0xff)
|
||||||
parsed_ok = false;
|
parsed_ok = false;
|
||||||
else if (tempType == PatchEngine::PATCH_16BIT && value > 0xffff)
|
else if (tempType == PatchEngine::PatchType::Patch16Bit && value > 0xffff)
|
||||||
parsed_ok = false;
|
parsed_ok = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user