diff --git a/Source/Core/DolphinQt/CheatsManager.cpp b/Source/Core/DolphinQt/CheatsManager.cpp index 0bd4e86bbb..e2ad942c7f 100644 --- a/Source/Core/DolphinQt/CheatsManager.cpp +++ b/Source/Core/DolphinQt/CheatsManager.cpp @@ -454,46 +454,101 @@ size_t CheatsManager::GetTypeSize() const } } -bool CheatsManager::MatchesSearch(u32 addr) const +std::function CheatsManager::CreateMatchFunction() { - const auto text = m_match_value->text(); - const auto op = static_cast(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(m_match_operation->currentIndex()); const int base = (m_match_decimal->isChecked() ? 10 : (m_match_hexadecimal->isChecked() ? 16 : 8)); + bool conversion_succeeded = false; + std::function matches_func; switch (static_cast(m_match_length->currentIndex())) { case DataType::Byte: - return Compare(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(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(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(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 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(m_match_length->currentIndex())}); } @@ -529,11 +588,15 @@ void CheatsManager::NextSearch() return; } - Core::RunAsCPUThread([this] { + std::function 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()); }); diff --git a/Source/Core/DolphinQt/CheatsManager.h b/Source/Core/DolphinQt/CheatsManager.h index 9a2e43eafc..7d0d1297f6 100644 --- a/Source/Core/DolphinQt/CheatsManager.h +++ b/Source/Core/DolphinQt/CheatsManager.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include @@ -48,7 +49,7 @@ private: void OnStateChanged(Core::State state); size_t GetTypeSize() const; - bool MatchesSearch(u32 addr) const; + std::function CreateMatchFunction(); void Reset(); void NewSearch();