GBA Config: Refresh configuration system to be more versatile
@@ -1,34 +1,44 @@
#include "gba-config.h" #include "platform/commandline.h" -#include "util/configuration.h" #define SECTION_NAME_MAX 128 -static const char* _lookupValue(const struct Configuration* config, const char* key, const char* port) { - if (port) { - char sectionName[SECTION_NAME_MAX]; - snprintf(sectionName, SECTION_NAME_MAX, "ports.%s", port); - sectionName[SECTION_NAME_MAX - 1] = '\0'; - const char* value = ConfigurationGetValue(config, sectionName, key); +static const char* _lookupValue(const struct GBAConfig* config, const char* key) { + const char* value; + if (config->port) { + value = ConfigurationGetValue(&config->configTable, config->port, key); if (value) { return value; } } - return ConfigurationGetValue(config, 0, key); + value = ConfigurationGetValue(&config->configTable, 0, key); + if (value) { + return value; + } + if (config->port) { + value = ConfigurationGetValue(&config->defaultsTable, config->port, key); + if (value) { + return value; + } + } + return ConfigurationGetValue(&config->defaultsTable, 0, key); } -static bool _lookupCharValue(const struct Configuration* config, const char* key, const char* port, char** out) { - const char* value = _lookupValue(config, key, port); +static bool _lookupCharValue(const struct GBAConfig* config, const char* key, char** out) { + const char* value = _lookupValue(config, key); if (!value) { return false; + } + if (*out) { + free(*out); } *out = strdup(value); return true; } -static bool _lookupIntValue(const struct Configuration* config, const char* key, const char* port, int* out) { - const char* charValue = _lookupValue(config, key, port); +static bool _lookupIntValue(const struct GBAConfig* config, const char* key, int* out) { + const char* charValue = _lookupValue(config, key); if (!charValue) { return false; }@@ -41,8 +51,8 @@ *out = value;
return true; } -static bool _lookupUIntValue(const struct Configuration* config, const char* key, const char* port, unsigned* out) { - const char* charValue = _lookupValue(config, key, port); +static bool _lookupUIntValue(const struct GBAConfig* config, const char* key, unsigned* out) { + const char* charValue = _lookupValue(config, key); if (!charValue) { return false; }@@ -55,8 +65,8 @@ *out = value;
return true; } -static bool _lookupFloatValue(const struct Configuration* config, const char* key, const char* port, float* out) { - const char* charValue = _lookupValue(config, key, port); +static bool _lookupFloatValue(const struct GBAConfig* config, const char* key, float* out) { + const char* charValue = _lookupValue(config, key); if (!charValue) { return false; }@@ -69,35 +79,97 @@ *out = value;
return true; } -bool GBAConfigLoad(struct Configuration* config) { - return ConfigurationRead(config, BINARY_NAME ".ini"); +void GBAConfigInit(struct GBAConfig* config, const char* port) { + ConfigurationInit(&config->configTable); + ConfigurationInit(&config->defaultsTable); + config->port = malloc(strlen("ports.") + strlen(port) + 1); + sprintf(config->port, "ports.%s", port); } -void GBAConfigMapGeneralOpts(const struct Configuration* config, const char* port, struct GBAOptions* opts) { - _lookupCharValue(config, "bios", port, &opts->bios); - _lookupIntValue(config, "logLevel", port, &opts->logLevel); - _lookupIntValue(config, "frameskip", port, &opts->frameskip); - _lookupIntValue(config, "rewindBufferCapacity", port, &opts->rewindBufferCapacity); - _lookupIntValue(config, "rewindBufferInterval", port, &opts->rewindBufferInterval); - _lookupFloatValue(config, "fpsTarget", port, &opts->fpsTarget); +void GBAConfigDeinit(struct GBAConfig* config) { + ConfigurationDeinit(&config->configTable); + ConfigurationDeinit(&config->defaultsTable); + free(config->port); +} + +bool GBAConfigLoad(struct GBAConfig* config) { + return ConfigurationRead(&config->configTable, BINARY_NAME ".ini"); +} + +bool GBAConfigSave(const struct GBAConfig* config) { + return ConfigurationWrite(&config->configTable, BINARY_NAME ".ini"); +} + +void GBAConfigSetValue(struct GBAConfig* config, const char* key, const char* value) { + ConfigurationSetValue(&config->configTable, config->port, key, value); +} + +void GBAConfigSetIntValue(struct GBAConfig* config, const char* key, int value) { + ConfigurationSetIntValue(&config->configTable, config->port, key, value); +} + +void GBAConfigSetUIntValue(struct GBAConfig* config, const char* key, unsigned value) { + ConfigurationSetUIntValue(&config->configTable, config->port, key, value); +} + +void GBAConfigSetFloatValue(struct GBAConfig* config, const char* key, float value) { + ConfigurationSetFloatValue(&config->configTable, config->port, key, value); +} + +void GBAConfigSetDefaultValue(struct GBAConfig* config, const char* key, const char* value) { + ConfigurationSetValue(&config->defaultsTable, config->port, key, value); +} + +void GBAConfigSetDefaultIntValue(struct GBAConfig* config, const char* key, int value) { + ConfigurationSetIntValue(&config->defaultsTable, config->port, key, value); +} + +void GBAConfigSetDefaultUIntValue(struct GBAConfig* config, const char* key, unsigned value) { + ConfigurationSetUIntValue(&config->defaultsTable, config->port, key, value); +} + +void GBAConfigSetDefaultFloatValue(struct GBAConfig* config, const char* key, float value) { + ConfigurationSetFloatValue(&config->defaultsTable, config->port, key, value); +} + +void GBAConfigMap(const struct GBAConfig* config, struct GBAOptions* opts) { + _lookupCharValue(config, "bios", &opts->bios); + _lookupIntValue(config, "logLevel", &opts->logLevel); + _lookupIntValue(config, "frameskip", &opts->frameskip); + _lookupIntValue(config, "rewindBufferCapacity", &opts->rewindBufferCapacity); + _lookupIntValue(config, "rewindBufferInterval", &opts->rewindBufferInterval); + _lookupFloatValue(config, "fpsTarget", &opts->fpsTarget); unsigned audioBuffers; - if (_lookupUIntValue(config, "audioBuffers", port, &audioBuffers)) { + if (_lookupUIntValue(config, "audioBuffers", &audioBuffers)) { opts->audioBuffers = audioBuffers; } int fakeBool; - if (_lookupIntValue(config, "audioSync", port, &fakeBool)) { + if (_lookupIntValue(config, "audioSync", &fakeBool)) { opts->audioSync = fakeBool; } - if (_lookupIntValue(config, "videoSync", port, &fakeBool)) { + if (_lookupIntValue(config, "videoSync", &fakeBool)) { opts->videoSync = fakeBool; } + + _lookupIntValue(config, "fullscreen", &opts->fullscreen); + _lookupIntValue(config, "width", &opts->width); + _lookupIntValue(config, "height", &opts->height); } -void GBAConfigMapGraphicsOpts(const struct Configuration* config, const char* port, struct GBAOptions* opts) { - _lookupIntValue(config, "fullscreen", port, &opts->fullscreen); - _lookupIntValue(config, "width", port, &opts->width); - _lookupIntValue(config, "height", port, &opts->height); +void GBAConfigLoadDefaults(struct GBAConfig* config, const struct GBAOptions* opts) { + ConfigurationSetValue(&config->defaultsTable, 0, "bios", opts->bios); + ConfigurationSetIntValue(&config->defaultsTable, 0, "logLevel", opts->logLevel); + ConfigurationSetIntValue(&config->defaultsTable, 0, "frameskip", opts->frameskip); + ConfigurationSetIntValue(&config->defaultsTable, 0, "rewindBufferCapacity", opts->rewindBufferCapacity); + ConfigurationSetIntValue(&config->defaultsTable, 0, "rewindBufferInterval", opts->rewindBufferInterval); + ConfigurationSetFloatValue(&config->defaultsTable, 0, "fpsTarget", opts->fpsTarget); + ConfigurationSetUIntValue(&config->defaultsTable, 0, "audioBuffers", opts->audioBuffers); + ConfigurationSetIntValue(&config->defaultsTable, 0, "audioSync", opts->audioSync); + ConfigurationSetIntValue(&config->defaultsTable, 0, "videoSync", opts->videoSync); + ConfigurationSetIntValue(&config->defaultsTable, 0, "fullscreen", opts->fullscreen); + ConfigurationSetIntValue(&config->defaultsTable, 0, "width", opts->width); + ConfigurationSetIntValue(&config->defaultsTable, 0, "height", opts->height); } void GBAConfigFreeOpts(struct GBAOptions* opts) {
@@ -3,7 +3,13 @@ #define GBA_CONFIG_H
#include "util/common.h" -struct Configuration; +#include "util/configuration.h" + +struct GBAConfig { + struct Configuration configTable; + struct Configuration defaultsTable; + char* port; +}; struct GBAOptions { char* bios;@@ -22,10 +28,25 @@ bool videoSync;
bool audioSync; }; -bool GBAConfigLoad(struct Configuration*); +void GBAConfigInit(struct GBAConfig*, const char* port); +void GBAConfigDeinit(struct GBAConfig*); + +bool GBAConfigLoad(struct GBAConfig*); +bool GBAConfigSave(const struct GBAConfig*); + +void GBAConfigSetValue(struct GBAConfig*, const char* key, const char* value); +void GBAConfigSetIntValue(struct GBAConfig*, const char* key, int value); +void GBAConfigSetUIntValue(struct GBAConfig*, const char* key, unsigned value); +void GBAConfigSetFloatValue(struct GBAConfig*, const char* key, float value); + +void GBAConfigSetDefaultValue(struct GBAConfig*, const char* key, const char* value); +void GBAConfigSetDefaultIntValue(struct GBAConfig*, const char* key, int value); +void GBAConfigSetDefaultUIntValue(struct GBAConfig*, const char* key, unsigned value); +void GBAConfigSetDefaultFloatValue(struct GBAConfig*, const char* key, float value); + +void GBAConfigMap(const struct GBAConfig* config, struct GBAOptions* opts); +void GBAConfigLoadDefaults(struct GBAConfig* config, const struct GBAOptions* opts); -void GBAConfigMapGeneralOpts(const struct Configuration*, const char* port, struct GBAOptions*); -void GBAConfigMapGraphicsOpts(const struct Configuration*, const char* port, struct GBAOptions*); -void GBAConfigFreeOpts(struct GBAOptions*); +void GBAConfigFreeOpts(struct GBAOptions* opts); #endif
@@ -38,9 +38,9 @@ { "patch", required_argument, 0, 'p' },
{ 0, 0, 0, 0 } }; -bool _parseGraphicsArg(struct SubParser* parser, struct GBAOptions* gbaOpts, int option, const char* arg); +bool _parseGraphicsArg(struct SubParser* parser, struct GBAConfig* config, int option, const char* arg); -bool parseArguments(struct GBAArguments* opts, struct GBAOptions* gbaOpts, int argc, char* const* argv, struct SubParser* subparser) { +bool parseArguments(struct GBAArguments* opts, struct GBAConfig* config, int argc, char* const* argv, struct SubParser* subparser) { int ch; char options[64] = "b:Dl:p:s:"@@ -58,10 +58,7 @@ }
while ((ch = getopt_long(argc, argv, options, _options, 0)) != -1) { switch (ch) { case 'b': - if (gbaOpts->bios) { - free(gbaOpts->bios); - } - gbaOpts->bios = strdup(optarg); + GBAConfigSetDefaultValue(config, "bios", optarg); break; case 'D': opts->dirmode = true;@@ -83,17 +80,17 @@ opts->debuggerType = DEBUGGER_GDB;
break; #endif case 'l': - gbaOpts->logLevel = atoi(optarg); + GBAConfigSetDefaultValue(config, "logLevel", optarg); break; case 'p': opts->patch = strdup(optarg); break; case 's': - gbaOpts->frameskip = atoi(optarg); + GBAConfigSetDefaultValue(config, "frameskip", optarg); break; default: if (subparser) { - if (!subparser->parse(subparser, gbaOpts, ch, optarg)) { + if (!subparser->parse(subparser, config, ch, optarg)) { return false; } }@@ -125,12 +122,12 @@ parser->extraOptions = GRAPHICS_OPTIONS;
opts->multiplier = 0; } -bool _parseGraphicsArg(struct SubParser* parser, struct GBAOptions* gbaOpts, int option, const char* arg) { +bool _parseGraphicsArg(struct SubParser* parser, struct GBAConfig* config, int option, const char* arg) { UNUSED(arg); struct GraphicsOpts* graphicsOpts = parser->opts; switch (option) { case 'f': - gbaOpts->fullscreen = 1; + GBAConfigSetDefaultIntValue(config, "fullscreen", 1); return true; case '1': case '2':@@ -140,8 +137,8 @@ if (graphicsOpts->multiplier) {
return false; } graphicsOpts->multiplier = option - '0'; - gbaOpts->width = VIDEO_HORIZONTAL_PIXELS * graphicsOpts->multiplier; - gbaOpts->height = VIDEO_VERTICAL_PIXELS * graphicsOpts->multiplier; + GBAConfigSetDefaultIntValue(config, "width", VIDEO_HORIZONTAL_PIXELS * graphicsOpts->multiplier); + GBAConfigSetDefaultIntValue(config, "height", VIDEO_VERTICAL_PIXELS * graphicsOpts->multiplier); return true; default: return false;
@@ -27,7 +27,7 @@ };
struct SubParser { const char* usage; - bool (*parse)(struct SubParser* parser, struct GBAOptions* gbaOpts, int option, const char* arg); + bool (*parse)(struct SubParser* parser, struct GBAConfig* config, int option, const char* arg); const char* extraOptions; void* opts; };@@ -36,7 +36,7 @@ struct GraphicsOpts {
int multiplier; }; -bool parseArguments(struct GBAArguments* opts, struct GBAOptions* gbaOpts, int argc, char* const* argv, struct SubParser* subparser); +bool parseArguments(struct GBAArguments* opts, struct GBAConfig* config, int argc, char* const* argv, struct SubParser* subparser); void freeArguments(struct GBAArguments* opts); void usage(const char* arg0, const char* extraOptions);
@@ -28,7 +28,7 @@ };
static void _GBAPerfRunloop(struct GBAThread* context, int* frames, bool quiet); static void _GBAPerfShutdown(int signal); -static bool _parsePerfOpts(struct SubParser* parser, struct GBAOptions* gbaOpts, int option, const char* arg); +static bool _parsePerfOpts(struct SubParser* parser, struct GBAConfig* config, int option, const char* arg); static struct GBAThread* _thread;@@ -46,10 +46,16 @@ .extraOptions = PERF_OPTIONS,
.opts = &perfOpts }; + struct GBAConfig config; + GBAConfigInit(&config, 0); + struct GBAOptions opts = {}; struct GBAArguments args = {}; - if (!parseArguments(&args, &opts, argc, argv, &subparser)) { + if (!parseArguments(&args, &config, argc, argv, &subparser)) { usage(argv[0], PERF_USAGE); + freeArguments(&args); + GBAConfigFreeOpts(&opts); + GBAConfigDeinit(&config); return 1; }@@ -66,11 +72,11 @@
context.debugger = createDebugger(&args); char gameCode[5] = { 0 }; + GBAConfigMap(&config, &opts); + opts.audioSync = false; + opts.videoSync = false; GBAMapArgumentsToContext(&args, &context); GBAMapOptionsToContext(&opts, &context); - - context.sync.audioWait = false; - context.sync.videoFrameWait = false; GBAThreadStart(&context); GBAGetGameCode(context.gba, gameCode);@@ -90,6 +96,7 @@
GBAThreadJoin(&context); GBAConfigFreeOpts(&opts); freeArguments(&args); + GBAConfigDeinit(&config); free(context.debugger); free(renderer.outputBuffer);@@ -153,8 +160,8 @@ _thread->state = THREAD_EXITING;
pthread_mutex_unlock(&_thread->stateMutex); } -static bool _parsePerfOpts(struct SubParser* parser, struct GBAOptions* gbaOpts, int option, const char* arg) { - UNUSED(gbaOpts); +static bool _parsePerfOpts(struct SubParser* parser, struct GBAConfig* config, int option, const char* arg) { + UNUSED(config); struct PerfOpts* opts = parser->opts; errno = 0; switch (option) {
@@ -16,24 +16,19 @@ {
QApplication::setApplicationName(PROJECT_NAME); QApplication::setApplicationVersion(PROJECT_VERSION); - struct Configuration config; - - ConfigurationInit(&config); - GBAConfigLoad(&config); + GBAConfigInit(&m_config, PORT); + GBAConfigLoad(&m_config); m_opts.audioSync = GameController::AUDIO_SYNC; m_opts.videoSync = GameController::VIDEO_SYNC; - - GBAConfigMapGeneralOpts(&config, PORT, &m_opts); - GBAConfigMapGraphicsOpts(&config, PORT, &m_opts); + GBAConfigLoadDefaults(&m_config, &m_opts); - ConfigurationDeinit(&config); + bool parsed = parseArguments(&m_args, &m_config, argc, argv, 0); + GBAConfigMap(&m_config, &m_opts); + m_window.setOptions(&m_opts); - if (parseArguments(&m_args, &m_opts, argc, argv, 0)) { - m_window.setOptions(&m_opts); + if (parsed) { m_window.argumentsPassed(&m_args); - } else { - m_window.setOptions(&m_opts); } m_window.show();@@ -42,6 +37,7 @@
GBAApp::~GBAApp() { freeArguments(&m_args); GBAConfigFreeOpts(&m_opts); + GBAConfigDeinit(&m_config); } bool GBAApp::event(QEvent* event) {
@@ -29,7 +29,7 @@ Window m_window;
GBAArguments m_args; GBAOptions m_opts; - Configuration m_config; + GBAConfig m_config; }; }
@@ -65,8 +65,8 @@ int main(int argc, char** argv) {
struct GLSoftwareRenderer renderer; GBAVideoSoftwareRendererCreate(&renderer.d); - struct Configuration config; - ConfigurationInit(&config); + struct GBAConfig config; + GBAConfigInit(&config, PORT); GBAConfigLoad(&config); struct GBAOptions opts = {@@ -74,19 +74,21 @@ .audioBuffers = 512,
.videoSync = false, .audioSync = true, }; + GBAConfigLoadDefaults(&config, &opts); + struct GBAArguments args = {}; struct GraphicsOpts graphicsOpts = {}; struct SubParser subparser; - GBAConfigMapGeneralOpts(&config, PORT, &opts); - GBAConfigMapGraphicsOpts(&config, PORT, &opts); + GBAConfigMap(&config, &opts); initParserForGraphics(&subparser, &graphicsOpts); - if (!parseArguments(&args, &opts, argc, argv, &subparser)) { + if (!parseArguments(&args, &config, argc, argv, &subparser)) { usage(argv[0], subparser.usage); freeArguments(&args); GBAConfigFreeOpts(&opts); + GBAConfigDeinit(&config); return 1; }@@ -100,6 +102,7 @@
if (!_GBASDLInit(&renderer)) { freeArguments(&args); GBAConfigFreeOpts(&opts); + GBAConfigDeinit(&config); return 1; }@@ -120,7 +123,7 @@ GBASDLInitAudio(&renderer.audio);
renderer.events.bindings = &context.inputMap; GBASDLInitEvents(&renderer.events); - GBASDLEventsLoadConfig(&renderer.events, &config); + GBASDLEventsLoadConfig(&renderer.events, &config.configTable); // TODO: Don't use this directly GBAThreadStart(&context);@@ -129,6 +132,7 @@
GBAThreadJoin(&context); freeArguments(&args); GBAConfigFreeOpts(&opts); + GBAConfigDeinit(&config); free(context.debugger); _GBASDLDeinit(&renderer);