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; switch (cheats->gsaVersion) { case 1: directive = StringListAppend(directives); *directive = strdup("GSAv1"); break; case 2: directive = StringListAppend(directives); *directive = strdup("GSAv1 raw"); break; case 3: directive = StringListAppend(directives); *directive = strdup("PARv3"); break; case 4: directive = StringListAppend(directives); *directive = strdup("PARv3 raw"); break; } }
bool mCheatSaveFile(struct mCheatDevice* device, struct VFile* vf) { static const char lineStart[3] = "# "; static const char lineEnd = '\n'; struct StringList directives; StringListInit(&directives, 4); size_t i; for (i = 0; i < mCheatSetsSize(&device->cheats); ++i) { struct mCheatSet* set = *mCheatSetsGetPointer(&device->cheats, i); 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) { vf->write(vf, set->name, strlen(set->name)); } vf->write(vf, &lineEnd, 1); size_t c; for (c = 0; c < StringListSize(&set->lines); ++c) { const char* line = *StringListGetPointer(&set->lines, c); 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; }
bool mCheatParseFile(struct mCheatDevice* device, struct VFile* vf) { char cheat[MAX_LINE_LENGTH]; struct mCheatSet* set = NULL; struct mCheatSet* newSet; bool nextDisabled = false; 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])) { ++i; } switch (cheat[i]) { case '#': do { ++i; } while (isspace((int) cheat[i])); newSet = device->createSet(device, &cheat[i]); newSet->enabled = !nextDisabled; nextDisabled = false; if (set) { mCheatAddSet(device, set); } if (set) { newSet->copyProperties(newSet, set); } newSet->parseDirectives(newSet, &directives); set = newSet; break; case '!': do { ++i; } while (isspace((int) cheat[i])); if (strcasecmp(&cheat[i], "disabled") == 0) { nextDisabled = true; break; } if (strcasecmp(&cheat[i], "reset") == 0) { size_t d; for (d = 0; d < StringListSize(&directives); ++d) { free(*StringListGetPointer(&directives, d)); } StringListClear(&directives); break; } *StringListAppend(&directives) = strdup(&cheat[i]); break; default: if (!set) { set = device->createSet(device, NULL); set->enabled = !nextDisabled; nextDisabled = false; } 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; }