all repos — mgba @ a1829a920d1b51bf0ff3f14e87260cd58c20e030

mGBA Game Boy Advance Emulator

src/gba/gba-config.c (view raw)

  1#include "gba-config.h"
  2
  3#include "platform/commandline.h"
  4
  5#include <sys/stat.h>
  6
  7#ifdef _WIN32
  8#include <windows.h>
  9#include <shlobj.h>
 10#include <strsafe.h>
 11#endif
 12
 13#define SECTION_NAME_MAX 128
 14
 15static const char* _lookupValue(const struct GBAConfig* config, const char* key) {
 16	const char* value;
 17	if (config->port) {
 18		value = ConfigurationGetValue(&config->configTable, config->port, key);
 19		if (value) {
 20			return value;
 21		}
 22	}
 23	value = ConfigurationGetValue(&config->configTable, 0, key);
 24	if (value) {
 25		return value;
 26	}
 27	if (config->port) {
 28		value = ConfigurationGetValue(&config->defaultsTable, config->port, key);
 29		if (value) {
 30			return value;
 31		}
 32	}
 33	return ConfigurationGetValue(&config->defaultsTable, 0, key);
 34}
 35
 36static bool _lookupCharValue(const struct GBAConfig* config, const char* key, char** out) {
 37	const char* value = _lookupValue(config, key);
 38	if (!value) {
 39		return false;
 40	}
 41	if (*out) {
 42		free(*out);
 43	}
 44	*out = strdup(value);
 45	return true;
 46}
 47
 48static bool _lookupIntValue(const struct GBAConfig* config, const char* key, int* out) {
 49	const char* charValue = _lookupValue(config, key);
 50	if (!charValue) {
 51		return false;
 52	}
 53	char* end;
 54	long value = strtol(charValue, &end, 10);
 55	if (*end) {
 56		return false;
 57	}
 58	*out = value;
 59	return true;
 60}
 61
 62static bool _lookupUIntValue(const struct GBAConfig* config, const char* key, unsigned* out) {
 63	const char* charValue = _lookupValue(config, key);
 64	if (!charValue) {
 65		return false;
 66	}
 67	char* end;
 68	unsigned long value = strtoul(charValue, &end, 10);
 69	if (*end) {
 70		return false;
 71	}
 72	*out = value;
 73	return true;
 74}
 75
 76static bool _lookupFloatValue(const struct GBAConfig* config, const char* key, float* out) {
 77	const char* charValue = _lookupValue(config, key);
 78	if (!charValue) {
 79		return false;
 80	}
 81	char* end;
 82	float value = strtof(charValue, &end);
 83	if (*end) {
 84		return false;
 85	}
 86	*out = value;
 87	return true;
 88}
 89
 90void GBAConfigInit(struct GBAConfig* config, const char* port) {
 91	ConfigurationInit(&config->configTable);
 92	ConfigurationInit(&config->defaultsTable);
 93	if (port) {
 94		config->port = malloc(strlen("ports.") + strlen(port) + 1);
 95		snprintf(config->port, strlen("ports.") + strlen(port) + 1, "ports.%s", port);
 96	} else {
 97		config->port = 0;
 98	}
 99}
100
101void GBAConfigDeinit(struct GBAConfig* config) {
102	ConfigurationDeinit(&config->configTable);
103	ConfigurationDeinit(&config->defaultsTable);
104	free(config->port);
105}
106
107bool GBAConfigLoad(struct GBAConfig* config) {
108	char path[PATH_MAX];
109#ifndef _WIN32
110	char* home = getenv("HOME");
111	snprintf(path, PATH_MAX, "%s/.config/%s/config.ini", home, BINARY_NAME);
112#else
113	char home[MAX_PATH];
114	SHGetFolderPath(0, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, home);
115	snprintf(path, PATH_MAX, "%s/%s/config.ini", home, PROJECT_NAME);
116#endif
117	return ConfigurationRead(&config->configTable, path);
118}
119
120bool GBAConfigSave(const struct GBAConfig* config) {
121	char path[PATH_MAX];
122#ifndef _WIN32
123	char* home = getenv("HOME");
124	snprintf(path, PATH_MAX, "%s/.config", home);
125	mkdir(path, 0755);
126	snprintf(path, PATH_MAX, "%s/.config/%s", home, BINARY_NAME);
127	mkdir(path, 0755);
128	snprintf(path, PATH_MAX, "%s/.config/%s/config.ini", home, BINARY_NAME);
129#else
130	char home[MAX_PATH];
131	SHGetFolderPath(0, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, home);
132	snprintf(path, PATH_MAX, "%s/%s", home, PROJECT_NAME);
133	CreateDirectoryA(path, NULL);
134	snprintf(path, PATH_MAX, "%s/%s/config.ini", home, PROJECT_NAME);
135#endif
136	return ConfigurationWrite(&config->configTable, path);
137}
138
139const char* GBAConfigGetValue(const struct GBAConfig* config, const char* key) {
140	return _lookupValue(config, key);
141}
142
143void GBAConfigSetValue(struct GBAConfig* config, const char* key, const char* value) {
144	ConfigurationSetValue(&config->configTable, config->port, key, value);
145}
146
147void GBAConfigSetIntValue(struct GBAConfig* config, const char* key, int value) {
148	ConfigurationSetIntValue(&config->configTable, config->port, key, value);
149}
150
151void GBAConfigSetUIntValue(struct GBAConfig* config, const char* key, unsigned value) {
152	ConfigurationSetUIntValue(&config->configTable, config->port, key, value);
153}
154
155void GBAConfigSetFloatValue(struct GBAConfig* config, const char* key, float value) {
156	ConfigurationSetFloatValue(&config->configTable, config->port, key, value);
157}
158
159void GBAConfigSetDefaultValue(struct GBAConfig* config, const char* key, const char* value) {
160	ConfigurationSetValue(&config->defaultsTable, config->port, key, value);
161}
162
163void GBAConfigSetDefaultIntValue(struct GBAConfig* config, const char* key, int value) {
164	ConfigurationSetIntValue(&config->defaultsTable, config->port, key, value);
165}
166
167void GBAConfigSetDefaultUIntValue(struct GBAConfig* config, const char* key, unsigned value) {
168	ConfigurationSetUIntValue(&config->defaultsTable, config->port, key, value);
169}
170
171void GBAConfigSetDefaultFloatValue(struct GBAConfig* config, const char* key, float value) {
172	ConfigurationSetFloatValue(&config->defaultsTable, config->port, key, value);
173}
174
175void GBAConfigMap(const struct GBAConfig* config, struct GBAOptions* opts) {
176	_lookupCharValue(config, "bios", &opts->bios);
177	_lookupIntValue(config, "logLevel", &opts->logLevel);
178	_lookupIntValue(config, "frameskip", &opts->frameskip);
179	_lookupIntValue(config, "rewindBufferCapacity", &opts->rewindBufferCapacity);
180	_lookupIntValue(config, "rewindBufferInterval", &opts->rewindBufferInterval);
181	_lookupFloatValue(config, "fpsTarget", &opts->fpsTarget);
182	unsigned audioBuffers;
183	if (_lookupUIntValue(config, "audioBuffers", &audioBuffers)) {
184		opts->audioBuffers = audioBuffers;
185	}
186
187	int fakeBool;
188	if (_lookupIntValue(config, "audioSync", &fakeBool)) {
189		opts->audioSync = fakeBool;
190	}
191	if (_lookupIntValue(config, "videoSync", &fakeBool)) {
192		opts->videoSync = fakeBool;
193	}
194
195	_lookupIntValue(config, "fullscreen", &opts->fullscreen);
196	_lookupIntValue(config, "width", &opts->width);
197	_lookupIntValue(config, "height", &opts->height);
198}
199
200void GBAConfigLoadDefaults(struct GBAConfig* config, const struct GBAOptions* opts) {
201	ConfigurationSetValue(&config->defaultsTable, 0, "bios", opts->bios);
202	ConfigurationSetIntValue(&config->defaultsTable, 0, "logLevel", opts->logLevel);
203	ConfigurationSetIntValue(&config->defaultsTable, 0, "frameskip", opts->frameskip);
204	ConfigurationSetIntValue(&config->defaultsTable, 0, "rewindBufferCapacity", opts->rewindBufferCapacity);
205	ConfigurationSetIntValue(&config->defaultsTable, 0, "rewindBufferInterval", opts->rewindBufferInterval);
206	ConfigurationSetFloatValue(&config->defaultsTable, 0, "fpsTarget", opts->fpsTarget);
207	ConfigurationSetUIntValue(&config->defaultsTable, 0, "audioBuffers", opts->audioBuffers);
208	ConfigurationSetIntValue(&config->defaultsTable, 0, "audioSync", opts->audioSync);
209	ConfigurationSetIntValue(&config->defaultsTable, 0, "videoSync", opts->videoSync);
210	ConfigurationSetIntValue(&config->defaultsTable, 0, "fullscreen", opts->fullscreen);
211	ConfigurationSetIntValue(&config->defaultsTable, 0, "width", opts->width);
212	ConfigurationSetIntValue(&config->defaultsTable, 0, "height", opts->height);
213}
214
215void GBAConfigFreeOpts(struct GBAOptions* opts) {
216	free(opts->bios);
217	opts->bios = 0;
218}