Core: Refactor config loading in mCore
jump to
@@ -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);
@@ -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
@@ -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); +}
@@ -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
@@ -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) {
@@ -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
@@ -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;
@@ -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);
@@ -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; };
@@ -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;
@@ -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);
@@ -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);
@@ -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
@@ -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
@@ -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); } }
@@ -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);
@@ -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; }
@@ -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;
@@ -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) {
@@ -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(); }
@@ -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; }
@@ -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);
@@ -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);
@@ -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 = {
@@ -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);
@@ -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) {
@@ -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) {