all repos — mgba @ 0e9ba00dbfd3ed4586fbe79b64ebb319db5221a5

mGBA Game Boy Advance Emulator

3DS: Add experimental autosave
Vicki Pfau vi@endrift.com
Wed, 10 Jan 2018 00:42:09 -0800
commit

0e9ba00dbfd3ed4586fbe79b64ebb319db5221a5

parent

789a84d2e25b2a6e7df0bb86351ec81726313eed

2 files changed, 91 insertions(+), 0 deletions(-)

jump to
M src/feature/gui/gui-runner.csrc/feature/gui/gui-runner.c

@@ -317,6 +317,13 @@ }

mLOG(GUI_RUNNER, DEBUG, "Reseting..."); runner->core->reset(runner->core); mLOG(GUI_RUNNER, DEBUG, "Reset!"); + + if (mCoreLoadState(runner->core, 0, SAVESTATE_SCREENSHOT | SAVESTATE_RTC)) { + struct VFile* autosave = mCoreGetState(runner->core, 0, true); + autosave->truncate(autosave, 0); + autosave->close(autosave); + } + bool running = true; if (runner->gameLoaded) { runner->gameLoaded(runner);

@@ -469,6 +476,14 @@ runner->core->desiredVideoDimensions(runner->core, &w, &h);

mappedMemoryFree(drawState.screenshot, w * h * 4); } + struct VFile* autosave = mCoreGetState(runner->core, 0, false); + if (autosave) { + autosave->close(autosave); + autosave = mCoreGetState(runner->core, 0, true); + autosave->truncate(autosave, 0); + autosave->close(autosave); + } + if (runner->config.port) { mLOG(GUI_RUNNER, DEBUG, "Saving key sources..."); if (runner->keySources) {

@@ -483,6 +498,7 @@ }

mInputMapDeinit(&runner->core->inputMap); mLOG(GUI_RUNNER, DEBUG, "Deinitializing core..."); runner->core->deinit(runner->core); + runner->core = NULL; GUIMenuItemListDeinit(&pauseMenu.items); GUIMenuItemListDeinit(&stateSaveMenu.items);
M src/platform/3ds/main.csrc/platform/3ds/main.c

@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <mgba/core/blip_buf.h> #include <mgba/core/core.h> +#include <mgba/core/serialize.h> #ifdef M_CORE_GBA #include <mgba/internal/gba/gba.h> #include <mgba/internal/gba/input.h>

@@ -22,6 +23,7 @@ #include <mgba-util/gui/menu.h>

#include <mgba-util/memory.h> #include <mgba-util/platform/3ds/3ds-vfs.h> +#include <mgba-util/threading.h> #include "ctr-gpu.h" #include <3ds.h>

@@ -104,6 +106,12 @@ static C3D_Tex upscaleBufferTex;

static aptHookCookie cookie; +static Thread autosave; +static struct VFile* autosaveBuffer = NULL; +static Mutex autosaveMutex; +static Condition autosaveCond; +static struct mCore* autosaveCore = NULL; + extern bool allocateRomBuffer(void); static bool _initGpu(void) {

@@ -191,6 +199,33 @@ break;

default: break; } +} + +static void _autosaveThread(void* context) { + bool* running = context; + MutexLock(&autosaveMutex); + while (*running) { + ConditionWait(&autosaveCond, &autosaveMutex); + if (*running && autosaveCore) { + struct VFile* vf = mCoreGetState(autosaveCore, 0, true); + void* mem = autosaveBuffer->map(autosaveBuffer, autosaveBuffer->size(autosaveBuffer), MAP_READ); + vf->write(vf, mem, autosaveBuffer->size(autosaveBuffer)); + autosaveBuffer->unmap(autosaveBuffer, mem, autosaveBuffer->size(autosaveBuffer)); + vf->close(vf); + } + } + MutexUnlock(&autosaveMutex); +} + +static void _tryAutosave(struct mCore* core) { + if (!autosaveBuffer) { + autosaveBuffer = VFileMemChunk(NULL, 0); + } + MutexLock(&autosaveMutex); + autosaveCore = core; + mCoreSaveStateNamed(core, autosaveBuffer, SAVESTATE_SAVEDATA | SAVESTATE_RTC | SAVESTATE_METADATA); + ConditionWake(&autosaveCond); + MutexUnlock(&autosaveMutex); } static void _map3DSKey(struct mInputMap* map, int ctrKey, enum GBAKey key) {

@@ -425,6 +460,10 @@ CAMU_Activate(camera.cam);

} } } + + MutexLock(&autosaveMutex); + autosaveCore = runner->core; + MutexUnlock(&autosaveMutex); } static void _gameUnloaded(struct mGUIRunner* runner) {

@@ -458,6 +497,10 @@ #endif

default: break; } + + MutexLock(&autosaveMutex); + autosaveCore = NULL; + MutexUnlock(&autosaveMutex); } static void _drawTex(struct mCore* core, bool faded) {

@@ -679,6 +722,16 @@ tickCounter = svcGetSystemTick();

} static bool _running(struct mGUIRunner* runner) { + static int frame = 0; + if (autosaveCore) { + ++frame; + if (frame == 300) { + _tryAutosave(autosaveCore); + frame = 0; + } + } else { + frame = 0; + } return aptMainLoop(); }

@@ -1041,7 +1094,29 @@ _map3DSKey(&runner.params.keyMap, KEY_RIGHT, GUI_INPUT_RIGHT);

_map3DSKey(&runner.params.keyMap, KEY_CSTICK_UP, mGUI_INPUT_INCREASE_BRIGHTNESS); _map3DSKey(&runner.params.keyMap, KEY_CSTICK_DOWN, mGUI_INPUT_DECREASE_BRIGHTNESS); + bool autosaveActive = true; + MutexInit(&autosaveMutex); + ConditionInit(&autosaveCond); + + APT_SetAppCpuTimeLimit(20); + autosave = threadCreate(_autosaveThread, &autosaveActive, 0x4000, 0x1F, 1, true); + mGUIRunloop(&runner); + + MutexLock(&autosaveMutex); + autosaveActive = false; + ConditionWake(&autosaveCond); + MutexUnlock(&autosaveMutex); + + threadJoin(autosave, U64_MAX); + + if (autosaveBuffer) { + autosaveBuffer->close(autosaveBuffer); + } + + ConditionDeinit(&autosaveCond); + MutexDeinit(&autosaveMutex); + mGUIDeinit(&runner); _cleanup();