From f84aadffd2d02827f095c58bce224172875393f1 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 26 Dec 2015 22:25:50 -0500 Subject: [PATCH] GBA: Support for VBA-style cheat codes --- CHANGES | 1 + src/gba/cheats.c | 59 +++++++++++++++++++++++++++++++++++++++-------- src/gba/cheats.h | 2 ++ src/util/string.c | 17 ++++++++++++++ src/util/string.h | 1 + 5 files changed, 71 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index b13d91035..289a2dd27 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,7 @@ Features: - Libretro: Cheat code support - Support for GLSL shaders - ROM information view + - Support for VBA-style cheat codes Bugfixes: - Util: Fix PowerPC PNG read/write pixel order - VFS: Fix VFileReadline and remove _vfdReadline diff --git a/src/gba/cheats.c b/src/gba/cheats.c index 5f7aee24d..0bbd2b06b 100644 --- a/src/gba/cheats.c +++ b/src/gba/cheats.c @@ -359,26 +359,67 @@ bool GBACheatSaveFile(struct GBACheatDevice* device, struct VFile* vf) { 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); } - line = hex16(line, &op2); - if (!line) { + while (isspace((int) lineNext[0])) { + ++lineNext; + } + 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; diff --git a/src/gba/cheats.h b/src/gba/cheats.h index 75a12622b..73b08940a 100644 --- a/src/gba/cheats.h +++ b/src/gba/cheats.h @@ -211,6 +211,8 @@ bool GBACheatAddGameSharkLine(struct GBACheatSet*, const char* line); 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*); diff --git a/src/util/string.c b/src/util/string.c index 91451a27d..6649a38ac 100644 --- a/src/util/string.c +++ b/src/util/string.c @@ -276,3 +276,20 @@ const char* hex16(const char* line, uint16_t* out) { *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; +} diff --git a/src/util/string.h b/src/util/string.h index 2597cbfda..b209f7d90 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -27,5 +27,6 @@ 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* hex16(const char* line, uint16_t* out); +const char* hex8(const char* line, uint8_t* out); #endif