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 config->port = malloc(strlen("ports.") + strlen(port) + 1);
94 snprintf(config->port, strlen("ports.") + strlen(port) + 1, "ports.%s", port);
95}
96
97void GBAConfigDeinit(struct GBAConfig* config) {
98 ConfigurationDeinit(&config->configTable);
99 ConfigurationDeinit(&config->defaultsTable);
100 free(config->port);
101}
102
103bool GBAConfigLoad(struct GBAConfig* config) {
104 char path[PATH_MAX];
105#ifndef _WIN32
106 char* home = getenv("HOME");
107 snprintf(path, PATH_MAX, "%s/.config/%s/config.ini", home, BINARY_NAME);
108#else
109 char home[MAX_PATH];
110 SHGetFolderPath(0, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, home);
111 snprintf(path, PATH_MAX, "%s/%s/config.ini", home, PROJECT_NAME);
112#endif
113 return ConfigurationRead(&config->configTable, path);
114}
115
116bool GBAConfigSave(const struct GBAConfig* config) {
117 char path[PATH_MAX];
118#ifndef _WIN32
119 char* home = getenv("HOME");
120 snprintf(path, PATH_MAX, "%s/.config", home);
121 mkdir(path, 0755);
122 snprintf(path, PATH_MAX, "%s/.config/%s", home, BINARY_NAME);
123 mkdir(path, 0755);
124 snprintf(path, PATH_MAX, "%s/.config/%s/config.ini", home, BINARY_NAME);
125#else
126 char home[MAX_PATH];
127 SHGetFolderPath(0, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, home);
128 snprintf(path, PATH_MAX, "%s/%s", home, PROJECT_NAME);
129 CreateDirectoryA(path, NULL);
130 snprintf(path, PATH_MAX, "%s/%s/config.ini", home, PROJECT_NAME);
131#endif
132 return ConfigurationWrite(&config->configTable, path);
133}
134
135const char* GBAConfigGetValue(const struct GBAConfig* config, const char* key) {
136 return _lookupValue(config, key);
137}
138
139void GBAConfigSetValue(struct GBAConfig* config, const char* key, const char* value) {
140 ConfigurationSetValue(&config->configTable, config->port, key, value);
141}
142
143void GBAConfigSetIntValue(struct GBAConfig* config, const char* key, int value) {
144 ConfigurationSetIntValue(&config->configTable, config->port, key, value);
145}
146
147void GBAConfigSetUIntValue(struct GBAConfig* config, const char* key, unsigned value) {
148 ConfigurationSetUIntValue(&config->configTable, config->port, key, value);
149}
150
151void GBAConfigSetFloatValue(struct GBAConfig* config, const char* key, float value) {
152 ConfigurationSetFloatValue(&config->configTable, config->port, key, value);
153}
154
155void GBAConfigSetDefaultValue(struct GBAConfig* config, const char* key, const char* value) {
156 ConfigurationSetValue(&config->defaultsTable, config->port, key, value);
157}
158
159void GBAConfigSetDefaultIntValue(struct GBAConfig* config, const char* key, int value) {
160 ConfigurationSetIntValue(&config->defaultsTable, config->port, key, value);
161}
162
163void GBAConfigSetDefaultUIntValue(struct GBAConfig* config, const char* key, unsigned value) {
164 ConfigurationSetUIntValue(&config->defaultsTable, config->port, key, value);
165}
166
167void GBAConfigSetDefaultFloatValue(struct GBAConfig* config, const char* key, float value) {
168 ConfigurationSetFloatValue(&config->defaultsTable, config->port, key, value);
169}
170
171void GBAConfigMap(const struct GBAConfig* config, struct GBAOptions* opts) {
172 _lookupCharValue(config, "bios", &opts->bios);
173 _lookupIntValue(config, "logLevel", &opts->logLevel);
174 _lookupIntValue(config, "frameskip", &opts->frameskip);
175 _lookupIntValue(config, "rewindBufferCapacity", &opts->rewindBufferCapacity);
176 _lookupIntValue(config, "rewindBufferInterval", &opts->rewindBufferInterval);
177 _lookupFloatValue(config, "fpsTarget", &opts->fpsTarget);
178 unsigned audioBuffers;
179 if (_lookupUIntValue(config, "audioBuffers", &audioBuffers)) {
180 opts->audioBuffers = audioBuffers;
181 }
182
183 int fakeBool;
184 if (_lookupIntValue(config, "audioSync", &fakeBool)) {
185 opts->audioSync = fakeBool;
186 }
187 if (_lookupIntValue(config, "videoSync", &fakeBool)) {
188 opts->videoSync = fakeBool;
189 }
190
191 _lookupIntValue(config, "fullscreen", &opts->fullscreen);
192 _lookupIntValue(config, "width", &opts->width);
193 _lookupIntValue(config, "height", &opts->height);
194}
195
196void GBAConfigLoadDefaults(struct GBAConfig* config, const struct GBAOptions* opts) {
197 ConfigurationSetValue(&config->defaultsTable, 0, "bios", opts->bios);
198 ConfigurationSetIntValue(&config->defaultsTable, 0, "logLevel", opts->logLevel);
199 ConfigurationSetIntValue(&config->defaultsTable, 0, "frameskip", opts->frameskip);
200 ConfigurationSetIntValue(&config->defaultsTable, 0, "rewindBufferCapacity", opts->rewindBufferCapacity);
201 ConfigurationSetIntValue(&config->defaultsTable, 0, "rewindBufferInterval", opts->rewindBufferInterval);
202 ConfigurationSetFloatValue(&config->defaultsTable, 0, "fpsTarget", opts->fpsTarget);
203 ConfigurationSetUIntValue(&config->defaultsTable, 0, "audioBuffers", opts->audioBuffers);
204 ConfigurationSetIntValue(&config->defaultsTable, 0, "audioSync", opts->audioSync);
205 ConfigurationSetIntValue(&config->defaultsTable, 0, "videoSync", opts->videoSync);
206 ConfigurationSetIntValue(&config->defaultsTable, 0, "fullscreen", opts->fullscreen);
207 ConfigurationSetIntValue(&config->defaultsTable, 0, "width", opts->width);
208 ConfigurationSetIntValue(&config->defaultsTable, 0, "height", opts->height);
209}
210
211void GBAConfigFreeOpts(struct GBAOptions* opts) {
212 free(opts->bios);
213 opts->bios = 0;
214}