mirror of
https://github.com/libretro/mgba.git
synced 2024-11-27 10:11:00 +00:00
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:
|
||||
- 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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user