6#if defined(SDL_LIBRETRO_IMPLEMENTATION) && !defined(SDL_LIBRETRO_OPTIONS_IMPL_ONCE)
7#define SDL_LIBRETRO_OPTIONS_IMPL_ONCE
9static char* SDL_Libretro_Strdup(
const char* s) {
10 if (!s)
return SDL_strdup(
"");
14static void SDL_Libretro_InitCoreOption(SDL_Libretro* lr,
const char* key,
const char* defaultValue,
15 const char* desc,
const struct retro_core_option_value* values,
16 const char* info,
const char* categoryKey) {
17 if (!lr || !key)
return;
27 if (lr->core.optionCount >= lr->core.optionCapacity) {
28 unsigned newCap = lr->core.optionCapacity ? lr->core.optionCapacity * 2 : 16;
31 lr->core.options = newOpts;
32 lr->core.optionCapacity = newCap;
37 slot->key = SDL_Libretro_Strdup(key);
38 slot->
value = SDL_Libretro_Strdup(defaultValue);
40 slot->
desc = SDL_Libretro_Strdup(desc);
41 slot->
info = SDL_Libretro_Strdup(info);
42 slot->
category = SDL_Libretro_Strdup(categoryKey);
52 while (values[count].value) count++;
59 for (
unsigned v = 0; v < count; v++) {
60 slot->
values[v].value = SDL_Libretro_Strdup(values[v].value);
61 slot->
values[v].
label = values[v].label ? SDL_Libretro_Strdup(values[v].label) : NULL;
68 lr->core.optionCount++;
71static void SDL_Libretro_InitCoreOptionCategory(SDL_Libretro* lr,
const char* key,
72 const char* desc,
const char* info) {
73 if (!lr || !key || key[0] ==
'\0')
return;
76 for (
unsigned i = 0; i < lr->core.optionCategoryCount; i++) {
77 if (lr->core.optionCategories[i].key && SDL_strcmp(lr->core.optionCategories[i].key, key) == 0) {
83 if (lr->core.optionCategoryCount >= lr->core.optionCategoryCapacity) {
84 unsigned newCap = lr->core.optionCategoryCapacity ? lr->core.optionCategoryCapacity * 2 : 8;
87 lr->core.optionCategories = newCats;
88 lr->core.optionCategoryCapacity = newCap;
93 cat->key = SDL_Libretro_Strdup(key);
94 cat->
desc = SDL_Libretro_Strdup(desc);
95 cat->
info = SDL_Libretro_Strdup(info);
97 lr->core.optionCategoryCount++;
100static void SDL_Libretro_FreeCoreOptions(SDL_Libretro* lr) {
104 if (lr->core.options) {
105 for (
unsigned i = 0; i < lr->core.optionCount; i++) {
107 SDL_free((
void*)opt->key);
108 SDL_free((
void*)opt->
value);
110 SDL_free((
void*)opt->
desc);
111 SDL_free((
void*)opt->
info);
114 SDL_free((
void*)opt->
values[v].value);
119 SDL_free(lr->core.options);
120 lr->core.options = NULL;
122 lr->core.optionCount = 0;
123 lr->core.optionCapacity = 0;
126 if (lr->core.optionCategories) {
127 for (
unsigned i = 0; i < lr->core.optionCategoryCount; i++) {
128 SDL_free((
void*)lr->core.optionCategories[i].key);
129 SDL_free((
void*)lr->core.optionCategories[i].desc);
130 SDL_free((
void*)lr->core.optionCategories[i].info);
132 SDL_free(lr->core.optionCategories);
133 lr->core.optionCategories = NULL;
135 lr->core.optionCategoryCount = 0;
136 lr->core.optionCategoryCapacity = 0;
143 return lr ? lr->core.optionCount : 0;
150 if (!lr || !key)
return NULL;
151 for (
unsigned i = 0; i < lr->core.optionCount; i++) {
152 if (lr->core.options[i].key && SDL_strcmp(lr->core.options[i].key, key) == 0) {
153 return &lr->core.options[i];
163 if (!lr || index >= lr->core.optionCount)
return NULL;
164 return &lr->core.options[index];
171 if (!lr || !key || !value)
return false;
173 if (!opt)
return false;
180 if (opt->
values[v].value && SDL_strcmp(opt->
values[v].value, value) == 0) {
186 return SDL_SetError(
"[SDL_Libretro] '%s' is not a valid value for option '%s'", value, key);
190 SDL_free((
void*)opt->
value);
191 opt->
value = SDL_strdup(value);
192 lr->core.optionsDirty =
true;
201 if (!opt)
return NULL;
213 if (!opt || !opt->
value)
return NULL;
226 if (direction == 0)
return false;
231 unsigned current = 0;
240 unsigned step = (direction > 0) ? 1 : count - 1;
241 unsigned next = (current + step) % count;
250 if (!opt)
return false;
251 SDL_free((
void*)opt->
value);
253 lr->core.optionsDirty =
true;
262 for (
unsigned i = 0; i < lr->core.optionCount; i++) {
264 SDL_free((
void*)opt->
value);
267 lr->core.optionsDirty =
true;
274 if (!lr)
return false;
275 bool dirty = lr->core.optionsDirty;
276 lr->core.optionsDirty =
false;
280bool SDL_Libretro_UpdateOptionVisibility(SDL_Libretro* lr) {
281 if (!lr || !lr->core.optionsUpdateDisplayCallback)
return false;
282 return lr->core.optionsUpdateDisplayCallback();
289 return lr ? lr->core.optionCategoryCount : 0;
296 if (!lr || !key)
return NULL;
297 for (
unsigned i = 0; i < lr->core.optionCategoryCount; i++) {
298 if (lr->core.optionCategories[i].key && SDL_strcmp(lr->core.optionCategories[i].key, key) == 0) {
299 return &lr->core.optionCategories[i];
309 if (!lr || index >= lr->core.optionCategoryCount)
return NULL;
310 return &lr->core.optionCategories[index];
bool SDL_Libretro_CycleOptionValue(SDL_Libretro *lr, const char *key, int direction)
Advance a core option to the next (+1) or previous (-1) value.
bool SDL_Libretro_AreOptionsDirty(SDL_Libretro *lr)
Retrieves whether the options have been changed since the last time they were checked.
const SDL_LibretroCategory * SDL_Libretro_GetCategoryByIndex(const SDL_Libretro *lr, unsigned index)
Retrieve an option category by index, or NULL if out of range.
const SDL_LibretroCategory * SDL_Libretro_GetCategory(const SDL_Libretro *lr, const char *key)
Retrieve an option category by key, or NULL if there's no such category.
unsigned SDL_Libretro_GetCategoryCount(const SDL_Libretro *lr)
Get the number of option categories registered by the core.
const char * SDL_Libretro_GetOptionValueLabel(SDL_Libretro *lr, const char *key)
Get the human-readable label for a core option's current value.
const SDL_LibretroOption * SDL_Libretro_GetOptionByIndex(const SDL_Libretro *lr, unsigned index)
Retrieve a core option by its registration index, or NULL if out of range.
const char * SDL_Libretro_GetOptionValue(SDL_Libretro *lr, const char *key)
Get a core option's current value, or NULL if there's no such option.
bool SDL_Libretro_ResetOption(SDL_Libretro *lr, const char *key)
Reset a core option to its default value.
bool SDL_Libretro_SetOptionValue(SDL_Libretro *lr, const char *key, const char *value)
Set a core option's value; fails if the value isn't one the core declared.
void SDL_Libretro_ResetAllOptions(SDL_Libretro *lr)
Reset every core option to its default value.
unsigned SDL_Libretro_GetOptionCount(const SDL_Libretro *lr)
Get the number of core options that have been set.
const SDL_LibretroOption * SDL_Libretro_GetOption(const SDL_Libretro *lr, const char *key)
Retrieve details about a given core option.
A group of related core options.
const char * desc
Unique identifier referenced by SDL_LibretroOption::category.
const char * info
Human-readable name.
A core option and its current state.
bool visible
Key of the category it belongs to; empty if none.
SDL_LibretroOptionValue * values
The number of populated entries in values.
unsigned valuesCapacity
The selectable values; dynamically allocated.
const char * desc
Unique identifier the core queries.
const char * value
Description / help text; may be empty.
const char * category
The default value.
unsigned valuesCount
Whether the frontend should display it.
const char * defaultValue
The current value.
const char * info
Human-readable name.
One selectable value for a core option.
const char * label
The value the core stores.