mirror of https://github.com/mgba-emu/mgba.git
Core: Add more memory search ops (closes #1510)
This commit is contained in:
parent
447c053f7e
commit
b9edcd8d93
1
CHANGES
1
CHANGES
|
@ -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:
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(¶ms)) {
|
||||
if (m_ui.opUnknown->isChecked()) {
|
||||
params.op = mCORE_MEMORY_SEARCH_DELTA_ANY;
|
||||
}
|
||||
mCoreMemorySearchRepeat(core, ¶ms, &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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue