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->cpu = anonymousMemoryMap(sizeof(struct ARMCore));
|
||||
context->rom = 0;
|
||||
context->fname = 0;
|
||||
context->save = 0;
|
||||
context->renderer = 0;
|
||||
memset(context->components, 0, sizeof(context->components));
|
||||
|
@ -61,6 +62,7 @@ bool GBAContextLoadROM(struct GBAContext* context, const char* path, bool autolo
|
|||
return false;
|
||||
}
|
||||
|
||||
context->fname = path;
|
||||
if (autoloadSave) {
|
||||
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);
|
||||
}
|
||||
|
||||
if (!GBALoadROM(context->gba, context->rom, context->save, 0)) {
|
||||
if (!GBALoadROM(context->gba, context->rom, context->save, context->fname)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ struct GBAContext {
|
|||
struct ARMCore* cpu;
|
||||
struct GBAVideoRenderer* renderer;
|
||||
struct VFile* rom;
|
||||
const char* fname;
|
||||
struct VFile* save;
|
||||
struct VFile* bios;
|
||||
struct ARMComponent* components[GBA_COMPONENT_MAX];
|
||||
|
|
|
@ -5,13 +5,17 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "gui-runner.h"
|
||||
|
||||
#include "gba/serialize.h"
|
||||
#include "util/gui/file-select.h"
|
||||
#include "util/gui/font.h"
|
||||
#include "util/gui/menu.h"
|
||||
#include "util/vfs.h"
|
||||
|
||||
enum {
|
||||
RUNNER_CONTINUE,
|
||||
RUNNER_EXIT
|
||||
RUNNER_EXIT,
|
||||
RUNNER_SAVE_STATE,
|
||||
RUNNER_LOAD_STATE,
|
||||
};
|
||||
|
||||
void GBAGUIInit(struct GBAGUIRunner* runner, const char* port) {
|
||||
|
@ -36,6 +40,11 @@ void GBAGUIRunloop(struct GBAGUIRunner* runner) {
|
|||
};
|
||||
GUIMenuItemListInit(&pauseMenu.items, 0);
|
||||
*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 };
|
||||
|
||||
while (true) {
|
||||
|
@ -95,29 +104,37 @@ void GBAGUIRunloop(struct GBAGUIRunner* runner) {
|
|||
runner->params.guiPrepare();
|
||||
}
|
||||
GUIInvalidateKeys(&runner->params);
|
||||
while (true) {
|
||||
struct GUIMenuItem item;
|
||||
enum GUIMenuExitReason reason = GUIShowMenu(&runner->params, &pauseMenu, &item);
|
||||
if (reason == GUI_MENU_EXIT_ACCEPT) {
|
||||
if (item.data == (void*) RUNNER_EXIT) {
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
if (item.data == (void*) RUNNER_CONTINUE) {
|
||||
int keys = -1;
|
||||
while (keys) {
|
||||
GUIPollInput(&runner->params, 0, &keys);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
int keys = -1;
|
||||
while (keys) {
|
||||
GUIPollInput(&runner->params, 0, &keys);
|
||||
int keys = -1; // Huge hack to avoid an extra variable!
|
||||
struct GUIMenuItem item;
|
||||
enum GUIMenuExitReason reason = GUIShowMenu(&runner->params, &pauseMenu, &item);
|
||||
if (reason == GUI_MENU_EXIT_ACCEPT) {
|
||||
struct VFile* vf;
|
||||
switch ((int) item.data) {
|
||||
case RUNNER_EXIT:
|
||||
running = false;
|
||||
keys = 0;
|
||||
break;
|
||||
case RUNNER_SAVE_STATE:
|
||||
vf = GBAGetState(runner->context.gba, 0, 1, true);
|
||||
if (vf) {
|
||||
GBASaveStateNamed(runner->context.gba, vf, true);
|
||||
vf->close(vf);
|
||||
}
|
||||
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) {
|
||||
runner->params.guiFinish();
|
||||
}
|
||||
|
|
|
@ -187,13 +187,11 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifndef _3DS
|
||||
struct VFile* GBAGetState(struct GBA* gba, struct VDir* dir, int slot, bool write) {
|
||||
char suffix[5] = { '\0' };
|
||||
snprintf(suffix, sizeof(suffix), ".ss%d", slot);
|
||||
return VDirOptionalOpenFile(dir, gba->activeFile, "savestate", suffix, write ? (O_CREAT | O_TRUNC | O_RDWR) : O_RDONLY);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_PNG
|
||||
static bool _savePNGState(struct GBA* gba, struct VFile* vf) {
|
||||
|
|
|
@ -26,8 +26,8 @@ extern char* fake_heap_start;
|
|||
extern char* fake_heap_end;
|
||||
u32 __linear_heap;
|
||||
u32 __heapBase;
|
||||
static u32 __heap_size = 0x03000000;
|
||||
static u32 __linear_heap_size = 0x00800000;
|
||||
static u32 __heap_size = 0x02800000;
|
||||
static u32 __linear_heap_size = 0x01000000;
|
||||
|
||||
extern void (*__system_retAddr)(void);
|
||||
|
||||
|
|
Loading…
Reference in New Issue