mirror of https://github.com/mgba-emu/mgba.git
GBA Cheats: Fix holding onto pointers that may get invalidated
This commit is contained in:
parent
1cb054ec67
commit
3b1d3292dd
1
CHANGES
1
CHANGES
|
@ -2,6 +2,7 @@
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
- GB MBC: Fix MBC7 when size is incorrectly specified
|
- GB MBC: Fix MBC7 when size is incorrectly specified
|
||||||
- GB Video: Setting LYC=LY during mode 2 should trigger an IRQ
|
- GB Video: Setting LYC=LY during mode 2 should trigger an IRQ
|
||||||
|
- GBA Cheats: Fix holding onto pointers that may get invalidated
|
||||||
Misc:
|
Misc:
|
||||||
- All: Only update version info if needed
|
- All: Only update version info if needed
|
||||||
|
|
||||||
|
|
|
@ -75,9 +75,9 @@ static struct mCheatSet* GBACheatSetCreate(struct mCheatDevice* device, const ch
|
||||||
UNUSED(device);
|
UNUSED(device);
|
||||||
struct GBACheatSet* set = malloc(sizeof(*set));
|
struct GBACheatSet* set = malloc(sizeof(*set));
|
||||||
mCheatSetInit(&set->d, name);
|
mCheatSetInit(&set->d, name);
|
||||||
set->incompleteCheat = 0;
|
set->incompleteCheat = -1;
|
||||||
set->incompletePatch = 0;
|
set->incompletePatch = 0;
|
||||||
set->currentBlock = 0;
|
set->currentBlock = -1;
|
||||||
set->gsaVersion = 0;
|
set->gsaVersion = 0;
|
||||||
set->cbRngState = 0;
|
set->cbRngState = 0;
|
||||||
set->cbMaster = 0;
|
set->cbMaster = 0;
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "core/cheats.h"
|
#include "core/cheats.h"
|
||||||
|
|
||||||
#define MAX_ROM_PATCHES 4
|
#define MAX_ROM_PATCHES 4
|
||||||
|
#define COMPLETE ((size_t) -1)
|
||||||
|
|
||||||
enum GBACheatType {
|
enum GBACheatType {
|
||||||
GBA_CHEAT_AUTODETECT,
|
GBA_CHEAT_AUTODETECT,
|
||||||
|
@ -143,9 +144,9 @@ struct GBACheatSet {
|
||||||
bool exists;
|
bool exists;
|
||||||
} romPatches[MAX_ROM_PATCHES];
|
} romPatches[MAX_ROM_PATCHES];
|
||||||
|
|
||||||
struct mCheat* incompleteCheat;
|
size_t incompleteCheat;
|
||||||
struct GBACheatPatch* incompletePatch;
|
struct GBACheatPatch* incompletePatch;
|
||||||
struct mCheat* currentBlock;
|
size_t currentBlock;
|
||||||
|
|
||||||
int gsaVersion;
|
int gsaVersion;
|
||||||
uint32_t gsaSeeds[4];
|
uint32_t gsaSeeds[4];
|
||||||
|
|
|
@ -197,11 +197,12 @@ bool GBACheatAddCodeBreaker(struct GBACheatSet* cheats, uint32_t op1, uint16_t o
|
||||||
enum GBACodeBreakerType type = op1 >> 28;
|
enum GBACodeBreakerType type = op1 >> 28;
|
||||||
struct mCheat* cheat = NULL;
|
struct mCheat* cheat = NULL;
|
||||||
|
|
||||||
if (cheats->incompleteCheat) {
|
if (cheats->incompleteCheat != COMPLETE) {
|
||||||
cheats->incompleteCheat->repeat = op1 & 0xFFFF;
|
struct mCheat* incompleteCheat = mCheatListGetPointer(&cheats->d.list, cheats->incompleteCheat);
|
||||||
cheats->incompleteCheat->addressOffset = op2;
|
incompleteCheat->repeat = op1 & 0xFFFF;
|
||||||
cheats->incompleteCheat->operandOffset = 0;
|
incompleteCheat->addressOffset = op2;
|
||||||
cheats->incompleteCheat = 0;
|
incompleteCheat->operandOffset = 0;
|
||||||
|
cheats->incompleteCheat = COMPLETE;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +234,7 @@ bool GBACheatAddCodeBreaker(struct GBACheatSet* cheats, uint32_t op1, uint16_t o
|
||||||
cheat = mCheatListAppend(&cheats->d.list);
|
cheat = mCheatListAppend(&cheats->d.list);
|
||||||
cheat->type = CHEAT_ASSIGN;
|
cheat->type = CHEAT_ASSIGN;
|
||||||
cheat->width = 2;
|
cheat->width = 2;
|
||||||
cheats->incompleteCheat = cheat;
|
cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat);
|
||||||
break;
|
break;
|
||||||
case CB_FILL_8:
|
case CB_FILL_8:
|
||||||
mLOG(CHEATS, STUB, "CodeBreaker code %08X %04X not supported", op1, op2);
|
mLOG(CHEATS, STUB, "CodeBreaker code %08X %04X not supported", op1, op2);
|
||||||
|
|
|
@ -91,13 +91,14 @@ bool GBACheatAddGameSharkRaw(struct GBACheatSet* cheats, uint32_t op1, uint32_t
|
||||||
enum GBAGameSharkType type = op1 >> 28;
|
enum GBAGameSharkType type = op1 >> 28;
|
||||||
struct mCheat* cheat = 0;
|
struct mCheat* cheat = 0;
|
||||||
|
|
||||||
if (cheats->incompleteCheat) {
|
if (cheats->incompleteCheat != COMPLETE) {
|
||||||
|
struct mCheat* incompleteCheat = mCheatListGetPointer(&cheats->d.list, cheats->incompleteCheat);
|
||||||
if (cheats->remainingAddresses > 0) {
|
if (cheats->remainingAddresses > 0) {
|
||||||
cheat = mCheatListAppend(&cheats->d.list);
|
cheat = mCheatListAppend(&cheats->d.list);
|
||||||
cheat->type = CHEAT_ASSIGN;
|
cheat->type = CHEAT_ASSIGN;
|
||||||
cheat->width = 4;
|
cheat->width = 4;
|
||||||
cheat->address = op1;
|
cheat->address = op1;
|
||||||
cheat->operand = cheats->incompleteCheat->operand;
|
cheat->operand = incompleteCheat->operand;
|
||||||
cheat->repeat = 1;
|
cheat->repeat = 1;
|
||||||
--cheats->remainingAddresses;
|
--cheats->remainingAddresses;
|
||||||
}
|
}
|
||||||
|
@ -106,12 +107,12 @@ bool GBACheatAddGameSharkRaw(struct GBACheatSet* cheats, uint32_t op1, uint32_t
|
||||||
cheat->type = CHEAT_ASSIGN;
|
cheat->type = CHEAT_ASSIGN;
|
||||||
cheat->width = 4;
|
cheat->width = 4;
|
||||||
cheat->address = op2;
|
cheat->address = op2;
|
||||||
cheat->operand = cheats->incompleteCheat->operand;
|
cheat->operand = incompleteCheat->operand;
|
||||||
cheat->repeat = 1;
|
cheat->repeat = 1;
|
||||||
--cheats->remainingAddresses;
|
--cheats->remainingAddresses;
|
||||||
}
|
}
|
||||||
if (cheats->remainingAddresses == 0) {
|
if (cheats->remainingAddresses == 0) {
|
||||||
cheats->incompleteCheat = 0;
|
cheats->incompleteCheat = COMPLETE;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -141,7 +142,7 @@ bool GBACheatAddGameSharkRaw(struct GBACheatSet* cheats, uint32_t op1, uint32_t
|
||||||
cheat->type = CHEAT_ASSIGN;
|
cheat->type = CHEAT_ASSIGN;
|
||||||
cheat->width = 4;
|
cheat->width = 4;
|
||||||
cheat->address = op2;
|
cheat->address = op2;
|
||||||
cheats->incompleteCheat = cheat;
|
cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat);
|
||||||
break;
|
break;
|
||||||
case GSA_PATCH:
|
case GSA_PATCH:
|
||||||
cheats->romPatches[0].address = (op1 & 0xFFFFFF) << 1;
|
cheats->romPatches[0].address = (op1 & 0xFFFFFF) << 1;
|
||||||
|
|
|
@ -53,18 +53,20 @@ static uint32_t _parAddr(uint32_t x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _parEndBlock(struct GBACheatSet* cheats) {
|
static void _parEndBlock(struct GBACheatSet* cheats) {
|
||||||
size_t size = mCheatListSize(&cheats->d.list) - mCheatListIndex(&cheats->d.list, cheats->currentBlock);
|
size_t size = mCheatListSize(&cheats->d.list) - cheats->currentBlock;
|
||||||
if (cheats->currentBlock->repeat) {
|
struct mCheat* currentBlock = mCheatListGetPointer(&cheats->d.list, cheats->currentBlock);
|
||||||
cheats->currentBlock->negativeRepeat = size - cheats->currentBlock->repeat;
|
if (currentBlock->repeat) {
|
||||||
|
currentBlock->negativeRepeat = size - currentBlock->repeat;
|
||||||
} else {
|
} else {
|
||||||
cheats->currentBlock->repeat = size;
|
currentBlock->repeat = size;
|
||||||
}
|
}
|
||||||
cheats->currentBlock = 0;
|
cheats->currentBlock = COMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _parElseBlock(struct GBACheatSet* cheats) {
|
static void _parElseBlock(struct GBACheatSet* cheats) {
|
||||||
size_t size = mCheatListSize(&cheats->d.list) - mCheatListIndex(&cheats->d.list, cheats->currentBlock);
|
size_t size = mCheatListSize(&cheats->d.list) - cheats->currentBlock;
|
||||||
cheats->currentBlock->repeat = size;
|
struct mCheat* currentBlock = mCheatListGetPointer(&cheats->d.list, cheats->currentBlock);
|
||||||
|
currentBlock->repeat = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _addPAR3Cond(struct GBACheatSet* cheats, uint32_t op1, uint32_t op2) {
|
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:
|
case PAR3_ACTION_BLOCK:
|
||||||
cheat->repeat = 0;
|
cheat->repeat = 0;
|
||||||
cheat->negativeRepeat = 0;
|
cheat->negativeRepeat = 0;
|
||||||
if (cheats->currentBlock) {
|
if (cheats->currentBlock != COMPLETE) {
|
||||||
_parEndBlock(cheats);
|
_parEndBlock(cheats);
|
||||||
}
|
}
|
||||||
cheats->currentBlock = cheat;
|
cheats->currentBlock = mCheatListIndex(&cheats->d.list, cheat);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,13 +177,13 @@ static bool _addPAR3Special(struct GBACheatSet* cheats, uint32_t op2) {
|
||||||
cheats->incompletePatch = &cheats->romPatches[3];
|
cheats->incompletePatch = &cheats->romPatches[3];
|
||||||
break;
|
break;
|
||||||
case PAR3_OTHER_ENDIF:
|
case PAR3_OTHER_ENDIF:
|
||||||
if (cheats->currentBlock) {
|
if (cheats->currentBlock != COMPLETE) {
|
||||||
_parEndBlock(cheats);
|
_parEndBlock(cheats);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case PAR3_OTHER_ELSE:
|
case PAR3_OTHER_ELSE:
|
||||||
if (cheats->currentBlock) {
|
if (cheats->currentBlock != COMPLETE) {
|
||||||
_parElseBlock(cheats);
|
_parElseBlock(cheats);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -190,19 +192,19 @@ static bool _addPAR3Special(struct GBACheatSet* cheats, uint32_t op2) {
|
||||||
cheat = mCheatListAppend(&cheats->d.list);
|
cheat = mCheatListAppend(&cheats->d.list);
|
||||||
cheat->address = _parAddr(op2);
|
cheat->address = _parAddr(op2);
|
||||||
cheat->width = 1;
|
cheat->width = 1;
|
||||||
cheats->incompleteCheat = cheat;
|
cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat);
|
||||||
break;
|
break;
|
||||||
case PAR3_OTHER_FILL_2:
|
case PAR3_OTHER_FILL_2:
|
||||||
cheat = mCheatListAppend(&cheats->d.list);
|
cheat = mCheatListAppend(&cheats->d.list);
|
||||||
cheat->address = _parAddr(op2);
|
cheat->address = _parAddr(op2);
|
||||||
cheat->width = 2;
|
cheat->width = 2;
|
||||||
cheats->incompleteCheat = cheat;
|
cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat);
|
||||||
break;
|
break;
|
||||||
case PAR3_OTHER_FILL_4:
|
case PAR3_OTHER_FILL_4:
|
||||||
cheat = mCheatListAppend(&cheats->d.list);
|
cheat = mCheatListAppend(&cheats->d.list);
|
||||||
cheat->address = _parAddr(op2);
|
cheat->address = _parAddr(op2);
|
||||||
cheat->width = 3;
|
cheat->width = 3;
|
||||||
cheats->incompleteCheat = cheat;
|
cheats->incompleteCheat = mCheatListIndex(&cheats->d.list, cheat);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -214,12 +216,13 @@ bool GBACheatAddProActionReplayRaw(struct GBACheatSet* cheats, uint32_t op1, uin
|
||||||
cheats->incompletePatch = 0;
|
cheats->incompletePatch = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (cheats->incompleteCheat) {
|
if (cheats->incompleteCheat != COMPLETE) {
|
||||||
cheats->incompleteCheat->operand = op1 & (0xFFFFFFFFU >> ((4 - cheats->incompleteCheat->width) * 8));
|
struct mCheat* incompleteCheat = mCheatListGetPointer(&cheats->d.list, cheats->incompleteCheat);
|
||||||
cheats->incompleteCheat->addressOffset = op2 >> 24;
|
incompleteCheat->operand = op1 & (0xFFFFFFFFU >> ((4 - incompleteCheat->width) * 8));
|
||||||
cheats->incompleteCheat->repeat = (op2 >> 16) & 0xFF;
|
incompleteCheat->addressOffset = op2 >> 24;
|
||||||
cheats->incompleteCheat->addressOffset = (op2 & 0xFFFF) * cheats->incompleteCheat->width;
|
incompleteCheat->repeat = (op2 >> 16) & 0xFF;
|
||||||
cheats->incompleteCheat = 0;
|
incompleteCheat->addressOffset = (op2 & 0xFFFF) * incompleteCheat->width;
|
||||||
|
cheats->incompleteCheat = COMPLETE;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue