From ee5c918ff24e6f5f23864518d9bdd64309115919 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Thu, 17 Jul 2014 00:53:17 -0700 Subject: [PATCH] Directory mode for loading the first ROM in a directory, still a bit buggy --- src/gba/gba-thread.c | 26 +++++++++++++++++++++++++- src/gba/gba-thread.h | 1 + src/gba/gba.c | 12 ++++++++++++ src/gba/gba.h | 2 ++ src/platform/commandline.c | 6 +++++- src/platform/commandline.h | 1 + src/util/vfs.c | 7 +++++++ src/util/vfs.h | 1 + 8 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/gba/gba-thread.c b/src/gba/gba-thread.c index 46a1bac49..a63a53773 100644 --- a/src/gba/gba-thread.c +++ b/src/gba/gba-thread.c @@ -169,7 +169,11 @@ static THREAD_ENTRY _GBAThreadRun(void* context) { } void GBAMapOptionsToContext(struct StartupOptions* opts, struct GBAThread* threadContext) { - threadContext->rom = VFileOpen(opts->fname, O_RDONLY); + if (opts->dirmode) { + threadContext->gamedir = VDirOpen(opts->fname); + } else { + threadContext->rom = VFileOpen(opts->fname, O_RDONLY); + } threadContext->fname = opts->fname; threadContext->bios = VFileOpen(opts->bios, O_RDONLY); threadContext->patch = VFileOpen(opts->patch, O_RDONLY); @@ -194,6 +198,26 @@ bool GBAThreadStart(struct GBAThread* threadContext) { threadContext->rewindBuffer = 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) { + 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); + } + } + if (threadContext->fname && !threadContext->save) { char* savedata = 0; char* dotPoint = strrchr(threadContext->fname, '.'); diff --git a/src/gba/gba-thread.h b/src/gba/gba-thread.h index ed73aeff8..4b2484d70 100644 --- a/src/gba/gba-thread.h +++ b/src/gba/gba-thread.h @@ -47,6 +47,7 @@ struct GBAThread { struct GBAVideoRenderer* renderer; struct GBASIODriverSet sioDrivers; struct ARMDebugger* debugger; + struct VDir* gamedir; struct VFile* rom; struct VFile* save; struct VFile* bios; diff --git a/src/gba/gba.c b/src/gba/gba.c index daf333c68..b81016601 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -12,6 +12,8 @@ const uint32_t GBA_ARM7TDMI_FREQUENCY = 0x1000000; const uint32_t GBA_COMPONENT_MAGIC = 0x1000000; +static const uint64_t GBA_ROM_MAGIC = 0x21A29A6951AEFF24; + enum { SP_BASE_SYSTEM = 0x03FFFF00, SP_BASE_IRQ = 0x03FFFFA0, @@ -582,6 +584,16 @@ void GBADebuggerLogShim(struct ARMDebugger* debugger, enum DebuggerLogLevel leve va_end(args); } +bool GBAIsROM(struct VFile* vf) { + if (vf->seek(vf, 4, SEEK_SET) < 0) { + return false; + } + uint64_t signature; + if (vf->read(vf, &signature, sizeof(signature)) != sizeof(signature)) { + return false; + } + return signature == GBA_ROM_MAGIC; +} void GBAHitStub(struct ARMCore* cpu, uint32_t opcode) { struct GBA* gba = (struct GBA*) cpu->master; diff --git a/src/gba/gba.h b/src/gba/gba.h index 68cf85101..cf4b303db 100644 --- a/src/gba/gba.h +++ b/src/gba/gba.h @@ -146,6 +146,8 @@ void GBALoadROM(struct GBA* gba, struct VFile* vf, struct VFile* sav, const char void GBALoadBIOS(struct GBA* gba, struct VFile* vf); void GBAApplyPatch(struct GBA* gba, struct Patch* patch); +bool GBAIsROM(struct VFile* vf); + __attribute__((format (printf, 3, 4))) void GBALog(struct GBA* gba, enum GBALogLevel level, const char* format, ...); diff --git a/src/platform/commandline.c b/src/platform/commandline.c index ff7720be9..a97f209ad 100644 --- a/src/platform/commandline.c +++ b/src/platform/commandline.c @@ -23,6 +23,7 @@ static const struct option _options[] = { { "bios", required_argument, 0, 'b' }, + { "dirmode", required_argument, 0, 'D' }, { "frameskip", required_argument, 0, 's' }, #ifdef USE_CLI_DEBUGGER { "debug", no_argument, 0, 'd' }, @@ -41,7 +42,7 @@ bool parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, int ch; char options[64] = - "b:l:p:s:" + "b:Dl:p:s:" #ifdef USE_CLI_DEBUGGER "d" #endif @@ -58,6 +59,9 @@ bool parseCommandArgs(struct StartupOptions* opts, int argc, char* const* argv, case 'b': opts->bios = strdup(optarg); break; + case 'D': + opts->dirmode = true; + break; #ifdef USE_CLI_DEBUGGER case 'd': if (opts->debuggerType != DEBUGGER_NONE) { diff --git a/src/platform/commandline.h b/src/platform/commandline.h index 18d611288..6eb5a7492 100644 --- a/src/platform/commandline.h +++ b/src/platform/commandline.h @@ -18,6 +18,7 @@ struct StartupOptions { char* fname; char* bios; char* patch; + bool dirmode; int logLevel; int frameskip; int rewindBufferCapacity; diff --git a/src/util/vfs.c b/src/util/vfs.c index 4e533a0a9..ce1457968 100644 --- a/src/util/vfs.c +++ b/src/util/vfs.c @@ -30,6 +30,7 @@ static void _vfdUnmap(struct VFile* vf, void* memory, size_t size); static void _vfdTruncate(struct VFile* vf, size_t size); static bool _vdClose(struct VDir* vd); +static void _vdRewind(struct VDir* vd); static struct VDirEntry* _vdListNext(struct VDir* vd); static struct VFile* _vdOpenFile(struct VDir* vd, const char* path, int mode); @@ -171,6 +172,7 @@ struct VDir* VDirOpen(const char* path) { } vd->d.close = _vdClose; + vd->d.rewind = _vdRewind; vd->d.listNext = _vdListNext; vd->d.openFile = _vdOpenFile; vd->path = strdup(path); @@ -191,6 +193,11 @@ bool _vdClose(struct VDir* vd) { return true; } +void _vdRewind(struct VDir* vd) { + struct VDirDE* vdde = (struct VDirDE*) vd; + rewinddir(vdde->de); +} + struct VDirEntry* _vdListNext(struct VDir* vd) { struct VDirDE* vdde = (struct VDirDE*) vd; vdde->vde.ent = readdir(vdde->de); diff --git a/src/util/vfs.h b/src/util/vfs.h index 0484d9503..05d6a5c68 100644 --- a/src/util/vfs.h +++ b/src/util/vfs.h @@ -22,6 +22,7 @@ struct VDirEntry { struct VDir { bool (*close)(struct VDir* vd); + void (*rewind)(struct VDir* vd); struct VDirEntry* (*listNext)(struct VDir* vd); struct VFile* (*openFile)(struct VDir* vd, const char* name, int mode); };