mirror of https://github.com/mgba-emu/mgba.git
Core: Add additional memory search operations
This commit is contained in:
parent
db9725a563
commit
8385869652
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue