Merge pull request #7448 from RolandMunsil/improve-cheat-search

Improve performance of cheat searching & add input validation
This commit is contained in:
Léo Lam 2019-05-26 18:07:49 +02:00 committed by GitHub
commit f819ea687a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 90 additions and 26 deletions

View File

@ -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 auto op = static_cast<CompareType>(m_match_operation->currentIndex());
const QString text = m_match_value->text();
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 =
(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()))
{
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:
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:
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:
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:
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:
{
bool is_equal = std::equal(text.toUtf8().cbegin(), text.toUtf8().cend(),
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)
if (op != CompareType::Equal && op != CompareType::NotEqual)
{
case CompareType::Equal:
return is_equal;
case CompareType::NotEqual:
return !is_equal;
default:
return false;
m_result_label->setText(tr("String values can only be compared using equality."));
return nullptr;
}
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()
@ -507,10 +562,14 @@ void CheatsManager::NewSearch()
return;
}
std::function<bool(u32)> matches_func = CreateMatchFunction();
if (matches_func == nullptr)
return;
Core::RunAsCPUThread([&] {
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(
{base_address + i, static_cast<DataType>(m_match_length->currentIndex())});
}
@ -529,11 +588,15 @@ void CheatsManager::NextSearch()
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(),
[this](Result r) {
[matches_func](Result r) {
return !PowerPC::HostIsRAMAddress(r.address) ||
!MatchesSearch(r.address);
!matches_func(r.address);
}),
m_results.end());
});

View File

@ -4,6 +4,7 @@
#pragma once
#include <functional>
#include <memory>
#include <vector>
@ -48,7 +49,7 @@ private:
void OnStateChanged(Core::State state);
size_t GetTypeSize() const;
bool MatchesSearch(u32 addr) const;
std::function<bool(u32)> CreateMatchFunction();
void Reset();
void NewSearch();