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}