GBA: Rom unloading and replacing
Jeffrey Pfau jeffrey@endrift.com
Fri, 19 Jun 2015 22:28:49 -0700
4 files changed,
79 insertions(+),
32 deletions(-)
M
src/gba/gba.c
→
src/gba/gba.c
@@ -96,14 +96,22 @@
gba->performingDMA = false; } -void GBADestroy(struct GBA* gba) { +void GBAUnloadROM(struct GBA* gba) { if (gba->pristineRom == gba->memory.rom) { gba->memory.rom = 0; + } else { + mappedMemoryFree(gba->pristineRom, gba->pristineRomSize); } if (gba->romVf) { gba->romVf->unmap(gba->romVf, gba->pristineRom, gba->pristineRomSize); + gba->pristineRom = 0; + gba->romVf = 0; } +} + +void GBADestroy(struct GBA* gba) { + GBAUnloadROM(gba); if (gba->biosVf) { gba->biosVf->unmap(gba->biosVf, gba->memory.bios, SIZE_BIOS);@@ -370,6 +378,7 @@ gba->cpu->components[GBA_COMPONENT_DEBUGGER] = 0;
} void GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char* fname) { + GBAUnloadROM(gba); gba->romVf = vf; gba->pristineRomSize = vf->size(vf); vf->seek(vf, 0, SEEK_SET);
M
src/gba/gba.h
→
src/gba/gba.h
@@ -208,6 +208,7 @@ void GBAClearBreakpoint(struct GBA* gba, uint32_t address, enum ExecutionMode mode, uint32_t opcode);
void GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char* fname); void GBAYankROM(struct GBA* gba); +void GBAUnloadROM(struct GBA* gba); void GBALoadBIOS(struct GBA* gba, struct VFile* vf); void GBAApplyPatch(struct GBA* gba, struct Patch* patch);
M
src/gba/supervisor/thread.c
→
src/gba/supervisor/thread.c
@@ -23,6 +23,8 @@ #include "platform/commandline.h"
#include <signal.h> +static void _loadGameDir(struct GBAThread* threadContext); + static const float _defaultFPSTarget = 60.f; #ifndef DISABLE_THREADING@@ -352,18 +354,7 @@ if (args->dirmode) {
threadContext->gameDir = VDirOpen(args->fname); threadContext->stateDir = threadContext->gameDir; } else { - threadContext->rom = VFileOpen(args->fname, O_RDONLY); - threadContext->gameDir = 0; -#if USE_LIBZIP - if (!threadContext->gameDir) { - threadContext->gameDir = VDirOpenZip(args->fname, 0); - } -#endif -#if USE_LZMA - if (!threadContext->gameDir) { - threadContext->gameDir = VDirOpen7z(args->fname, 0); - } -#endif + GBAThreadLoadROM(threadContext, args->fname); } threadContext->fname = args->fname; threadContext->patch = VFileOpen(args->patch, O_RDONLY);@@ -398,25 +389,7 @@ threadContext->rom = 0;
} if (threadContext->gameDir) { - threadContext->gameDir->rewind(threadContext->gameDir); - struct VDirEntry* dirent = threadContext->gameDir->listNext(threadContext->gameDir); - while (dirent) { - struct Patch patchTemp; - struct VFile* vf = threadContext->gameDir->openFile(threadContext->gameDir, dirent->name(dirent), O_RDONLY); - if (!vf) { - dirent = threadContext->gameDir->listNext(threadContext->gameDir); - continue; - } - if (!threadContext->rom && GBAIsROM(vf)) { - threadContext->rom = vf; - } else if (!threadContext->patch && loadPatch(vf, &patchTemp)) { - threadContext->patch = vf; - } else { - vf->close(vf); - } - dirent = threadContext->gameDir->listNext(threadContext->gameDir); - } - + _loadGameDir(threadContext); } if (!threadContext->rom && !bootBios) {@@ -676,6 +649,67 @@ }
MutexUnlock(&threadContext->stateMutex); GBASyncSetVideoSync(&threadContext->sync, frameOn); +} + +void GBAThreadLoadROM(struct GBAThread* threadContext, const char* fname) { + threadContext->rom = VFileOpen(fname, O_RDONLY); + threadContext->gameDir = 0; +#if USE_LIBZIP + if (!threadContext->gameDir) { + threadContext->gameDir = VDirOpenZip(fname, 0); + } +#endif +#if USE_LZMA + if (!threadContext->gameDir) { + threadContext->gameDir = VDirOpen7z(fname, 0); + } +#endif +} + +static void _loadGameDir(struct GBAThread* threadContext) { + threadContext->gameDir->rewind(threadContext->gameDir); + struct VDirEntry* dirent = threadContext->gameDir->listNext(threadContext->gameDir); + while (dirent) { + struct Patch patchTemp; + struct VFile* vf = threadContext->gameDir->openFile(threadContext->gameDir, dirent->name(dirent), O_RDONLY); + if (!vf) { + dirent = threadContext->gameDir->listNext(threadContext->gameDir); + continue; + } + if (!threadContext->rom && GBAIsROM(vf)) { + threadContext->rom = vf; + } else if (!threadContext->patch && loadPatch(vf, &patchTemp)) { + threadContext->patch = vf; + } else { + vf->close(vf); + } + dirent = threadContext->gameDir->listNext(threadContext->gameDir); + } +} + +void GBAThreadReplaceROM(struct GBAThread* threadContext, const char* fname) { + GBAUnloadROM(threadContext->gba); + + if (threadContext->rom) { + threadContext->rom->close(threadContext->rom); + threadContext->rom = 0; + } + + if (threadContext->save) { + threadContext->save->close(threadContext->save); + threadContext->save = 0; + } + + GBAThreadLoadROM(threadContext, fname); + if(threadContext->gameDir) { + _loadGameDir(threadContext); + } + + threadContext->fname = fname; + threadContext->save = VDirOptionalOpenFile(threadContext->stateDir, threadContext->fname, "sram", ".sav", O_CREAT | O_RDWR); + + GBARaiseIRQ(threadContext->gba, IRQ_GAMEPAK); + GBALoadROM(threadContext->gba, threadContext->rom, threadContext->save, threadContext->fname); } #ifdef USE_PTHREADS
M
src/gba/supervisor/thread.h
→
src/gba/supervisor/thread.h
@@ -126,6 +126,9 @@ void GBAThreadTogglePause(struct GBAThread* threadContext);
void GBAThreadPauseFromThread(struct GBAThread* threadContext); struct GBAThread* GBAThreadGetContext(void); +void GBAThreadLoadROM(struct GBAThread* threadContext, const char* fname); +void GBAThreadReplaceROM(struct GBAThread* threadContext, const char* fname); + #ifdef USE_PNG void GBAThreadTakeScreenshot(struct GBAThread* threadContext); #endif