all repos — mgba @ 407335e2f464828d5fe517372442fce798b58490

mGBA Game Boy Advance Emulator

Core: Refactor config loading in mCore
Jeffrey Pfau jeffrey@endrift.com
Thu, 04 Feb 2016 21:58:45 -0800
commit

407335e2f464828d5fe517372442fce798b58490

parent

7bc15e50c5f14c70453be3a09e83ed3909175c2a

M src/core/config.csrc/core/config.c

@@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this

* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "config.h" +#include "gba/gba.h" #include "util/formatting.h" #include "util/string.h" #include "util/vfs.h"

@@ -299,7 +300,7 @@ void mCoreConfigSetOverrideFloatValue(struct mCoreConfig* config, const char* key, float value) {

ConfigurationSetFloatValue(&config->overridesTable, config->port, key, value); } -void mCoreConfigMap(const struct mCoreConfig* config, struct GBAOptions* opts) { +void mCoreConfigMap(const struct mCoreConfig* config, struct mCoreOptions* opts) { _lookupCharValue(config, "bios", &opts->bios); _lookupCharValue(config, "shader", &opts->shader); _lookupIntValue(config, "logLevel", &opts->logLevel);

@@ -351,21 +352,9 @@ _lookupCharValue(config, "savegamePath", &opts->savegamePath);

_lookupCharValue(config, "savestatePath", &opts->savestatePath); _lookupCharValue(config, "screenshotPath", &opts->screenshotPath); _lookupCharValue(config, "patchPath", &opts->patchPath); - - char* idleOptimization = 0; - if (_lookupCharValue(config, "idleOptimization", &idleOptimization)) { - if (strcasecmp(idleOptimization, "ignore") == 0) { - opts->idleOptimization = IDLE_LOOP_IGNORE; - } else if (strcasecmp(idleOptimization, "remove") == 0) { - opts->idleOptimization = IDLE_LOOP_REMOVE; - } else if (strcasecmp(idleOptimization, "detect") == 0) { - opts->idleOptimization = IDLE_LOOP_DETECT; - } - free(idleOptimization); - } } -void mCoreConfigLoadDefaults(struct mCoreConfig* config, const struct GBAOptions* opts) { +void mCoreConfigLoadDefaults(struct mCoreConfig* config, const struct mCoreOptions* opts) { ConfigurationSetValue(&config->defaultsTable, 0, "bios", opts->bios); ConfigurationSetValue(&config->defaultsTable, 0, "shader", opts->shader); ConfigurationSetIntValue(&config->defaultsTable, 0, "skipBios", opts->skipBios);

@@ -388,18 +377,6 @@ ConfigurationSetIntValue(&config->defaultsTable, 0, "mute", opts->mute);

ConfigurationSetIntValue(&config->defaultsTable, 0, "lockAspectRatio", opts->lockAspectRatio); ConfigurationSetIntValue(&config->defaultsTable, 0, "resampleVideo", opts->resampleVideo); ConfigurationSetIntValue(&config->defaultsTable, 0, "suspendScreensaver", opts->suspendScreensaver); - - switch (opts->idleOptimization) { - case IDLE_LOOP_IGNORE: - ConfigurationSetValue(&config->defaultsTable, 0, "idleOptimization", "ignore"); - break; - case IDLE_LOOP_REMOVE: - ConfigurationSetValue(&config->defaultsTable, 0, "idleOptimization", "remove"); - break; - case IDLE_LOOP_DETECT: - ConfigurationSetValue(&config->defaultsTable, 0, "idleOptimization", "detect"); - break; - } } // These two are basically placeholders in case the internal layout changes, e.g. for loading separate files

@@ -411,7 +388,7 @@ struct Configuration* mCoreConfigGetOverrides(struct mCoreConfig* config) {

return &config->configTable; } -void mCoreConfigFreeOpts(struct GBAOptions* opts) { +void mCoreConfigFreeOpts(struct mCoreOptions* opts) { free(opts->bios); free(opts->shader); free(opts->savegamePath);
M src/core/config.hsrc/core/config.h

@@ -8,8 +8,6 @@ #define M_CORE_CONFIG_H

#include "util/common.h" -#include "gba/gba.h" - #include "util/configuration.h" struct mCoreConfig {

@@ -19,7 +17,7 @@ struct Configuration overridesTable;

char* port; }; -struct GBAOptions { +struct mCoreOptions { char* bios; bool skipBios; bool useBios;

@@ -50,8 +48,6 @@ bool mute;

bool videoSync; bool audioSync; - - enum GBAIdleLoopOptimization idleOptimization; }; void mCoreConfigInit(struct mCoreConfig*, const char* port);

@@ -87,12 +83,12 @@ void mCoreConfigSetOverrideIntValue(struct mCoreConfig*, const char* key, int value);

void mCoreConfigSetOverrideUIntValue(struct mCoreConfig*, const char* key, unsigned value); void mCoreConfigSetOverrideFloatValue(struct mCoreConfig*, const char* key, float value); -void mCoreConfigMap(const struct mCoreConfig* config, struct GBAOptions* opts); -void mCoreConfigLoadDefaults(struct mCoreConfig* config, const struct GBAOptions* opts); +void mCoreConfigMap(const struct mCoreConfig* config, struct mCoreOptions* opts); +void mCoreConfigLoadDefaults(struct mCoreConfig* config, const struct mCoreOptions* opts); struct Configuration* mCoreConfigGetInput(struct mCoreConfig*); struct Configuration* mCoreConfigGetOverrides(struct mCoreConfig*); -void mCoreConfigFreeOpts(struct GBAOptions* opts); +void mCoreConfigFreeOpts(struct mCoreOptions* opts); #endif
A src/core/core.c

@@ -0,0 +1,93 @@

+/* Copyright (c) 2013-2016 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "core.h" + +#include "core/log.h" +#include "util/vfs.h" + +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 +bool mCoreLoadFile(struct mCore* core, const char* path) { + struct VFile* rom = mDirectorySetOpenPath(&core->dirs, path, core->isROM); + if (!rom) { + return false; + } + + bool ret = core->loadROM(core, rom); + if (!ret) { + rom->close(rom); + } + return ret; +} + +bool mCoreAutoloadSave(struct mCore* core) { + return core->loadSave(core, mDirectorySetOpenSuffix(&core->dirs, ".sav", O_CREAT | O_RDWR)); +} + +bool mCoreAutoloadPatch(struct mCore* core) { + return core->loadPatch(core, mDirectorySetOpenSuffix(&core->dirs, ".ups", O_RDONLY)) || + core->loadPatch(core, mDirectorySetOpenSuffix(&core->dirs, ".ips", O_RDONLY)) || + core->loadPatch(core, mDirectorySetOpenSuffix(&core->dirs, ".bps", O_RDONLY)); +} + +bool mCoreSaveState(struct mCore* core, int slot, int flags) { + struct VFile* vf = mCoreGetState(core, slot, true); + if (!vf) { + return false; + } + bool success = core->saveState(core, vf, flags); + vf->close(vf); + if (success) { + mLOG(STATUS, INFO, "State %i saved", slot); + } else { + mLOG(STATUS, INFO, "State %i failed to save", slot); + } + + return success; +} + +bool mCoreLoadState(struct mCore* core, int slot, int flags) { + struct VFile* vf = mCoreGetState(core, slot, false); + if (!vf) { + return false; + } + bool success = core->loadState(core, vf, flags); + vf->close(vf); + if (success) { + mLOG(STATUS, INFO, "State %i loaded", slot); + } else { + mLOG(STATUS, INFO, "State %i failed to loaded", slot); + } + + return success; +} + +struct VFile* mCoreGetState(struct mCore* core, int slot, bool write) { + char name[PATH_MAX]; + snprintf(name, sizeof(name), "%s.ss%i", core->dirs.baseName, slot); + return core->dirs.state->openFile(core->dirs.state, name, write ? (O_CREAT | O_TRUNC | O_RDWR) : O_RDONLY); +} + +void mCoreDeleteState(struct mCore* core, int slot) { + char name[PATH_MAX]; + snprintf(name, sizeof(name), "%s.ss%i", core->dirs.baseName, slot); + core->dirs.state->deleteFile(core->dirs.state, name); +} +#endif + +void mCoreInitConfig(struct mCore* core, const char* port) { + mCoreConfigInit(&core->config, port); +} + +void mCoreLoadConfig(struct mCore* core) { +#ifndef MINIMAL_CORE + mCoreConfigLoad(&core->config); +#endif + mCoreConfigMap(&core->config, &core->opts); +#ifndef MINIMAL_CORE + mDirectorySetMapOptions(&core->dirs, &core->opts); +#endif + core->loadConfig(core); +}
M src/core/core.hsrc/core/core.h

@@ -11,9 +11,14 @@

#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 #include "core/directories.h" #endif +#ifndef MINIMAL_CORE +#include "core/input.h" +#endif +#include "core/config.h" struct VFile; struct mRTCSource; +struct mCoreConfig; #ifdef COLOR_16_BIT typedef uint16_t color_t;

@@ -32,11 +37,17 @@

#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 struct mDirectorySet dirs; #endif +#ifndef MINIMAL_CORE + struct mInputMap inputMap; +#endif + struct mCoreConfig config; + struct mCoreOptions opts; bool (*init)(struct mCore*); void (*deinit)(struct mCore*); void (*setSync)(struct mCore*, struct mCoreSync*); + void (*loadConfig)(struct mCore*); void (*desiredVideoDimensions)(struct mCore*, unsigned* width, unsigned* height); void (*setVideoBuffer)(struct mCore*, color_t* buffer, size_t stride);

@@ -72,9 +83,9 @@

void (*setRTC)(struct mCore*, struct mRTCSource*); }; +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 bool mCoreLoadFile(struct mCore* core, const char* path); -#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 bool mCoreAutoloadSave(struct mCore* core); bool mCoreAutoloadPatch(struct mCore* core);

@@ -83,5 +94,8 @@ bool mCoreLoadState(struct mCore* core, int slot, int flags);

struct VFile* mCoreGetState(struct mCore* core, int slot, bool write); void mCoreDeleteState(struct mCore* core, int slot); #endif + +void mCoreInitConfig(struct mCore* core, const char* port); +void mCoreLoadConfig(struct mCore* core); #endif
M src/core/directories.csrc/core/directories.c

@@ -113,7 +113,7 @@ snprintf(name, sizeof(name), "%s%s", dirs->baseName, suffix);

return dirs->base->openFile(dirs->base, name, mode); } -void mDirectorySetMapOptions(struct mDirectorySet* dirs, const struct GBAOptions* opts) { +void mDirectorySetMapOptions(struct mDirectorySet* dirs, const struct mCoreOptions* opts) { if (opts->savegamePath) { struct VDir* dir = VDirOpen(opts->savegamePath); if (dir) {
M src/core/directories.hsrc/core/directories.h

@@ -30,8 +30,8 @@

struct VFile* mDirectorySetOpenPath(struct mDirectorySet* dirs, const char* path, bool (*filter)(struct VFile*)); struct VFile* mDirectorySetOpenSuffix(struct mDirectorySet* dirs, const char* suffix, int mode); -struct GBAOptions; -void mDirectorySetMapOptions(struct mDirectorySet* dirs, const struct GBAOptions* opts); +struct mCoreOptions; +void mDirectorySetMapOptions(struct mDirectorySet* dirs, const struct mCoreOptions* opts); #endif #endif
M src/gb/core.csrc/gb/core.c

@@ -60,6 +60,11 @@ struct GB* gb = core->board;

gb->sync = sync; } +static void _GBCoreLoadConfig(struct mCore* core) { + UNUSED(core); + // TODO +} + static void _GBCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) { UNUSED(core); *width = GB_VIDEO_HORIZONTAL_PIXELS;

@@ -184,6 +189,7 @@ core->board = 0;

core->init = _GBCoreInit; core->deinit = _GBCoreDeinit; core->setSync = _GBCoreSetSync; + core->loadConfig = _GBCoreLoadConfig; core->desiredVideoDimensions = _GBCoreDesiredVideoDimensions; core->setVideoBuffer = _GBCoreSetVideoBuffer; core->getAudioChannel = _GBCoreGetAudioChannel;
M src/gba/context/context.csrc/gba/context/context.c

@@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this

* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "gba/context/context.h" +#include "gba/video.h" #include "gba/context/overrides.h" #include "util/memory.h"

@@ -54,10 +55,9 @@ char biosPath[PATH_MAX];

mCoreConfigDirectory(biosPath, PATH_MAX); strncat(biosPath, PATH_SEP "gba_bios.bin", PATH_MAX - strlen(biosPath)); - struct GBAOptions opts = { + struct mCoreOptions opts = { .bios = biosPath, .useBios = true, - .idleOptimization = IDLE_LOOP_DETECT, .logLevel = GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL | GBA_LOG_STATUS }; mCoreConfigLoad(&context->config);

@@ -161,7 +161,7 @@ return true;

} bool GBAContextStart(struct GBAContext* context) { - struct GBAOptions opts = { .bios = 0 }; + struct mCoreOptions opts = { .bios = 0 }; if (context->renderer) { GBAVideoAssociateRenderer(&context->gba->video, context->renderer);

@@ -180,7 +180,6 @@ if (opts.useBios && context->bios) {

GBALoadBIOS(context->gba, context->bios); } context->gba->logLevel = opts.logLevel; - context->gba->idleOptimization = opts.idleOptimization; GBAContextReset(context);
M src/gba/context/context.hsrc/gba/context/context.h

@@ -11,6 +11,7 @@

#include "core/directories.h" #include "core/config.h" #include "core/sync.h" +#include "gba/gba.h" #include "gba/input.h" struct GBAContext {

@@ -26,7 +27,7 @@ struct mDirectorySet dirs;

#endif struct ARMComponent* components[GBA_COMPONENT_MAX]; struct mCoreConfig config; - struct GBAOptions opts; + struct mCoreOptions opts; struct mInputMap inputMap; };
M src/gba/core.csrc/gba/core.c

@@ -11,6 +11,7 @@ #include "gba/gba.h"

#include "gba/renderers/video-software.h" #include "gba/serialize.h" #include "util/memory.h" +#include "util/vfs.h" struct GBACore { struct mCore d;

@@ -30,6 +31,8 @@ return false;

} core->cpu = cpu; core->board = gba; + + memset(&core->opts, 0, sizeof(core->opts)); GBACreate(gba); // TODO: Restore debugger and cheats

@@ -63,6 +66,29 @@ struct GBA* gba = core->board;

gba->sync = sync; } +static void _GBACoreLoadConfig(struct mCore* core) { + struct GBA* gba = core->board; + +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 + struct VFile* bios = 0; + if (core->opts.useBios) { + bios = VFileOpen(core->opts.bios, O_RDONLY); + } + GBALoadBIOS(gba, bios); +#endif + + const char* idleOptimization = mCoreConfigGetValue(&core->config, "idleOptimization"); + if (idleOptimization) { + if (strcasecmp(idleOptimization, "ignore") == 0) { + gba->idleOptimization = IDLE_LOOP_IGNORE; + } else if (strcasecmp(idleOptimization, "remove") == 0) { + gba->idleOptimization = IDLE_LOOP_REMOVE; + } else if (strcasecmp(idleOptimization, "detect") == 0) { + gba->idleOptimization = IDLE_LOOP_DETECT; + } + } +} + static void _GBACoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) { UNUSED(core); *width = VIDEO_HORIZONTAL_PIXELS;

@@ -109,6 +135,9 @@ }

static void _GBACoreReset(struct mCore* core) { ARMReset(core->cpu); + if (core->opts.skipBios) { + GBASkipBIOS(core->board); + } } static void _GBACoreRunFrame(struct mCore* core) {

@@ -178,6 +207,7 @@ core->board = 0;

core->init = _GBACoreInit; core->deinit = _GBACoreDeinit; core->setSync = _GBACoreSetSync; + core->loadConfig = _GBACoreLoadConfig; core->desiredVideoDimensions = _GBACoreDesiredVideoDimensions; core->setVideoBuffer = _GBACoreSetVideoBuffer; core->getAudioChannel = _GBACoreGetAudioChannel;
M src/gba/supervisor/thread.csrc/gba/supervisor/thread.c

@@ -372,7 +372,7 @@

return 0; } -void GBAMapOptionsToContext(const struct GBAOptions* opts, struct GBAThread* threadContext) { +void GBAMapOptionsToContext(const struct mCoreOptions* opts, struct GBAThread* threadContext) { if (opts->useBios) { threadContext->bios = VFileOpen(opts->bios, O_RDONLY); } else {

@@ -400,12 +400,10 @@ if (opts->audioBuffers) {

threadContext->audioBuffers = opts->audioBuffers; } - threadContext->idleOptimization = opts->idleOptimization; - mDirectorySetMapOptions(&threadContext->dirs, opts); } -void GBAMapArgumentsToContext(const struct GBAArguments* args, struct GBAThread* threadContext) { +void GBAMapArgumentsToContext(const struct mArguments* args, struct GBAThread* threadContext) { GBAThreadLoadROM(threadContext, args->fname); threadContext->fname = args->fname; threadContext->patch = VFileOpen(args->patch, O_RDONLY);
M src/gba/supervisor/thread.hsrc/gba/supervisor/thread.h

@@ -18,9 +18,9 @@

#include "util/threading.h" struct GBAThread; -struct GBAArguments; +struct mArguments; struct GBACheatSet; -struct GBAOptions; +struct mCoreOptions; typedef void (*GBAThreadCallback)(struct GBAThread* threadContext); typedef bool (*ThreadStopCallback)(struct GBAThread* threadContext);

@@ -93,8 +93,8 @@

struct GBACheatDevice* cheats; }; -void GBAMapOptionsToContext(const struct GBAOptions*, struct GBAThread*); -void GBAMapArgumentsToContext(const struct GBAArguments*, struct GBAThread*); +void GBAMapOptionsToContext(const struct mCoreOptions*, struct GBAThread*); +void GBAMapArgumentsToContext(const struct mArguments*, struct GBAThread*); bool GBAThreadStart(struct GBAThread* threadContext); bool GBAThreadHasStarted(struct GBAThread* threadContext);
M src/platform/commandline.csrc/platform/commandline.c

@@ -50,9 +50,10 @@ { "version", no_argument, 0, '\0' },

{ 0, 0, 0, 0 } }; -static bool _parseGraphicsArg(struct SubParser* parser, struct mCoreConfig* config, int option, const char* arg); +static bool _parseGraphicsArg(struct mSubParser* parser, int option, const char* arg); +static void _applyGraphicsArgs(struct mSubParser* parser, struct mCoreConfig* config); -bool parseArguments(struct GBAArguments* opts, struct mCoreConfig* config, int argc, char* const* argv, struct SubParser* subparser) { +bool parseArguments(struct mArguments* args, int argc, char* const* argv, struct mSubParser* subparser) { int ch; char options[64] = "b:c:hl:p:s:v:"

@@ -63,7 +64,7 @@ #ifdef USE_GDB_STUB

"g" #endif ; - memset(opts, 0, sizeof(*opts)); + memset(args, 0, sizeof(*args)); if (subparser && subparser->extraOptions) { // TODO: modularize options to subparsers strncat(options, subparser->extraOptions, sizeof(options) - strlen(options) - 1);

@@ -74,51 +75,51 @@ const struct option* opt = &_options[index];

switch (ch) { case '\0': if (strcmp(opt->name, "version") == 0) { - opts->showVersion = true; + args->showVersion = true; } else { return false; } break; case 'b': - mCoreConfigSetOverrideValue(config, "bios", optarg); + args->bios = strdup(optarg); break; case 'c': - opts->cheatsFile = strdup(optarg); + args->cheatsFile = strdup(optarg); break; #ifdef USE_CLI_DEBUGGER case 'd': - if (opts->debuggerType != DEBUGGER_NONE) { + if (args->debuggerType != DEBUGGER_NONE) { return false; } - opts->debuggerType = DEBUGGER_CLI; + args->debuggerType = DEBUGGER_CLI; break; #endif #ifdef USE_GDB_STUB case 'g': - if (opts->debuggerType != DEBUGGER_NONE) { + if (args->debuggerType != DEBUGGER_NONE) { return false; } - opts->debuggerType = DEBUGGER_GDB; + args->debuggerType = DEBUGGER_GDB; break; #endif case 'h': - opts->showHelp = true; + args->showHelp = true; break; case 'l': - mCoreConfigSetOverrideValue(config, "logLevel", optarg); + args->logLevel = atoi(optarg); break; case 'p': - opts->patch = strdup(optarg); + args->patch = strdup(optarg); break; case 's': - mCoreConfigSetOverrideValue(config, "frameskip", optarg); + args->frameskip = atoi(optarg); break; case 'v': - opts->movie = strdup(optarg); + args->movie = strdup(optarg); break; default: if (subparser) { - if (!subparser->parse(subparser, config, ch, optarg)) { + if (!subparser->parse(subparser, ch, optarg)) { return false; } }

@@ -128,39 +129,54 @@ }

argc -= optind; argv += optind; if (argc != 1) { - return opts->showHelp || opts->showVersion; + return args->showHelp || args->showVersion; } - opts->fname = strdup(argv[0]); + args->fname = strdup(argv[0]); return true; } -void freeArguments(struct GBAArguments* opts) { - free(opts->fname); - opts->fname = 0; +void applyArguments(struct mArguments* args, struct mSubParser* subparser, struct mCoreConfig* config) { + mCoreConfigSetOverrideIntValue(config, "frameskip", args->frameskip); + mCoreConfigSetOverrideIntValue(config, "logLevel", args->logLevel); + mCoreConfigSetOverrideValue(config, "bios", args->bios); + if (subparser) { + subparser->apply(subparser, config); + } +} + +void freeArguments(struct mArguments* args) { + free(args->fname); + args->fname = 0; + + free(args->patch); + args->patch = 0; + + free(args->movie); + args->movie = 0; - free(opts->patch); - opts->patch = 0; + free(args->cheatsFile); + args->cheatsFile = 0; - free(opts->movie); - opts->movie = 0; + free(args->bios); + args->bios = 0; } -void initParserForGraphics(struct SubParser* parser, struct GraphicsOpts* opts) { +void initParserForGraphics(struct mSubParser* parser, struct mGraphicsOpts* opts) { parser->usage = GRAPHICS_USAGE; parser->opts = opts; parser->parse = _parseGraphicsArg; + parser->apply = _applyGraphicsArgs; parser->extraOptions = GRAPHICS_OPTIONS; opts->multiplier = 0; opts->fullscreen = false; } -bool _parseGraphicsArg(struct SubParser* parser, struct mCoreConfig* config, int option, const char* arg) { +bool _parseGraphicsArg(struct mSubParser* parser, int option, const char* arg) { UNUSED(arg); - struct GraphicsOpts* graphicsOpts = parser->opts; + struct mGraphicsOpts* graphicsOpts = parser->opts; switch (option) { case 'f': graphicsOpts->fullscreen = true; - mCoreConfigSetOverrideIntValue(config, "fullscreen", 1); return true; case '1': case '2':

@@ -172,15 +188,18 @@ if (graphicsOpts->multiplier) {

return false; } graphicsOpts->multiplier = option - '0'; - mCoreConfigSetOverrideIntValue(config, "width", VIDEO_HORIZONTAL_PIXELS * graphicsOpts->multiplier); - mCoreConfigSetOverrideIntValue(config, "height", VIDEO_VERTICAL_PIXELS * graphicsOpts->multiplier); return true; default: return false; } } -struct ARMDebugger* createDebugger(struct GBAArguments* opts, struct GBAThread* context) { +void _applyGraphicsArgs(struct mSubParser* parser, struct mCoreConfig* config) { + struct mGraphicsOpts* graphicsOpts = parser->opts; + mCoreConfigSetOverrideIntValue(config, "fullscreen", graphicsOpts->fullscreen); +} + +struct ARMDebugger* createDebugger(struct mArguments* opts, struct GBAThread* context) { #ifndef USE_CLI_DEBUGGER UNUSED(context); #endif
M src/platform/commandline.hsrc/platform/commandline.h

@@ -8,8 +8,6 @@ #define COMMAND_LINE_H

#include "util/common.h" -#include "core/config.h" - enum DebuggerType { DEBUGGER_NONE = 0, #ifdef USE_CLI_DEBUGGER

@@ -21,11 +19,14 @@ #endif

DEBUGGER_MAX }; -struct GBAArguments { +struct mArguments { char* fname; char* patch; char* cheatsFile; char* movie; + char* bios; + int logLevel; + int frameskip; enum DebuggerType debuggerType; bool debugAtStart;

@@ -33,28 +34,31 @@ bool showHelp;

bool showVersion; }; -struct SubParser { +struct mCoreConfig; +struct mSubParser { const char* usage; - bool (*parse)(struct SubParser* parser, struct mCoreConfig* config, int option, const char* arg); + bool (*parse)(struct mSubParser* parser, int option, const char* arg); + void (*apply)(struct mSubParser* parser, struct mCoreConfig* config); const char* extraOptions; void* opts; }; -struct GraphicsOpts { +struct mGraphicsOpts { int multiplier; bool fullscreen; }; struct GBAThread; -bool parseArguments(struct GBAArguments* opts, struct mCoreConfig* config, int argc, char* const* argv, - struct SubParser* subparser); -void freeArguments(struct GBAArguments* opts); +bool parseArguments(struct mArguments* args, int argc, char* const* argv, + struct mSubParser* subparser); +void applyArguments(struct mArguments* args, struct mSubParser* subparser, struct mCoreConfig* config); +void freeArguments(struct mArguments* args); void usage(const char* arg0, const char* extraOptions); void version(const char* arg0); -void initParserForGraphics(struct SubParser* parser, struct GraphicsOpts* opts); -struct ARMDebugger* createDebugger(struct GBAArguments* opts, struct GBAThread* context); +void initParserForGraphics(struct mSubParser* parser, struct mGraphicsOpts* opts); +struct ARMDebugger* createDebugger(struct mArguments* opts, struct GBAThread* context); #endif
M src/platform/libretro/libretro.csrc/platform/libretro/libretro.c

@@ -48,9 +48,8 @@ static struct GBACheatDevice cheats;

static struct GBACheatSet cheatSet; static void _reloadSettings(void) { - struct GBAOptions opts = { + struct mCoreOptions opts = { .useBios = true, - .idleOptimization = IDLE_LOOP_REMOVE }; struct retro_variable var;

@@ -71,11 +70,11 @@ var.key = "mgba_idle_optimization";

var.value = 0; if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (strcmp(var.value, "Don't Remove") == 0) { - opts.idleOptimization = IDLE_LOOP_IGNORE; + mCoreConfigSetDefaultIntValue(&context.config, "idleOptimization", IDLE_LOOP_IGNORE); } else if (strcmp(var.value, "Remove Known") == 0) { - opts.idleOptimization = IDLE_LOOP_REMOVE; + mCoreConfigSetDefaultIntValue(&context.config, "idleOptimization", IDLE_LOOP_REMOVE); } else if (strcmp(var.value, "Detect and Remove") == 0) { - opts.idleOptimization = IDLE_LOOP_DETECT; + mCoreConfigSetDefaultIntValue(&context.config, "idleOptimization", IDLE_LOOP_DETECT); } }
M src/platform/openemu/mGBAGameCore.msrc/platform/openemu/mGBAGameCore.m

@@ -59,9 +59,8 @@ if ((self = [super init]))

{ // TODO: Add a log handler GBAContextInit(&context, 0); - struct GBAOptions opts = { + struct mCoreOptions opts = { .useBios = true, - .idleOptimization = IDLE_LOOP_REMOVE }; mCoreConfigLoadDefaults(&context.config, &opts); GBAVideoSoftwareRendererCreate(&renderer);
M src/platform/qt/ConfigController.cppsrc/platform/qt/ConfigController.cpp

@@ -126,9 +126,10 @@ mCoreConfigDeinit(&m_config);

mCoreConfigFreeOpts(&m_opts); } -bool ConfigController::parseArguments(GBAArguments* args, int argc, char* argv[], SubParser* subparser) { - if (::parseArguments(args, &m_config, argc, argv, subparser)) { +bool ConfigController::parseArguments(mArguments* args, int argc, char* argv[], mSubParser* subparser) { + if (::parseArguments(args, argc, argv, subparser)) { mCoreConfigFreeOpts(&m_opts); + applyArguments(args, subparser, &m_config); mCoreConfigMap(&m_config, &m_opts); return true; }
M src/platform/qt/ConfigController.hsrc/platform/qt/ConfigController.h

@@ -22,7 +22,7 @@

class QAction; class QMenu; -struct GBAArguments; +struct mArguments; struct GBACartridgeOverride; namespace QGBA {

@@ -64,8 +64,8 @@

ConfigController(QObject* parent = nullptr); ~ConfigController(); - const GBAOptions* options() const { return &m_opts; } - bool parseArguments(GBAArguments* args, int argc, char* argv[], SubParser* subparser = nullptr); + const mCoreOptions* options() const { return &m_opts; } + bool parseArguments(mArguments* args, int argc, char* argv[], mSubParser* subparser = nullptr); ConfigOption* addOption(const char* key); void updateOption(const char* key);

@@ -97,7 +97,7 @@ private:

Configuration* defaults() { return &m_config.defaultsTable; } mCoreConfig m_config; - GBAOptions m_opts; + mCoreOptions m_opts; QMap<QString, ConfigOption*> m_optionSet; QSettings* m_settings;
M src/platform/qt/GBAApp.cppsrc/platform/qt/GBAApp.cpp

@@ -52,9 +52,9 @@ if (!m_configController.getQtOption("displayDriver").isNull()) {

Display::setDriver(static_cast<Display::Driver>(m_configController.getQtOption("displayDriver").toInt())); } - GBAArguments args; - GraphicsOpts graphicsOpts; - SubParser subparser; + mArguments args; + mGraphicsOpts graphicsOpts; + mSubParser subparser; initParserForGraphics(&subparser, &graphicsOpts); bool loaded = m_configController.parseArguments(&args, argc, argv, &subparser); if (loaded && args.showHelp) {
M src/platform/qt/GameController.cppsrc/platform/qt/GameController.cpp

@@ -245,7 +245,7 @@ m_threadContext.override = override;

m_threadContext.hasOverride = true; } -void GameController::setOptions(const GBAOptions* opts) { +void GameController::setOptions(const mCoreOptions* opts) { setFrameskip(opts->frameskip); setAudioSync(opts->audioSync); setVideoSync(opts->videoSync);

@@ -257,7 +257,7 @@ setMute(opts->mute);

threadInterrupt(); mDirectorySetMapOptions(&m_threadContext.dirs, opts); - m_threadContext.idleOptimization = opts->idleOptimization; + // TODO: Put back idle optimization threadContinue(); }
M src/platform/qt/GameController.hsrc/platform/qt/GameController.h

@@ -25,7 +25,7 @@ #endif

} struct GBAAudio; -struct GBAOptions; +struct mCoreOptions; struct GBAVideoSoftwareRenderer; struct Configuration;

@@ -70,7 +70,7 @@

void setOverride(const GBACartridgeOverride& override); void clearOverride() { m_threadContext.hasOverride = false; } - void setOptions(const GBAOptions*); + void setOptions(const mCoreOptions*); int stateSlot() const { return m_stateSlot; }
M src/platform/qt/Window.cppsrc/platform/qt/Window.cpp

@@ -172,7 +172,7 @@ delete m_gifView;

#endif } -void Window::argumentsPassed(GBAArguments* args) { +void Window::argumentsPassed(mArguments* args) { loadConfig(); if (args->patch) {

@@ -197,7 +197,7 @@ m_config = config;

} void Window::loadConfig() { - const GBAOptions* opts = m_config->options(); + const mCoreOptions* opts = m_config->options(); reloadConfig(); // TODO: Move these to ConfigController

@@ -237,7 +237,7 @@ m_inputController.setConfiguration(m_config);

} void Window::reloadConfig() { - const GBAOptions* opts = m_config->options(); + const mCoreOptions* opts = m_config->options(); m_log.setLevels(opts->logLevel);
M src/platform/qt/Window.hsrc/platform/qt/Window.h

@@ -21,9 +21,7 @@ #include "GDBController.h"

#include "InputController.h" #include "LoadSaveState.h" #include "LogController.h" - -struct GBAOptions; -struct GBAArguments; +struct mArguments; namespace QGBA {

@@ -47,7 +45,7 @@

GameController* controller() { return m_controller; } void setConfig(ConfigController*); - void argumentsPassed(GBAArguments*); + void argumentsPassed(mArguments*); void resizeFrame(int width, int height);
M src/platform/sdl/main.csrc/platform/sdl/main.c

@@ -53,22 +53,15 @@ static void mSDLDeinit(struct mSDLRenderer* renderer);

// TODO: Clean up signatures #ifdef M_CORE_GBA -static int mSDLRunGBA(struct mSDLRenderer* renderer, struct GBAArguments* args, struct GBAOptions* opts, struct mCoreConfig* config); +static int mSDLRunGBA(struct mSDLRenderer* renderer, struct mArguments* args, struct mCoreOptions* opts, struct mCoreConfig* config); #endif -static int mSDLRun(struct mSDLRenderer* renderer, struct GBAArguments* args); +static int mSDLRun(struct mSDLRenderer* renderer, struct mArguments* args); int main(int argc, char** argv) { struct mSDLRenderer renderer = {}; - struct mInputMap inputMap; - mInputMapInit(&inputMap, &GBAInputInfo); - - struct mCoreConfig config; - mCoreConfigInit(&config, PORT); - mCoreConfigLoad(&config); - - struct GBAOptions opts = { + struct mCoreOptions opts = { .width = 0, .height = 0, .useBios = true,

@@ -78,25 +71,21 @@ .videoSync = false,

.audioSync = true, }; - struct GBAArguments args; - struct GraphicsOpts graphicsOpts; + struct mArguments args; + struct mGraphicsOpts graphicsOpts; - struct SubParser subparser; + struct mSubParser subparser; initParserForGraphics(&subparser, &graphicsOpts); - bool parsed = parseArguments(&args, &config, argc, argv, &subparser); + bool parsed = parseArguments(&args, argc, argv, &subparser); if (!parsed || args.showHelp) { usage(argv[0], subparser.usage); - freeArguments(&args); mCoreConfigFreeOpts(&opts); - mCoreConfigDeinit(&config); return !parsed; } if (args.showVersion) { version(argv[0]); - freeArguments(&args); mCoreConfigFreeOpts(&opts); - mCoreConfigDeinit(&config); return 0; }

@@ -108,7 +97,6 @@ if (!vf) {

printf("Could not open game. Are you sure the file exists?\n"); freeArguments(&args); mCoreConfigFreeOpts(&opts); - mCoreConfigDeinit(&config); return 1; } #ifdef M_CORE_GBA

@@ -153,13 +141,15 @@ else {

printf("Could not run game. Are you sure the file exists and is a compatible game?\n"); freeArguments(&args); mCoreConfigFreeOpts(&opts); - mCoreConfigDeinit(&config); return 1; } } - mCoreConfigLoadDefaults(&config, &opts); - mCoreConfigMap(&config, &opts); + mInputMapInit(&renderer.core->inputMap, &GBAInputInfo); + mCoreInitConfig(renderer.core, PORT); + applyArguments(&args, &subparser, &renderer.core->config); + + mCoreConfigLoadDefaults(&renderer.core->config, &opts); renderer.viewportWidth = opts.width; renderer.viewportHeight = opts.height;

@@ -180,7 +170,7 @@

if (!mSDLInit(&renderer)) { freeArguments(&args); mCoreConfigFreeOpts(&opts); - mCoreConfigDeinit(&config); + mCoreConfigDeinit(&renderer.core->config); return 1; }

@@ -188,32 +178,33 @@ if (renderer.core) {

// TODO: Check return code renderer.core->init(renderer.core); } + mCoreLoadConfig(renderer.core); - renderer.player.bindings = &inputMap; - mSDLInitBindingsGBA(&inputMap); + renderer.player.bindings = &renderer.core->inputMap; + mSDLInitBindingsGBA(&renderer.core->inputMap); mSDLInitEvents(&renderer.events); - mSDLEventsLoadConfig(&renderer.events, mCoreConfigGetInput(&config)); + mSDLEventsLoadConfig(&renderer.events, mCoreConfigGetInput(&renderer.core->config)); mSDLAttachPlayer(&renderer.events, &renderer.player); - mSDLPlayerLoadConfig(&renderer.player, mCoreConfigGetInput(&config)); + mSDLPlayerLoadConfig(&renderer.player, mCoreConfigGetInput(&renderer.core->config)); int ret; // TODO: Use opts and config ret = mSDLRun(&renderer, &args); mSDLDetachPlayer(&renderer.events, &renderer.player); - mInputMapDeinit(&inputMap); + mInputMapDeinit(&renderer.core->inputMap); mSDLDeinit(&renderer); freeArguments(&args); mCoreConfigFreeOpts(&opts); - mCoreConfigDeinit(&config); + mCoreConfigDeinit(&renderer.core->config); return ret; } #ifdef M_CORE_GBA -int mSDLRunGBA(struct mSDLRenderer* renderer, struct GBAArguments* args, struct GBAOptions* opts, struct mCoreConfig* config) { +int mSDLRunGBA(struct mSDLRenderer* renderer, struct mArguments* args, struct mCoreOptions* opts, struct mCoreConfig* config) { struct GBAThread context = { .userData = renderer };

@@ -265,7 +256,7 @@ return didFail;

} #endif -int mSDLRun(struct mSDLRenderer* renderer, struct GBAArguments* args) { +int mSDLRun(struct mSDLRenderer* renderer, struct mArguments* args) { struct mCoreThread thread = { .core = renderer->core, .sync = {
M src/platform/sdl/sdl-events.csrc/platform/sdl/sdl-events.c

@@ -375,9 +375,9 @@ }

#endif } -static void _pauseAfterFrame(struct GBAThread* context) { +static void _pauseAfterFrame(struct mCoreThread* context) { context->frameCallback = 0; - GBAThreadPauseFromThread(context); + mCoreThreadPauseFromThread(context); } static void _mSDLHandleKeypressGBA(struct GBAThread* context, struct mSDLPlayer* sdlContext, const struct SDL_KeyboardEvent* event) {

@@ -415,11 +415,6 @@ GBAThreadTakeScreenshot(context);

GBAThreadContinue(context); return; #endif - case SDLK_BACKSLASH: - GBAThreadPause(context); - context->frameCallback = _pauseAfterFrame; - GBAThreadUnpause(context); - return; case SDLK_BACKQUOTE: GBAThreadInterrupt(context); GBARewind(context, 10);

@@ -442,11 +437,6 @@ break;

#endif case SDLK_p: GBAThreadTogglePause(context); - break; - case SDLK_n: - GBAThreadPause(context); - context->frameCallback = _pauseAfterFrame; - GBAThreadUnpause(context); break; case SDLK_r: GBAThreadReset(context);

@@ -575,7 +565,9 @@ // TODO: Put back screenshots

return; #endif case SDLK_BACKSLASH: - // TODO: Put back frame advance + mCoreThreadPause(context); + context->frameCallback = _pauseAfterFrame; + mCoreThreadUnpause(context); return; case SDLK_BACKQUOTE: // TODO: Put back rewind

@@ -599,7 +591,9 @@ case SDLK_p:

mCoreThreadTogglePause(context); break; case SDLK_n: - // TODO: Put back frame advance + mCoreThreadPause(context); + context->frameCallback = _pauseAfterFrame; + mCoreThreadUnpause(context); break; case SDLK_r: mCoreThreadReset(context);
M src/platform/test/fuzz-main.csrc/platform/test/fuzz-main.c

@@ -36,7 +36,7 @@ };

static void _GBAFuzzRunloop(struct GBAContext* context, int frames); static void _GBAFuzzShutdown(int signal); -static bool _parseFuzzOpts(struct SubParser* parser, struct mCoreConfig* config, int option, const char* arg); +static bool _parseFuzzOpts(struct mSubParser* parser, int option, const char* arg); static bool _dispatchExiting = false;

@@ -44,7 +44,7 @@ int main(int argc, char** argv) {

signal(SIGINT, _GBAFuzzShutdown); struct FuzzOpts fuzzOpts = { false, 0, 0, 0, 0 }; - struct SubParser subparser = { + struct mSubParser subparser = { .usage = FUZZ_USAGE, .parse = _parseFuzzOpts, .extraOptions = FUZZ_OPTIONS,

@@ -53,26 +53,23 @@ };

struct GBAContext context; GBAContextInit(&context, "fuzz"); - struct GBAOptions opts = { - .idleOptimization = IDLE_LOOP_DETECT - }; + struct mCoreOptions opts = {}; // TODO: Put back idle loops mCoreConfigLoadDefaults(&context.config, &opts); mCoreConfigFreeOpts(&opts); - struct GBAArguments args; - bool parsed = parseArguments(&args, &context.config, argc, argv, &subparser); + struct mArguments args; + bool parsed = parseArguments(&args, argc, argv, &subparser); if (!parsed || args.showHelp) { usage(argv[0], FUZZ_USAGE); - freeArguments(&args); GBAContextDeinit(&context); return !parsed; } if (args.showVersion) { version(argv[0]); - freeArguments(&args); GBAContextDeinit(&context); return 0; } + applyArguments(&args, NULL, &context.config); struct GBAVideoSoftwareRenderer renderer; renderer.outputBuffer = 0;

@@ -161,8 +158,7 @@ UNUSED(signal);

_dispatchExiting = true; } -static bool _parseFuzzOpts(struct SubParser* parser, struct mCoreConfig* config, int option, const char* arg) { - UNUSED(config); +static bool _parseFuzzOpts(struct mSubParser* parser, int option, const char* arg) { struct FuzzOpts* opts = parser->opts; errno = 0; switch (option) {
M src/platform/test/perf-main.csrc/platform/test/perf-main.c

@@ -38,7 +38,7 @@ };

static void _GBAPerfRunloop(struct GBAThread* context, int* frames, bool quiet); static void _GBAPerfShutdown(int signal); -static bool _parsePerfOpts(struct SubParser* parser, struct mCoreConfig* config, int option, const char* arg); +static bool _parsePerfOpts(struct mSubParser* parser, int option, const char* arg); static void _loadSavestate(struct GBAThread* context); static struct GBAThread* _thread;

@@ -52,7 +52,7 @@ struct GBAVideoSoftwareRenderer renderer;

GBAVideoSoftwareRendererCreate(&renderer); struct PerfOpts perfOpts = { false, false, 0, 0, 0 }; - struct SubParser subparser = { + struct mSubParser subparser = { .usage = PERF_USAGE, .parse = _parsePerfOpts, .extraOptions = PERF_OPTIONS,

@@ -63,13 +63,11 @@ struct mCoreConfig config;

mCoreConfigInit(&config, "perf"); mCoreConfigLoad(&config); - struct GBAOptions opts = { - .idleOptimization = IDLE_LOOP_DETECT - }; + struct mCoreOptions opts = {}; // TODO: Put back idle loops mCoreConfigLoadDefaults(&config, &opts); - struct GBAArguments args; - bool parsed = parseArguments(&args, &config, argc, argv, &subparser); + struct mArguments args; + bool parsed = parseArguments(&args, argc, argv, &subparser); if (!parsed || args.showHelp) { usage(argv[0], PERF_USAGE); freeArguments(&args);

@@ -84,6 +82,7 @@ mCoreConfigFreeOpts(&opts);

mCoreConfigDeinit(&config); return 0; } + applyArguments(&args, NULL, &config); renderer.outputBuffer = malloc(256 * 256 * 4); renderer.outputBufferStride = 256;

@@ -212,8 +211,7 @@ _dispatchExiting = true;

ConditionWake(&_thread->sync.videoFrameAvailableCond); } -static bool _parsePerfOpts(struct SubParser* parser, struct mCoreConfig* config, int option, const char* arg) { - UNUSED(config); +static bool _parsePerfOpts(struct mSubParser* parser, int option, const char* arg) { struct PerfOpts* opts = parser->opts; errno = 0; switch (option) {