From fe28120f2abb24311ae17abd60188db5d8b35205 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 20 Sep 2016 12:09:28 -0700 Subject: [PATCH] GBA Cheats: Fix holding onto pointers that may get invalidated --- CHANGES | 1 + src/gba/cheats.c | 4 ++-- src/gba/cheats.h | 5 +++-- src/gba/cheats/codebreaker.c | 13 ++++++----- src/gba/cheats/gameshark.c | 11 ++++----- src/gba/cheats/parv3.c | 43 +++++++++++++++++++----------------- 6 files changed, 42 insertions(+), 35 deletions(-) diff --git a/CHANGES b/CHANGES index c7ca6135a..ced41a783 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,7 @@ Bugfixes: - GB MBC: Fix MBC7 when size is incorrectly specified - GB Video: Setting LYC=LY during mode 2 should trigger an IRQ + - GBA Cheats: Fix holding onto pointers that may get invalidated Misc: - All: Only update version info if needed diff --git a/src/gba/cheats.c b/src/gba/cheats.c index e2f3827b7..747caab48 100644 --- a/src/gba/cheats.c +++ b/src/gba/cheats.c @@ -75,9 +75,9 @@ static struct mCheatSet* GBACheatSetCreate(struct mCheatDevice* device, const ch UNUSED(device); struct GBACheatSet* set = malloc(sizeof(*set)); mCheatSetInit(&set->d, name); - set->incompleteCheat = 0; + set->incompleteCheat = -1; set->incompletePatch = 0; - set->currentBlock = 0; + set->currentBlock = -1; set->gsaVersion = 0; set->cbRngState = 0; set->cbMaster = 0; diff --git a/src/gba/cheats.h b/src/gba/cheats.h index 138c83880..db5ea4663 100644 --- a/src/gba/cheats.h +++ b/src/gba/cheats.h @@ -12,6 +12,7 @@ #include "core/cheats.h" #define MAX_ROM_PATCHES 4 +#define COMPLETE ((size_t) -1) enum GBACheatType { GBA_CHEAT_AUTODETECT, @@ -143,9 +144,9 @@ struct GBACheatSet { bool exists; } romPatches[MAX_ROM_PATCHES]; - struct mCheat* incompleteCheat; + size_t incompleteCheat; struct GBACheatPatch* incompletePatch; - struct mCheat* currentBlock; + size_t currentBlock; int gsaVersion; uint32_t gsaSeeds[4]; diff --git a/src/gba/cheats/codebreaker.c b/src/gba/cheats/codebreaker.c index a8735b646..a90e367f6 100644 --- a/src/gba/cheats/codebreaker.c +++ b/src/gba/cheats/codebreaker.c @@ -197,11 +197,12 @@ bool GBACheatAddCodeBreaker(struct GBACheatSet* cheats, uint32_t op1, uint16_t o enum GBACodeBreakerType type = op1 >> 28; struct mCheat* cheat = NULL; - if (cheats->incompleteCheat) { - cheats->incompleteCheat->repeat = op1 & 0xFFFF; - cheats->incompleteCheat->addressOffset = op2; - cheats->incompleteCheat->operandOffset = 0; - cheats->incompleteCheat = 0; + if (cheats->incompleteCheat != COMPLETE) { + struct mCheat* incompleteCheat = mCheatListGetPointer(&cheats->d.list, cheats->incompleteCheat); + incompleteCheat->repeat = op1 & 0xFFFF; + incompleteCheat->addressOffset = op2; + incompleteCheat->operandOffset = 0; + cheats->incompleteCheat = COMPLETE; return true; } @@ -233,7 +234,7 @@ bool GBACheatAddCodeBreaker(struct GBACheatSet* cheats, uint32_t op1, uint16_t o cheat = mCheatListAppend(&cheats->d.list); cheat->type = CHEAT_ASSIGN; cheat->width = 2; - cheats->incompleteCheat = cheat; + cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat); break; case CB_FILL_8: mLOG(CHEATS, STUB, "CodeBreaker code %08X %04X not supported", op1, op2); diff --git a/src/gba/cheats/gameshark.c b/src/gba/cheats/gameshark.c index 1b8f368b2..6a7b17fed 100644 --- a/src/gba/cheats/gameshark.c +++ b/src/gba/cheats/gameshark.c @@ -91,13 +91,14 @@ bool GBACheatAddGameSharkRaw(struct GBACheatSet* cheats, uint32_t op1, uint32_t enum GBAGameSharkType type = op1 >> 28; struct mCheat* cheat = 0; - if (cheats->incompleteCheat) { + if (cheats->incompleteCheat != COMPLETE) { + struct mCheat* incompleteCheat = mCheatListGetPointer(&cheats->d.list, cheats->incompleteCheat); if (cheats->remainingAddresses > 0) { cheat = mCheatListAppend(&cheats->d.list); cheat->type = CHEAT_ASSIGN; cheat->width = 4; cheat->address = op1; - cheat->operand = cheats->incompleteCheat->operand; + cheat->operand = incompleteCheat->operand; cheat->repeat = 1; --cheats->remainingAddresses; } @@ -106,12 +107,12 @@ bool GBACheatAddGameSharkRaw(struct GBACheatSet* cheats, uint32_t op1, uint32_t cheat->type = CHEAT_ASSIGN; cheat->width = 4; cheat->address = op2; - cheat->operand = cheats->incompleteCheat->operand; + cheat->operand = incompleteCheat->operand; cheat->repeat = 1; --cheats->remainingAddresses; } if (cheats->remainingAddresses == 0) { - cheats->incompleteCheat = 0; + cheats->incompleteCheat = COMPLETE; } return true; } @@ -141,7 +142,7 @@ bool GBACheatAddGameSharkRaw(struct GBACheatSet* cheats, uint32_t op1, uint32_t cheat->type = CHEAT_ASSIGN; cheat->width = 4; cheat->address = op2; - cheats->incompleteCheat = cheat; + cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat); break; case GSA_PATCH: cheats->romPatches[0].address = (op1 & 0xFFFFFF) << 1; diff --git a/src/gba/cheats/parv3.c b/src/gba/cheats/parv3.c index 5701f3eb4..09c0c09c9 100644 --- a/src/gba/cheats/parv3.c +++ b/src/gba/cheats/parv3.c @@ -53,18 +53,20 @@ static uint32_t _parAddr(uint32_t x) { } static void _parEndBlock(struct GBACheatSet* cheats) { - size_t size = mCheatListSize(&cheats->d.list) - mCheatListIndex(&cheats->d.list, cheats->currentBlock); - if (cheats->currentBlock->repeat) { - cheats->currentBlock->negativeRepeat = size - cheats->currentBlock->repeat; + size_t size = mCheatListSize(&cheats->d.list) - cheats->currentBlock; + struct mCheat* currentBlock = mCheatListGetPointer(&cheats->d.list, cheats->currentBlock); + if (currentBlock->repeat) { + currentBlock->negativeRepeat = size - currentBlock->repeat; } else { - cheats->currentBlock->repeat = size; + currentBlock->repeat = size; } - cheats->currentBlock = 0; + cheats->currentBlock = COMPLETE; } static void _parElseBlock(struct GBACheatSet* cheats) { - size_t size = mCheatListSize(&cheats->d.list) - mCheatListIndex(&cheats->d.list, cheats->currentBlock); - cheats->currentBlock->repeat = size; + size_t size = mCheatListSize(&cheats->d.list) - cheats->currentBlock; + struct mCheat* currentBlock = mCheatListGetPointer(&cheats->d.list, cheats->currentBlock); + currentBlock->repeat = size; } static bool _addPAR3Cond(struct GBACheatSet* cheats, uint32_t op1, uint32_t op2) { @@ -98,10 +100,10 @@ static bool _addPAR3Cond(struct GBACheatSet* cheats, uint32_t op1, uint32_t op2) case PAR3_ACTION_BLOCK: cheat->repeat = 0; cheat->negativeRepeat = 0; - if (cheats->currentBlock) { + if (cheats->currentBlock != COMPLETE) { _parEndBlock(cheats); } - cheats->currentBlock = cheat; + cheats->currentBlock = mCheatListIndex(&cheats->d.list, cheat); break; } @@ -175,13 +177,13 @@ static bool _addPAR3Special(struct GBACheatSet* cheats, uint32_t op2) { cheats->incompletePatch = &cheats->romPatches[3]; break; case PAR3_OTHER_ENDIF: - if (cheats->currentBlock) { + if (cheats->currentBlock != COMPLETE) { _parEndBlock(cheats); return true; } return false; case PAR3_OTHER_ELSE: - if (cheats->currentBlock) { + if (cheats->currentBlock != COMPLETE) { _parElseBlock(cheats); return true; } @@ -190,19 +192,19 @@ static bool _addPAR3Special(struct GBACheatSet* cheats, uint32_t op2) { cheat = mCheatListAppend(&cheats->d.list); cheat->address = _parAddr(op2); cheat->width = 1; - cheats->incompleteCheat = cheat; + cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat); break; case PAR3_OTHER_FILL_2: cheat = mCheatListAppend(&cheats->d.list); cheat->address = _parAddr(op2); cheat->width = 2; - cheats->incompleteCheat = cheat; + cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat); break; case PAR3_OTHER_FILL_4: cheat = mCheatListAppend(&cheats->d.list); cheat->address = _parAddr(op2); cheat->width = 3; - cheats->incompleteCheat = cheat; + cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat); break; } return true; @@ -214,12 +216,13 @@ bool GBACheatAddProActionReplayRaw(struct GBACheatSet* cheats, uint32_t op1, uin cheats->incompletePatch = 0; return true; } - if (cheats->incompleteCheat) { - cheats->incompleteCheat->operand = op1 & (0xFFFFFFFFU >> ((4 - cheats->incompleteCheat->width) * 8)); - cheats->incompleteCheat->addressOffset = op2 >> 24; - cheats->incompleteCheat->repeat = (op2 >> 16) & 0xFF; - cheats->incompleteCheat->addressOffset = (op2 & 0xFFFF) * cheats->incompleteCheat->width; - cheats->incompleteCheat = 0; + if (cheats->incompleteCheat != COMPLETE) { + struct mCheat* incompleteCheat = mCheatListGetPointer(&cheats->d.list, cheats->incompleteCheat); + incompleteCheat->operand = op1 & (0xFFFFFFFFU >> ((4 - incompleteCheat->width) * 8)); + incompleteCheat->addressOffset = op2 >> 24; + incompleteCheat->repeat = (op2 >> 16) & 0xFF; + incompleteCheat->addressOffset = (op2 & 0xFFFF) * incompleteCheat->width; + cheats->incompleteCheat = COMPLETE; return true; }