Skip to content
Permalink
Browse files

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

Improve performance of cheat searching & add input validation
  • Loading branch information...
leoetlino committed May 26, 2019
2 parents 526698d + 4ce7079 commit f819ea687a9b5b291091b4964f5266c49bb91ccf
Showing with 90 additions and 26 deletions.
  1. +88 −25 Source/Core/DolphinQt/CheatsManager.cpp
  2. +2 −1 Source/Core/DolphinQt/CheatsManager.h
@@ -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());
});
@@ -4,6 +4,7 @@

#pragma once

#include <functional>
#include <memory>
#include <vector>

@@ -48,7 +49,7 @@ class CheatsManager : public QDialog
void OnStateChanged(Core::State state);

size_t GetTypeSize() const;
bool MatchesSearch(u32 addr) const;
std::function<bool(u32)> CreateMatchFunction();

void Reset();
void NewSearch();

0 comments on commit f819ea6

Please sign in to comment.
You can’t perform that action at this time.