GBA: Cheat saving
Jeffrey Pfau jeffrey@endrift.com
Sun, 15 Feb 2015 04:52:21 -0800
7 files changed,
78 insertions(+),
3 deletions(-)
M
src/gba/cheats.c
→
src/gba/cheats.c
@@ -695,6 +695,7 @@ struct GBACheatSet* set = 0;
struct GBACheatSet* newSet; int gsaVersion = 0; bool nextDisabled = false; + bool reset = false; while (true) { size_t i = 0; ssize_t bytesRead = vf->readline(vf, cheat, sizeof(cheat));@@ -718,6 +719,8 @@ newSet->enabled = !nextDisabled;
nextDisabled = false; if (set) { GBACheatAddSet(device, set); + } + if (set && !reset) { newSet->gsaVersion = set->gsaVersion; memcpy(newSet->gsaSeeds, set->gsaSeeds, sizeof(newSet->gsaSeeds)); if (set->hook) {@@ -727,6 +730,7 @@ }
} else { _setGameSharkVersion(newSet, gsaVersion); } + reset = false; set = newSet; break; case '!':@@ -742,6 +746,10 @@ if (strcasecmp(&cheat[i], "disabled") == 0) {
nextDisabled = true; break; } + if (strcasecmp(&cheat[i], "reset") == 0) { + reset = true; + break; + } break; default: if (!set) {@@ -757,6 +765,54 @@ }
} if (set) { GBACheatAddSet(device, set); + } + return true; +} + +bool GBACheatSaveFile(struct GBACheatDevice* device, struct VFile* vf) { + static const char lineStart[3] = "# "; + static const char lineEnd = '\n'; + + struct GBACheatHook* lastHook = 0; + + size_t i; + for (i = 0; i < GBACheatSetsSize(&device->cheats); ++i) { + struct GBACheatSet* set = *GBACheatSetsGetPointer(&device->cheats, i); + if (lastHook && set->hook != lastHook) { + static const char* resetDirective = "!reset\n"; + vf->write(vf, resetDirective, strlen(resetDirective)); + } + switch (set->gsaVersion) { + case 1: { + static const char* versionDirective = "!GSAv1\n"; + vf->write(vf, versionDirective, strlen(versionDirective)); + break; + } + case 3: { + static const char* versionDirective = "!PARv3\n"; + vf->write(vf, versionDirective, strlen(versionDirective)); + break; + } + default: + break; + } + lastHook = set->hook; + if (!set->enabled) { + static const char* disabledDirective = "!disabled\n"; + vf->write(vf, disabledDirective, strlen(disabledDirective)); + } + + 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); + } } return true; }
M
src/gba/cheats.h
→
src/gba/cheats.h
@@ -199,6 +199,8 @@ bool GBACheatAddAutodetect(struct GBACheatSet*, uint32_t op1, uint32_t op2);
bool GBACheatAddAutodetectLine(struct GBACheatSet*, const char* line); bool GBACheatParseFile(struct GBACheatDevice*, struct VFile*); +bool GBACheatSaveFile(struct GBACheatDevice*, struct VFile*); + bool GBACheatAddLine(struct GBACheatSet*, const char* line); void GBACheatRefresh(struct GBACheatDevice*, struct GBACheatSet*);
M
src/platform/qt/CheatsModel.cpp
→
src/platform/qt/CheatsModel.cpp
@@ -176,6 +176,15 @@ endResetModel();
vf->close(vf); } +void CheatsModel::saveFile(const QString& path) { + VFile* vf = VFileOpen(path.toLocal8Bit().constData(), O_TRUNC | O_CREAT | O_WRONLY); + if (!vf) { + return; + } + GBACheatSaveFile(m_device, vf); + vf->close(vf); +} + void CheatsModel::addSet(GBACheatSet* set) { beginInsertRows(QModelIndex(), GBACheatSetsSize(&m_device->cheats), GBACheatSetsSize(&m_device->cheats)); GBACheatAddSet(m_device, set);
M
src/platform/qt/CheatsModel.h
→
src/platform/qt/CheatsModel.h
@@ -36,6 +36,8 @@ void beginAppendRow(const QModelIndex& index);
void endAppendRow(); void loadFile(const QString& path); + void saveFile(const QString& path); + void addSet(GBACheatSet* set); public slots:
M
src/platform/qt/CheatsView.cpp
→
src/platform/qt/CheatsView.cpp
@@ -25,6 +25,7 @@
m_ui.cheatList->setModel(&m_model); connect(m_ui.load, SIGNAL(clicked()), this, SLOT(load())); + connect(m_ui.save, SIGNAL(clicked()), this, SLOT(save())); connect(m_ui.addSet, SIGNAL(clicked()), this, SLOT(addSet())); connect(m_ui.remove, SIGNAL(clicked()), this, SLOT(removeSet())); connect(controller, SIGNAL(gameStopped(GBAThread*)), &m_model, SLOT(invalidated()));@@ -46,6 +47,13 @@ void CheatsView::load() {
QString filename = QFileDialog::getOpenFileName(this, tr("Select cheats file")); if (!filename.isEmpty()) { m_model.loadFile(filename); + } +} + +void CheatsView::save() { + QString filename = QFileDialog::getSaveFileName(this, tr("Select cheats file")); + if (!filename.isEmpty()) { + m_model.saveFile(filename); } }
M
src/platform/qt/CheatsView.h
→
src/platform/qt/CheatsView.h
@@ -28,6 +28,7 @@ CheatsView(GameController* controller, QWidget* parent = nullptr);
private slots: void load(); + void save(); void addSet(); void removeSet();
M
src/platform/qt/CheatsView.ui
→
src/platform/qt/CheatsView.ui
@@ -68,9 +68,6 @@ </widget>
</item> <item row="1" column="2"> <widget class="QPushButton" name="save"> - <property name="enabled"> - <bool>false</bool> - </property> <property name="text"> <string>Save</string> </property>