all repos — mgba @ affe5e31a786e39122d932cc9f38e0e3cb643749

mGBA Game Boy Advance Emulator

All: Restore cheat loading/saving
Jeffrey Pfau jeffrey@endrift.com
Fri, 19 Aug 2016 05:13:37 -0700
commit

affe5e31a786e39122d932cc9f38e0e3cb643749

parent

0367d94aad98534aa4d997c7cb9fb85b44063c74

4 files changed, 98 insertions(+), 15 deletions(-)

jump to
M src/core/cheats.csrc/core/cheats.c

@@ -131,21 +131,22 @@ cheats->remove(cheats, device);

} 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 @@ case '#':

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 @@ }

if (set) { newSet->copyProperties(newSet, set); } + newSet->parseDirectives(newSet, &directives); set = newSet; break; case '!':

@@ -177,10 +178,14 @@ nextDisabled = true;

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 @@ set = device->createSet(device, NULL);

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 @@ vf->write(vf, line, strlen(line));

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) {
M src/core/cheats.hsrc/core/cheats.h

@@ -58,6 +58,9 @@

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;
M src/gb/cheats.csrc/gb/cheats.c

@@ -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) {

@@ -62,6 +64,9 @@ set->d.remove = GBCheatRemoveSet;

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* oldSet) {

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); +}
M src/gba/cheats.csrc/gba/cheats.c

@@ -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) {

@@ -88,6 +90,9 @@ set->d.remove = GBACheatRemoveSet;

set->d.addLine = GBACheatAddLine; set->d.copyProperties = GBACheatSetCopyProperties; + + set->d.parseDirectives = GBACheatParseDirectives; + set->d.dumpDirectives = GBACheatDumpDirectives; set->d.refresh = GBACheatRefresh;

@@ -268,3 +273,42 @@ newSet->hook = gbaset->hook;

++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; + } +}