mirror of https://github.com/mgba-emu/mgba.git
GUI: Load/save states
This commit is contained in:
parent
933a6c4f36
commit
41452ec4e6
|
@ -14,6 +14,7 @@ bool GBAContextInit(struct GBAContext* context, const char* port) {
|
||||||
context->gba = anonymousMemoryMap(sizeof(struct GBA));
|
context->gba = anonymousMemoryMap(sizeof(struct GBA));
|
||||||
context->cpu = anonymousMemoryMap(sizeof(struct ARMCore));
|
context->cpu = anonymousMemoryMap(sizeof(struct ARMCore));
|
||||||
context->rom = 0;
|
context->rom = 0;
|
||||||
|
context->fname = 0;
|
||||||
context->save = 0;
|
context->save = 0;
|
||||||
context->renderer = 0;
|
context->renderer = 0;
|
||||||
memset(context->components, 0, sizeof(context->components));
|
memset(context->components, 0, sizeof(context->components));
|
||||||
|
@ -61,6 +62,7 @@ bool GBAContextLoadROM(struct GBAContext* context, const char* path, bool autolo
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context->fname = path;
|
||||||
if (autoloadSave) {
|
if (autoloadSave) {
|
||||||
context->save = VDirOptionalOpenFile(0, path, 0, ".sav", O_RDWR | O_CREAT);
|
context->save = VDirOptionalOpenFile(0, path, 0, ".sav", O_RDWR | O_CREAT);
|
||||||
}
|
}
|
||||||
|
@ -123,7 +125,7 @@ bool GBAContextStart(struct GBAContext* context) {
|
||||||
GBAVideoAssociateRenderer(&context->gba->video, context->renderer);
|
GBAVideoAssociateRenderer(&context->gba->video, context->renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GBALoadROM(context->gba, context->rom, context->save, 0)) {
|
if (!GBALoadROM(context->gba, context->rom, context->save, context->fname)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ struct GBAContext {
|
||||||
struct ARMCore* cpu;
|
struct ARMCore* cpu;
|
||||||
struct GBAVideoRenderer* renderer;
|
struct GBAVideoRenderer* renderer;
|
||||||
struct VFile* rom;
|
struct VFile* rom;
|
||||||
|
const char* fname;
|
||||||
struct VFile* save;
|
struct VFile* save;
|
||||||
struct VFile* bios;
|
struct VFile* bios;
|
||||||
struct ARMComponent* components[GBA_COMPONENT_MAX];
|
struct ARMComponent* components[GBA_COMPONENT_MAX];
|
||||||
|
|
|
@ -5,13 +5,17 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
#include "gui-runner.h"
|
#include "gui-runner.h"
|
||||||
|
|
||||||
|
#include "gba/serialize.h"
|
||||||
#include "util/gui/file-select.h"
|
#include "util/gui/file-select.h"
|
||||||
#include "util/gui/font.h"
|
#include "util/gui/font.h"
|
||||||
#include "util/gui/menu.h"
|
#include "util/gui/menu.h"
|
||||||
|
#include "util/vfs.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
RUNNER_CONTINUE,
|
RUNNER_CONTINUE,
|
||||||
RUNNER_EXIT
|
RUNNER_EXIT,
|
||||||
|
RUNNER_SAVE_STATE,
|
||||||
|
RUNNER_LOAD_STATE,
|
||||||
};
|
};
|
||||||
|
|
||||||
void GBAGUIInit(struct GBAGUIRunner* runner, const char* port) {
|
void GBAGUIInit(struct GBAGUIRunner* runner, const char* port) {
|
||||||
|
@ -36,6 +40,11 @@ void GBAGUIRunloop(struct GBAGUIRunner* runner) {
|
||||||
};
|
};
|
||||||
GUIMenuItemListInit(&pauseMenu.items, 0);
|
GUIMenuItemListInit(&pauseMenu.items, 0);
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Unpause", .data = (void*) RUNNER_CONTINUE };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Unpause", .data = (void*) RUNNER_CONTINUE };
|
||||||
|
#if !(defined(__POWERPC__) || defined(__PPC__))
|
||||||
|
// PPC doesn't have working savestates yet
|
||||||
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Save state", .data = (void*) RUNNER_SAVE_STATE };
|
||||||
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Load state", .data = (void*) RUNNER_LOAD_STATE };
|
||||||
|
#endif
|
||||||
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Exit game", .data = (void*) RUNNER_EXIT };
|
*GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Exit game", .data = (void*) RUNNER_EXIT };
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -95,29 +104,37 @@ void GBAGUIRunloop(struct GBAGUIRunner* runner) {
|
||||||
runner->params.guiPrepare();
|
runner->params.guiPrepare();
|
||||||
}
|
}
|
||||||
GUIInvalidateKeys(&runner->params);
|
GUIInvalidateKeys(&runner->params);
|
||||||
while (true) {
|
int keys = -1; // Huge hack to avoid an extra variable!
|
||||||
struct GUIMenuItem item;
|
struct GUIMenuItem item;
|
||||||
enum GUIMenuExitReason reason = GUIShowMenu(&runner->params, &pauseMenu, &item);
|
enum GUIMenuExitReason reason = GUIShowMenu(&runner->params, &pauseMenu, &item);
|
||||||
if (reason == GUI_MENU_EXIT_ACCEPT) {
|
if (reason == GUI_MENU_EXIT_ACCEPT) {
|
||||||
if (item.data == (void*) RUNNER_EXIT) {
|
struct VFile* vf;
|
||||||
running = false;
|
switch ((int) item.data) {
|
||||||
break;
|
case RUNNER_EXIT:
|
||||||
}
|
running = false;
|
||||||
if (item.data == (void*) RUNNER_CONTINUE) {
|
keys = 0;
|
||||||
int keys = -1;
|
break;
|
||||||
while (keys) {
|
case RUNNER_SAVE_STATE:
|
||||||
GUIPollInput(&runner->params, 0, &keys);
|
vf = GBAGetState(runner->context.gba, 0, 1, true);
|
||||||
}
|
if (vf) {
|
||||||
break;
|
GBASaveStateNamed(runner->context.gba, vf, true);
|
||||||
}
|
vf->close(vf);
|
||||||
} else {
|
|
||||||
int keys = -1;
|
|
||||||
while (keys) {
|
|
||||||
GUIPollInput(&runner->params, 0, &keys);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case RUNNER_LOAD_STATE:
|
||||||
|
vf = GBAGetState(runner->context.gba, 0, 1, false);
|
||||||
|
if (vf) {
|
||||||
|
GBALoadStateNamed(runner->context.gba, vf);
|
||||||
|
vf->close(vf);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RUNNER_CONTINUE:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
while (keys) {
|
||||||
|
GUIPollInput(&runner->params, 0, &keys);
|
||||||
|
}
|
||||||
if (runner->params.guiFinish) {
|
if (runner->params.guiFinish) {
|
||||||
runner->params.guiFinish();
|
runner->params.guiFinish();
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,13 +187,11 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _3DS
|
|
||||||
struct VFile* GBAGetState(struct GBA* gba, struct VDir* dir, int slot, bool write) {
|
struct VFile* GBAGetState(struct GBA* gba, struct VDir* dir, int slot, bool write) {
|
||||||
char suffix[5] = { '\0' };
|
char suffix[5] = { '\0' };
|
||||||
snprintf(suffix, sizeof(suffix), ".ss%d", slot);
|
snprintf(suffix, sizeof(suffix), ".ss%d", slot);
|
||||||
return VDirOptionalOpenFile(dir, gba->activeFile, "savestate", suffix, write ? (O_CREAT | O_TRUNC | O_RDWR) : O_RDONLY);
|
return VDirOptionalOpenFile(dir, gba->activeFile, "savestate", suffix, write ? (O_CREAT | O_TRUNC | O_RDWR) : O_RDONLY);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_PNG
|
#ifdef USE_PNG
|
||||||
static bool _savePNGState(struct GBA* gba, struct VFile* vf) {
|
static bool _savePNGState(struct GBA* gba, struct VFile* vf) {
|
||||||
|
|
|
@ -26,8 +26,8 @@ extern char* fake_heap_start;
|
||||||
extern char* fake_heap_end;
|
extern char* fake_heap_end;
|
||||||
u32 __linear_heap;
|
u32 __linear_heap;
|
||||||
u32 __heapBase;
|
u32 __heapBase;
|
||||||
static u32 __heap_size = 0x03000000;
|
static u32 __heap_size = 0x02800000;
|
||||||
static u32 __linear_heap_size = 0x00800000;
|
static u32 __linear_heap_size = 0x01000000;
|
||||||
|
|
||||||
extern void (*__system_retAddr)(void);
|
extern void (*__system_retAddr)(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue