all repos — mgba @ db9725a563710b73baaa5580371143706bb7c627

mGBA Game Boy Advance Emulator

Core: Add memory delta search
Vicki Pfau vi@endrift.com
Sat, 14 Oct 2017 16:18:19 -0700
commit

db9725a563710b73baaa5580371143706bb7c627

parent

591ab468e9df1fe7c1ab06239e2973c99401fbaa

M include/mgba/core/mem-search.hinclude/mgba/core/mem-search.h

@@ -18,24 +18,31 @@ mCORE_MEMORY_SEARCH_STRING,

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);
M src/core/mem-search.csrc/core/mem-search.c

@@ -34,6 +34,7 @@ res->width = 4;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value32; ++found; } if ((mask & 2) && (!limit || found < limit)) {

@@ -44,6 +45,7 @@ res->width = 4;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value32; ++found; } if ((mask & 4) && (!limit || found < limit)) {

@@ -54,6 +56,7 @@ res->width = 4;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value32; ++found; } if ((mask & 8) && (!limit || found < limit)) {

@@ -64,6 +67,7 @@ res->width = 4;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value32; ++found; } }

@@ -99,6 +103,7 @@ res->width = 2;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } if ((mask & 2) && (!limit || found < limit)) {

@@ -109,6 +114,7 @@ res->width = 2;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } if ((mask & 4) && (!limit || found < limit)) {

@@ -119,6 +125,7 @@ res->width = 2;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } if ((mask & 8) && (!limit || found < limit)) {

@@ -129,6 +136,7 @@ res->width = 2;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } if ((mask & 16) && (!limit || found < limit)) {

@@ -139,6 +147,7 @@ res->width = 2;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } if ((mask & 32) && (!limit || found < limit)) {

@@ -149,6 +158,7 @@ res->width = 2;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } if ((mask & 64) && (!limit || found < limit)) {

@@ -159,6 +169,7 @@ res->width = 2;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } if ((mask & 128) && (!limit || found < limit)) {

@@ -169,6 +180,7 @@ res->width = 2;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value16; ++found; } }

@@ -203,6 +215,7 @@ res->width = 1;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } if ((mask & 2) && (!limit || found < limit)) {

@@ -213,6 +226,7 @@ res->width = 1;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } if ((mask & 4) && (!limit || found < limit)) {

@@ -223,6 +237,7 @@ res->width = 1;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } if ((mask & 8) && (!limit || found < limit)) {

@@ -233,6 +248,7 @@ res->width = 1;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } if ((mask & 16) && (!limit || found < limit)) {

@@ -243,6 +259,7 @@ res->width = 1;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } if ((mask & 32) && (!limit || found < limit)) {

@@ -253,6 +270,7 @@ res->width = 1;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } if ((mask & 64) && (!limit || found < limit)) {

@@ -263,6 +281,7 @@ res->width = 1;

res->segment = -1; // TODO res->guessDivisor = 1; res->guessMultiplier = 1; + res->oldValue = value8; ++found; } if ((mask & 128) && (!limit || found < limit)) {

@@ -273,6 +292,7 @@ res->width = 1;

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 mCoreMemoryBlock* block, const char* valueStr, struct mCoreMemorySearchResults* out, size_t limit) {

// TODO: As str char* end; - uint64_t value; + int64_t value; size_t found = 0;

@@ -325,7 +345,7 @@ struct mCoreMemorySearchResults tmp;

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 @@ }

} // 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 @@ found += _search(mem, size, block, params, out, limit ? limit - found : 0);

} } -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; + if (params->op == mCORE_MEMORY_SEARCH_DELTA) { + offset = res->oldValue; + } - value = strtoull(params->valueStr, &end, 10); + 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 = strtoull(params->valueStr, &end, 16); + value = strtoll(params->valueStr, &end, 16); 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; } return false; }

@@ -466,33 +494,36 @@ for (i = 0; i < mCoreMemorySearchResultsSize(inout); ++i) {

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) { + if (params->type == mCORE_MEMORY_SEARCH_GUESS) { + if (!_testGuess(core, res, params)) { mCoreMemorySearchResultsShift(inout, i, 1); --i; } - break; - case 2: - if (core->rawRead8(core, res->address, res->segment) != params->valueInt) { - mCoreMemorySearchResultsShift(inout, i, 1); - --i; + } else if (params->type == mCORE_MEMORY_SEARCH_INT) { + int32_t oldValue = params->valueInt; + if (params->op == mCORE_MEMORY_SEARCH_DELTA) { + oldValue += res->oldValue; } - break; - case 4: - if (core->rawRead32(core, res->address, res->segment) != params->valueInt) { - mCoreMemorySearchResultsShift(inout, i, 1); - --i; + 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; } - break; - case -1: - if (!_testGuess(core, res, params)) { + if (value != oldValue) { mCoreMemorySearchResultsShift(inout, i, 1); --i; + } else { + res->oldValue = value; } - break; - default: - break; } break; case mCORE_MEMORY_SEARCH_STRING:
M src/platform/qt/MemorySearch.cppsrc/platform/qt/MemorySearch.cpp

@@ -40,8 +40,9 @@ mCore* core = m_controller->thread()->core;

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 @@ mCore* core = m_controller->thread()->core;

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 @@ type = new QTableWidgetItem("string");

} 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); }
M src/platform/qt/MemorySearch.uisrc/platform/qt/MemorySearch.ui

@@ -6,8 +6,8 @@ <property name="geometry">

<rect> <x>0</x> <y>0</y> - <width>631</width> - <height>378</height> + <width>639</width> + <height>397</height> </rect> </property> <property name="minimumSize">

@@ -89,7 +89,7 @@ <string notr="true">type</string>

</attribute> </widget> </item> - <item row="2" column="1"> + <item row="3" column="1"> <widget class="QRadioButton" name="typeStr"> <property name="text"> <string>Text</string>

@@ -99,14 +99,14 @@ <string notr="true">type</string>

</attribute> </widget> </item> - <item row="3" column="0"> + <item row="5" column="0"> <widget class="QLabel" name="label_3"> <property name="text"> <string>Width</string> </property> </widget> </item> - <item row="3" column="1"> + <item row="5" column="1"> <widget class="QRadioButton" name="bits8"> <property name="text"> <string>1 Byte (8-bit)</string>

@@ -116,7 +116,7 @@ <string notr="true">width</string>

</attribute> </widget> </item> - <item row="4" column="1"> + <item row="6" column="1"> <widget class="QRadioButton" name="bits16"> <property name="text"> <string>2 Bytes (16-bit)</string>

@@ -126,7 +126,7 @@ <string notr="true">width</string>

</attribute> </widget> </item> - <item row="5" column="1"> + <item row="7" column="1"> <widget class="QRadioButton" name="bits32"> <property name="text"> <string>4 Bytes (32-bit)</string>

@@ -139,14 +139,14 @@ <string notr="true">width</string>

</attribute> </widget> </item> - <item row="6" column="0"> + <item row="9" column="0"> <widget class="QLabel" name="label_4"> <property name="text"> <string>Number type</string> </property> </widget> </item> - <item row="6" column="1"> + <item row="9" column="1"> <widget class="QRadioButton" name="numHex"> <property name="text"> <string>Hexadecimal</string>

@@ -156,18 +156,45 @@ <bool>true</bool>

</property> </widget> </item> - <item row="7" column="1"> + <item row="10" column="1"> <widget class="QRadioButton" name="numDec"> <property name="text"> <string>Decimal</string> </property> </widget> </item> - <item row="8" column="1"> + <item row="11" column="1"> <widget class="QRadioButton" name="numGuess"> <property name="text"> <string>Guess</string> </property> + </widget> + </item> + <item row="4" column="0" colspan="2"> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="8" column="0" colspan="2"> + <widget class="Line" name="line_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QRadioButton" name="typeDelta"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Delta</string> + </property> + <attribute name="buttonGroup"> + <string notr="true">type</string> + </attribute> </widget> </item> </layout>