GBA: Support for VBA-style cheat codes
Jeffrey Pfau jeffrey@endrift.com
Sat, 26 Dec 2015 22:25:50 -0500
5 files changed,
71 insertions(+),
9 deletions(-)
M
src/gba/cheats.c
→
src/gba/cheats.c
@@ -359,26 +359,67 @@ }
return true; } +bool GBACheatAddVBALine(struct GBACheatSet* cheats, const char* line) { + uint32_t address; + uint8_t op; + uint32_t value = 0; + int width = 0; + const char* lineNext = hex32(line, &address); + if (!lineNext) { + return false; + } + if (lineNext[0] != ':') { + return false; + } + ++lineNext; + while (width < 4) { + lineNext = hex8(lineNext, &op); + if (!lineNext) { + break; + } + value <<= 8; + value |= op; + ++width; + } + if (width == 0 || width == 3) { + return false; + } + + struct GBACheat* cheat = GBACheatListAppend(&cheats->list); + cheat->address = address; + cheat->operandOffset = 0; + cheat->addressOffset = 0; + cheat->repeat = 1; + cheat->type = CHEAT_ASSIGN; + cheat->width = width; + cheat->operand = value; + GBACheatRegisterLine(cheats, line); + return true; +} + bool GBACheatAddLine(struct GBACheatSet* cheats, const char* line) { uint32_t op1; uint16_t op2; uint16_t op3; - line = hex32(line, &op1); - if (!line) { + const char* lineNext = hex32(line, &op1); + if (!lineNext) { return false; } - while (isspace((int) line[0])) { - ++line; + if (lineNext[0] == ':') { + return GBACheatAddVBALine(cheats, line); + } + while (isspace((int) lineNext[0])) { + ++lineNext; } - line = hex16(line, &op2); - if (!line) { + lineNext = hex16(lineNext, &op2); + if (!lineNext) { return false; } - if (!line[0] || isspace((int) line[0])) { + if (!lineNext[0] || isspace((int) lineNext[0])) { return GBACheatAddCodeBreaker(cheats, op1, op2); } - line = hex16(line, &op3); - if (!line) { + lineNext = hex16(lineNext, &op3); + if (!lineNext) { return false; } uint32_t realOp2 = op2;
M
src/gba/cheats.h
→
src/gba/cheats.h
@@ -211,6 +211,8 @@
bool GBACheatAddProActionReplay(struct GBACheatSet*, uint32_t op1, uint32_t op2); bool GBACheatAddProActionReplayLine(struct GBACheatSet*, const char* line); +bool GBACheatAddVBALine(struct GBACheatSet*, const char* line); + bool GBACheatAddAutodetect(struct GBACheatSet*, uint32_t op1, uint32_t op2); bool GBACheatParseFile(struct GBACheatDevice*, struct VFile*);
M
src/util/string.c
→
src/util/string.c
@@ -276,3 +276,20 @@ }
*out = value; return line; } + +const char* hex8(const char* line, uint8_t* out) { + uint8_t value = 0; + *out = 0; + int i; + for (i = 0; i < 2; ++i, ++line) { + char digit = *line; + value <<= 4; + int nybble = hexDigit(digit); + if (nybble < 0) { + return 0; + } + value |= nybble; + } + *out = value; + return line; +}
M
src/util/string.h
→
src/util/string.h
@@ -27,5 +27,6 @@
int hexDigit(char digit); const char* hex32(const char* line, uint32_t* out); const char* hex16(const char* line, uint16_t* out); +const char* hex8(const char* line, uint8_t* out); #endif