Core: Add additional memory search operations

This commit is contained in:
Vicki Pfau 2017-10-14 17:13:06 -07:00
parent db9725a563
commit 8385869652
4 changed files with 165 additions and 315 deletions

View File

@ -19,7 +19,9 @@ enum mCoreMemorySearchType {
};
enum mCoreMemorySearchOp {
mCORE_MEMORY_SEARCH_FIXED,
mCORE_MEMORY_SEARCH_EQUAL,
mCORE_MEMORY_SEARCH_GREATER,
mCORE_MEMORY_SEARCH_LESS,
mCORE_MEMORY_SEARCH_DELTA,
};

View File

@ -10,23 +10,27 @@
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,65 +41,19 @@ static size_t _search32(const void* mem, size_t size, const struct mCoreMemoryBl
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;
@ -106,108 +64,18 @@ static size_t _search16(const void* mem, size_t size, const struct mCoreMemoryBl
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
res->guessDivisor = 1;
res->guessMultiplier = 1;
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 @@ static size_t _search8(const void* mem, size_t size, const struct mCoreMemoryBlo
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 mCoreMemoryB
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 @@ static size_t _searchStr(const void* mem, size_t size, const struct mCoreMemoryB
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 @@ static size_t _searchGuess(const void* mem, size_t size, const struct mCoreMemor
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 @@ static size_t _searchGuess(const void* mem, size_t size, const struct mCoreMemor
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 @@ static size_t _searchGuess(const void* mem, size_t size, const struct mCoreMemor
}
// 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 @@ static size_t _searchGuess(const void* mem, size_t size, const struct mCoreMemor
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 @@ static size_t _search(const void* mem, size_t size, const struct mCoreMemoryBloc
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 @@ bool _testGuess(struct mCore* core, struct mCoreMemorySearchResult* res, const s
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 @@ bool _testGuess(struct mCore* core, struct mCoreMemorySearchResult* res, const s
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 @@ void mCoreMemorySearchRepeat(struct mCore* core, const struct mCoreMemorySearchP
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 @@ void mCoreMemorySearchRepeat(struct mCore* core, const struct mCoreMemorySearchP
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;

View File

@ -40,9 +40,17 @@ bool MemorySearch::createParams(mCoreMemorySearchParams* params) {
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 @@ void MemorySearch::refresh() {
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 @@ void MemorySearch::refresh() {
}
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);
}

View File

@ -6,8 +6,8 @@
<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 @@
</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 @@
</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 @@
</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 @@
</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 @@
</attribute>
</widget>
</item>
<item row="9" 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">
<property name="text">
<string>Hexadecimal</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="10" 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">
<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">
<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="2" column="1">
<widget class="QRadioButton" name="typeDelta">
<item row="8" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Number type</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QRadioButton" name="numGuess">
<property name="text">
<string>Guess</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QRadioButton" name="numDec">
<property name="text">
<string>Decimal</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QRadioButton" name="numHex">
<property name="text">
<string>Hexadecimal</string>
</property>
</widget>
</item>
<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="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="15" column="1">
<widget class="QRadioButton" name="opDelta">
<property name="enabled">
<bool>false</bool>
</property>
@ -193,7 +240,7 @@
<string>Delta</string>
</property>
<attribute name="buttonGroup">
<string notr="true">type</string>
<string notr="true">op</string>
</attribute>
</widget>
</item>
@ -262,5 +309,6 @@
<buttongroups>
<buttongroup name="width"/>
<buttongroup name="type"/>
<buttongroup name="op"/>
</buttongroups>
</ui>