vbagx/source/vba/gba/CheatSearch.cpp

330 lines
7.1 KiB
C++

// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or(at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <stdlib.h>
#include <string.h>
#include "CheatSearch.h"
CheatSearchBlock cheatSearchBlocks[4];
CheatSearchData cheatSearchData = {
0,
cheatSearchBlocks
};
static bool cheatSearchEQ(u32 a, u32 b)
{
return a == b;
}
static bool cheatSearchNE(u32 a, u32 b)
{
return a != b;
}
static bool cheatSearchLT(u32 a, u32 b)
{
return a < b;
}
static bool cheatSearchLE(u32 a, u32 b)
{
return a <= b;
}
static bool cheatSearchGT(u32 a, u32 b)
{
return a > b;
}
static bool cheatSearchGE(u32 a, u32 b)
{
return a >= b;
}
static bool cheatSearchSignedEQ(s32 a, s32 b)
{
return a == b;
}
static bool cheatSearchSignedNE(s32 a, s32 b)
{
return a != b;
}
static bool cheatSearchSignedLT(s32 a, s32 b)
{
return a < b;
}
static bool cheatSearchSignedLE(s32 a, s32 b)
{
return a <= b;
}
static bool cheatSearchSignedGT(s32 a, s32 b)
{
return a > b;
}
static bool cheatSearchSignedGE(s32 a, s32 b)
{
return a >= b;
}
static bool (*cheatSearchFunc[])(u32,u32) = {
cheatSearchEQ,
cheatSearchNE,
cheatSearchLT,
cheatSearchLE,
cheatSearchGT,
cheatSearchGE
};
static bool (*cheatSearchSignedFunc[])(s32,s32) = {
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);
}
}
s32 cheatSearchSignedRead(u8 *data, int off, int size)
{
u32 res = data[off++];
switch(size) {
case BITS_8:
res <<= 24;
return ((s32)res) >> 24;
case BITS_16:
res |= ((u32)data[off++])<<8;
res <<= 16;
return ((s32)res) >> 16;
case BITS_32:
res |= ((u32)data[off++])<<8;
res |= ((u32)data[off++])<<16;
res |= ((u32)data[off++])<<24;
return (s32)res;
}
return (s32)res;
}
u32 cheatSearchRead(u8 *data, int off, int size)
{
u32 res = data[off++];
if(size == BITS_16)
res |= ((u32)data[off++])<<8;
else if(size == BITS_32) {
res |= ((u32)data[off++])<<8;
res |= ((u32)data[off++])<<16;
res |= ((u32)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)(s32,s32) = cheatSearchSignedFunc[compare];
for(int i = 0; i < cs->count; i++) {
CheatSearchBlock *block = &cs->blocks[i];
int size2 = block->size;
u8 *bits = block->bits;
u8 *data = block->data;
u8 *saved = block->saved;
for(int j = 0; j < size2; j += inc) {
if(IS_BIT_SET(bits, j)) {
s32 a = cheatSearchSignedRead(data, j, size);
s32 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)(u32,u32) = cheatSearchFunc[compare];
for(int i = 0; i < cs->count; i++) {
CheatSearchBlock *block = &cs->blocks[i];
int size2 = block->size;
u8 *bits = block->bits;
u8 *data = block->data;
u8 *saved = block->saved;
for(int j = 0; j < size2; j += inc) {
if(IS_BIT_SET(bits, j)) {
u32 a = cheatSearchRead(data, j, size);
u32 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, u32 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)(s32,s32) = cheatSearchSignedFunc[compare];
for(int i = 0; i < cs->count; i++) {
CheatSearchBlock *block = &cs->blocks[i];
int size2 = block->size;
u8 *bits = block->bits;
u8 *data = block->data;
for(int j = 0; j < size2; j += inc) {
if(IS_BIT_SET(bits, j)) {
s32 a = cheatSearchSignedRead(data, j, size);
s32 b = (s32)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)(u32,u32) = cheatSearchFunc[compare];
for(int i = 0; i < cs->count; i++) {
CheatSearchBlock *block = &cs->blocks[i];
int size2 = block->size;
u8 *bits = block->bits;
u8 *data = block->data;
for(int j = 0; j < size2; j += inc) {
if(IS_BIT_SET(bits, j)) {
u32 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;
u8 *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);
}
}