bsnes/sfc/cheat/cheat.cpp

111 lines
2.5 KiB
C++

#include <sfc/sfc.hpp>
#define CHEAT_CPP
namespace SuperFamicom {
Cheat cheat;
bool Cheat::enabled() const {
return system_enabled;
}
void Cheat::enable(bool state) {
system_enabled = state;
cheat_enabled = system_enabled && code_enabled;
}
void Cheat::synchronize() {
memset(override, 0x00, 16 * 1024 * 1024);
code_enabled = size() > 0;
for(unsigned i = 0; i < size(); i++) {
const CheatCode &code = operator[](i);
unsigned addr = mirror(code.addr);
override[addr] = true;
if((addr & 0xffe000) == 0x7e0000) {
//mirror $7e:0000-1fff to $00-3f|80-bf:0000-1fff
unsigned mirroraddr;
for(unsigned x = 0; x <= 0x3f; x++) {
mirroraddr = ((0x00 + x) << 16) + (addr & 0x1fff);
override[mirroraddr] = true;
mirroraddr = ((0x80 + x) << 16) + (addr & 0x1fff);
override[mirroraddr] = true;
}
}
}
cheat_enabled = system_enabled && code_enabled;
}
uint8 Cheat::read(unsigned addr) const {
addr = mirror(addr);
for(unsigned i = 0; i < size(); i++) {
const CheatCode& code = operator[](i);
if(addr == mirror(code.addr)) {
return code.data;
}
}
return 0x00;
}
void Cheat::init() {
memset(override, 0x00, 16 * 1024 * 1024);
}
Cheat::Cheat() {
override = new uint8[16 * 1024 * 1024];
system_enabled = true;
}
Cheat::~Cheat() {
delete[] override;
}
bool Cheat::decode(string code, unsigned& addr, unsigned& data) {
string t = code;
t.lower();
#define ischr(n) ((n >= '0' && n <= '9') || (n >= 'a' && n <= 'f'))
if(t.match("??????:??")) {
//Direct
t = {substr(t, 0, 6), substr(t, 7, 2)};
for(unsigned n = 0; n < 8; n++) if(!ischr(t[n])) return false; //validate input
unsigned r = hex(t);
addr = r >> 8;
data = r & 0xff;
return true;
}
if(t.match(R"(????-????)")) {
//Game Genie
t = {substr(t, 0, 4), substr(t, 5, 4)};
for(unsigned n = 0; n < 8; n++) if(!ischr(t[n])) return false; //validate input
t.transform("df4709156bc8a23e", "0123456789abcdef");
unsigned r = hex(t);
static unsigned bits[] = {13, 12, 11, 10, 5, 4, 3, 2, 23, 22, 21, 20, 1, 0, 15, 14, 19, 18, 17, 16, 9, 8, 7, 6};
addr = 0;
for(unsigned n = 0; n < 24; n++) addr |= r & (1 << bits[n]) ? 0x800000 >> n : 0;
data = r >> 24;
return true;
} else {
return false;
}
#undef ischr
}
unsigned Cheat::mirror(unsigned addr) const {
//$00-3f|80-bf:0000-1fff -> $7e:0000-1fff
if((addr & 0x40e000) == 0x000000) return (0x7e0000 + (addr & 0x1fff));
return addr;
}
}