mirror of https://github.com/mgba-emu/mgba.git
All: Restore cheat loading/saving
This commit is contained in:
parent
0367d94aad
commit
affe5e31a7
|
@ -131,21 +131,22 @@ void mCheatRemoveSet(struct mCheatDevice* device, struct mCheatSet* cheats) {
|
|||
}
|
||||
|
||||
bool mCheatParseFile(struct mCheatDevice* device, struct VFile* vf) {
|
||||
#warning Cheat loading is currently broken
|
||||
return false;
|
||||
#if 0
|
||||
char cheat[MAX_LINE_LENGTH];
|
||||
struct mCheatSet* set = NULL;
|
||||
struct mCheatSet* newSet;
|
||||
bool nextDisabled = false;
|
||||
void* directives = NULL;
|
||||
struct StringList directives;
|
||||
StringListInit(&directives, 4);
|
||||
|
||||
while (true) {
|
||||
size_t i = 0;
|
||||
ssize_t bytesRead = vf->readline(vf, cheat, sizeof(cheat));
|
||||
rtrim(cheat);
|
||||
if (bytesRead == 0) {
|
||||
break;
|
||||
}
|
||||
if (bytesRead < 0) {
|
||||
StringListDeinit(&directives);
|
||||
return false;
|
||||
}
|
||||
while (isspace((int) cheat[i])) {
|
||||
|
@ -156,7 +157,6 @@ bool mCheatParseFile(struct mCheatDevice* device, struct VFile* vf) {
|
|||
do {
|
||||
++i;
|
||||
} while (isspace((int) cheat[i]));
|
||||
cheat[strlen(cheat) - 1] = '\0'; // Remove trailing newline
|
||||
newSet = device->createSet(device, &cheat[i]);
|
||||
newSet->enabled = !nextDisabled;
|
||||
nextDisabled = false;
|
||||
|
@ -166,6 +166,7 @@ bool mCheatParseFile(struct mCheatDevice* device, struct VFile* vf) {
|
|||
if (set) {
|
||||
newSet->copyProperties(newSet, set);
|
||||
}
|
||||
newSet->parseDirectives(newSet, &directives);
|
||||
set = newSet;
|
||||
break;
|
||||
case '!':
|
||||
|
@ -177,10 +178,14 @@ bool mCheatParseFile(struct mCheatDevice* device, struct VFile* vf) {
|
|||
break;
|
||||
}
|
||||
if (strcasecmp(&cheat[i], "reset") == 0) {
|
||||
directives = NULL;
|
||||
size_t d;
|
||||
for (d = 0; d < StringListSize(&directives); ++d) {
|
||||
free(*StringListGetPointer(&directives, d));
|
||||
}
|
||||
StringListClear(&directives);
|
||||
break;
|
||||
}
|
||||
directives = set->parseDirective(set, &cheat[i], directives);
|
||||
*StringListAppend(&directives) = strdup(&cheat[i]);
|
||||
break;
|
||||
default:
|
||||
if (!set) {
|
||||
|
@ -188,33 +193,44 @@ bool mCheatParseFile(struct mCheatDevice* device, struct VFile* vf) {
|
|||
set->enabled = !nextDisabled;
|
||||
nextDisabled = false;
|
||||
}
|
||||
mCheatAddLine(set, cheat);
|
||||
mCheatAddLine(set, cheat, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (set) {
|
||||
mCheatAddSet(device, set);
|
||||
}
|
||||
size_t d;
|
||||
for (d = 0; d < StringListSize(&directives); ++d) {
|
||||
free(*StringListGetPointer(&directives, d));
|
||||
}
|
||||
StringListClear(&directives);
|
||||
StringListDeinit(&directives);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool mCheatSaveFile(struct mCheatDevice* device, struct VFile* vf) {
|
||||
#warning Cheat saving is currently broken
|
||||
return false;
|
||||
#if 0
|
||||
static const char lineStart[3] = "# ";
|
||||
static const char lineEnd = '\n';
|
||||
void* directives = NULL;
|
||||
struct StringList directives;
|
||||
StringListInit(&directives, 4);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < mCheatSetsSize(&device->cheats); ++i) {
|
||||
struct mCheatSet* set = *mCheatSetsGetPointer(&device->cheats, i);
|
||||
void* directives = set->dumpDirectives(set, vf, directives);
|
||||
set->dumpDirectives(set, &directives);
|
||||
if (!set->enabled) {
|
||||
static const char* disabledDirective = "!disabled\n";
|
||||
vf->write(vf, disabledDirective, strlen(disabledDirective));
|
||||
}
|
||||
size_t d;
|
||||
for (d = 0; d < StringListSize(&directives); ++d) {
|
||||
char directive[64];
|
||||
ssize_t len = snprintf(directive, sizeof(directive) - 1, "!%s\n", *StringListGetPointer(&directives, d));
|
||||
if (len > 1) {
|
||||
vf->write(vf, directive, (size_t) len > sizeof(directive) ? sizeof(directive) : len);
|
||||
}
|
||||
}
|
||||
|
||||
vf->write(vf, lineStart, 2);
|
||||
if (set->name) {
|
||||
|
@ -228,8 +244,13 @@ bool mCheatSaveFile(struct mCheatDevice* device, struct VFile* vf) {
|
|||
vf->write(vf, &lineEnd, 1);
|
||||
}
|
||||
}
|
||||
size_t d;
|
||||
for (d = 0; d < StringListSize(&directives); ++d) {
|
||||
free(*StringListGetPointer(&directives, d));
|
||||
}
|
||||
StringListClear(&directives);
|
||||
StringListDeinit(&directives);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void mCheatRefresh(struct mCheatDevice* device, struct mCheatSet* cheats) {
|
||||
|
|
|
@ -58,6 +58,9 @@ struct mCheatSet {
|
|||
bool (*addLine)(struct mCheatSet* set, const char* cheat, int type);
|
||||
void (*copyProperties)(struct mCheatSet* set, struct mCheatSet* oldSet);
|
||||
|
||||
void (*parseDirectives)(struct mCheatSet* set, const struct StringList* directives);
|
||||
void (*dumpDirectives)(struct mCheatSet* set, struct StringList* directives);
|
||||
|
||||
void (*refresh)(struct mCheatSet* set, struct mCheatDevice* device);
|
||||
|
||||
char* name;
|
||||
|
|
|
@ -47,6 +47,8 @@ static void GBCheatAddSet(struct mCheatSet* cheats, struct mCheatDevice* device)
|
|||
static void GBCheatRemoveSet(struct mCheatSet* cheats, struct mCheatDevice* device);
|
||||
static void GBCheatRefresh(struct mCheatSet* cheats, struct mCheatDevice* device);
|
||||
static void GBCheatSetCopyProperties(struct mCheatSet* set, struct mCheatSet* oldSet);
|
||||
static void GBCheatParseDirectives(struct mCheatSet* set, const struct StringList* directives);
|
||||
static void GBCheatDumpDirectives(struct mCheatSet* set, struct StringList* directives);
|
||||
static bool GBCheatAddLine(struct mCheatSet*, const char* line, int type);
|
||||
|
||||
static struct mCheatSet* GBCheatSetCreate(struct mCheatDevice* device, const char* name) {
|
||||
|
@ -63,6 +65,9 @@ static struct mCheatSet* GBCheatSetCreate(struct mCheatDevice* device, const cha
|
|||
set->d.addLine = GBCheatAddLine;
|
||||
set->d.copyProperties = GBCheatSetCopyProperties;
|
||||
|
||||
set->d.parseDirectives = GBCheatParseDirectives;
|
||||
set->d.dumpDirectives = GBCheatDumpDirectives;
|
||||
|
||||
set->d.refresh = GBCheatRefresh;
|
||||
return &set->d;
|
||||
}
|
||||
|
@ -212,3 +217,13 @@ static void GBCheatSetCopyProperties(struct mCheatSet* set, struct mCheatSet* ol
|
|||
UNUSED(set);
|
||||
UNUSED(oldSet);
|
||||
}
|
||||
|
||||
static void GBCheatParseDirectives(struct mCheatSet* set, const struct StringList* directives) {
|
||||
UNUSED(set);
|
||||
UNUSED(directives);
|
||||
}
|
||||
|
||||
static void GBCheatDumpDirectives(struct mCheatSet* set, struct StringList* directives) {
|
||||
UNUSED(set);
|
||||
UNUSED(directives);
|
||||
}
|
||||
|
|
|
@ -67,6 +67,8 @@ static void GBACheatAddSet(struct mCheatSet* cheats, struct mCheatDevice* device
|
|||
static void GBACheatRemoveSet(struct mCheatSet* cheats, struct mCheatDevice* device);
|
||||
static void GBACheatRefresh(struct mCheatSet* cheats, struct mCheatDevice* device);
|
||||
static void GBACheatSetCopyProperties(struct mCheatSet* set, struct mCheatSet* oldSet);
|
||||
static void GBACheatParseDirectives(struct mCheatSet*, const struct StringList* directives);
|
||||
static void GBACheatDumpDirectives(struct mCheatSet*, struct StringList* directives);
|
||||
static bool GBACheatAddLine(struct mCheatSet*, const char* line, int type);
|
||||
|
||||
static struct mCheatSet* GBACheatSetCreate(struct mCheatDevice* device, const char* name) {
|
||||
|
@ -89,6 +91,9 @@ static struct mCheatSet* GBACheatSetCreate(struct mCheatDevice* device, const ch
|
|||
set->d.addLine = GBACheatAddLine;
|
||||
set->d.copyProperties = GBACheatSetCopyProperties;
|
||||
|
||||
set->d.parseDirectives = GBACheatParseDirectives;
|
||||
set->d.dumpDirectives = GBACheatDumpDirectives;
|
||||
|
||||
set->d.refresh = GBACheatRefresh;
|
||||
|
||||
int i;
|
||||
|
@ -268,3 +273,42 @@ static void GBACheatSetCopyProperties(struct mCheatSet* set, struct mCheatSet* o
|
|||
++newSet->hook->refs;
|
||||
}
|
||||
}
|
||||
|
||||
static void GBACheatParseDirectives(struct mCheatSet* set, const struct StringList* directives) {
|
||||
struct GBACheatSet* cheats = (struct GBACheatSet*) set;
|
||||
size_t d;
|
||||
for (d = 0; d < StringListSize(directives); ++d) {
|
||||
const char* directive = *StringListGetConstPointer(directives, d);
|
||||
if (strcmp(directive, "GSAv1") == 0) {
|
||||
GBACheatSetGameSharkVersion(cheats, 1);
|
||||
continue;
|
||||
}
|
||||
if (strcmp(directive, "PARv3") == 0) {
|
||||
GBACheatSetGameSharkVersion(cheats, 3);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GBACheatDumpDirectives(struct mCheatSet* set, struct StringList* directives) {
|
||||
struct GBACheatSet* cheats = (struct GBACheatSet*) set;
|
||||
|
||||
// TODO: Check previous directives
|
||||
size_t d;
|
||||
for (d = 0; d < StringListSize(directives); ++d) {
|
||||
free(*StringListGetPointer(directives, d));
|
||||
}
|
||||
StringListClear(directives);
|
||||
|
||||
char** directive = StringListAppend(directives);
|
||||
switch (cheats->gsaVersion) {
|
||||
case 1:
|
||||
case 2:
|
||||
*directive = strdup("GSAv1");
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
*directive = strdup("PARv3");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue