mirror of https://github.com/mgba-emu/mgba.git
GBA: Cheat saving
This commit is contained in:
parent
bc8175515b
commit
cc214e0f44
|
@ -695,6 +695,7 @@ bool GBACheatParseFile(struct GBACheatDevice* device, struct VFile* vf) {
|
||||||
struct GBACheatSet* newSet;
|
struct GBACheatSet* newSet;
|
||||||
int gsaVersion = 0;
|
int gsaVersion = 0;
|
||||||
bool nextDisabled = false;
|
bool nextDisabled = false;
|
||||||
|
bool reset = false;
|
||||||
while (true) {
|
while (true) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
ssize_t bytesRead = vf->readline(vf, cheat, sizeof(cheat));
|
ssize_t bytesRead = vf->readline(vf, cheat, sizeof(cheat));
|
||||||
|
@ -718,6 +719,8 @@ bool GBACheatParseFile(struct GBACheatDevice* device, struct VFile* vf) {
|
||||||
nextDisabled = false;
|
nextDisabled = false;
|
||||||
if (set) {
|
if (set) {
|
||||||
GBACheatAddSet(device, set);
|
GBACheatAddSet(device, set);
|
||||||
|
}
|
||||||
|
if (set && !reset) {
|
||||||
newSet->gsaVersion = set->gsaVersion;
|
newSet->gsaVersion = set->gsaVersion;
|
||||||
memcpy(newSet->gsaSeeds, set->gsaSeeds, sizeof(newSet->gsaSeeds));
|
memcpy(newSet->gsaSeeds, set->gsaSeeds, sizeof(newSet->gsaSeeds));
|
||||||
if (set->hook) {
|
if (set->hook) {
|
||||||
|
@ -727,6 +730,7 @@ bool GBACheatParseFile(struct GBACheatDevice* device, struct VFile* vf) {
|
||||||
} else {
|
} else {
|
||||||
_setGameSharkVersion(newSet, gsaVersion);
|
_setGameSharkVersion(newSet, gsaVersion);
|
||||||
}
|
}
|
||||||
|
reset = false;
|
||||||
set = newSet;
|
set = newSet;
|
||||||
break;
|
break;
|
||||||
case '!':
|
case '!':
|
||||||
|
@ -742,6 +746,10 @@ bool GBACheatParseFile(struct GBACheatDevice* device, struct VFile* vf) {
|
||||||
nextDisabled = true;
|
nextDisabled = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (strcasecmp(&cheat[i], "reset") == 0) {
|
||||||
|
reset = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (!set) {
|
if (!set) {
|
||||||
|
@ -761,6 +769,54 @@ bool GBACheatParseFile(struct GBACheatDevice* device, struct VFile* vf) {
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
|
@ -199,6 +199,8 @@ bool GBACheatAddAutodetect(struct GBACheatSet*, uint32_t op1, uint32_t op2);
|
||||||
bool GBACheatAddAutodetectLine(struct GBACheatSet*, const char* line);
|
bool GBACheatAddAutodetectLine(struct GBACheatSet*, const char* line);
|
||||||
|
|
||||||
bool GBACheatParseFile(struct GBACheatDevice*, struct VFile*);
|
bool GBACheatParseFile(struct GBACheatDevice*, struct VFile*);
|
||||||
|
bool GBACheatSaveFile(struct GBACheatDevice*, struct VFile*);
|
||||||
|
|
||||||
bool GBACheatAddLine(struct GBACheatSet*, const char* line);
|
bool GBACheatAddLine(struct GBACheatSet*, const char* line);
|
||||||
|
|
||||||
void GBACheatRefresh(struct GBACheatDevice*, struct GBACheatSet*);
|
void GBACheatRefresh(struct GBACheatDevice*, struct GBACheatSet*);
|
||||||
|
|
|
@ -176,6 +176,15 @@ void CheatsModel::loadFile(const QString& path) {
|
||||||
vf->close(vf);
|
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) {
|
void CheatsModel::addSet(GBACheatSet* set) {
|
||||||
beginInsertRows(QModelIndex(), GBACheatSetsSize(&m_device->cheats), GBACheatSetsSize(&m_device->cheats));
|
beginInsertRows(QModelIndex(), GBACheatSetsSize(&m_device->cheats), GBACheatSetsSize(&m_device->cheats));
|
||||||
GBACheatAddSet(m_device, set);
|
GBACheatAddSet(m_device, set);
|
||||||
|
|
|
@ -36,6 +36,8 @@ public:
|
||||||
void endAppendRow();
|
void endAppendRow();
|
||||||
|
|
||||||
void loadFile(const QString& path);
|
void loadFile(const QString& path);
|
||||||
|
void saveFile(const QString& path);
|
||||||
|
|
||||||
void addSet(GBACheatSet* set);
|
void addSet(GBACheatSet* set);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
@ -25,6 +25,7 @@ CheatsView::CheatsView(GameController* controller, QWidget* parent)
|
||||||
m_ui.cheatList->setModel(&m_model);
|
m_ui.cheatList->setModel(&m_model);
|
||||||
|
|
||||||
connect(m_ui.load, SIGNAL(clicked()), this, SLOT(load()));
|
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.addSet, SIGNAL(clicked()), this, SLOT(addSet()));
|
||||||
connect(m_ui.remove, SIGNAL(clicked()), this, SLOT(removeSet()));
|
connect(m_ui.remove, SIGNAL(clicked()), this, SLOT(removeSet()));
|
||||||
connect(controller, SIGNAL(gameStopped(GBAThread*)), &m_model, SLOT(invalidated()));
|
connect(controller, SIGNAL(gameStopped(GBAThread*)), &m_model, SLOT(invalidated()));
|
||||||
|
@ -49,6 +50,13 @@ void CheatsView::load() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheatsView::save() {
|
||||||
|
QString filename = QFileDialog::getSaveFileName(this, tr("Select cheats file"));
|
||||||
|
if (!filename.isEmpty()) {
|
||||||
|
m_model.saveFile(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CheatsView::addSet() {
|
void CheatsView::addSet() {
|
||||||
GBACheatSet* set = new GBACheatSet;
|
GBACheatSet* set = new GBACheatSet;
|
||||||
GBACheatSetInit(set, nullptr);
|
GBACheatSetInit(set, nullptr);
|
||||||
|
|
|
@ -28,6 +28,7 @@ public:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void load();
|
void load();
|
||||||
|
void save();
|
||||||
void addSet();
|
void addSet();
|
||||||
void removeSet();
|
void removeSet();
|
||||||
|
|
||||||
|
|
|
@ -68,9 +68,6 @@
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="2">
|
<item row="1" column="2">
|
||||||
<widget class="QPushButton" name="save">
|
<widget class="QPushButton" name="save">
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Save</string>
|
<string>Save</string>
|
||||||
</property>
|
</property>
|
||||||
|
|
Loading…
Reference in New Issue