mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-22 05:40:01 -06:00
PatchEngine: Make PatchType an enum class
Makes the enum strongly typed. A function for retrieving the string representation of the enum is also added, which allows hiding the array that contains all of the strings from view (i.e. we operate on the API, not the exposed internals). This also allows us to bounds check any querying for the strings.
This commit is contained in:
@ -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,15 +28,20 @@
|
|||||||
|
|
||||||
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> onFrame;
|
||||||
static std::map<u32, int> speedHacks;
|
static std::map<u32, int> speedHacks;
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
@ -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:
|
||||||
|
@ -13,20 +13,18 @@ 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() = default;
|
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::PATCH_8BIT;
|
PatchType type = PatchType::Patch8Bit;
|
||||||
u32 address = 0;
|
u32 address = 0;
|
||||||
u32 value = 0;
|
u32 value = 0;
|
||||||
};
|
};
|
||||||
@ -39,6 +37,8 @@ struct Patch
|
|||||||
bool user_defined = false; // 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;
|
||||||
}
|
}
|
||||||
|
@ -161,24 +161,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;
|
||||||
|
@ -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:"));
|
||||||
@ -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
|
||||||
|
Reference in New Issue
Block a user