GBA Config: Refresh configuration system to be more versatile

This commit is contained in:
Jeffrey Pfau 2014-11-04 23:54:09 -08:00
parent e884bc4d7a
commit 2ddb074bda
8 changed files with 175 additions and 78 deletions

View File

@ -1,34 +1,44 @@
#include "gba-config.h" #include "gba-config.h"
#include "platform/commandline.h" #include "platform/commandline.h"
#include "util/configuration.h"
#define SECTION_NAME_MAX 128 #define SECTION_NAME_MAX 128
static const char* _lookupValue(const struct Configuration* config, const char* key, const char* port) { static const char* _lookupValue(const struct GBAConfig* config, const char* key) {
if (port) { const char* value;
char sectionName[SECTION_NAME_MAX]; if (config->port) {
snprintf(sectionName, SECTION_NAME_MAX, "ports.%s", port); value = ConfigurationGetValue(&config->configTable, config->port, key);
sectionName[SECTION_NAME_MAX - 1] = '\0';
const char* value = ConfigurationGetValue(config, sectionName, key);
if (value) { if (value) {
return 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) { static bool _lookupCharValue(const struct GBAConfig* config, const char* key, char** out) {
const char* value = _lookupValue(config, key, port); const char* value = _lookupValue(config, key);
if (!value) { if (!value) {
return false; return false;
} }
if (*out) {
free(*out);
}
*out = strdup(value); *out = strdup(value);
return true; return true;
} }
static bool _lookupIntValue(const struct Configuration* config, const char* key, const char* port, int* out) { static bool _lookupIntValue(const struct GBAConfig* config, const char* key, int* out) {
const char* charValue = _lookupValue(config, key, port); const char* charValue = _lookupValue(config, key);
if (!charValue) { if (!charValue) {
return false; return false;
} }
@ -41,8 +51,8 @@ static bool _lookupIntValue(const struct Configuration* config, const char* key,
return true; return true;
} }
static bool _lookupUIntValue(const struct Configuration* config, const char* key, const char* port, unsigned* out) { static bool _lookupUIntValue(const struct GBAConfig* config, const char* key, unsigned* out) {
const char* charValue = _lookupValue(config, key, port); const char* charValue = _lookupValue(config, key);
if (!charValue) { if (!charValue) {
return false; return false;
} }
@ -55,8 +65,8 @@ static bool _lookupUIntValue(const struct Configuration* config, const char* key
return true; return true;
} }
static bool _lookupFloatValue(const struct Configuration* config, const char* key, const char* port, float* out) { static bool _lookupFloatValue(const struct GBAConfig* config, const char* key, float* out) {
const char* charValue = _lookupValue(config, key, port); const char* charValue = _lookupValue(config, key);
if (!charValue) { if (!charValue) {
return false; return false;
} }
@ -69,35 +79,97 @@ static bool _lookupFloatValue(const struct Configuration* config, const char* ke
return true; return true;
} }
bool GBAConfigLoad(struct Configuration* config) { void GBAConfigInit(struct GBAConfig* config, const char* port) {
return ConfigurationRead(config, BINARY_NAME ".ini"); 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) { void GBAConfigDeinit(struct GBAConfig* config) {
_lookupCharValue(config, "bios", port, &opts->bios); ConfigurationDeinit(&config->configTable);
_lookupIntValue(config, "logLevel", port, &opts->logLevel); ConfigurationDeinit(&config->defaultsTable);
_lookupIntValue(config, "frameskip", port, &opts->frameskip); free(config->port);
_lookupIntValue(config, "rewindBufferCapacity", port, &opts->rewindBufferCapacity); }
_lookupIntValue(config, "rewindBufferInterval", port, &opts->rewindBufferInterval);
_lookupFloatValue(config, "fpsTarget", port, &opts->fpsTarget); 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; unsigned audioBuffers;
if (_lookupUIntValue(config, "audioBuffers", port, &audioBuffers)) { if (_lookupUIntValue(config, "audioBuffers", &audioBuffers)) {
opts->audioBuffers = audioBuffers; opts->audioBuffers = audioBuffers;
} }
int fakeBool; int fakeBool;
if (_lookupIntValue(config, "audioSync", port, &fakeBool)) { if (_lookupIntValue(config, "audioSync", &fakeBool)) {
opts->audioSync = fakeBool; opts->audioSync = fakeBool;
} }
if (_lookupIntValue(config, "videoSync", port, &fakeBool)) { if (_lookupIntValue(config, "videoSync", &fakeBool)) {
opts->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) { void GBAConfigLoadDefaults(struct GBAConfig* config, const struct GBAOptions* opts) {
_lookupIntValue(config, "fullscreen", port, &opts->fullscreen); ConfigurationSetValue(&config->defaultsTable, 0, "bios", opts->bios);
_lookupIntValue(config, "width", port, &opts->width); ConfigurationSetIntValue(&config->defaultsTable, 0, "logLevel", opts->logLevel);
_lookupIntValue(config, "height", port, &opts->height); 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) { void GBAConfigFreeOpts(struct GBAOptions* opts) {

View File

@ -3,7 +3,13 @@
#include "util/common.h" #include "util/common.h"
struct Configuration; #include "util/configuration.h"
struct GBAConfig {
struct Configuration configTable;
struct Configuration defaultsTable;
char* port;
};
struct GBAOptions { struct GBAOptions {
char* bios; char* bios;
@ -22,10 +28,25 @@ struct GBAOptions {
bool audioSync; bool audioSync;
}; };
bool GBAConfigLoad(struct Configuration*); void GBAConfigInit(struct GBAConfig*, const char* port);
void GBAConfigDeinit(struct GBAConfig*);
void GBAConfigMapGeneralOpts(const struct Configuration*, const char* port, struct GBAOptions*); bool GBAConfigLoad(struct GBAConfig*);
void GBAConfigMapGraphicsOpts(const struct Configuration*, const char* port, struct GBAOptions*); bool GBAConfigSave(const struct GBAConfig*);
void GBAConfigFreeOpts(struct GBAOptions*);
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 GBAConfigFreeOpts(struct GBAOptions* opts);
#endif #endif

View File

@ -38,9 +38,9 @@ static const struct option _options[] = {
{ 0, 0, 0, 0 } { 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; int ch;
char options[64] = char options[64] =
"b:Dl:p:s:" "b:Dl:p:s:"
@ -58,10 +58,7 @@ bool parseArguments(struct GBAArguments* opts, struct GBAOptions* gbaOpts, int a
while ((ch = getopt_long(argc, argv, options, _options, 0)) != -1) { while ((ch = getopt_long(argc, argv, options, _options, 0)) != -1) {
switch (ch) { switch (ch) {
case 'b': case 'b':
if (gbaOpts->bios) { GBAConfigSetDefaultValue(config, "bios", optarg);
free(gbaOpts->bios);
}
gbaOpts->bios = strdup(optarg);
break; break;
case 'D': case 'D':
opts->dirmode = true; opts->dirmode = true;
@ -83,17 +80,17 @@ bool parseArguments(struct GBAArguments* opts, struct GBAOptions* gbaOpts, int a
break; break;
#endif #endif
case 'l': case 'l':
gbaOpts->logLevel = atoi(optarg); GBAConfigSetDefaultValue(config, "logLevel", optarg);
break; break;
case 'p': case 'p':
opts->patch = strdup(optarg); opts->patch = strdup(optarg);
break; break;
case 's': case 's':
gbaOpts->frameskip = atoi(optarg); GBAConfigSetDefaultValue(config, "frameskip", optarg);
break; break;
default: default:
if (subparser) { if (subparser) {
if (!subparser->parse(subparser, gbaOpts, ch, optarg)) { if (!subparser->parse(subparser, config, ch, optarg)) {
return false; return false;
} }
} }
@ -125,12 +122,12 @@ void initParserForGraphics(struct SubParser* parser, struct GraphicsOpts* opts)
opts->multiplier = 0; 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); UNUSED(arg);
struct GraphicsOpts* graphicsOpts = parser->opts; struct GraphicsOpts* graphicsOpts = parser->opts;
switch (option) { switch (option) {
case 'f': case 'f':
gbaOpts->fullscreen = 1; GBAConfigSetDefaultIntValue(config, "fullscreen", 1);
return true; return true;
case '1': case '1':
case '2': case '2':
@ -140,8 +137,8 @@ bool _parseGraphicsArg(struct SubParser* parser, struct GBAOptions* gbaOpts, int
return false; return false;
} }
graphicsOpts->multiplier = option - '0'; graphicsOpts->multiplier = option - '0';
gbaOpts->width = VIDEO_HORIZONTAL_PIXELS * graphicsOpts->multiplier; GBAConfigSetDefaultIntValue(config, "width", VIDEO_HORIZONTAL_PIXELS * graphicsOpts->multiplier);
gbaOpts->height = VIDEO_VERTICAL_PIXELS * graphicsOpts->multiplier; GBAConfigSetDefaultIntValue(config, "height", VIDEO_VERTICAL_PIXELS * graphicsOpts->multiplier);
return true; return true;
default: default:
return false; return false;

View File

@ -27,7 +27,7 @@ struct GBAArguments {
struct SubParser { struct SubParser {
const char* usage; 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; const char* extraOptions;
void* opts; void* opts;
}; };
@ -36,7 +36,7 @@ struct GraphicsOpts {
int multiplier; 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 freeArguments(struct GBAArguments* opts);
void usage(const char* arg0, const char* extraOptions); void usage(const char* arg0, const char* extraOptions);

View File

@ -28,7 +28,7 @@ struct PerfOpts {
static void _GBAPerfRunloop(struct GBAThread* context, int* frames, bool quiet); static void _GBAPerfRunloop(struct GBAThread* context, int* frames, bool quiet);
static void _GBAPerfShutdown(int signal); 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; static struct GBAThread* _thread;
@ -46,10 +46,16 @@ int main(int argc, char** argv) {
.opts = &perfOpts .opts = &perfOpts
}; };
struct GBAConfig config;
GBAConfigInit(&config, 0);
struct GBAOptions opts = {}; struct GBAOptions opts = {};
struct GBAArguments args = {}; struct GBAArguments args = {};
if (!parseArguments(&args, &opts, argc, argv, &subparser)) { if (!parseArguments(&args, &config, argc, argv, &subparser)) {
usage(argv[0], PERF_USAGE); usage(argv[0], PERF_USAGE);
freeArguments(&args);
GBAConfigFreeOpts(&opts);
GBAConfigDeinit(&config);
return 1; return 1;
} }
@ -66,12 +72,12 @@ int main(int argc, char** argv) {
context.debugger = createDebugger(&args); context.debugger = createDebugger(&args);
char gameCode[5] = { 0 }; char gameCode[5] = { 0 };
GBAConfigMap(&config, &opts);
opts.audioSync = false;
opts.videoSync = false;
GBAMapArgumentsToContext(&args, &context); GBAMapArgumentsToContext(&args, &context);
GBAMapOptionsToContext(&opts, &context); GBAMapOptionsToContext(&opts, &context);
context.sync.audioWait = false;
context.sync.videoFrameWait = false;
GBAThreadStart(&context); GBAThreadStart(&context);
GBAGetGameCode(context.gba, gameCode); GBAGetGameCode(context.gba, gameCode);
@ -90,6 +96,7 @@ int main(int argc, char** argv) {
GBAThreadJoin(&context); GBAThreadJoin(&context);
GBAConfigFreeOpts(&opts); GBAConfigFreeOpts(&opts);
freeArguments(&args); freeArguments(&args);
GBAConfigDeinit(&config);
free(context.debugger); free(context.debugger);
free(renderer.outputBuffer); free(renderer.outputBuffer);
@ -153,8 +160,8 @@ static void _GBAPerfShutdown(int signal) {
pthread_mutex_unlock(&_thread->stateMutex); pthread_mutex_unlock(&_thread->stateMutex);
} }
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) {
UNUSED(gbaOpts); UNUSED(config);
struct PerfOpts* opts = parser->opts; struct PerfOpts* opts = parser->opts;
errno = 0; errno = 0;
switch (option) { switch (option) {

View File

@ -16,24 +16,19 @@ GBAApp::GBAApp(int& argc, char* argv[])
QApplication::setApplicationName(PROJECT_NAME); QApplication::setApplicationName(PROJECT_NAME);
QApplication::setApplicationVersion(PROJECT_VERSION); QApplication::setApplicationVersion(PROJECT_VERSION);
struct Configuration config; GBAConfigInit(&m_config, PORT);
GBAConfigLoad(&m_config);
ConfigurationInit(&config);
GBAConfigLoad(&config);
m_opts.audioSync = GameController::AUDIO_SYNC; m_opts.audioSync = GameController::AUDIO_SYNC;
m_opts.videoSync = GameController::VIDEO_SYNC; m_opts.videoSync = GameController::VIDEO_SYNC;
GBAConfigLoadDefaults(&m_config, &m_opts);
GBAConfigMapGeneralOpts(&config, PORT, &m_opts); bool parsed = parseArguments(&m_args, &m_config, argc, argv, 0);
GBAConfigMapGraphicsOpts(&config, PORT, &m_opts); GBAConfigMap(&m_config, &m_opts);
m_window.setOptions(&m_opts);
ConfigurationDeinit(&config); if (parsed) {
if (parseArguments(&m_args, &m_opts, argc, argv, 0)) {
m_window.setOptions(&m_opts);
m_window.argumentsPassed(&m_args); m_window.argumentsPassed(&m_args);
} else {
m_window.setOptions(&m_opts);
} }
m_window.show(); m_window.show();
@ -42,6 +37,7 @@ GBAApp::GBAApp(int& argc, char* argv[])
GBAApp::~GBAApp() { GBAApp::~GBAApp() {
freeArguments(&m_args); freeArguments(&m_args);
GBAConfigFreeOpts(&m_opts); GBAConfigFreeOpts(&m_opts);
GBAConfigDeinit(&m_config);
} }
bool GBAApp::event(QEvent* event) { bool GBAApp::event(QEvent* event) {

View File

@ -29,7 +29,7 @@ private:
GBAArguments m_args; GBAArguments m_args;
GBAOptions m_opts; GBAOptions m_opts;
Configuration m_config; GBAConfig m_config;
}; };
} }

View File

@ -65,8 +65,8 @@ int main(int argc, char** argv) {
struct GLSoftwareRenderer renderer; struct GLSoftwareRenderer renderer;
GBAVideoSoftwareRendererCreate(&renderer.d); GBAVideoSoftwareRendererCreate(&renderer.d);
struct Configuration config; struct GBAConfig config;
ConfigurationInit(&config); GBAConfigInit(&config, PORT);
GBAConfigLoad(&config); GBAConfigLoad(&config);
struct GBAOptions opts = { struct GBAOptions opts = {
@ -74,19 +74,21 @@ int main(int argc, char** argv) {
.videoSync = false, .videoSync = false,
.audioSync = true, .audioSync = true,
}; };
GBAConfigLoadDefaults(&config, &opts);
struct GBAArguments args = {}; struct GBAArguments args = {};
struct GraphicsOpts graphicsOpts = {}; struct GraphicsOpts graphicsOpts = {};
struct SubParser subparser; struct SubParser subparser;
GBAConfigMapGeneralOpts(&config, PORT, &opts); GBAConfigMap(&config, &opts);
GBAConfigMapGraphicsOpts(&config, PORT, &opts);
initParserForGraphics(&subparser, &graphicsOpts); initParserForGraphics(&subparser, &graphicsOpts);
if (!parseArguments(&args, &opts, argc, argv, &subparser)) { if (!parseArguments(&args, &config, argc, argv, &subparser)) {
usage(argv[0], subparser.usage); usage(argv[0], subparser.usage);
freeArguments(&args); freeArguments(&args);
GBAConfigFreeOpts(&opts); GBAConfigFreeOpts(&opts);
GBAConfigDeinit(&config);
return 1; return 1;
} }
@ -100,6 +102,7 @@ int main(int argc, char** argv) {
if (!_GBASDLInit(&renderer)) { if (!_GBASDLInit(&renderer)) {
freeArguments(&args); freeArguments(&args);
GBAConfigFreeOpts(&opts); GBAConfigFreeOpts(&opts);
GBAConfigDeinit(&config);
return 1; return 1;
} }
@ -120,7 +123,7 @@ int main(int argc, char** argv) {
renderer.events.bindings = &context.inputMap; renderer.events.bindings = &context.inputMap;
GBASDLInitEvents(&renderer.events); GBASDLInitEvents(&renderer.events);
GBASDLEventsLoadConfig(&renderer.events, &config); GBASDLEventsLoadConfig(&renderer.events, &config.configTable); // TODO: Don't use this directly
GBAThreadStart(&context); GBAThreadStart(&context);
@ -129,6 +132,7 @@ int main(int argc, char** argv) {
GBAThreadJoin(&context); GBAThreadJoin(&context);
freeArguments(&args); freeArguments(&args);
GBAConfigFreeOpts(&opts); GBAConfigFreeOpts(&opts);
GBAConfigDeinit(&config);
free(context.debugger); free(context.debugger);
_GBASDLDeinit(&renderer); _GBASDLDeinit(&renderer);