mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-08 13:43:33 +01:00
Merge pull request #7448 from RolandMunsil/improve-cheat-search
Improve performance of cheat searching & add input validation
This commit is contained in:
commit
f819ea687a
@ -454,46 +454,101 @@ size_t CheatsManager::GetTypeSize() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheatsManager::MatchesSearch(u32 addr) const
|
std::function<bool(u32)> CheatsManager::CreateMatchFunction()
|
||||||
{
|
{
|
||||||
const auto text = m_match_value->text();
|
const QString text = m_match_value->text();
|
||||||
const auto op = static_cast<CompareType>(m_match_operation->currentIndex());
|
|
||||||
|
if (text.isEmpty())
|
||||||
|
{
|
||||||
|
m_result_label->setText(tr("No search value entered."));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CompareType op = static_cast<CompareType>(m_match_operation->currentIndex());
|
||||||
|
|
||||||
const int base =
|
const int base =
|
||||||
(m_match_decimal->isChecked() ? 10 : (m_match_hexadecimal->isChecked() ? 16 : 8));
|
(m_match_decimal->isChecked() ? 10 : (m_match_hexadecimal->isChecked() ? 16 : 8));
|
||||||
|
|
||||||
|
bool conversion_succeeded = false;
|
||||||
|
std::function<bool(u32)> matches_func;
|
||||||
switch (static_cast<DataType>(m_match_length->currentIndex()))
|
switch (static_cast<DataType>(m_match_length->currentIndex()))
|
||||||
{
|
{
|
||||||
case DataType::Byte:
|
case DataType::Byte:
|
||||||
return Compare<u8>(PowerPC::HostRead_U8(addr), text.toUShort(nullptr, base) & 0xFF, op);
|
{
|
||||||
|
u8 comparison_value = text.toUShort(&conversion_succeeded, base) & 0xFF;
|
||||||
|
matches_func = [=](u32 addr) {
|
||||||
|
return Compare<u8>(PowerPC::HostRead_U8(addr), comparison_value, op);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DataType::Short:
|
case DataType::Short:
|
||||||
return Compare(PowerPC::HostRead_U16(addr), text.toUShort(nullptr, base), op);
|
{
|
||||||
|
u16 comparison_value = text.toUShort(&conversion_succeeded, base);
|
||||||
|
matches_func = [=](u32 addr) {
|
||||||
|
return Compare(PowerPC::HostRead_U16(addr), comparison_value, op);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DataType::Int:
|
case DataType::Int:
|
||||||
return Compare(PowerPC::HostRead_U32(addr), text.toUInt(nullptr, base), op);
|
{
|
||||||
|
u32 comparison_value = text.toUInt(&conversion_succeeded, base);
|
||||||
|
matches_func = [=](u32 addr) {
|
||||||
|
return Compare(PowerPC::HostRead_U32(addr), comparison_value, op);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DataType::Float:
|
case DataType::Float:
|
||||||
return Compare(PowerPC::HostRead_F32(addr), text.toFloat(), op);
|
{
|
||||||
|
float comparison_value = text.toFloat(&conversion_succeeded);
|
||||||
|
matches_func = [=](u32 addr) {
|
||||||
|
return Compare(PowerPC::HostRead_F32(addr), comparison_value, op);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DataType::Double:
|
case DataType::Double:
|
||||||
return Compare(PowerPC::HostRead_F64(addr), text.toDouble(), op);
|
{
|
||||||
|
double comparison_value = text.toDouble(&conversion_succeeded);
|
||||||
|
matches_func = [=](u32 addr) {
|
||||||
|
return Compare(PowerPC::HostRead_F64(addr), comparison_value, op);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DataType::String:
|
case DataType::String:
|
||||||
{
|
{
|
||||||
bool is_equal = std::equal(text.toUtf8().cbegin(), text.toUtf8().cend(),
|
if (op != CompareType::Equal && op != CompareType::NotEqual)
|
||||||
reinterpret_cast<char*>(Memory::m_pRAM + addr - 0x80000000));
|
|
||||||
|
|
||||||
// String only supports equals and not equals comparisons because the other ones frankly don't
|
|
||||||
// make any sense here
|
|
||||||
switch (op)
|
|
||||||
{
|
{
|
||||||
case CompareType::Equal:
|
m_result_label->setText(tr("String values can only be compared using equality."));
|
||||||
return is_equal;
|
return nullptr;
|
||||||
case CompareType::NotEqual:
|
|
||||||
return !is_equal;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conversion_succeeded = true;
|
||||||
|
|
||||||
|
const QString lambda_text = m_match_value->text();
|
||||||
|
const QByteArray utf8_bytes = lambda_text.toUtf8();
|
||||||
|
|
||||||
|
matches_func = [op, utf8_bytes](u32 addr) {
|
||||||
|
bool is_equal = std::equal(utf8_bytes.cbegin(), utf8_bytes.cend(),
|
||||||
|
reinterpret_cast<char*>(Memory::m_pRAM + addr - 0x80000000));
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case CompareType::Equal:
|
||||||
|
return is_equal;
|
||||||
|
case CompareType::NotEqual:
|
||||||
|
return !is_equal;
|
||||||
|
default:
|
||||||
|
// This should never occur since we've already checked the type of op
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if (conversion_succeeded)
|
||||||
|
return matches_func;
|
||||||
|
|
||||||
|
m_result_label->setText(tr("Cannot interpret the given value.\nHave you chosen the right type?"));
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheatsManager::NewSearch()
|
void CheatsManager::NewSearch()
|
||||||
@ -507,10 +562,14 @@ void CheatsManager::NewSearch()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::function<bool(u32)> matches_func = CreateMatchFunction();
|
||||||
|
if (matches_func == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
Core::RunAsCPUThread([&] {
|
Core::RunAsCPUThread([&] {
|
||||||
for (u32 i = 0; i < Memory::REALRAM_SIZE - GetTypeSize(); i++)
|
for (u32 i = 0; i < Memory::REALRAM_SIZE - GetTypeSize(); i++)
|
||||||
{
|
{
|
||||||
if (PowerPC::HostIsRAMAddress(base_address + i) && MatchesSearch(base_address + i))
|
if (PowerPC::HostIsRAMAddress(base_address + i) && matches_func(base_address + i))
|
||||||
m_results.push_back(
|
m_results.push_back(
|
||||||
{base_address + i, static_cast<DataType>(m_match_length->currentIndex())});
|
{base_address + i, static_cast<DataType>(m_match_length->currentIndex())});
|
||||||
}
|
}
|
||||||
@ -529,11 +588,15 @@ void CheatsManager::NextSearch()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::RunAsCPUThread([this] {
|
std::function<bool(u32)> matches_func = CreateMatchFunction();
|
||||||
|
if (matches_func == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Core::RunAsCPUThread([this, matches_func] {
|
||||||
m_results.erase(std::remove_if(m_results.begin(), m_results.end(),
|
m_results.erase(std::remove_if(m_results.begin(), m_results.end(),
|
||||||
[this](Result r) {
|
[matches_func](Result r) {
|
||||||
return !PowerPC::HostIsRAMAddress(r.address) ||
|
return !PowerPC::HostIsRAMAddress(r.address) ||
|
||||||
!MatchesSearch(r.address);
|
!matches_func(r.address);
|
||||||
}),
|
}),
|
||||||
m_results.end());
|
m_results.end());
|
||||||
});
|
});
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -48,7 +49,7 @@ private:
|
|||||||
void OnStateChanged(Core::State state);
|
void OnStateChanged(Core::State state);
|
||||||
|
|
||||||
size_t GetTypeSize() const;
|
size_t GetTypeSize() const;
|
||||||
bool MatchesSearch(u32 addr) const;
|
std::function<bool(u32)> CreateMatchFunction();
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
void NewSearch();
|
void NewSearch();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user