From db9725a563710b73baaa5580371143706bb7c627 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 14 Oct 2017 16:18:19 -0700 Subject: [PATCH] Core: Add memory delta search --- include/mgba/core/mem-search.h | 13 +++- src/core/mem-search.c | 119 +++++++++++++++++++------------ src/platform/qt/MemorySearch.cpp | 8 ++- src/platform/qt/MemorySearch.ui | 49 ++++++++++--- 4 files changed, 130 insertions(+), 59 deletions(-) diff --git a/include/mgba/core/mem-search.h b/include/mgba/core/mem-search.h index a9a3a8223..b879d6f09 100644 --- a/include/mgba/core/mem-search.h +++ b/include/mgba/core/mem-search.h @@ -18,24 +18,31 @@ enum mCoreMemorySearchType { mCORE_MEMORY_SEARCH_GUESS, }; +enum mCoreMemorySearchOp { + mCORE_MEMORY_SEARCH_FIXED, + mCORE_MEMORY_SEARCH_DELTA, +}; + struct mCoreMemorySearchParams { int memoryFlags; enum mCoreMemorySearchType type; + enum mCoreMemorySearchOp op; int align; int width; union { const char* valueStr; - uint32_t valueInt; + int32_t valueInt; }; }; struct mCoreMemorySearchResult { uint32_t address; int segment; - uint64_t guessDivisor; - uint64_t guessMultiplier; + uint32_t guessDivisor; + uint32_t guessMultiplier; enum mCoreMemorySearchType type; int width; + int32_t oldValue; }; DECLARE_VECTOR(mCoreMemorySearchResults, struct mCoreMemorySearchResult); diff --git a/src/core/mem-search.c b/src/core/mem-search.c index 1c47b633c..1b0ce9ae9 100644 --- a/src/core/mem-search.c +++ b/src/core/mem-search.c @@ -34,6 +34,7 @@ static size_t _search32(const void* mem, size_t size, const struct mCoreMemoryBl res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value32; ++found; } if ((mask & 2) && (!limit || found < limit)) { @@ -44,6 +45,7 @@ static size_t _search32(const void* mem, size_t size, const struct mCoreMemoryBl res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value32; ++found; } if ((mask & 4) && (!limit || found < limit)) { @@ -54,6 +56,7 @@ static size_t _search32(const void* mem, size_t size, const struct mCoreMemoryBl res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value32; ++found; } if ((mask & 8) && (!limit || found < limit)) { @@ -64,6 +67,7 @@ static size_t _search32(const void* mem, size_t size, const struct mCoreMemoryBl res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value32; ++found; } } @@ -99,6 +103,7 @@ static size_t _search16(const void* mem, size_t size, const struct mCoreMemoryBl res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } if ((mask & 2) && (!limit || found < limit)) { @@ -109,6 +114,7 @@ static size_t _search16(const void* mem, size_t size, const struct mCoreMemoryBl res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } if ((mask & 4) && (!limit || found < limit)) { @@ -119,6 +125,7 @@ static size_t _search16(const void* mem, size_t size, const struct mCoreMemoryBl res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } if ((mask & 8) && (!limit || found < limit)) { @@ -129,6 +136,7 @@ static size_t _search16(const void* mem, size_t size, const struct mCoreMemoryBl res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } if ((mask & 16) && (!limit || found < limit)) { @@ -139,6 +147,7 @@ static size_t _search16(const void* mem, size_t size, const struct mCoreMemoryBl res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } if ((mask & 32) && (!limit || found < limit)) { @@ -149,6 +158,7 @@ static size_t _search16(const void* mem, size_t size, const struct mCoreMemoryBl res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } if ((mask & 64) && (!limit || found < limit)) { @@ -159,6 +169,7 @@ static size_t _search16(const void* mem, size_t size, const struct mCoreMemoryBl res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } if ((mask & 128) && (!limit || found < limit)) { @@ -169,6 +180,7 @@ static size_t _search16(const void* mem, size_t size, const struct mCoreMemoryBl res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } } @@ -203,6 +215,7 @@ static size_t _search8(const void* mem, size_t size, const struct mCoreMemoryBlo res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } if ((mask & 2) && (!limit || found < limit)) { @@ -213,6 +226,7 @@ static size_t _search8(const void* mem, size_t size, const struct mCoreMemoryBlo res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } if ((mask & 4) && (!limit || found < limit)) { @@ -223,6 +237,7 @@ static size_t _search8(const void* mem, size_t size, const struct mCoreMemoryBlo res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } if ((mask & 8) && (!limit || found < limit)) { @@ -233,6 +248,7 @@ static size_t _search8(const void* mem, size_t size, const struct mCoreMemoryBlo res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } if ((mask & 16) && (!limit || found < limit)) { @@ -243,6 +259,7 @@ static size_t _search8(const void* mem, size_t size, const struct mCoreMemoryBlo res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } if ((mask & 32) && (!limit || found < limit)) { @@ -253,6 +270,7 @@ static size_t _search8(const void* mem, size_t size, const struct mCoreMemoryBlo res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } if ((mask & 64) && (!limit || found < limit)) { @@ -263,6 +281,7 @@ static size_t _search8(const void* mem, size_t size, const struct mCoreMemoryBlo res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } if ((mask & 128) && (!limit || found < limit)) { @@ -273,6 +292,7 @@ static size_t _search8(const void* mem, size_t size, const struct mCoreMemoryBlo res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } } @@ -317,7 +337,7 @@ static size_t _searchGuess(const void* mem, size_t size, const struct mCoreMemor // TODO: As str char* end; - uint64_t value; + int64_t value; size_t found = 0; @@ -325,7 +345,7 @@ static size_t _searchGuess(const void* mem, size_t size, const struct mCoreMemor mCoreMemorySearchResultsInit(&tmp, 0); // Decimal: - value = strtoull(valueStr, &end, 10); + value = strtoll(valueStr, &end, 10); if (end && !end[0]) { if (value > 0x10000) { found += _search32(mem, size, block, value, out, limit ? limit - found : 0); @@ -358,7 +378,7 @@ static size_t _searchGuess(const void* mem, size_t size, const struct mCoreMemor } // Hex: - value = strtoull(valueStr, &end, 16); + value = strtoll(valueStr, &end, 16); if (end && !end[0]) { if (value > 0x10000) { found += _search32(mem, size, block, value, out, limit ? limit - found : 0); @@ -428,34 +448,42 @@ void mCoreMemorySearch(struct mCore* core, const struct mCoreMemorySearchParams* } } -bool _testGuess(struct mCore* core, const struct mCoreMemorySearchResult* res, const struct mCoreMemorySearchParams* params) { - uint64_t value; +bool _testGuess(struct mCore* core, struct mCoreMemorySearchResult* res, const struct mCoreMemorySearchParams* params) { + int64_t value; + int32_t offset = 0; char* end; - - value = strtoull(params->valueStr, &end, 10); - if (end) { - if (core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value) { - return true; - } - if (!(res->address & 1) && core->rawRead16(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value) { - return true; - } - if (!(res->address & 3) && core->rawRead32(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value) { - return true; - } + if (params->op == mCORE_MEMORY_SEARCH_DELTA) { + offset = res->oldValue; } - value = strtoull(params->valueStr, &end, 16); + value = strtoll(params->valueStr, &end, 10); if (end) { - if (core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value) { + res->oldValue += value; + if (core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value + offset) { return true; } - if (!(res->address & 1) && core->rawRead16(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value) { + if (!(res->address & 1) && core->rawRead16(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value + offset) { return true; } - if (!(res->address & 3) && core->rawRead32(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value) { + if (!(res->address & 3) && core->rawRead32(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value + offset) { return true; } + res->oldValue -= value; + } + + value = strtoll(params->valueStr, &end, 16); + if (end) { + res->oldValue += value; + if (core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value + offset) { + return true; + } + if (!(res->address & 1) && core->rawRead16(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value + offset) { + return true; + } + if (!(res->address & 3) && core->rawRead32(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value + offset) { + return true; + } + res->oldValue -= value; } return false; } @@ -466,33 +494,36 @@ void mCoreMemorySearchRepeat(struct mCore* core, const struct mCoreMemorySearchP struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsGetPointer(inout, i); switch (res->type) { case mCORE_MEMORY_SEARCH_INT: - switch (params->width) { - case 1: - if (core->rawRead8(core, res->address, res->segment) != params->valueInt) { - mCoreMemorySearchResultsShift(inout, i, 1); - --i; - } - break; - case 2: - if (core->rawRead8(core, res->address, res->segment) != params->valueInt) { - mCoreMemorySearchResultsShift(inout, i, 1); - --i; - } - break; - case 4: - if (core->rawRead32(core, res->address, res->segment) != params->valueInt) { - mCoreMemorySearchResultsShift(inout, i, 1); - --i; - } - break; - case -1: + if (params->type == mCORE_MEMORY_SEARCH_GUESS) { if (!_testGuess(core, res, params)) { mCoreMemorySearchResultsShift(inout, i, 1); --i; } - break; - default: - break; + } else if (params->type == mCORE_MEMORY_SEARCH_INT) { + int32_t oldValue = params->valueInt; + if (params->op == mCORE_MEMORY_SEARCH_DELTA) { + oldValue += res->oldValue; + } + int32_t value = 0; + switch (params->width) { + case 1: + value = core->rawRead8(core, res->address, res->segment); + break; + case 2: + value = core->rawRead16(core, res->address, res->segment); + break; + case 4: + value = core->rawRead32(core, res->address, res->segment); + break; + default: + break; + } + if (value != oldValue) { + mCoreMemorySearchResultsShift(inout, i, 1); + --i; + } else { + res->oldValue = value; + } } break; case mCORE_MEMORY_SEARCH_STRING: diff --git a/src/platform/qt/MemorySearch.cpp b/src/platform/qt/MemorySearch.cpp index c7c1d9373..7c06791dd 100644 --- a/src/platform/qt/MemorySearch.cpp +++ b/src/platform/qt/MemorySearch.cpp @@ -40,8 +40,9 @@ bool MemorySearch::createParams(mCoreMemorySearchParams* params) { QByteArray string; bool ok = false; - if (m_ui.typeNum->isChecked()) { + if (m_ui.typeNum->isChecked() || m_ui.typeDelta->isChecked()) { params->type = mCORE_MEMORY_SEARCH_INT; + params->op = m_ui.typeDelta->isChecked() ? mCORE_MEMORY_SEARCH_DELTA : mCORE_MEMORY_SEARCH_FIXED; params->align = -1; if (m_ui.bits8->isChecked()) { params->width = 1; @@ -140,6 +141,7 @@ void MemorySearch::refresh() { m_ui.results->clearContents(); m_ui.results->setRowCount(mCoreMemorySearchResultsSize(&m_results)); + m_ui.typeDelta->setEnabled(false); for (size_t i = 0; i < mCoreMemorySearchResultsSize(&m_results); ++i) { mCoreMemorySearchResult* result = mCoreMemorySearchResultsGetPointer(&m_results, i); QTableWidgetItem* item = new QTableWidgetItem(QString("%1").arg(result->address, 8, 16, QChar('0'))); @@ -200,6 +202,10 @@ void MemorySearch::refresh() { } m_ui.results->setItem(i, 1, item); m_ui.results->setItem(i, 2, type); + m_ui.typeDelta->setEnabled(true); + } + if (m_ui.typeDelta->isChecked() && !m_ui.typeDelta->isEnabled()) { + m_ui.typeNum->setChecked(true); } m_ui.results->sortItems(0); } diff --git a/src/platform/qt/MemorySearch.ui b/src/platform/qt/MemorySearch.ui index ccbe07076..678405867 100644 --- a/src/platform/qt/MemorySearch.ui +++ b/src/platform/qt/MemorySearch.ui @@ -6,8 +6,8 @@ 0 0 - 631 - 378 + 639 + 397 @@ -89,7 +89,7 @@ - + Text @@ -99,14 +99,14 @@ - + Width - + 1 Byte (8-bit) @@ -116,7 +116,7 @@ - + 2 Bytes (16-bit) @@ -126,7 +126,7 @@ - + 4 Bytes (32-bit) @@ -139,14 +139,14 @@ - + Number type - + Hexadecimal @@ -156,20 +156,47 @@ - + Decimal - + Guess + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + false + + + Delta + + + type + + +