all repos — mgba @ 8385869652605c3a6f147134bda3c9ea9b220134

mGBA Game Boy Advance Emulator

Core: Add additional memory search operations
Vicki Pfau vi@endrift.com
Sat, 14 Oct 2017 17:13:06 -0700
commit

8385869652605c3a6f147134bda3c9ea9b220134

parent

db9725a563710b73baaa5580371143706bb7c627

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

@@ -19,7 +19,9 @@ mCORE_MEMORY_SEARCH_GUESS,

}; enum mCoreMemorySearchOp { - mCORE_MEMORY_SEARCH_FIXED, + mCORE_MEMORY_SEARCH_EQUAL, + mCORE_MEMORY_SEARCH_GREATER, + mCORE_MEMORY_SEARCH_LESS, mCORE_MEMORY_SEARCH_DELTA, };
M src/core/mem-search.csrc/core/mem-search.c

@@ -10,23 +10,27 @@ #include <mgba/core/interface.h>

DEFINE_VECTOR(mCoreMemorySearchResults, struct mCoreMemorySearchResult); -static size_t _search32(const void* mem, size_t size, const struct mCoreMemoryBlock* block, uint32_t value32, struct mCoreMemorySearchResults* out, size_t limit) { +static bool _op(int32_t value, int32_t match, enum mCoreMemorySearchOp op) { + switch (op) { + case mCORE_MEMORY_SEARCH_GREATER: + return value > match; + case mCORE_MEMORY_SEARCH_LESS: + return value < match; + case mCORE_MEMORY_SEARCH_EQUAL: + case mCORE_MEMORY_SEARCH_DELTA: + return value == match; + } +} + +static size_t _search32(const void* mem, size_t size, const struct mCoreMemoryBlock* block, uint32_t value32, enum mCoreMemorySearchOp op, struct mCoreMemorySearchResults* out, size_t limit) { const uint32_t* mem32 = mem; size_t found = 0; uint32_t start = block->start; uint32_t end = size; // TODO: Segments size_t i; // TODO: Big endian - for (i = 0; (!limit || found < limit) && i < end; i += 16) { - int mask = 0; - mask |= (mem32[(i >> 2) + 0] == value32) << 0; - mask |= (mem32[(i >> 2) + 1] == value32) << 1; - mask |= (mem32[(i >> 2) + 2] == value32) << 2; - mask |= (mem32[(i >> 2) + 3] == value32) << 3; - if (!mask) { - continue; - } - if ((mask & 1) && (!limit || found < limit)) { + for (i = 0; (!limit || found < limit) && i < end; i += 4) { + if (_op(mem32[i >> 2], value32, op)) { struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); res->address = start + i; res->type = mCORE_MEMORY_SEARCH_INT;

@@ -37,144 +41,21 @@ res->guessMultiplier = 1;

res->oldValue = value32; ++found; } - if ((mask & 2) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 4; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 4; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value32; - ++found; - } - if ((mask & 4) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 8; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 4; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value32; - ++found; - } - if ((mask & 8) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 12; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 4; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value32; - ++found; - } } - // TODO: last 12 bytes return found; } -static size_t _search16(const void* mem, size_t size, const struct mCoreMemoryBlock* block, uint16_t value16, struct mCoreMemorySearchResults* out, size_t limit) { +static size_t _search16(const void* mem, size_t size, const struct mCoreMemoryBlock* block, uint16_t value16, enum mCoreMemorySearchOp op, struct mCoreMemorySearchResults* out, size_t limit) { const uint16_t* mem16 = mem; size_t found = 0; uint32_t start = block->start; uint32_t end = size; // TODO: Segments size_t i; // TODO: Big endian - for (i = 0; (!limit || found < limit) && i < end; i += 16) { - int mask = 0; - mask |= (mem16[(i >> 1) + 0] == value16) << 0; - mask |= (mem16[(i >> 1) + 1] == value16) << 1; - mask |= (mem16[(i >> 1) + 2] == value16) << 2; - mask |= (mem16[(i >> 1) + 3] == value16) << 3; - mask |= (mem16[(i >> 1) + 4] == value16) << 4; - mask |= (mem16[(i >> 1) + 5] == value16) << 5; - mask |= (mem16[(i >> 1) + 6] == value16) << 6; - mask |= (mem16[(i >> 1) + 7] == value16) << 7; - if (!mask) { - continue; - } - if ((mask & 1) && (!limit || found < limit)) { + for (i = 0; (!limit || found < limit) && i < end; i += 2) { + if (_op(mem16[i >> 1], value16, op)) { struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); res->address = start + i; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 2; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value16; - ++found; - } - if ((mask & 2) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 2; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 2; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value16; - ++found; - } - if ((mask & 4) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 4; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 2; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value16; - ++found; - } - if ((mask & 8) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 6; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 2; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value16; - ++found; - } - if ((mask & 16) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 8; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 2; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value16; - ++found; - } - if ((mask & 32) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 10; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 2; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value16; - ++found; - } - if ((mask & 64) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 12; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 2; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value16; - ++found; - } - if ((mask & 128) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 14; res->type = mCORE_MEMORY_SEARCH_INT; res->width = 2; res->segment = -1; // TODO

@@ -184,30 +65,17 @@ res->oldValue = value16;

++found; } } - // TODO: last 14 bytes return found; } -static size_t _search8(const void* mem, size_t size, const struct mCoreMemoryBlock* block, uint8_t value8, struct mCoreMemorySearchResults* out, size_t limit) { +static size_t _search8(const void* mem, size_t size, const struct mCoreMemoryBlock* block, uint8_t value8, enum mCoreMemorySearchOp op, struct mCoreMemorySearchResults* out, size_t limit) { const uint8_t* mem8 = mem; size_t found = 0; uint32_t start = block->start; uint32_t end = size; // TODO: Segments size_t i; - for (i = 0; (!limit || found < limit) && i < end; i += 8) { - int mask = 0; - mask |= (mem8[i + 0] == value8) << 0; - mask |= (mem8[i + 1] == value8) << 1; - mask |= (mem8[i + 2] == value8) << 2; - mask |= (mem8[i + 3] == value8) << 3; - mask |= (mem8[i + 4] == value8) << 4; - mask |= (mem8[i + 5] == value8) << 5; - mask |= (mem8[i + 6] == value8) << 6; - mask |= (mem8[i + 7] == value8) << 7; - if (!mask) { - continue; - } - if ((mask & 1) && (!limit || found < limit)) { + for (i = 0; (!limit || found < limit) && i < end; ++i) { + if (_op(mem8[i], value8, op)) { struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); res->address = start + i; res->type = mCORE_MEMORY_SEARCH_INT;

@@ -218,85 +86,7 @@ res->guessMultiplier = 1;

res->oldValue = value8; ++found; } - if ((mask & 2) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 1; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 1; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value8; - ++found; - } - if ((mask & 4) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 2; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 1; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value8; - ++found; - } - if ((mask & 8) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 3; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 1; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value8; - ++found; - } - if ((mask & 16) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 4; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 1; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value8; - ++found; - } - if ((mask & 32) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 5; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 1; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value8; - ++found; - } - if ((mask & 64) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 6; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 1; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value8; - ++found; - } - if ((mask & 128) && (!limit || found < limit)) { - struct mCoreMemorySearchResult* res = mCoreMemorySearchResultsAppend(out); - res->address = start + i + 7; - res->type = mCORE_MEMORY_SEARCH_INT; - res->width = 1; - res->segment = -1; // TODO - res->guessDivisor = 1; - res->guessMultiplier = 1; - res->oldValue = value8; - ++found; - } } - // TODO: last 7 bytes return found; }

@@ -304,11 +94,11 @@ static size_t _searchInt(const void* mem, size_t size, const struct mCoreMemoryBlock* block, const struct mCoreMemorySearchParams* params, struct mCoreMemorySearchResults* out, size_t limit) {

if (params->align == params->width || params->align == -1) { switch (params->width) { case 4: - return _search32(mem, size, block, params->valueInt, out, limit); + return _search32(mem, size, block, params->valueInt, params->op, out, limit); case 2: - return _search16(mem, size, block, params->valueInt, out, limit); + return _search16(mem, size, block, params->valueInt, params->op, out, limit); case 1: - return _search8(mem, size, block, params->valueInt, out, limit); + return _search8(mem, size, block, params->valueInt, params->op, out, limit); } } return 0;

@@ -333,7 +123,7 @@ }

return found; } -static size_t _searchGuess(const void* mem, size_t size, const struct mCoreMemoryBlock* block, const char* valueStr, struct mCoreMemorySearchResults* out, size_t limit) { +static size_t _searchGuess(const void* mem, size_t size, const struct mCoreMemoryBlock* block, const struct mCoreMemorySearchParams* params, struct mCoreMemorySearchResults* out, size_t limit) { // TODO: As str char* end;

@@ -345,14 +135,14 @@ struct mCoreMemorySearchResults tmp;

mCoreMemorySearchResultsInit(&tmp, 0); // Decimal: - value = strtoll(valueStr, &end, 10); + value = strtoll(params->valueStr, &end, 10); if (end && !end[0]) { if (value > 0x10000) { - found += _search32(mem, size, block, value, out, limit ? limit - found : 0); + found += _search32(mem, size, block, value, params->op, out, limit ? limit - found : 0); } else if (value > 0x100) { - found += _search16(mem, size, block, value, out, limit ? limit - found : 0); + found += _search16(mem, size, block, value, params->op, out, limit ? limit - found : 0); } else { - found += _search8(mem, size, block, value, out, limit ? limit - found : 0); + found += _search8(mem, size, block, value, params->op, out, limit ? limit - found : 0); } uint32_t divisor = 1;

@@ -362,11 +152,11 @@ value /= 10;

divisor *= 10; if (value > 0x10000) { - found += _search32(mem, size, block, value, &tmp, limit ? limit - found : 0); + found += _search32(mem, size, block, value, params->op, &tmp, limit ? limit - found : 0); } else if (value > 0x100) { - found += _search16(mem, size, block, value, &tmp, limit ? limit - found : 0); + found += _search16(mem, size, block, value, params->op, &tmp, limit ? limit - found : 0); } else { - found += _search8(mem, size, block, value, &tmp, limit ? limit - found : 0); + found += _search8(mem, size, block, value, params->op, &tmp, limit ? limit - found : 0); } size_t i; for (i = 0; i < mCoreMemorySearchResultsSize(&tmp); ++i) {

@@ -378,14 +168,14 @@ }

} // Hex: - value = strtoll(valueStr, &end, 16); + value = strtoll(params->valueStr, &end, 16); if (end && !end[0]) { if (value > 0x10000) { - found += _search32(mem, size, block, value, out, limit ? limit - found : 0); + found += _search32(mem, size, block, value, params->op, out, limit ? limit - found : 0); } else if (value > 0x100) { - found += _search16(mem, size, block, value, out, limit ? limit - found : 0); + found += _search16(mem, size, block, value, params->op, out, limit ? limit - found : 0); } else { - found += _search8(mem, size, block, value, out, limit ? limit - found : 0); + found += _search8(mem, size, block, value, params->op, out, limit ? limit - found : 0); } uint32_t divisor = 1;

@@ -395,11 +185,11 @@ value >>= 4;

divisor <<= 4; if (value > 0x10000) { - found += _search32(mem, size, block, value, &tmp, limit ? limit - found : 0); + found += _search32(mem, size, block, value, params->op, &tmp, limit ? limit - found : 0); } else if (value > 0x100) { - found += _search16(mem, size, block, value, &tmp, limit ? limit - found : 0); + found += _search16(mem, size, block, value, params->op, &tmp, limit ? limit - found : 0); } else { - found += _search8(mem, size, block, value, &tmp, limit ? limit - found : 0); + found += _search8(mem, size, block, value, params->op, &tmp, limit ? limit - found : 0); } size_t i; for (i = 0; i < mCoreMemorySearchResultsSize(&tmp); ++i) {

@@ -421,7 +211,7 @@ return _searchInt(mem, size, block, params, out, limit);

case mCORE_MEMORY_SEARCH_STRING: return _searchStr(mem, size, block, params->valueStr, params->width, out, limit); case mCORE_MEMORY_SEARCH_GUESS: - return _searchGuess(mem, size, block, params->valueStr, out, limit); + return _searchGuess(mem, size, block, params, out, limit); } }

@@ -459,13 +249,13 @@

value = strtoll(params->valueStr, &end, 10); if (end) { res->oldValue += value; - if (core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value + offset) { + if (_op(core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier, value + offset, params->op)) { return true; } - if (!(res->address & 1) && core->rawRead16(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value + offset) { + 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)) { return true; } - if (!(res->address & 3) && core->rawRead32(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value + offset) { + 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)) { return true; } res->oldValue -= value;

@@ -474,13 +264,13 @@

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) { + if (_op(core->rawRead8(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier, value + offset, params->op)) { return true; } - if (!(res->address & 1) && core->rawRead16(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value + offset) { + 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)) { return true; } - if (!(res->address & 3) && core->rawRead32(core, res->address, res->segment) * res->guessDivisor / res->guessMultiplier == value + offset) { + 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)) { return true; } res->oldValue -= value;

@@ -496,7 +286,8 @@ switch (res->type) {

case mCORE_MEMORY_SEARCH_INT: if (params->type == mCORE_MEMORY_SEARCH_GUESS) { if (!_testGuess(core, res, params)) { - mCoreMemorySearchResultsShift(inout, i, 1); + *res = *mCoreMemorySearchResultsGetPointer(inout, mCoreMemorySearchResultsSize(inout) - 1); + mCoreMemorySearchResultsResize(inout, -1); --i; } } else if (params->type == mCORE_MEMORY_SEARCH_INT) {

@@ -518,8 +309,9 @@ break;

default: break; } - if (value != oldValue) { - mCoreMemorySearchResultsShift(inout, i, 1); + if (!_op(value, oldValue, params->op)) { + *res = *mCoreMemorySearchResultsGetPointer(inout, mCoreMemorySearchResultsSize(inout) - 1); + mCoreMemorySearchResultsResize(inout, -1); --i; } else { res->oldValue = value;
M src/platform/qt/MemorySearch.cppsrc/platform/qt/MemorySearch.cpp

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

QByteArray string; bool ok = false; - if (m_ui.typeNum->isChecked() || m_ui.typeDelta->isChecked()) { + if (m_ui.typeNum->isChecked()) { params->type = mCORE_MEMORY_SEARCH_INT; - params->op = m_ui.typeDelta->isChecked() ? mCORE_MEMORY_SEARCH_DELTA : mCORE_MEMORY_SEARCH_FIXED; + if (m_ui.opDelta->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 { + params->op = mCORE_MEMORY_SEARCH_EQUAL; + } params->align = -1; if (m_ui.bits8->isChecked()) { params->width = 1;

@@ -141,7 +149,7 @@ mCore* core = m_controller->thread()->core;

m_ui.results->clearContents(); m_ui.results->setRowCount(mCoreMemorySearchResultsSize(&m_results)); - m_ui.typeDelta->setEnabled(false); + m_ui.opDelta->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')));

@@ -202,10 +210,10 @@ type = new QTableWidgetItem("string");

} m_ui.results->setItem(i, 1, item); m_ui.results->setItem(i, 2, type); - m_ui.typeDelta->setEnabled(true); + m_ui.opDelta->setEnabled(true); } - if (m_ui.typeDelta->isChecked() && !m_ui.typeDelta->isEnabled()) { - m_ui.typeNum->setChecked(true); + if (m_ui.opDelta->isChecked() && !m_ui.opDelta->isEnabled()) { + m_ui.opEqual->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>639</width> - <height>397</height> + <width>540</width> + <height>491</height> </rect> </property> <property name="minimumSize">

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

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

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

</attribute> </widget> </item> - <item row="5" column="0"> + <item row="3" column="0" colspan="2"> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="4" column="0"> <widget class="QLabel" name="label_3"> <property name="text"> <string>Width</string> </property> </widget> </item> - <item row="5" column="1"> + <item row="4" column="1"> <widget class="QRadioButton" name="bits8"> <property name="text"> <string>1 Byte (8-bit)</string>

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

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

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

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

@@ -139,53 +146,93 @@ <string notr="true">width</string>

</attribute> </widget> </item> - <item row="9" column="0"> + <item row="7" column="0" colspan="2"> + <widget class="Line" name="line_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="8" column="0"> <widget class="QLabel" name="label_4"> <property name="text"> <string>Number type</string> </property> </widget> </item> - <item row="9" column="1"> - <widget class="QRadioButton" name="numHex"> + <item row="8" column="1"> + <widget class="QRadioButton" name="numGuess"> <property name="text"> - <string>Hexadecimal</string> + <string>Guess</string> </property> <property name="checked"> <bool>true</bool> </property> </widget> </item> - <item row="10" column="1"> + <item row="9" column="1"> <widget class="QRadioButton" name="numDec"> <property name="text"> <string>Decimal</string> </property> </widget> </item> - <item row="11" column="1"> - <widget class="QRadioButton" name="numGuess"> + <item row="10" column="1"> + <widget class="QRadioButton" name="numHex"> <property name="text"> - <string>Guess</string> + <string>Hexadecimal</string> </property> </widget> </item> - <item row="4" column="0" colspan="2"> - <widget class="Line" name="line"> + <item row="11" column="0" colspan="2"> + <widget class="Line" name="line_3"> <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> + <item row="12" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Compare</string> + </property> + </widget> + </item> + <item row="12" column="1"> + <widget class="QRadioButton" name="opEqual"> + <property name="text"> + <string>Equal</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <attribute name="buttonGroup"> + <string notr="true">op</string> + </attribute> + </widget> + </item> + <item row="13" 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="14" column="1"> + <widget class="QRadioButton" name="opLess"> + <property name="text"> + <string>Less</string> </property> + <attribute name="buttonGroup"> + <string notr="true">op</string> + </attribute> </widget> </item> - <item row="2" column="1"> - <widget class="QRadioButton" name="typeDelta"> + <item row="15" column="1"> + <widget class="QRadioButton" name="opDelta"> <property name="enabled"> <bool>false</bool> </property>

@@ -193,7 +240,7 @@ <property name="text">

<string>Delta</string> </property> <attribute name="buttonGroup"> - <string notr="true">type</string> + <string notr="true">op</string> </attribute> </widget> </item>

@@ -262,5 +309,6 @@ </connections>

<buttongroups> <buttongroup name="width"/> <buttongroup name="type"/> + <buttongroup name="op"/> </buttongroups> </ui>