mirror of https://github.com/mgba-emu/mgba.git
GBA: Cheats can now be grouped and named
This commit is contained in:
parent
3d44065826
commit
31a9bafae8
176
src/gba/cheats.c
176
src/gba/cheats.c
|
@ -7,10 +7,14 @@
|
||||||
|
|
||||||
#include "gba/gba.h"
|
#include "gba/gba.h"
|
||||||
#include "gba/io.h"
|
#include "gba/io.h"
|
||||||
|
#include "util/vfs.h"
|
||||||
|
|
||||||
|
#define MAX_LINE_LENGTH 128
|
||||||
|
|
||||||
const uint32_t GBA_CHEAT_DEVICE_ID = 0xABADC0DE;
|
const uint32_t GBA_CHEAT_DEVICE_ID = 0xABADC0DE;
|
||||||
|
|
||||||
DEFINE_VECTOR(GBACheatList, struct GBACheat);
|
DEFINE_VECTOR(GBACheatList, struct GBACheat);
|
||||||
|
DEFINE_VECTOR(GBACheatSets, struct GBACheatSet*);
|
||||||
|
|
||||||
static const uint32_t _gsa1S[4] = { 0x09F4FBBD, 0x9681884A, 0x352027E9, 0xF3DEE5A7 };
|
static const uint32_t _gsa1S[4] = { 0x09F4FBBD, 0x9681884A, 0x352027E9, 0xF3DEE5A7 };
|
||||||
static const uint32_t _par3S[4] = { 0x7AA9648F, 0x7FAE6994, 0xC0EFAAD5, 0x42712C57 };
|
static const uint32_t _par3S[4] = { 0x7AA9648F, 0x7FAE6994, 0xC0EFAAD5, 0x42712C57 };
|
||||||
|
@ -292,18 +296,21 @@ static bool _addGSA1(struct GBACheatSet* cheats, uint32_t op1, uint32_t op2) {
|
||||||
cheat->repeat = (op1 >> 16) & 0xFF;
|
cheat->repeat = (op1 >> 16) & 0xFF;
|
||||||
return true;
|
return true;
|
||||||
case GSA_HOOK:
|
case GSA_HOOK:
|
||||||
if (cheats->hookAddress) {
|
if (cheats->hook) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cheats->hookAddress = BASE_CART0 | (op1 & (SIZE_CART0 - 1));
|
cheats->hook = malloc(sizeof(*cheats->hook));
|
||||||
cheats->hookMode = MODE_THUMB;
|
cheats->hook->address = BASE_CART0 | (op1 & (SIZE_CART0 - 1));
|
||||||
|
cheats->hook->mode = MODE_THUMB;
|
||||||
|
cheats->hook->refs = 1;
|
||||||
|
cheats->hook->reentries = 0;
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cheat->operand = op2;
|
cheat->operand = op2;
|
||||||
cheat->repeat = 1;
|
cheat->repeat = 1;
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _addGSA3(struct GBACheatSet* cheats, uint32_t op1, uint32_t op2) {
|
static bool _addGSA3(struct GBACheatSet* cheats, uint32_t op1, uint32_t op2) {
|
||||||
|
@ -314,45 +321,53 @@ static bool _addGSA3(struct GBACheatSet* cheats, uint32_t op1, uint32_t op2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _addBreakpoint(struct GBACheatDevice* device) {
|
static void _addBreakpoint(struct GBACheatDevice* device, struct GBACheatSet* cheats) {
|
||||||
if (!device->cheats || !device->p) {
|
if (!device->p || !cheats->hook) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GBASetBreakpoint(device->p, &device->d, device->cheats->hookAddress, device->cheats->hookMode, &device->cheats->patchedOpcode);
|
++cheats->hook->reentries;
|
||||||
}
|
if (cheats->hook->reentries > 1) {
|
||||||
|
|
||||||
static void _removeBreakpoint(struct GBACheatDevice* device) {
|
|
||||||
if (!device->cheats || !device->p) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GBAClearBreakpoint(device->p, device->cheats->hookAddress, device->cheats->hookMode, device->cheats->patchedOpcode);
|
GBASetBreakpoint(device->p, &device->d, cheats->hook->address, cheats->hook->mode, &cheats->hook->patchedOpcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _patchROM(struct GBACheatDevice* device) {
|
static void _removeBreakpoint(struct GBACheatDevice* device, struct GBACheatSet* cheats) {
|
||||||
if (!device->cheats || !device->p) {
|
if (!device->p || !cheats->hook) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
--cheats->hook->reentries;
|
||||||
|
if (cheats->hook->reentries > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GBAClearBreakpoint(device->p, cheats->hook->address, cheats->hook->mode, cheats->hook->patchedOpcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _patchROM(struct GBACheatDevice* device, struct GBACheatSet* cheats) {
|
||||||
|
if (!device->p) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < MAX_ROM_PATCHES; ++i) {
|
for (i = 0; i < MAX_ROM_PATCHES; ++i) {
|
||||||
if (!device->cheats->romPatches[i].exists || device->cheats->romPatches[i].applied) {
|
if (!cheats->romPatches[i].exists || cheats->romPatches[i].applied) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
GBAPatch16(device->p->cpu, device->cheats->romPatches[i].address, device->cheats->romPatches[i].newValue, &device->cheats->romPatches[i].oldValue);
|
GBAPatch16(device->p->cpu, cheats->romPatches[i].address, cheats->romPatches[i].newValue, &cheats->romPatches[i].oldValue);
|
||||||
device->cheats->romPatches[i].applied = true;
|
cheats->romPatches[i].applied = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _unpatchROM(struct GBACheatDevice* device) {
|
static void _unpatchROM(struct GBACheatDevice* device, struct GBACheatSet* cheats) {
|
||||||
if (!device->cheats || !device->p) {
|
if (!device->p) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < MAX_ROM_PATCHES; ++i) {
|
for (i = 0; i < MAX_ROM_PATCHES; ++i) {
|
||||||
if (!device->cheats->romPatches[i].exists || !device->cheats->romPatches[i].applied) {
|
if (!cheats->romPatches[i].exists || !cheats->romPatches[i].applied) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
GBAPatch16(device->p->cpu, device->cheats->romPatches[i].address, device->cheats->romPatches[i].oldValue, 0);
|
GBAPatch16(device->p->cpu, cheats->romPatches[i].address, cheats->romPatches[i].oldValue, 0);
|
||||||
device->cheats->romPatches[i].applied = false;
|
cheats->romPatches[i].applied = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,24 +378,47 @@ void GBACheatDeviceCreate(struct GBACheatDevice* device) {
|
||||||
device->d.id = GBA_CHEAT_DEVICE_ID;
|
device->d.id = GBA_CHEAT_DEVICE_ID;
|
||||||
device->d.init = GBACheatDeviceInit;
|
device->d.init = GBACheatDeviceInit;
|
||||||
device->d.deinit = GBACheatDeviceDeinit;
|
device->d.deinit = GBACheatDeviceDeinit;
|
||||||
|
GBACheatSetsInit(&device->cheats, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBACheatSetInit(struct GBACheatSet* set) {
|
void GBACheatDeviceDestroy(struct GBACheatDevice* device) {
|
||||||
set->hookAddress = 0;
|
size_t i;
|
||||||
set->hookMode = MODE_THUMB;
|
for (i = 0; i < GBACheatSetsSize(&device->cheats); ++i) {
|
||||||
|
struct GBACheatSet* set = *GBACheatSetsGetPointer(&device->cheats, i);
|
||||||
|
GBACheatSetDeinit(set);
|
||||||
|
free(set);
|
||||||
|
}
|
||||||
|
GBACheatSetsDeinit(&device->cheats);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GBACheatSetInit(struct GBACheatSet* set, const char* name) {
|
||||||
GBACheatListInit(&set->list, 4);
|
GBACheatListInit(&set->list, 4);
|
||||||
set->incompleteCheat = 0;
|
set->incompleteCheat = 0;
|
||||||
set->patchedOpcode = 0;
|
|
||||||
set->gsaVersion = 0;
|
set->gsaVersion = 0;
|
||||||
set->remainingAddresses = 0;
|
set->remainingAddresses = 0;
|
||||||
|
set->hook = 0;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < MAX_ROM_PATCHES; ++i) {
|
for (i = 0; i < MAX_ROM_PATCHES; ++i) {
|
||||||
set->romPatches[i].exists = false;
|
set->romPatches[i].exists = false;
|
||||||
}
|
}
|
||||||
|
if (name) {
|
||||||
|
set->name = strdup(name);
|
||||||
|
} else {
|
||||||
|
set->name = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBACheatSetDeinit(struct GBACheatSet* set) {
|
void GBACheatSetDeinit(struct GBACheatSet* set) {
|
||||||
GBACheatListDeinit(&set->list);
|
GBACheatListDeinit(&set->list);
|
||||||
|
if (set->name) {
|
||||||
|
free(set->name);
|
||||||
|
}
|
||||||
|
if (set->hook) {
|
||||||
|
--set->hook->refs;
|
||||||
|
if (set->hook->refs == 0) {
|
||||||
|
free(set->hook);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBACheatAttachDevice(struct GBA* gba, struct GBACheatDevice* device) {
|
void GBACheatAttachDevice(struct GBA* gba, struct GBACheatDevice* device) {
|
||||||
|
@ -391,12 +429,10 @@ void GBACheatAttachDevice(struct GBA* gba, struct GBACheatDevice* device) {
|
||||||
ARMHotplugAttach(gba->cpu, GBA_COMPONENT_CHEAT_DEVICE);
|
ARMHotplugAttach(gba->cpu, GBA_COMPONENT_CHEAT_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBACheatInstallSet(struct GBACheatDevice* device, struct GBACheatSet* cheats) {
|
void GBACheatAddSet(struct GBACheatDevice* device, struct GBACheatSet* cheats) {
|
||||||
_removeBreakpoint(device);
|
*GBACheatSetsAppend(&device->cheats) = cheats;
|
||||||
_unpatchROM(device);
|
_patchROM(device, cheats);
|
||||||
device->cheats = cheats;
|
_addBreakpoint(device, cheats);
|
||||||
_addBreakpoint(device);
|
|
||||||
_patchROM(device);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GBACheatAddCodeBreaker(struct GBACheatSet* cheats, uint32_t op1, uint16_t op2) {
|
bool GBACheatAddCodeBreaker(struct GBACheatSet* cheats, uint32_t op1, uint16_t op2) {
|
||||||
|
@ -416,11 +452,14 @@ bool GBACheatAddCodeBreaker(struct GBACheatSet* cheats, uint32_t op1, uint16_t o
|
||||||
// TODO: Run checksum
|
// TODO: Run checksum
|
||||||
return true;
|
return true;
|
||||||
case CB_HOOK:
|
case CB_HOOK:
|
||||||
if (cheats->hookAddress) {
|
if (cheats->hook) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cheats->hookAddress = BASE_CART0 | (op1 & (SIZE_CART0 - 1));
|
cheats->hook = malloc(sizeof(*cheats->hook));
|
||||||
cheats->hookMode = MODE_THUMB;
|
cheats->hook->address = BASE_CART0 | (op1 & (SIZE_CART0 - 1));
|
||||||
|
cheats->hook->mode = MODE_THUMB;
|
||||||
|
cheats->hook->refs = 1;
|
||||||
|
cheats->hook->reentries = 0;
|
||||||
return true;
|
return true;
|
||||||
case CB_OR_2:
|
case CB_OR_2:
|
||||||
cheat = GBACheatListAppend(&cheats->list);
|
cheat = GBACheatListAppend(&cheats->list);
|
||||||
|
@ -571,6 +610,51 @@ bool GBACheatAddGameSharkLine(struct GBACheatSet* cheats, const char* line) {
|
||||||
return GBACheatAddGameShark(cheats, op1, op2);
|
return GBACheatAddGameShark(cheats, op1, op2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GBACheatParseFile(struct GBACheatDevice* device, struct VFile* vf) {
|
||||||
|
char cheat[MAX_LINE_LENGTH];
|
||||||
|
struct GBACheatSet* set = 0;
|
||||||
|
struct GBACheatSet* newSet;
|
||||||
|
while (true) {
|
||||||
|
size_t i;
|
||||||
|
ssize_t bytesRead = vf->readline(vf, cheat, sizeof(cheat));
|
||||||
|
if (bytesRead == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (bytesRead < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (cheat[0]) {
|
||||||
|
case '#':
|
||||||
|
i = 1;
|
||||||
|
while (isspace(cheat[i])) {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
newSet = malloc(sizeof(*set));
|
||||||
|
GBACheatSetInit(newSet, &cheat[i]);
|
||||||
|
if (set) {
|
||||||
|
GBACheatAddSet(device, set);
|
||||||
|
newSet->gsaVersion = set->gsaVersion;
|
||||||
|
memcpy(newSet->gsaSeeds, set->gsaSeeds, sizeof(newSet->gsaSeeds));
|
||||||
|
newSet->hook = set->hook;
|
||||||
|
++newSet->hook->refs;
|
||||||
|
}
|
||||||
|
set = newSet;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!set) {
|
||||||
|
set = malloc(sizeof(*set));
|
||||||
|
GBACheatSetInit(set, 0);
|
||||||
|
}
|
||||||
|
GBACheatAddLine(set, cheat);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (set) {
|
||||||
|
GBACheatAddSet(device, set);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool GBACheatAddLine(struct GBACheatSet* cheats, const char* line) {
|
bool GBACheatAddLine(struct GBACheatSet* cheats, const char* line) {
|
||||||
uint32_t op1;
|
uint32_t op1;
|
||||||
uint16_t op2;
|
uint16_t op2;
|
||||||
|
@ -599,12 +683,12 @@ bool GBACheatAddLine(struct GBACheatSet* cheats, const char* line) {
|
||||||
return GBACheatAddGameShark(cheats, op1, realOp2);
|
return GBACheatAddGameShark(cheats, op1, realOp2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBACheatRefresh(struct GBACheatDevice* device) {
|
void GBACheatRefresh(struct GBACheatDevice* device, struct GBACheatSet* cheats) {
|
||||||
bool condition = true;
|
bool condition = true;
|
||||||
int conditionRemaining = 0;
|
int conditionRemaining = 0;
|
||||||
_patchROM(device);
|
_patchROM(device, cheats);
|
||||||
|
|
||||||
size_t nCodes = GBACheatListSize(&device->cheats->list);
|
size_t nCodes = GBACheatListSize(&cheats->list);
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < nCodes; ++i) {
|
for (i = 0; i < nCodes; ++i) {
|
||||||
if (conditionRemaining > 0) {
|
if (conditionRemaining > 0) {
|
||||||
|
@ -615,7 +699,7 @@ void GBACheatRefresh(struct GBACheatDevice* device) {
|
||||||
} else {
|
} else {
|
||||||
condition = true;
|
condition = true;
|
||||||
}
|
}
|
||||||
struct GBACheat* cheat = GBACheatListGetPointer(&device->cheats->list, i);
|
struct GBACheat* cheat = GBACheatListGetPointer(&cheats->list, i);
|
||||||
int32_t value = 0;
|
int32_t value = 0;
|
||||||
int32_t operand = cheat->operand;
|
int32_t operand = cheat->operand;
|
||||||
uint32_t operationsRemaining = cheat->repeat;
|
uint32_t operationsRemaining = cheat->repeat;
|
||||||
|
@ -686,10 +770,20 @@ void GBACheatRefresh(struct GBACheatDevice* device) {
|
||||||
void GBACheatDeviceInit(struct ARMCore* cpu, struct ARMComponent* component) {
|
void GBACheatDeviceInit(struct ARMCore* cpu, struct ARMComponent* component) {
|
||||||
struct GBACheatDevice* device = (struct GBACheatDevice*) component;
|
struct GBACheatDevice* device = (struct GBACheatDevice*) component;
|
||||||
device->p = (struct GBA*) cpu->master;
|
device->p = (struct GBA*) cpu->master;
|
||||||
_addBreakpoint(device);
|
size_t i;
|
||||||
|
for (i = 0; i < GBACheatSetsSize(&device->cheats); ++i) {
|
||||||
|
struct GBACheatSet* cheats = *GBACheatSetsGetPointer(&device->cheats, i);
|
||||||
|
_addBreakpoint(device, cheats);
|
||||||
|
_patchROM(device, cheats);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBACheatDeviceDeinit(struct ARMComponent* component) {
|
void GBACheatDeviceDeinit(struct ARMComponent* component) {
|
||||||
struct GBACheatDevice* device = (struct GBACheatDevice*) component;
|
struct GBACheatDevice* device = (struct GBACheatDevice*) component;
|
||||||
_removeBreakpoint(device);
|
size_t i;
|
||||||
|
for (i = GBACheatSetsSize(&device->cheats); i--;) {
|
||||||
|
struct GBACheatSet* cheats = *GBACheatSetsGetPointer(&device->cheats, i);
|
||||||
|
_unpatchROM(device, cheats);
|
||||||
|
_removeBreakpoint(device, cheats);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,15 +133,21 @@ struct GBACheat {
|
||||||
int32_t operandOffset;
|
int32_t operandOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GBACheatHook {
|
||||||
|
uint32_t address;
|
||||||
|
enum ExecutionMode mode;
|
||||||
|
uint32_t patchedOpcode;
|
||||||
|
size_t refs;
|
||||||
|
size_t reentries;
|
||||||
|
};
|
||||||
|
|
||||||
DECLARE_VECTOR(GBACheatList, struct GBACheat);
|
DECLARE_VECTOR(GBACheatList, struct GBACheat);
|
||||||
|
|
||||||
struct GBACheatSet {
|
struct GBACheatSet {
|
||||||
uint32_t hookAddress;
|
struct GBACheatHook* hook;
|
||||||
enum ExecutionMode hookMode;
|
|
||||||
struct GBACheatList list;
|
struct GBACheatList list;
|
||||||
|
|
||||||
struct GBACheat* incompleteCheat;
|
struct GBACheat* incompleteCheat;
|
||||||
uint32_t patchedOpcode;
|
|
||||||
|
|
||||||
struct GBACheatPatch {
|
struct GBACheatPatch {
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
|
@ -154,22 +160,31 @@ struct GBACheatSet {
|
||||||
int gsaVersion;
|
int gsaVersion;
|
||||||
uint32_t gsaSeeds[4];
|
uint32_t gsaSeeds[4];
|
||||||
int remainingAddresses;
|
int remainingAddresses;
|
||||||
|
|
||||||
|
char* name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DECLARE_VECTOR(GBACheatSets, struct GBACheatSet*);
|
||||||
|
|
||||||
struct GBACheatDevice {
|
struct GBACheatDevice {
|
||||||
struct ARMComponent d;
|
struct ARMComponent d;
|
||||||
struct GBA* p;
|
struct GBA* p;
|
||||||
|
|
||||||
struct GBACheatSet* cheats;
|
struct GBACheatSets cheats;
|
||||||
};
|
};
|
||||||
|
|
||||||
void GBACheatDeviceCreate(struct GBACheatDevice*);
|
struct VFile;
|
||||||
|
|
||||||
void GBACheatSetInit(struct GBACheatSet*);
|
void GBACheatDeviceCreate(struct GBACheatDevice*);
|
||||||
|
void GBACheatDeviceDestroy(struct GBACheatDevice*);
|
||||||
|
|
||||||
|
void GBACheatSetInit(struct GBACheatSet*, const char* name);
|
||||||
void GBACheatSetDeinit(struct GBACheatSet*);
|
void GBACheatSetDeinit(struct GBACheatSet*);
|
||||||
|
|
||||||
void GBACheatAttachDevice(struct GBA* gba, struct GBACheatDevice*);
|
void GBACheatAttachDevice(struct GBA* gba, struct GBACheatDevice*);
|
||||||
void GBACheatInstallSet(struct GBACheatDevice*, struct GBACheatSet*);
|
|
||||||
|
void GBACheatAddSet(struct GBACheatDevice*, struct GBACheatSet*);
|
||||||
|
void GBACheatRemoveSet(struct GBACheatDevice*, struct GBACheatSet*);
|
||||||
|
|
||||||
bool GBACheatAddCodeBreaker(struct GBACheatSet*, uint32_t op1, uint16_t op2);
|
bool GBACheatAddCodeBreaker(struct GBACheatSet*, uint32_t op1, uint16_t op2);
|
||||||
bool GBACheatAddCodeBreakerLine(struct GBACheatSet*, const char* line);
|
bool GBACheatAddCodeBreakerLine(struct GBACheatSet*, const char* line);
|
||||||
|
@ -177,8 +192,9 @@ bool GBACheatAddCodeBreakerLine(struct GBACheatSet*, const char* line);
|
||||||
bool GBACheatAddGameShark(struct GBACheatSet*, uint32_t op1, uint32_t op2);
|
bool GBACheatAddGameShark(struct GBACheatSet*, uint32_t op1, uint32_t op2);
|
||||||
bool GBACheatAddGameSharkLine(struct GBACheatSet*, const char* line);
|
bool GBACheatAddGameSharkLine(struct GBACheatSet*, const char* line);
|
||||||
|
|
||||||
|
bool GBACheatParseFile(struct GBACheatDevice*, struct VFile*);
|
||||||
bool GBACheatAddLine(struct GBACheatSet*, const char* line);
|
bool GBACheatAddLine(struct GBACheatSet*, const char* line);
|
||||||
|
|
||||||
void GBACheatRefresh(struct GBACheatDevice*);
|
void GBACheatRefresh(struct GBACheatDevice*, struct GBACheatSet*);
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -674,9 +674,17 @@ void GBABreakpoint(struct ARMCore* cpu, int immediate) {
|
||||||
case GBA_COMPONENT_CHEAT_DEVICE:
|
case GBA_COMPONENT_CHEAT_DEVICE:
|
||||||
if (gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]) {
|
if (gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]) {
|
||||||
struct GBACheatDevice* device = (struct GBACheatDevice*) gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE];
|
struct GBACheatDevice* device = (struct GBACheatDevice*) gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE];
|
||||||
if (device->cheats) {
|
struct GBACheatHook* hook = 0;
|
||||||
GBACheatRefresh(device);
|
size_t i;
|
||||||
ARMRunFake(cpu, device->cheats->patchedOpcode);
|
for (i = 0; i < GBACheatSetsSize(&device->cheats); ++i) {
|
||||||
|
struct GBACheatSet* cheats = *GBACheatSetsGetPointer(&device->cheats, i);
|
||||||
|
if (cheats->hook && cheats->hook->address == _ARMPCAddress(cpu)) {
|
||||||
|
GBACheatRefresh(device, cheats);
|
||||||
|
hook = cheats->hook;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hook) {
|
||||||
|
ARMRunFake(cpu, hook->patchedOpcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -106,7 +106,6 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
|
||||||
struct ARMCore cpu;
|
struct ARMCore cpu;
|
||||||
struct Patch patch;
|
struct Patch patch;
|
||||||
struct GBACheatDevice cheatDevice;
|
struct GBACheatDevice cheatDevice;
|
||||||
struct GBACheatSet cheats;
|
|
||||||
struct GBAThread* threadContext = context;
|
struct GBAThread* threadContext = context;
|
||||||
struct ARMComponent* components[GBA_COMPONENT_MAX] = {};
|
struct ARMComponent* components[GBA_COMPONENT_MAX] = {};
|
||||||
int numComponents = GBA_COMPONENT_MAX;
|
int numComponents = GBA_COMPONENT_MAX;
|
||||||
|
@ -167,23 +166,14 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
|
||||||
GBASkipBIOS(&cpu);
|
GBASkipBIOS(&cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
GBACheatDeviceCreate(&cheatDevice);
|
|
||||||
GBACheatSetInit(&cheats);
|
|
||||||
if (!threadContext->cheats) {
|
if (!threadContext->cheats) {
|
||||||
threadContext->cheats = &cheats;
|
GBACheatDeviceCreate(&cheatDevice);
|
||||||
|
threadContext->cheats = &cheatDevice;
|
||||||
}
|
}
|
||||||
if (threadContext->cheatsFile) {
|
if (threadContext->cheatsFile) {
|
||||||
char cheat[32];
|
GBACheatParseFile(threadContext->cheats, threadContext->cheatsFile);
|
||||||
while (true) {
|
|
||||||
size_t bytesRead = threadContext->cheatsFile->readline(threadContext->cheatsFile, cheat, sizeof(cheat));
|
|
||||||
if (!bytesRead) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
GBACheatAddLine(threadContext->cheats, cheat);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
GBACheatInstallSet(&cheatDevice, threadContext->cheats);
|
GBACheatAttachDevice(&gba, threadContext->cheats);
|
||||||
GBACheatAttachDevice(&gba, &cheatDevice);
|
|
||||||
|
|
||||||
if (threadContext->debugger) {
|
if (threadContext->debugger) {
|
||||||
threadContext->debugger->log = GBADebuggerLogShim;
|
threadContext->debugger->log = GBADebuggerLogShim;
|
||||||
|
@ -253,7 +243,9 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
|
||||||
threadContext->gba = 0;
|
threadContext->gba = 0;
|
||||||
ARMDeinit(&cpu);
|
ARMDeinit(&cpu);
|
||||||
GBADestroy(&gba);
|
GBADestroy(&gba);
|
||||||
GBACheatSetDeinit(&cheats);
|
if (&cheatDevice == threadContext->cheats) {
|
||||||
|
GBACheatDeviceDestroy(&cheatDevice);
|
||||||
|
}
|
||||||
|
|
||||||
threadContext->sync.videoFrameOn = false;
|
threadContext->sync.videoFrameOn = false;
|
||||||
ConditionWake(&threadContext->sync.videoFrameAvailableCond);
|
ConditionWake(&threadContext->sync.videoFrameAvailableCond);
|
||||||
|
|
|
@ -110,7 +110,7 @@ struct GBAThread {
|
||||||
struct GBASerializedState** rewindBuffer;
|
struct GBASerializedState** rewindBuffer;
|
||||||
int rewindBufferWriteOffset;
|
int rewindBufferWriteOffset;
|
||||||
|
|
||||||
struct GBACheatSet* cheats;
|
struct GBACheatDevice* cheats;
|
||||||
};
|
};
|
||||||
|
|
||||||
void GBAMapOptionsToContext(const struct GBAOptions*, struct GBAThread*);
|
void GBAMapOptionsToContext(const struct GBAOptions*, struct GBAThread*);
|
||||||
|
|
Loading…
Reference in New Issue