mirror of
https://github.com/libretro/RetroArch
synced 2025-03-02 19:13:34 +00:00
Add enviroment callback to enable cores to notify the frontend that a core option value has changed
This commit is contained in:
parent
54cbeecbb7
commit
534f8da487
@ -725,13 +725,20 @@ static bool core_option_manager_parse_variable(
|
||||
if (!option->val_labels)
|
||||
goto error;
|
||||
|
||||
/* > Loop over values and 'extract' labels */
|
||||
/* > Loop over values and:
|
||||
* - Set value hashes
|
||||
* - 'Extract' labels */
|
||||
for (i = 0; i < option->vals->size; i++)
|
||||
{
|
||||
const char *value = option->vals->elems[i].data;
|
||||
uint32_t *value_hash = (uint32_t *)malloc(sizeof(uint32_t));
|
||||
const char *value_label = core_option_manager_parse_value_label(
|
||||
value, NULL);
|
||||
|
||||
/* Set value hash */
|
||||
*value_hash = core_option_manager_hash_string(value);
|
||||
option->vals->elems[i].userdata = (void*)value_hash;
|
||||
|
||||
/* Redundant safely check... */
|
||||
value_label = string_is_empty(value_label) ?
|
||||
value : value_label;
|
||||
@ -753,9 +760,15 @@ static bool core_option_manager_parse_variable(
|
||||
/* Set current config value */
|
||||
if (entry && !string_is_empty(entry->value))
|
||||
{
|
||||
uint32_t entry_value_hash = core_option_manager_hash_string(entry->value);
|
||||
|
||||
for (i = 0; i < option->vals->size; i++)
|
||||
{
|
||||
if (string_is_equal(option->vals->elems[i].data, entry->value))
|
||||
const char *value = option->vals->elems[i].data;
|
||||
uint32_t value_hash = *((uint32_t*)option->vals->elems[i].userdata);
|
||||
|
||||
if ((value_hash == entry_value_hash) &&
|
||||
string_is_equal(value, entry->value))
|
||||
{
|
||||
option->index = i;
|
||||
break;
|
||||
@ -998,12 +1011,17 @@ static bool core_option_manager_parse_option(
|
||||
for (i = 0; i < num_vals; i++)
|
||||
{
|
||||
const char *value = values[i].value;
|
||||
uint32_t *value_hash = (uint32_t *)malloc(sizeof(uint32_t));
|
||||
const char *value_label = values[i].label;
|
||||
|
||||
/* Append value string
|
||||
* > We know that 'value' is always valid */
|
||||
string_list_append(option->vals, value, attr);
|
||||
|
||||
/* > Set value hash */
|
||||
*value_hash = core_option_manager_hash_string(value);
|
||||
option->vals->elems[option->vals->size - 1].userdata = (void*)value_hash;
|
||||
|
||||
/* Value label requires additional processing */
|
||||
value_label = core_option_manager_parse_value_label(
|
||||
value, value_label);
|
||||
@ -1034,9 +1052,15 @@ static bool core_option_manager_parse_option(
|
||||
/* Set current config value */
|
||||
if (entry && !string_is_empty(entry->value))
|
||||
{
|
||||
uint32_t entry_value_hash = core_option_manager_hash_string(entry->value);
|
||||
|
||||
for (i = 0; i < option->vals->size; i++)
|
||||
{
|
||||
if (string_is_equal(option->vals->elems[i].data, entry->value))
|
||||
const char *value = option->vals->elems[i].data;
|
||||
uint32_t value_hash = *((uint32_t*)option->vals->elems[i].userdata);
|
||||
|
||||
if ((value_hash == entry_value_hash) &&
|
||||
string_is_equal(value, entry->value))
|
||||
{
|
||||
option->index = i;
|
||||
break;
|
||||
@ -1479,6 +1503,57 @@ bool core_option_manager_get_idx(core_option_manager_t *opt,
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* core_option_manager_get_val_idx:
|
||||
*
|
||||
* @opt : options manager handle
|
||||
* @idx : core option index
|
||||
* @val : string representation of the
|
||||
* core option value
|
||||
* @val_idx : index of core option value
|
||||
* corresponding to @val
|
||||
*
|
||||
* Fetches the index of the core option value
|
||||
* identified by the specified core option @idx
|
||||
* and @val string.
|
||||
*
|
||||
* Returns: true if option value matching the
|
||||
* specified option index and value string
|
||||
* was found, otherwise false.
|
||||
**/
|
||||
bool core_option_manager_get_val_idx(core_option_manager_t *opt,
|
||||
size_t idx, const char *val, size_t *val_idx)
|
||||
{
|
||||
struct core_option *option = NULL;
|
||||
uint32_t val_hash;
|
||||
size_t i;
|
||||
|
||||
if (!opt ||
|
||||
(idx >= opt->size) ||
|
||||
string_is_empty(val) ||
|
||||
!val_idx)
|
||||
return false;
|
||||
|
||||
val_hash = core_option_manager_hash_string(val);
|
||||
option = (struct core_option*)&opt->opts[idx];
|
||||
|
||||
for (i = 0; i < option->vals->size; i++)
|
||||
{
|
||||
const char *option_val = option->vals->elems[i].data;
|
||||
uint32_t option_val_hash = *((uint32_t*)option->vals->elems[i].userdata);
|
||||
|
||||
if ((val_hash == option_val_hash) &&
|
||||
!string_is_empty(option_val) &&
|
||||
string_is_equal(val, option_val))
|
||||
{
|
||||
*val_idx = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* core_option_manager_get_desc:
|
||||
*
|
||||
|
@ -278,6 +278,27 @@ bool core_option_manager_get_category_visible(core_option_manager_t *opt,
|
||||
bool core_option_manager_get_idx(core_option_manager_t *opt,
|
||||
const char *key, size_t *idx);
|
||||
|
||||
/**
|
||||
* core_option_manager_get_val_idx:
|
||||
*
|
||||
* @opt : options manager handle
|
||||
* @idx : core option index
|
||||
* @val : string representation of the
|
||||
* core option value
|
||||
* @val_idx : index of core option value
|
||||
* corresponding to @val
|
||||
*
|
||||
* Fetches the index of the core option value
|
||||
* identified by the specified core option @idx
|
||||
* and @val string.
|
||||
*
|
||||
* Returns: true if option value matching the
|
||||
* specified option index and value string
|
||||
* was found, otherwise false.
|
||||
**/
|
||||
bool core_option_manager_get_val_idx(core_option_manager_t *opt,
|
||||
size_t idx, const char *val, size_t *val_idx);
|
||||
|
||||
/**
|
||||
* core_option_manager_get_desc:
|
||||
*
|
||||
|
@ -1722,6 +1722,31 @@ enum retro_mod
|
||||
* Must be called in retro_set_environment().
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_VARIABLE 70
|
||||
/* const struct retro_variable * --
|
||||
* Allows an implementation to notify the frontend
|
||||
* that a core option value has changed.
|
||||
*
|
||||
* retro_variable::key and retro_variable::value
|
||||
* must match strings that have been set previously
|
||||
* via one of the following:
|
||||
*
|
||||
* - RETRO_ENVIRONMENT_SET_VARIABLES
|
||||
* - RETRO_ENVIRONMENT_SET_CORE_OPTIONS
|
||||
* - RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL
|
||||
* - RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2
|
||||
* - RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL
|
||||
*
|
||||
* After changing a core option value via this
|
||||
* callback, RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE
|
||||
* will return true.
|
||||
*
|
||||
* If data is NULL, no changes will be registered
|
||||
* and the callback will return true; an
|
||||
* implementation may therefore pass NULL in order
|
||||
* to test whether the callback is supported.
|
||||
*/
|
||||
|
||||
/* VFS functionality */
|
||||
|
||||
/* File paths:
|
||||
|
54
retroarch.c
54
retroarch.c
@ -10267,6 +10267,60 @@ static bool retroarch_environment_cb(unsigned cmd, void *data)
|
||||
|
||||
break;
|
||||
|
||||
case RETRO_ENVIRONMENT_SET_VARIABLE:
|
||||
{
|
||||
unsigned log_level = settings->uints.libretro_log_level;
|
||||
const struct retro_variable *var = (const struct retro_variable*)data;
|
||||
size_t opt_idx;
|
||||
size_t val_idx;
|
||||
|
||||
/* If core passes NULL to the callback, return
|
||||
* value indicates whether callback is supported */
|
||||
if (!var)
|
||||
return true;
|
||||
|
||||
if (string_is_empty(var->key) ||
|
||||
string_is_empty(var->value))
|
||||
return false;
|
||||
|
||||
if (!runloop_state.core_options)
|
||||
{
|
||||
RARCH_LOG("[Environ]: SET_VARIABLE %s: not implemented.\n",
|
||||
var->key);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check whether key is valid */
|
||||
if (!core_option_manager_get_idx(runloop_state.core_options,
|
||||
var->key, &opt_idx))
|
||||
{
|
||||
RARCH_LOG("[Environ]: SET_VARIABLE %s: invalid key.\n",
|
||||
var->key);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check whether value is valid */
|
||||
if (!core_option_manager_get_val_idx(runloop_state.core_options,
|
||||
opt_idx, var->value, &val_idx))
|
||||
{
|
||||
RARCH_LOG("[Environ]: SET_VARIABLE %s: invalid value: %s\n",
|
||||
var->key, var->value);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Update option value if core-requested value
|
||||
* is not currently set */
|
||||
if (val_idx != runloop_state.core_options->opts[opt_idx].index)
|
||||
core_option_manager_set_val(runloop_state.core_options,
|
||||
opt_idx, val_idx, true);
|
||||
|
||||
if (log_level == RETRO_LOG_DEBUG)
|
||||
RARCH_LOG("[Environ]: SET_VARIABLE %s:\n\t%s\n",
|
||||
var->key, var->value);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* SET_VARIABLES: Legacy path */
|
||||
case RETRO_ENVIRONMENT_SET_VARIABLES:
|
||||
RARCH_LOG("[Environ]: SET_VARIABLES.\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user