this should be two commits
1. renaming menu option structs and callbacks
2. hiding locked options from menus
but I forgot to commit in the middle and the changes are too intertwined to stage individually
🙁
This commit is contained in:
Shaun Inman 2023-01-29 21:31:13 -05:00
parent 04e053b228
commit 9da9b41a16
2 changed files with 105 additions and 76 deletions

View file

@ -340,7 +340,7 @@ typedef struct Option {
int default_value; int default_value;
int value; int value;
int count; // TODO: drop this? int count; // TODO: drop this?
int visible; int lock;
char** values; char** values;
char** labels; char** labels;
} Option; } Option;
@ -350,6 +350,8 @@ typedef struct OptionList {
int count; int count;
int changed; int changed;
Option* options; Option* options;
int enabled_count;
Option** enabled_options;
// OptionList_callback_t on_set; // OptionList_callback_t on_set;
} OptionList; } OptionList;
@ -767,6 +769,7 @@ static void OptionList_init(const struct retro_core_option_definition *defs) {
if (count) { if (count) {
config.core.options = calloc(count+1, sizeof(Option)); config.core.options = calloc(count+1, sizeof(Option));
int enabled_count = 0;
for (int i=0; i<config.core.count; i++) { for (int i=0; i<config.core.count; i++) {
int len; int len;
const struct retro_core_option_definition *def = &defs[i]; const struct retro_core_option_definition *def = &defs[i];
@ -789,8 +792,6 @@ static void OptionList_init(const struct retro_core_option_definition *defs) {
GFX_wrapText(font.tiny, item->desc, SCALE1(240), 2); // TODO magic number! (this is more about chars per line than pixel width so it's not going to be relative to the screen size, only the scale) GFX_wrapText(font.tiny, item->desc, SCALE1(240), 2); // TODO magic number! (this is more about chars per line than pixel width so it's not going to be relative to the screen size, only the scale)
} }
item->visible = 1;
for (count=0; def->values[count].value; count++); for (count=0; def->values[count].value; count++);
item->count = count; item->count = count;
@ -822,6 +823,7 @@ static void OptionList_init(const struct retro_core_option_definition *defs) {
OptionOverride* override = &core.overrides->option_overrides[k]; OptionOverride* override = &core.overrides->option_overrides[k];
if (!strcmp(override->key, item->key)) { if (!strcmp(override->key, item->key)) {
default_value = override->value; default_value = override->value;
item->lock = override->lock;
break; break;
} }
} }
@ -829,6 +831,17 @@ static void OptionList_init(const struct retro_core_option_definition *defs) {
item->value = Option_getValueIndex(item, default_value); item->value = Option_getValueIndex(item, default_value);
item->default_value = item->value; item->default_value = item->value;
if (!item->lock) enabled_count += 1;
}
config.core.enabled_count = enabled_count;
config.core.enabled_options = calloc(enabled_count+1, sizeof(Option*));
int j = 0;
for (int i=0; i<config.core.count; i++) {
Option* item = &config.core.options[i];
if (item->lock) continue;
config.core.enabled_options[j] = item;
j += 1;
} }
} }
// fflush(stdout); // fflush(stdout);
@ -841,6 +854,7 @@ static void OptionList_vars(const struct retro_variable *vars) {
if (count) { if (count) {
config.core.options = calloc(count+1, sizeof(Option)); config.core.options = calloc(count+1, sizeof(Option));
int enabled_count = 0;
for (int i=0; i<config.core.count; i++) { for (int i=0; i<config.core.count; i++) {
int len; int len;
const struct retro_variable *var = &vars[i]; const struct retro_variable *var = &vars[i];
@ -861,8 +875,6 @@ static void OptionList_vars(const struct retro_variable *vars) {
tmp += 2; tmp += 2;
} }
item->visible = 1;
char* opt = tmp; char* opt = tmp;
for (count=0; (tmp=strchr(tmp, '|')); tmp++, count++); for (count=0; (tmp=strchr(tmp, '|')); tmp++, count++);
count += 1; // last entry after final '|' count += 1; // last entry after final '|'
@ -890,6 +902,7 @@ static void OptionList_vars(const struct retro_variable *vars) {
OptionOverride* override = &core.overrides->option_overrides[k]; OptionOverride* override = &core.overrides->option_overrides[k];
if (!strcmp(override->key, item->key)) { if (!strcmp(override->key, item->key)) {
default_value = override->value; default_value = override->value;
item->lock = override->lock;
break; break;
} }
} }
@ -897,8 +910,18 @@ static void OptionList_vars(const struct retro_variable *vars) {
item->value = Option_getValueIndex(item, default_value); item->value = Option_getValueIndex(item, default_value);
item->default_value = item->value; item->default_value = item->value;
if (!item->lock) enabled_count += 1;
// printf("SET %s to %s (%i)\n", item->key, default_value, item->value); fflush(stdout); // printf("SET %s to %s (%i)\n", item->key, default_value, item->value); fflush(stdout);
} }
config.core.enabled_count = enabled_count;
config.core.enabled_options = calloc(enabled_count+1, sizeof(Option*));
int j = 0;
for (int i=0; i<config.core.count; i++) {
Option* item = &config.core.options[i];
if (item->lock) continue;
config.core.enabled_options[j] = item;
j += 1;
}
} }
// fflush(stdout); // fflush(stdout);
} }
@ -926,6 +949,7 @@ static void OptionList_reset(void) {
free(item->key); free(item->key);
free(item->name); free(item->name);
} }
free(config.core.enabled_options);
free(config.core.options); free(config.core.options);
} }
@ -960,11 +984,11 @@ static void OptionList_setOptionValue(OptionList* list, const char* key, const c
} }
else printf("unknown option %s \n", key); fflush(stdout); else printf("unknown option %s \n", key); fflush(stdout);
} }
static void OptionList_setOptionVisibility(OptionList* list, const char* key, int visible) { // static void OptionList_setOptionVisibility(OptionList* list, const char* key, int visible) {
Option* item = OptionList_getOption(list, key); // Option* item = OptionList_getOption(list, key);
if (item) item->visible = visible; // if (item) item->visible = visible;
else printf("unknown option %s \n", key); fflush(stdout); // else printf("unknown option %s \n", key); fflush(stdout);
} // }
/////////////////////////////// ///////////////////////////////
@ -1245,12 +1269,12 @@ static bool environment_callback(unsigned cmd, void *data) { // copied from pico
} }
break; break;
} }
case RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY: { /* 55 */ // case RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY: { /* 55 */
// puts("RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY"); // // puts("RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY");
const struct retro_core_option_display *display = (const struct retro_core_option_display *)data; // const struct retro_core_option_display *display = (const struct retro_core_option_display *)data;
if (display) OptionList_setOptionVisibility(&config.core, display->key, display->visible); // if (display) OptionList_setOptionVisibility(&config.core, display->key, display->visible);
break; // break;
} // }
case RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION: { /* 57 */ case RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION: { /* 57 */
unsigned *out = (unsigned *)data; unsigned *out = (unsigned *)data;
if (out) if (out)
@ -2453,7 +2477,13 @@ static void Menu_detail(MenuItem* item) {
#define COMMIT_HASH "0b74e5f8" #define COMMIT_HASH "0b74e5f8"
static int Menu_options(MenuList* list); static int Menu_options(MenuList* list);
static int options_frontend_change(MenuList* list, int i) { static int MenuList_freeItems(MenuList* list, int i) {
// TODO: what calls this? do menu's register for needing it? then call it on quit for each?
if (list->items) free(list->items);
return MENU_CALLBACK_NOP;
}
static int OptionFrontend_optionChanged(MenuList* list, int i) {
MenuItem* item = &list->items[i]; MenuItem* item = &list->items[i];
Option* option = &config.frontend.options[i]; Option* option = &config.frontend.options[i];
LOG_info("%s (%s) changed from `%s` (%s) to `%s` (%s)\n", item->name, item->key, LOG_info("%s (%s) changed from `%s` (%s) to `%s` (%s)\n", item->name, item->key,
@ -2463,18 +2493,18 @@ static int options_frontend_change(MenuList* list, int i) {
option->value = item->value; option->value = item->value;
Config_syncFrontend(i, item->value); Config_syncFrontend(i, item->value);
} }
static MenuList options_frontend_menu = { static MenuList OptionFrontend_menu = {
.type = MENU_VAR, .type = MENU_VAR,
.on_change = options_frontend_change, .on_change = OptionFrontend_optionChanged,
.items = NULL, .items = NULL,
}; };
static int options_frontend_open(MenuList* list, int i) { static int OptionFrontend_openMenu(MenuList* list, int i) {
if (options_frontend_menu.items==NULL) { if (OptionFrontend_menu.items==NULL) {
// TODO: where do I free this? // TODO: where do I free this?
options_frontend_menu.items = calloc(config.frontend.count+1, sizeof(MenuItem)); OptionFrontend_menu.items = calloc(config.frontend.count+1, sizeof(MenuItem));
for (int j=0; j<config.frontend.count; j++) { for (int j=0; j<config.frontend.count; j++) {
Option* option = &config.frontend.options[j]; Option* option = &config.frontend.options[j];
MenuItem* item = &options_frontend_menu.items[j]; MenuItem* item = &OptionFrontend_menu.items[j];
item->key = option->key; item->key = option->key;
item->name = option->name; item->name = option->name;
item->desc = option->desc; item->desc = option->desc;
@ -2486,16 +2516,16 @@ static int options_frontend_open(MenuList* list, int i) {
// update values // update values
for (int j=0; j<config.frontend.count; j++) { for (int j=0; j<config.frontend.count; j++) {
Option* option = &config.frontend.options[j]; Option* option = &config.frontend.options[j];
MenuItem* item = &options_frontend_menu.items[j]; MenuItem* item = &OptionFrontend_menu.items[j];
item->value = option->value; item->value = option->value;
} }
} }
Menu_options(&options_frontend_menu); Menu_options(&OptionFrontend_menu);
return MENU_CALLBACK_NOP; return MENU_CALLBACK_NOP;
} }
static int options_emulator_change(MenuList* list, int i) { static int OptionEmulator_optionChanged(MenuList* list, int i) {
MenuItem* item = &list->items[i]; MenuItem* item = &list->items[i];
Option* option = OptionList_getOption(&config.core, item->key); Option* option = OptionList_getOption(&config.core, item->key);
LOG_info("%s (%s) changed from `%s` (%s) to `%s` (%s)\n", item->name, item->key, LOG_info("%s (%s) changed from `%s` (%s) to `%s` (%s)\n", item->name, item->key,
@ -2504,39 +2534,38 @@ static int options_emulator_change(MenuList* list, int i) {
); );
OptionList_setOptionRawValue(&config.core, item->key, item->value); OptionList_setOptionRawValue(&config.core, item->key, item->value);
} }
static MenuList options_emulator_menu = { static MenuList OptionEmulator_menu = {
.type = MENU_FIXED, .type = MENU_FIXED,
.on_change = options_emulator_change, .on_change = OptionEmulator_optionChanged,
.items = NULL, .items = NULL,
}; };
static int options_emulator_open(MenuList* list, int i) { static int OptionEmulator_openMenu(MenuList* list, int i) {
if (options_emulator_menu.items==NULL) { if (OptionEmulator_menu.items==NULL) {
// TODO: where do I free this? // TODO: where do I free this?
options_emulator_menu.items = calloc(config.core.count+1, sizeof(MenuItem)); OptionEmulator_menu.items = calloc(config.core.enabled_count+1, sizeof(MenuItem));
for (int j=0; j<config.core.count; j++) { for (int j=0; j<config.core.enabled_count; j++) {
Option* option = &config.core.options[j]; Option* option = config.core.enabled_options[j];
MenuItem* item = &options_emulator_menu.items[j]; MenuItem* item = &OptionEmulator_menu.items[j];
item->key = option->key; item->key = option->key;
item->name = option->name; item->name = option->name;
item->desc = NULL; // gambatte crashes if this isn't set to NULL :thinking_face: item->desc = option->desc;
item->desc = option->desc; // TODO: these need to be copyfit/truncated
item->value = option->value; item->value = option->value;
item->values = option->labels; item->values = option->labels;
} }
} }
else { else {
// update values // update values
for (int j=0; j<config.core.count; j++) { for (int j=0; j<config.core.enabled_count; j++) {
Option* option = &config.core.options[j]; Option* option = config.core.enabled_options[j];
MenuItem* item = &options_emulator_menu.items[j]; MenuItem* item = &OptionEmulator_menu.items[j];
item->value = option->value; item->value = option->value;
} }
} }
Menu_options(&options_emulator_menu); Menu_options(&OptionEmulator_menu);
return MENU_CALLBACK_NOP; return MENU_CALLBACK_NOP;
} }
int options_controls_bind_confirm(MenuList* list, int i) { int OptionControls_bind(MenuList* list, int i) {
MenuItem* item = &list->items[i]; MenuItem* item = &list->items[i];
ButtonMapping* button = &config.controls[item->id]; ButtonMapping* button = &config.controls[item->id];
@ -2558,19 +2587,19 @@ int options_controls_bind_confirm(MenuList* list, int i) {
} }
return MENU_CALLBACK_NEXT_ITEM; return MENU_CALLBACK_NEXT_ITEM;
} }
static MenuList options_controls_menu = { static MenuList OptionControls_menu = {
.type = MENU_INPUT, .type = MENU_INPUT,
.desc = "Press A to set and X to clear.", .desc = "Press A to set and X to clear.",
.on_confirm = options_controls_bind_confirm, .on_confirm = OptionControls_bind,
.items = NULL .items = NULL
}; };
static int options_controls_open(MenuList* list, int i) { static int OptionControls_openMenu(MenuList* list, int i) {
if (options_controls_menu.items==NULL) { if (OptionControls_menu.items==NULL) {
// TODO: where do I free this? // TODO: where do I free this?
options_controls_menu.items = calloc(RETRO_BUTTON_COUNT+1, sizeof(MenuItem)); OptionControls_menu.items = calloc(RETRO_BUTTON_COUNT+1, sizeof(MenuItem));
for (int j=0; config.controls[j].name; j++) { for (int j=0; config.controls[j].name; j++) {
ButtonMapping* button = &config.controls[j]; ButtonMapping* button = &config.controls[j];
MenuItem* item = &options_controls_menu.items[j]; MenuItem* item = &OptionControls_menu.items[j];
item->id = j; item->id = j;
// item->key = button->name; // TODO: tmp, lowercase this? prefix with "bind_" or don't lowercase and "bind " // item->key = button->name; // TODO: tmp, lowercase this? prefix with "bind_" or don't lowercase and "bind "
item->name = button->name; item->name = button->name;
@ -2583,15 +2612,15 @@ static int options_controls_open(MenuList* list, int i) {
// update values // update values
for (int j=0; config.controls[j].name; j++) { for (int j=0; config.controls[j].name; j++) {
ButtonMapping* button = &config.controls[j]; ButtonMapping* button = &config.controls[j];
MenuItem* item = &options_controls_menu.items[j]; MenuItem* item = &OptionControls_menu.items[j];
item->value = button->local + 1; item->value = button->local + 1;
} }
} }
Menu_options(&options_controls_menu); Menu_options(&OptionControls_menu);
return MENU_CALLBACK_NOP; return MENU_CALLBACK_NOP;
} }
static int options_shortcuts_bind_confirm(MenuList* list, int i) { static int OptionShortcuts_bind(MenuList* list, int i) {
MenuItem* item = &list->items[i]; MenuItem* item = &list->items[i];
ButtonMapping* button = &config.shortcuts[item->id]; ButtonMapping* button = &config.shortcuts[item->id];
int bound = 0; int bound = 0;
@ -2621,10 +2650,10 @@ static int options_shortcuts_bind_confirm(MenuList* list, int i) {
fflush(stdout); fflush(stdout);
return MENU_CALLBACK_NEXT_ITEM; return MENU_CALLBACK_NEXT_ITEM;
} }
static MenuList options_shortcuts_menu = { static MenuList OptionShortcuts_menu = {
.type = MENU_INPUT, .type = MENU_INPUT,
.desc = "Press A to set and X to clear.\nSupports single button and MENU+button.", .desc = "Press A to set and X to clear.\nSupports single button and MENU+button.",
.on_confirm = options_shortcuts_bind_confirm, .on_confirm = OptionShortcuts_bind,
.items = NULL .items = NULL
}; };
static char* getSaveDesc(void) { static char* getSaveDesc(void) {
@ -2634,13 +2663,13 @@ static char* getSaveDesc(void) {
case CONFIG_GAME: return "Using game config."; break; case CONFIG_GAME: return "Using game config."; break;
} }
} }
static int options_shortcuts_open(MenuList* list, int i) { static int OptionShortcuts_openMenu(MenuList* list, int i) {
if (options_shortcuts_menu.items==NULL) { if (OptionShortcuts_menu.items==NULL) {
// TODO: where do I free this? // TODO: where do I free this?
options_shortcuts_menu.items = calloc(SHORTCUT_COUNT+1, sizeof(MenuItem)); OptionShortcuts_menu.items = calloc(SHORTCUT_COUNT+1, sizeof(MenuItem));
for (int j=0; config.shortcuts[j].name; j++) { for (int j=0; config.shortcuts[j].name; j++) {
ButtonMapping* button = &config.shortcuts[j]; ButtonMapping* button = &config.shortcuts[j];
MenuItem* item = &options_shortcuts_menu.items[j]; MenuItem* item = &OptionShortcuts_menu.items[j];
item->id = j; item->id = j;
item->name = button->name; item->name = button->name;
item->desc = NULL; item->desc = NULL;
@ -2653,17 +2682,17 @@ static int options_shortcuts_open(MenuList* list, int i) {
// update values // update values
for (int j=0; config.shortcuts[j].name; j++) { for (int j=0; config.shortcuts[j].name; j++) {
ButtonMapping* button = &config.shortcuts[j]; ButtonMapping* button = &config.shortcuts[j];
MenuItem* item = &options_shortcuts_menu.items[j]; MenuItem* item = &OptionShortcuts_menu.items[j];
item->value = button->local + 1; item->value = button->local + 1;
if (button->mod) item->value += RETRO_BUTTON_COUNT; if (button->mod) item->value += RETRO_BUTTON_COUNT;
} }
} }
Menu_options(&options_shortcuts_menu); Menu_options(&OptionShortcuts_menu);
return MENU_CALLBACK_NOP; return MENU_CALLBACK_NOP;
} }
static void update_save_option_desc(void); static void OptionSaveChanges_updateDesc(void);
static int options_save_confirm(MenuList* list, int i) { static int OptionSaveChanges_onConfirm(MenuList* list, int i) {
char* message; char* message;
switch (i) { switch (i) {
case 0: { case 0: {
@ -2703,12 +2732,12 @@ static int options_save_confirm(MenuList* list, int i) {
else GFX_sync(); else GFX_sync();
} }
GFX_setMode(MODE_MENU); GFX_setMode(MODE_MENU);
update_save_option_desc(); OptionSaveChanges_updateDesc();
return MENU_CALLBACK_EXIT; return MENU_CALLBACK_EXIT;
} }
static MenuList options_save_menu = { static MenuList OptionSaveChanges_menu = {
.type = MENU_LIST, .type = MENU_LIST,
.on_confirm = options_save_confirm, .on_confirm = OptionSaveChanges_onConfirm,
.items = (MenuItem[]){ .items = (MenuItem[]){
{"Save for all games"}, {"Save for all games"},
{"Save for this game"}, {"Save for this game"},
@ -2716,26 +2745,26 @@ static MenuList options_save_menu = {
{NULL}, {NULL},
} }
}; };
static int options_save_open(MenuList* list, int i) { static int OptionSaveChanges_openMenu(MenuList* list, int i) {
update_save_option_desc(); OptionSaveChanges_updateDesc();
options_save_menu.desc = getSaveDesc(); OptionSaveChanges_menu.desc = getSaveDesc();
Menu_options(&options_save_menu); Menu_options(&OptionSaveChanges_menu);
return MENU_CALLBACK_NOP; return MENU_CALLBACK_NOP;
} }
static MenuList options_menu = { static MenuList options_menu = {
.type = MENU_LIST, .type = MENU_LIST,
.items = (MenuItem[]) { .items = (MenuItem[]) {
{"Frontend", "MinUI (" RELEASE_NAME " " COMMIT_HASH ")",.on_confirm=options_frontend_open}, {"Frontend", "MinUI (" RELEASE_NAME " " COMMIT_HASH ")",.on_confirm=OptionFrontend_openMenu},
{"Emulator",.on_confirm=options_emulator_open}, {"Emulator",.on_confirm=OptionEmulator_openMenu},
{"Controls",.on_confirm=options_controls_open}, {"Controls",.on_confirm=OptionControls_openMenu},
{"Shortcuts",.on_confirm=options_shortcuts_open}, {"Shortcuts",.on_confirm=OptionShortcuts_openMenu},
{"Save Changes",.on_confirm=options_save_open}, {"Save Changes",.on_confirm=OptionSaveChanges_openMenu},
{NULL}, {NULL},
} }
}; };
static void update_save_option_desc(void) { static void OptionSaveChanges_updateDesc(void) {
options_menu.items[4].desc = getSaveDesc(); options_menu.items[4].desc = getSaveDesc();
} }
@ -2754,7 +2783,7 @@ static int Menu_options(MenuList* list) {
int end = MIN(count,MAX_VISIBLE_OPTIONS); int end = MIN(count,MAX_VISIBLE_OPTIONS);
int visible_rows = end; int visible_rows = end;
update_save_option_desc(); OptionSaveChanges_updateDesc();
while (show_options) { while (show_options) {
if (await_input) { if (await_input) {

View file

@ -4,7 +4,7 @@
typedef struct OptionOverride { typedef struct OptionOverride {
char* key; char* key;
char* value; char* value;
int lock; // TODO: prevent changing this value int lock; // prevents changing this value
} OptionOverride; } OptionOverride;
typedef struct ButtonMapping { typedef struct ButtonMapping {