Core: Add more memory search ops (closes #1510)

This commit is contained in:
Vicki Pfau 2019-10-13 15:53:40 -07:00
parent 447c053f7e
commit b9edcd8d93
6 changed files with 183 additions and 51 deletions

View File

@ -84,6 +84,7 @@ Misc:
- Qt: Add copy and QoL improvements to graphic views (closes mgba.io/i/1541)
- Qt: Show list of all sprites in sprite view
- Qt: Add option for disabling OSD messages
- Core: Add more memory search ops (closes mgba.io/i/1510)
0.7.3: (2019-09-15)
Emulation fixes:

View File

@ -22,7 +22,11 @@ enum mCoreMemorySearchOp {
mCORE_MEMORY_SEARCH_EQUAL,
mCORE_MEMORY_SEARCH_GREATER,
mCORE_MEMORY_SEARCH_LESS,
mCORE_MEMORY_SEARCH_ANY,
mCORE_MEMORY_SEARCH_DELTA,
mCORE_MEMORY_SEARCH_DELTA_POSITIVE,
mCORE_MEMORY_SEARCH_DELTA_NEGATIVE,
mCORE_MEMORY_SEARCH_DELTA_ANY,
};
struct mCoreMemorySearchParams {

View File

@ -19,6 +19,14 @@ static bool _op(int32_t value, int32_t match, enum mCoreMemorySearchOp op) {
case mCORE_MEMORY_SEARCH_EQUAL:
case mCORE_MEMORY_SEARCH_DELTA:
return value == match;
case mCORE_MEMORY_SEARCH_DELTA_POSITIVE:
return value > 0;
case mCORE_MEMORY_SEARCH_DELTA_NEGATIVE:
return value < 0;
case mCORE_MEMORY_SEARCH_DELTA_ANY:
return value != 0;
case mCORE_MEMORY_SEARCH_ANY:
return true;
}
return false;
}
@ -244,20 +252,20 @@ bool _testGuess(struct mCore* core, struct mCoreMemorySearchResult* res, const s
int64_t value;
int32_t offset = 0;
char* end;
if (params->op == mCORE_MEMORY_SEARCH_DELTA) {
if (params->op >= mCORE_MEMORY_SEARCH_DELTA) {
offset = res->oldValue;
}
value = strtoll(params->valueStr, &end, 10);
if (end) {
res->oldValue += value;
if (_op(core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier, value + offset, params->op)) {
if (_op(core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier - offset, value, params->op)) {
return true;
}
if (!(res->address & 1) && (res->width >= 2 || res->width == -1) && _op(core->rawRead16(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier, value + offset, params->op)) {
if (!(res->address & 1) && (res->width >= 2 || res->width == -1) && _op(core->rawRead16(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier - offset, value, params->op)) {
return true;
}
if (!(res->address & 3) && (res->width >= 4 || res->width == -1) && _op(core->rawRead32(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier, value + offset, params->op)) {
if (!(res->address & 3) && (res->width >= 4 || res->width == -1) && _op(core->rawRead32(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier - offset, value, params->op)) {
return true;
}
res->oldValue -= value;
@ -266,13 +274,13 @@ bool _testGuess(struct mCore* core, struct mCoreMemorySearchResult* res, const s
value = strtoll(params->valueStr, &end, 16);
if (end) {
res->oldValue += value;
if (_op(core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier, value + offset, params->op)) {
if (_op(core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier - offset, value, params->op)) {
return true;
}
if (!(res->address & 1) && (res->width >= 2 || res->width == -1) && _op(core->rawRead16(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier, value + offset, params->op)) {
if (!(res->address & 1) && (res->width >= 2 || res->width == -1) && _op(core->rawRead16(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier - offset, value, params->op)) {
return true;
}
if (!(res->address & 3) && (res->width >= 4 || res->width == -1) && _op(core->rawRead32(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier, value + offset, params->op)) {
if (!(res->address & 3) && (res->width >= 4 || res->width == -1) && _op(core->rawRead32(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier - offset, value, params->op)) {
return true;
}
res->oldValue -= value;
@ -293,10 +301,7 @@ void mCoreMemorySearchRepeat(struct mCore* core, const struct mCoreMemorySearchP
--i;
}
} 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 match = params->valueInt;
int32_t value = 0;
switch (params->width) {
case 1:
@ -311,7 +316,11 @@ void mCoreMemorySearchRepeat(struct mCore* core, const struct mCoreMemorySearchP
default:
break;
}
if (!_op(value, oldValue, params->op)) {
int32_t opValue = value;
if (params->op >= mCORE_MEMORY_SEARCH_DELTA) {
opValue -= res->oldValue;
}
if (!_op(opValue, match, params->op)) {
*res = *mCoreMemorySearchResultsGetPointer(inout, mCoreMemorySearchResultsSize(inout) - 1);
mCoreMemorySearchResultsResize(inout, -1);
--i;
@ -322,7 +331,7 @@ void mCoreMemorySearchRepeat(struct mCore* core, const struct mCoreMemorySearchP
break;
case mCORE_MEMORY_SEARCH_STRING:
case mCORE_MEMORY_SEARCH_GUESS:
// TOOD
// TODO
break;
}
}

View File

@ -35,19 +35,28 @@ MemorySearch::~MemorySearch() {
}
bool MemorySearch::createParams(mCoreMemorySearchParams* params) {
params->memoryFlags = mCORE_MEMORY_RW;
params->memoryFlags = mCORE_MEMORY_WRITE;
if (m_ui.searchROM->isChecked()) {
params->memoryFlags |= mCORE_MEMORY_READ;
}
mCore* core = m_controller->thread()->core;
QByteArray string;
bool ok = false;
if (m_ui.typeNum->isChecked()) {
params->type = mCORE_MEMORY_SEARCH_INT;
if (m_ui.opDelta->isChecked()) {
if (m_ui.opDelta->isChecked() || m_ui.opDelta0->isChecked()) {
params->op = mCORE_MEMORY_SEARCH_DELTA;
} else if (m_ui.opGreater->isChecked()) {
params->op = mCORE_MEMORY_SEARCH_GREATER;
} else if (m_ui.opLess->isChecked()) {
params->op = mCORE_MEMORY_SEARCH_LESS;
} else if (m_ui.opUnknown->isChecked()) {
params->op = mCORE_MEMORY_SEARCH_ANY;
} else if (m_ui.opDeltaPositive->isChecked()) {
params->op = mCORE_MEMORY_SEARCH_DELTA_POSITIVE;
} else if (m_ui.opDeltaNegative->isChecked()) {
params->op = mCORE_MEMORY_SEARCH_DELTA_NEGATIVE;
} else {
params->op = mCORE_MEMORY_SEARCH_EQUAL;
}
@ -103,9 +112,15 @@ bool MemorySearch::createParams(mCoreMemorySearchParams* params) {
}
if (m_ui.numGuess->isChecked()) {
params->type = mCORE_MEMORY_SEARCH_GUESS;
m_string = m_ui.value->text().toLocal8Bit();
if (m_ui.opDelta0->isChecked()) {
m_string = QString("0").toLocal8Bit();
} else {
m_string = m_ui.value->text().toLocal8Bit();
}
params->valueStr = m_string.constData();
ok = true;
} else if (m_ui.opDelta0->isChecked()) {
params->valueInt = 0;
}
}
if (m_ui.typeStr->isChecked()) {
@ -140,6 +155,9 @@ void MemorySearch::searchWithin() {
mCore* core = m_controller->thread()->core;
if (createParams(&params)) {
if (m_ui.opUnknown->isChecked()) {
params.op = mCORE_MEMORY_SEARCH_DELTA_ANY;
}
mCoreMemorySearchRepeat(core, &params, &m_results);
}
@ -153,6 +171,9 @@ void MemorySearch::refresh() {
m_ui.results->clearContents();
m_ui.results->setRowCount(mCoreMemorySearchResultsSize(&m_results));
m_ui.opDelta->setEnabled(false);
m_ui.opDelta0->setEnabled(false);
m_ui.opDeltaPositive->setEnabled(false);
m_ui.opDeltaNegative->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')));
@ -214,9 +235,18 @@ void MemorySearch::refresh() {
m_ui.results->setItem(i, 1, item);
m_ui.results->setItem(i, 2, type);
m_ui.opDelta->setEnabled(true);
m_ui.opDelta0->setEnabled(true);
m_ui.opDeltaPositive->setEnabled(true);
m_ui.opDeltaNegative->setEnabled(true);
}
if (m_ui.opDelta->isChecked() && !m_ui.opDelta->isEnabled()) {
m_ui.opEqual->setChecked(true);
} else if (m_ui.opDelta0->isChecked() && !m_ui.opDelta0->isEnabled()) {
m_ui.opEqual->setChecked(true);
} else if (m_ui.opDeltaPositive->isChecked() && !m_ui.opDeltaPositive->isEnabled()) {
m_ui.opEqual->setChecked(true);
} else if (m_ui.opDeltaNegative->isChecked() && !m_ui.opDeltaNegative->isEnabled()) {
m_ui.opEqual->setChecked(true);
}
m_ui.results->sortItems(0);
}

View File

@ -6,14 +6,20 @@
<rect>
<x>0</x>
<y>0</y>
<width>540</width>
<height>491</height>
<width>725</width>
<height>813</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>540</width>
<height>241</height>
<height>400</height>
</size>
</property>
<property name="windowTitle">
@ -99,21 +105,21 @@
</attribute>
</widget>
</item>
<item row="3" column="0" colspan="2">
<item row="4" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="0">
<item row="5" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Width</string>
</property>
</widget>
</item>
<item row="4" column="1">
<item row="5" column="1">
<widget class="QRadioButton" name="bitsGuess">
<property name="text">
<string>Guess</string>
@ -126,7 +132,7 @@
</attribute>
</widget>
</item>
<item row="5" column="1">
<item row="6" column="1">
<widget class="QRadioButton" name="bits8">
<property name="text">
<string>1 Byte (8-bit)</string>
@ -136,7 +142,7 @@
</attribute>
</widget>
</item>
<item row="6" column="1">
<item row="7" column="1">
<widget class="QRadioButton" name="bits16">
<property name="text">
<string>2 Bytes (16-bit)</string>
@ -146,7 +152,7 @@
</attribute>
</widget>
</item>
<item row="7" column="1">
<item row="8" column="1">
<widget class="QRadioButton" name="bits32">
<property name="text">
<string>4 Bytes (32-bit)</string>
@ -159,21 +165,21 @@
</attribute>
</widget>
</item>
<item row="8" column="0" colspan="2">
<item row="9" column="0" colspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="9" column="0">
<item row="10" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Number type</string>
</property>
</widget>
</item>
<item row="9" column="1">
<item row="10" column="1">
<widget class="QRadioButton" name="numGuess">
<property name="text">
<string>Guess</string>
@ -183,38 +189,38 @@
</property>
</widget>
</item>
<item row="10" column="1">
<item row="11" column="1">
<widget class="QRadioButton" name="numDec">
<property name="text">
<string>Decimal</string>
</property>
</widget>
</item>
<item row="11" column="1">
<item row="12" column="1">
<widget class="QRadioButton" name="numHex">
<property name="text">
<string>Hexadecimal</string>
</property>
</widget>
</item>
<item row="12" column="0" colspan="2">
<item row="13" column="0" colspan="2">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="13" column="0">
<item row="14" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Compare</string>
<string>Search type</string>
</property>
</widget>
</item>
<item row="13" column="1">
<item row="14" column="1">
<widget class="QRadioButton" name="opEqual">
<property name="text">
<string>Equal</string>
<string>Equal to value</string>
</property>
<property name="checked">
<bool>true</bool>
@ -224,20 +230,10 @@
</attribute>
</widget>
</item>
<item row="14" column="1">
<item row="15" column="1">
<widget class="QRadioButton" name="opGreater">
<property name="text">
<string>Greater</string>
</property>
<attribute name="buttonGroup">
<string notr="true">op</string>
</attribute>
</widget>
</item>
<item row="15" column="1">
<widget class="QRadioButton" name="opLess">
<property name="text">
<string>Less</string>
<string>Greater than value</string>
</property>
<attribute name="buttonGroup">
<string notr="true">op</string>
@ -245,18 +241,84 @@
</widget>
</item>
<item row="16" column="1">
<widget class="QRadioButton" name="opLess">
<property name="text">
<string>Less than value</string>
</property>
<attribute name="buttonGroup">
<string notr="true">op</string>
</attribute>
</widget>
</item>
<item row="17" column="1">
<widget class="QRadioButton" name="opUnknown">
<property name="text">
<string>Unknown/changed</string>
</property>
<attribute name="buttonGroup">
<string notr="true">op</string>
</attribute>
</widget>
</item>
<item row="18" column="1">
<widget class="QRadioButton" name="opDelta">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Delta</string>
<string>Changed by value</string>
</property>
<attribute name="buttonGroup">
<string notr="true">op</string>
</attribute>
</widget>
</item>
<item row="21" column="1">
<widget class="QRadioButton" name="opDelta0">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Unchanged</string>
</property>
<attribute name="buttonGroup">
<string notr="true">op</string>
</attribute>
</widget>
</item>
<item row="19" column="1">
<widget class="QRadioButton" name="opDeltaPositive">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Increased</string>
</property>
<attribute name="buttonGroup">
<string notr="true">op</string>
</attribute>
</widget>
</item>
<item row="20" column="1">
<widget class="QRadioButton" name="opDeltaNegative">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Decreased</string>
</property>
<attribute name="buttonGroup">
<string notr="true">op</string>
</attribute>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="searchROM">
<property name="text">
<string>Search ROM</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0" colspan="2">
@ -271,7 +333,7 @@
<item>
<widget class="QPushButton" name="search">
<property name="text">
<string>Search</string>
<string>New Search</string>
</property>
</widget>
</item>
@ -318,10 +380,26 @@
</hint>
</hints>
</connection>
<connection>
<sender>opDelta0</sender>
<signal>toggled(bool)</signal>
<receiver>value</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>231</x>
<y>768</y>
</hint>
<hint type="destinationlabel">
<x>272</x>
<y>26</y>
</hint>
</hints>
</connection>
</connections>
<buttongroups>
<buttongroup name="width"/>
<buttongroup name="type"/>
<buttongroup name="op"/>
<buttongroup name="width"/>
</buttongroups>
</ui>

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>849</width>
<width>885</width>
<height>797</height>
</rect>
</property>
@ -2043,6 +2043,16 @@
<signal>toggled(bool)</signal>
<receiver>fastForwardHeldRatio</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>20</x>
<y>20</y>
</hint>
<hint type="destinationlabel">
<x>20</x>
<y>20</y>
</hint>
</hints>
</connection>
</connections>
</ui>