311 lines
7.8 KiB
C++
311 lines
7.8 KiB
C++
#include <memory.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "CheatSearch.h"
|
|
|
|
CheatSearchBlock cheatSearchBlocks[4];
|
|
|
|
CheatSearchData cheatSearchData = {
|
|
0,
|
|
cheatSearchBlocks
|
|
};
|
|
|
|
static bool cheatSearchEQ(uint32_t a, uint32_t b)
|
|
{
|
|
return a == b;
|
|
}
|
|
|
|
static bool cheatSearchNE(uint32_t a, uint32_t b)
|
|
{
|
|
return a != b;
|
|
}
|
|
|
|
static bool cheatSearchLT(uint32_t a, uint32_t b)
|
|
{
|
|
return a < b;
|
|
}
|
|
|
|
static bool cheatSearchLE(uint32_t a, uint32_t b)
|
|
{
|
|
return a <= b;
|
|
}
|
|
|
|
static bool cheatSearchGT(uint32_t a, uint32_t b)
|
|
{
|
|
return a > b;
|
|
}
|
|
|
|
static bool cheatSearchGE(uint32_t a, uint32_t b)
|
|
{
|
|
return a >= b;
|
|
}
|
|
|
|
static bool cheatSearchSignedEQ(int32_t a, int32_t b)
|
|
{
|
|
return a == b;
|
|
}
|
|
|
|
static bool cheatSearchSignedNE(int32_t a, int32_t b)
|
|
{
|
|
return a != b;
|
|
}
|
|
|
|
static bool cheatSearchSignedLT(int32_t a, int32_t b)
|
|
{
|
|
return a < b;
|
|
}
|
|
|
|
static bool cheatSearchSignedLE(int32_t a, int32_t b)
|
|
{
|
|
return a <= b;
|
|
}
|
|
|
|
static bool cheatSearchSignedGT(int32_t a, int32_t b)
|
|
{
|
|
return a > b;
|
|
}
|
|
|
|
static bool cheatSearchSignedGE(int32_t a, int32_t b)
|
|
{
|
|
return a >= b;
|
|
}
|
|
|
|
static bool (*cheatSearchFunc[])(uint32_t, uint32_t) = {
|
|
cheatSearchEQ,
|
|
cheatSearchNE,
|
|
cheatSearchLT,
|
|
cheatSearchLE,
|
|
cheatSearchGT,
|
|
cheatSearchGE
|
|
};
|
|
|
|
static bool (*cheatSearchSignedFunc[])(int32_t, int32_t) = {
|
|
cheatSearchSignedEQ,
|
|
cheatSearchSignedNE,
|
|
cheatSearchSignedLT,
|
|
cheatSearchSignedLE,
|
|
cheatSearchSignedGT,
|
|
cheatSearchSignedGE
|
|
};
|
|
|
|
void cheatSearchCleanup(CheatSearchData* cs)
|
|
{
|
|
int count = cs->count;
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
free(cs->blocks[i].saved);
|
|
free(cs->blocks[i].bits);
|
|
}
|
|
cs->count = 0;
|
|
}
|
|
|
|
void cheatSearchStart(const CheatSearchData* cs)
|
|
{
|
|
int count = cs->count;
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
CheatSearchBlock* block = &cs->blocks[i];
|
|
|
|
memset(block->bits, 0xff, block->size >> 3);
|
|
memcpy(block->saved, block->data, block->size);
|
|
}
|
|
}
|
|
|
|
int32_t cheatSearchSignedRead(uint8_t* data, int off, int size)
|
|
{
|
|
uint32_t res = data[off++];
|
|
|
|
switch (size) {
|
|
case BITS_8:
|
|
res <<= 24;
|
|
return ((int32_t)res) >> 24;
|
|
case BITS_16:
|
|
res |= ((uint32_t)data[off++]) << 8;
|
|
res <<= 16;
|
|
return ((int32_t)res) >> 16;
|
|
case BITS_32:
|
|
res |= ((uint32_t)data[off++]) << 8;
|
|
res |= ((uint32_t)data[off++]) << 16;
|
|
res |= ((uint32_t)data[off++]) << 24;
|
|
return (int32_t)res;
|
|
}
|
|
return (int32_t)res;
|
|
}
|
|
|
|
uint32_t cheatSearchRead(uint8_t* data, int off, int size)
|
|
{
|
|
uint32_t res = data[off++];
|
|
if (size == BITS_16)
|
|
res |= ((uint32_t)data[off++]) << 8;
|
|
else if (size == BITS_32) {
|
|
res |= ((uint32_t)data[off++]) << 8;
|
|
res |= ((uint32_t)data[off++]) << 16;
|
|
res |= ((uint32_t)data[off++]) << 24;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void cheatSearch(const CheatSearchData* cs, int compare, int size,
|
|
bool isSigned)
|
|
{
|
|
if (compare < 0 || compare > SEARCH_GE)
|
|
return;
|
|
int inc = 1;
|
|
if (size == BITS_16)
|
|
inc = 2;
|
|
else if (size == BITS_32)
|
|
inc = 4;
|
|
|
|
if (isSigned) {
|
|
bool (*func)(int32_t, int32_t) = cheatSearchSignedFunc[compare];
|
|
|
|
for (int i = 0; i < cs->count; i++) {
|
|
CheatSearchBlock* block = &cs->blocks[i];
|
|
int size2 = block->size;
|
|
uint8_t* bits = block->bits;
|
|
uint8_t* data = block->data;
|
|
uint8_t* saved = block->saved;
|
|
|
|
for (int j = 0; j < size2; j += inc) {
|
|
if (IS_BIT_SET(bits, j)) {
|
|
int32_t a = cheatSearchSignedRead(data, j, size);
|
|
int32_t b = cheatSearchSignedRead(saved, j, size);
|
|
|
|
if (!func(a, b)) {
|
|
CLEAR_BIT(bits, j);
|
|
if (size == BITS_16)
|
|
CLEAR_BIT(bits, j + 1);
|
|
if (size == BITS_32) {
|
|
CLEAR_BIT(bits, j + 2);
|
|
CLEAR_BIT(bits, j + 3);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
bool (*func)(uint32_t, uint32_t) = cheatSearchFunc[compare];
|
|
|
|
for (int i = 0; i < cs->count; i++) {
|
|
CheatSearchBlock* block = &cs->blocks[i];
|
|
int size2 = block->size;
|
|
uint8_t* bits = block->bits;
|
|
uint8_t* data = block->data;
|
|
uint8_t* saved = block->saved;
|
|
|
|
for (int j = 0; j < size2; j += inc) {
|
|
if (IS_BIT_SET(bits, j)) {
|
|
uint32_t a = cheatSearchRead(data, j, size);
|
|
uint32_t b = cheatSearchRead(saved, j, size);
|
|
|
|
if (!func(a, b)) {
|
|
CLEAR_BIT(bits, j);
|
|
if (size == BITS_16)
|
|
CLEAR_BIT(bits, j + 1);
|
|
if (size == BITS_32) {
|
|
CLEAR_BIT(bits, j + 2);
|
|
CLEAR_BIT(bits, j + 3);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void cheatSearchValue(const CheatSearchData* cs, int compare, int size,
|
|
bool isSigned, uint32_t value)
|
|
{
|
|
if (compare < 0 || compare > SEARCH_GE)
|
|
return;
|
|
int inc = 1;
|
|
if (size == BITS_16)
|
|
inc = 2;
|
|
else if (size == BITS_32)
|
|
inc = 4;
|
|
|
|
if (isSigned) {
|
|
bool (*func)(int32_t, int32_t) = cheatSearchSignedFunc[compare];
|
|
|
|
for (int i = 0; i < cs->count; i++) {
|
|
CheatSearchBlock* block = &cs->blocks[i];
|
|
int size2 = block->size;
|
|
uint8_t* bits = block->bits;
|
|
uint8_t* data = block->data;
|
|
|
|
for (int j = 0; j < size2; j += inc) {
|
|
if (IS_BIT_SET(bits, j)) {
|
|
int32_t a = cheatSearchSignedRead(data, j, size);
|
|
int32_t b = (int32_t)value;
|
|
|
|
if (!func(a, b)) {
|
|
CLEAR_BIT(bits, j);
|
|
if (size == BITS_16)
|
|
CLEAR_BIT(bits, j + 1);
|
|
if (size == BITS_32) {
|
|
CLEAR_BIT(bits, j + 2);
|
|
CLEAR_BIT(bits, j + 3);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
bool (*func)(uint32_t, uint32_t) = cheatSearchFunc[compare];
|
|
|
|
for (int i = 0; i < cs->count; i++) {
|
|
CheatSearchBlock* block = &cs->blocks[i];
|
|
int size2 = block->size;
|
|
uint8_t* bits = block->bits;
|
|
uint8_t* data = block->data;
|
|
|
|
for (int j = 0; j < size2; j += inc) {
|
|
if (IS_BIT_SET(bits, j)) {
|
|
uint32_t a = cheatSearchRead(data, j, size);
|
|
|
|
if (!func(a, value)) {
|
|
CLEAR_BIT(bits, j);
|
|
if (size == BITS_16)
|
|
CLEAR_BIT(bits, j + 1);
|
|
if (size == BITS_32) {
|
|
CLEAR_BIT(bits, j + 2);
|
|
CLEAR_BIT(bits, j + 3);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int cheatSearchGetCount(const CheatSearchData* cs, int size)
|
|
{
|
|
int res = 0;
|
|
int inc = 1;
|
|
if (size == BITS_16)
|
|
inc = 2;
|
|
else if (size == BITS_32)
|
|
inc = 4;
|
|
|
|
for (int i = 0; i < cs->count; i++) {
|
|
CheatSearchBlock* block = &cs->blocks[i];
|
|
|
|
int size2 = block->size;
|
|
uint8_t* bits = block->bits;
|
|
for (int j = 0; j < size2; j += inc) {
|
|
if (IS_BIT_SET(bits, j))
|
|
res++;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void cheatSearchUpdateValues(const CheatSearchData* cs)
|
|
{
|
|
for (int i = 0; i < cs->count; i++) {
|
|
CheatSearchBlock* block = &cs->blocks[i];
|
|
|
|
memcpy(block->saved, block->data, block->size);
|
|
}
|
|
}
|