GB: Add partial Game Genie support

This commit is contained in:
Jeffrey Pfau 2016-05-08 23:18:42 -07:00
parent 7477c36cb5
commit 273d2db575
5 changed files with 118 additions and 13 deletions

View File

@ -5,8 +5,43 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cheats.h"
#include "core/core.h"
#include "gb/memory.h"
#include "util/string.h"
DEFINE_VECTOR(GBCheatPatchList, struct GBCheatPatch);
static void _patchROM(struct mCheatDevice* device, struct GBCheatSet* cheats) {
if (!device->p) {
return;
}
size_t i;
for (i = 0; i < GBCheatPatchListSize(&cheats->romPatches); ++i) {
struct GBCheatPatch* patch = GBCheatPatchListGetPointer(&cheats->romPatches, i);
if (patch->applied) {
continue;
}
// TODO: Byte check
GBPatch8(device->p->cpu, patch->address, patch->newValue, &patch->oldValue);
patch->applied = true;
}
}
static void _unpatchROM(struct mCheatDevice* device, struct GBCheatSet* cheats) {
if (!device->p) {
return;
}
size_t i;
for (i = 0; i < GBCheatPatchListSize(&cheats->romPatches); ++i) {
struct GBCheatPatch* patch = GBCheatPatchListGetPointer(&cheats->romPatches, i);
if (!patch->applied) {
continue;
}
GBPatch8(device->p->cpu, patch->address, patch->oldValue, NULL);
patch->applied = false;
}
}
static void GBCheatSetDeinit(struct mCheatSet* set);
static void GBCheatAddSet(struct mCheatSet* cheats, struct mCheatDevice* device);
static void GBCheatRemoveSet(struct mCheatSet* cheats, struct mCheatDevice* device);
@ -19,6 +54,8 @@ static struct mCheatSet* GBCheatSetCreate(struct mCheatDevice* device, const cha
struct GBCheatSet* set = malloc(sizeof(*set));
mCheatSetInit(&set->d, name);
GBCheatPatchListInit(&set->romPatches, 0);
set->d.deinit = GBCheatSetDeinit;
set->d.add = GBCheatAddSet;
set->d.remove = GBCheatRemoveSet;
@ -39,19 +76,17 @@ struct mCheatDevice* GBCheatDeviceCreate(void) {
static void GBCheatSetDeinit(struct mCheatSet* set) {
struct GBCheatSet* gbset = (struct GBCheatSet*) set;
UNUSED(gbset);
GBCheatPatchListDeinit(&gbset->romPatches);
}
static void GBCheatAddSet(struct mCheatSet* cheats, struct mCheatDevice* device) {
struct GBCheatSet* gbset = (struct GBCheatSet*) cheats;
UNUSED(gbset);
UNUSED(device);
_patchROM(device, gbset);
}
static void GBCheatRemoveSet(struct mCheatSet* cheats, struct mCheatDevice* device) {
struct GBCheatSet* gbset = (struct GBCheatSet*) cheats;
UNUSED(gbset);
UNUSED(device);
_unpatchROM(device, gbset);
}
static bool GBCheatAddCodebreaker(struct GBCheatSet* cheats, uint16_t address, uint8_t data) {
@ -77,6 +112,28 @@ static bool GBCheatAddGameSharkLine(struct GBCheatSet* cheats, const char* line)
return GBCheatAddGameShark(cheats, op);
}
static bool GBCheatAddGameGenieLine(struct GBCheatSet* cheats, const char* line) {
uint16_t op1;
uint16_t op2;
const char* lineNext = hex12(line, &op1);
if (!lineNext || lineNext[0] != '-') {
return false;
}
++lineNext;
lineNext = hex12(lineNext, &op2);
if (!lineNext) {
return false;
}
uint16_t address = (op1 & 0xF) << 8;
address |= (op2 >> 4) & 0xFF;
address |= ((op2 & 0xF) ^ 0xF) << 12;
struct GBCheatPatch* patch = GBCheatPatchListAppend(&cheats->romPatches);
patch->address = address;
patch->newValue = op1 >> 4;
patch->applied = false;
return true;
}
static bool GBCheatAddVBALine(struct GBCheatSet* cheats, const char* line) {
uint16_t address;
uint8_t value;
@ -103,7 +160,7 @@ bool GBCheatAddLine(struct mCheatSet* set, const char* line, int type) {
case GB_CHEAT_AUTODETECT:
break;
case GB_CHEAT_GAME_GENIE:
return false;
return GBCheatAddGameGenieLine(cheats, line);
case GB_CHEAT_GAMESHARK:
return GBCheatAddGameSharkLine(cheats, line);
case GB_CHEAT_VBA:
@ -118,7 +175,7 @@ bool GBCheatAddLine(struct mCheatSet* set, const char* line, int type) {
bool codebreaker = false;
const char* lineNext = hex16(line, &op1);
if (!lineNext) {
return false;
return GBCheatAddGameGenieLine(cheats, line);
}
if (lineNext[0] == ':') {
return GBCheatAddVBALine(cheats, line);
@ -148,8 +205,7 @@ bool GBCheatAddLine(struct mCheatSet* set, const char* line, int type) {
static void GBCheatRefresh(struct mCheatSet* cheats, struct mCheatDevice* device) {
struct GBCheatSet* gbset = (struct GBCheatSet*) cheats;
UNUSED(gbset);
UNUSED(device);
_patchROM(device, gbset);
}
static void GBCheatSetCopyProperties(struct mCheatSet* set, struct mCheatSet* oldSet) {

View File

@ -11,8 +11,6 @@
#include "core/cheats.h"
#include "util/vector.h"
#define MAX_ROM_PATCHES 4
enum GBACheatType {
GB_CHEAT_AUTODETECT,
GB_CHEAT_GAMESHARK,
@ -25,11 +23,13 @@ struct GBCheatPatch {
int8_t newValue;
int8_t oldValue;
bool applied;
bool exists;
};
DECLARE_VECTOR(GBCheatPatchList, struct GBCheatPatch);
struct GBCheatSet {
struct mCheatSet d;
struct GBCheatPatchList romPatches;
};
struct mCheatDevice* GBCheatDeviceCreate(void);

View File

@ -10,7 +10,6 @@
#include "arm/arm.h"
#include "core/cheats.h"
#include "util/vector.h"
#define MAX_ROM_PATCHES 4

View File

@ -260,6 +260,22 @@ const char* hex32(const char* line, uint32_t* out) {
return line;
}
const char* hex24(const char* line, uint32_t* out) {
uint32_t value = 0;
int i;
for (i = 0; i < 6; ++i, ++line) {
char digit = *line;
value <<= 4;
int nybble = hexDigit(digit);
if (nybble < 0) {
return 0;
}
value |= nybble;
}
*out = value;
return line;
}
const char* hex16(const char* line, uint16_t* out) {
uint16_t value = 0;
*out = 0;
@ -277,6 +293,23 @@ const char* hex16(const char* line, uint16_t* out) {
return line;
}
const char* hex12(const char* line, uint16_t* out) {
uint16_t value = 0;
*out = 0;
int i;
for (i = 0; i < 3; ++i, ++line) {
char digit = *line;
value <<= 4;
int nybble = hexDigit(digit);
if (nybble < 0) {
return 0;
}
value |= nybble;
}
*out = value;
return line;
}
const char* hex8(const char* line, uint8_t* out) {
uint8_t value = 0;
*out = 0;
@ -293,3 +326,17 @@ const char* hex8(const char* line, uint8_t* out) {
*out = value;
return line;
}
const char* hex4(const char* line, uint8_t* out) {
uint8_t value = 0;
*out = 0;
char digit = *line;
value <<= 4;
int nybble = hexDigit(digit);
if (nybble < 0) {
return 0;
}
value |= nybble;
*out = value;
return line;
}

View File

@ -26,7 +26,10 @@ uint32_t utf16Char(const uint16_t** unicode, size_t* length);
int hexDigit(char digit);
const char* hex32(const char* line, uint32_t* out);
const char* hex24(const char* line, uint32_t* out);
const char* hex16(const char* line, uint16_t* out);
const char* hex12(const char* line, uint16_t* out);
const char* hex8(const char* line, uint8_t* out);
const char* hex4(const char* line, uint8_t* out);
#endif