11#define CONFIG_LOOKUP_KEY_CAPACITY 64
13KHASH_MAP_INIT_STR(dttr_config_lookup,
int)
16#define FIELD(_section, _key, _field, _type) \
18 .section = (_section), \
20 .offset = offsetof(DTTR_Config, _field), \
21 .size = sizeof(((DTTR_Config *)0)->_field), \
22 .value_type = (_type) \
25#define FIELD_TOP(_key, _field, _type) FIELD(NULL, _key, _field, _type)
26#define FIELD_GAMEPAD_AXIS(_key, _index) \
27 FIELD("gamepad", _key, gamepad_axes[_index], CONFIG_GAMEPAD_AXIS),
28#define FIELD_GAMEPAD_DEADZONE(_key, _index) \
29 FIELD("gamepad", _key, gamepad_axis_deadzone[_index], CONFIG_INT),
38 "present_scaling_algorithm",
46 FIELD(
"graphics",
"generate_texture_mipmaps", generate_texture_mipmaps,
CONFIG_BOOL),
72#define CONFIG_SCHEMA_COUNT ((int)SDL_arraysize(config_schema))
74#undef FIELD_GAMEPAD_DEADZONE
75#undef FIELD_GAMEPAD_AXIS
80static bool config_build_lookup_key(
86 const int written = section ? snprintf(out, out_size,
"%s.%s", section, key)
87 : snprintf(out, out_size,
"%s", key);
88 return written > 0 && (size_t)written < out_size;
107 return ((
const char *)config) + spec->
offset;
115 if (!current || !base || !spec) {
125 return spec->
size > 0 && memcmp(current_field, base_field, spec->
size) != 0;
144 config_lookup = kh_init(dttr_config_lookup);
145 if (!config_lookup) {
151 if (!config_build_lookup_key(
152 config_lookup_keys[i],
153 sizeof(config_lookup_keys[i]),
161 const khint_t it = kh_put(
164 config_lookup_keys[i],
167 if (it != kh_end(config_lookup)) {
168 kh_value(config_lookup, it) = i;
175 if (!config_lookup) {
180 if (!config_build_lookup_key(lookup_key,
sizeof(lookup_key), section, key)) {
184 const khint_t it = kh_get(dttr_config_lookup, config_lookup, lookup_key);
185 if (it == kh_end(config_lookup)) {
189 const int index = kh_value(config_lookup, it);
193#define CONFIG_ASSIGN_TYPES(X) \
194 X(CONFIG_BOOL, bool, false, config_parse_bool, config_assign_bool) \
195 X(CONFIG_SCALING_FIT, \
197 DTTR_SCALING_MODE_LETTERBOX, \
198 config_parse_scaling_fit, \
199 config_assign_scaling_fit) \
200 X(CONFIG_SCALING_METHOD, \
201 DTTR_ScalingMethod, \
202 DTTR_SCALING_METHOD_PRESENT, \
203 config_parse_scaling_method, \
204 config_assign_scaling_method) \
205 X(CONFIG_GRAPHICS_API, \
207 DTTR_GRAPHICS_API_AUTO, \
208 config_parse_graphics_api, \
209 config_assign_graphics_api) \
210 X(CONFIG_INT, int, 0, config_parse_int, config_assign_int) \
211 X(CONFIG_FLOAT, float, 0.0f, config_parse_float, config_assign_float) \
212 X(CONFIG_PRESENT_FILTER, \
214 SDL_GPU_FILTER_LINEAR, \
215 config_parse_present_filter, \
216 config_assign_present_filter) \
217 X(CONFIG_LOG_LEVEL, int, LOG_INFO, config_parse_log_level, config_assign_log_level) \
218 X(CONFIG_MINIDUMP_TYPE, \
220 DTTR_MINIDUMP_NORMAL, \
221 config_parse_minidump_type, \
222 config_assign_minidump_type) \
223 X(CONFIG_VERTEX_PRECISION, \
224 DTTR_VertexPrecision, \
225 DTTR_VERTEX_PRECISION_NATIVE, \
226 config_parse_vertex_precision, \
227 config_assign_vertex_precision) \
228 X(CONFIG_GAMEPAD_AXIS, \
230 DTTR_GAMEPAD_MAPPING_NONE, \
231 config_parse_gamepad_axis, \
232 config_assign_gamepad_axis)
234#define CONFIG_ASSIGN_FN(value_type, type, default_val, parse_fn, fn_name) \
235 static bool fn_name(char *field, const char *value) { \
236 type parsed = default_val; \
237 if (!parse_fn(value, &parsed)) { \
240 *(type *)field = parsed; \
246#undef CONFIG_ASSIGN_FN
258 if (!config || !key || !value) {
267 char *
const field = ((
char *)config) + spec->
offset;
268#define CONFIG_ASSIGN_CASE(value_type, type, default_val, parse_fn, fn_name) \
270 return fn_name(field, value);
281#undef CONFIG_ASSIGN_CASE
284#undef CONFIG_SCHEMA_COUNT
DTTR_Graphics_COM_DirectDrawSurface7 DWORD flags void NULL
bool config_parse_string(const char *value, char *out_value, size_t out_size)
#define CONFIG_GAMEPAD_AXIS_FIELDS(X)
#define CONFIG_GAMEPAD_DEADZONE_FIELDS(X)
@ CONFIG_VERTEX_PRECISION
static MINIDUMP_TYPE minidump_type()
@ DTTR_CONFIG_VALUE_STRING
bool DTTR_Path_MatchesNormalized(const char *lhs, const char *rhs)
#define CONFIG_ASSIGN_CASE(value_type, type, default_val, parse_fn, fn_name)
bool config_apply_entry(DTTR_Config *config, const char *section, const char *key, const char *value)
static void config_schema_init()
static bool config_assign_string(char *field, size_t field_size, const char *value)
#define CONFIG_ASSIGN_TYPES(X)
static const char * config_field_bytes(const DTTR_Config *config, const DTTR_ConfigFieldSpec *spec)
#define CONFIG_SCHEMA_COUNT
int DTTR_Config_SchemaCount()
#define FIELD_TOP(_key, _field, _type)
#define FIELD_GAMEPAD_DEADZONE(_key, _index)
bool DTTR_Config_SchemaChanged(const DTTR_Config *current, const DTTR_Config *base)
const DTTR_ConfigFieldSpec * config_schema_find(const char *section, const char *key)
static const DTTR_ConfigFieldSpec config_schema[]
#define CONFIG_ASSIGN_FN(value_type, type, default_val, parse_fn, fn_name)
#define FIELD_GAMEPAD_AXIS(_key, _index)
const DTTR_ConfigFieldSpec * DTTR_Config_SchemaGet(int index)
bool DTTR_Config_FieldChanged(const DTTR_Config *current, const DTTR_Config *base, const DTTR_ConfigFieldSpec *spec)
#define CONFIG_LOOKUP_KEY_CAPACITY
static khash_t(dttr_config_lookup)
#define FIELD(_section, _key, _field, _type)
DTTR_ConfigValueType value_type