void menu_list_pop_stack_by_needle(menu_list_t *list, const char *needle) { uint32_t needle_hash, label_hash; const char *path = NULL; const char *label = NULL; unsigned type = 0; size_t entry_idx = 0; menu_navigation_t *nav = menu_navigation_get_ptr(); if (!list) return; menu_entries_set_refresh(false); menu_list_get_last(list->menu_stack, &path, &label, &type, &entry_idx); needle_hash = menu_hash_calculate(needle); label_hash = menu_hash_calculate(label); while (needle_hash == label_hash) { menu_list_pop(list->menu_stack, &nav->selection_ptr); menu_list_get_last(list->menu_stack, &path, &label, &type, &entry_idx); label_hash = menu_hash_calculate(label); needle_hash = menu_hash_calculate(needle); } }
int menu_cbs_init_bind_deferred_push(menu_file_list_cbs_t *cbs, const char *path, const char *label, unsigned type, size_t idx, const char *elem0, const char *elem1, uint32_t label_hash, uint32_t menu_label_hash) { settings_t *settings = config_get_ptr(); rarch_setting_t *setting = menu_setting_find(elem0); if (!cbs) return -1; cbs->action_deferred_push = deferred_push_default; if (setting) { uint32_t parent_group_hash = menu_hash_calculate(setting->parent_group); if ((parent_group_hash == MENU_VALUE_MAIN_MENU) && setting->type == ST_GROUP) { if (!settings->menu.collapse_subgroups_enable) { cbs->action_deferred_push = deferred_push_settings_subgroup; return 0; } } } if (menu_cbs_init_bind_deferred_push_compare_label(cbs, label, label_hash) == 0) return 0; if (menu_cbs_init_bind_deferred_push_compare_type(cbs, type, label_hash) == 0) return 0; return -1; }
int menu_cbs_init_bind_deferred_push(menu_file_list_cbs_t *cbs, const char *path, const char *label, unsigned type, size_t idx, const char *elem0, const char *elem1, uint32_t label_hash, uint32_t menu_label_hash) { settings_t *settings = config_get_ptr(); if (!cbs) return -1; BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_default); if (cbs->setting) { const char *parent_group = menu_setting_get_parent_group(cbs->setting); uint32_t parent_group_hash = menu_hash_calculate(parent_group); if ((parent_group_hash == MENU_VALUE_MAIN_MENU) && menu_setting_get_type(cbs->setting) == ST_GROUP) { if (!settings->menu.collapse_subgroups_enable) { BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_settings_subgroup); return 0; } } } if (menu_cbs_init_bind_deferred_push_compare_label(cbs, label, label_hash) == 0) return 0; if (menu_cbs_init_bind_deferred_push_compare_type(cbs, type, label_hash) == 0) return 0; return -1; }
/** * menu_content_find_first_core: * @core_info : Core info list handle. * @dir : Directory. Gets joined with @path. * @path : Path. Gets joined with @dir. * @menu_label : Label identifier of menu setting. * @s : Deferred core path. Will be filled in * by function. * @len : Size of @s. * * Gets deferred core. * * Returns: false if there are multiple deferred cores and a * selection needs to be made from a list, otherwise * returns true and fills in @s with path to core. **/ static bool menu_content_find_first_core(void *data) { char new_core_path[PATH_MAX_LENGTH]; const core_info_t *info = NULL; size_t supported = 0; menu_content_ctx_defer_info_t *def_info = (menu_content_ctx_defer_info_t *)data; core_info_list_t *core_info = (core_info_list_t*)def_info->data; uint32_t menu_label_hash = menu_hash_calculate(def_info->menu_label); if ( !string_is_empty(def_info->dir) && !string_is_empty(def_info->path)) fill_pathname_join(def_info->s, def_info->dir, def_info->path, def_info->len); #ifdef HAVE_COMPRESSION if (path_is_compressed_file(def_info->dir)) { /* In case of a compressed archive, we have to join with a hash */ /* We are going to write at the position of dir: */ retro_assert(strlen(def_info->dir) < strlen(def_info->s)); def_info->s[strlen(def_info->dir)] = '#'; } #endif if (core_info) core_info_list_get_supported_cores(core_info, def_info->s, &info, &supported); /* We started the menu with 'Load Content', we are * going to use the current core to load this. */ if (menu_label_hash == MENU_LABEL_LOAD_CONTENT) { core_info_ctl(CORE_INFO_CTL_CURRENT_CORE_GET, (void*)&info); if (info) { RARCH_LOG("Use the current core (%s) to load this content...\n", info->path); supported = 1; } } /* There are multiple deferred cores and a * selection needs to be made from a list, return 0. */ if (supported != 1) return false; if (info) strlcpy(new_core_path, info->path, sizeof(new_core_path)); runloop_ctl(RUNLOOP_CTL_SET_CONTENT_PATH, def_info->s); if (path_file_exists(new_core_path)) runloop_ctl(RUNLOOP_CTL_SET_LIBRETRO_PATH, new_core_path); return true; }
void menu_input_st_string_callback(void *userdata, const char *str) { if (str && *str) { rarch_setting_t *setting = NULL; const char *label = NULL; global_t *global = global_get_ptr(); menu_input_ctl(MENU_INPUT_CTL_KEYBOARD_LABEL_SETTING, &label); setting = menu_setting_find(label); if (setting) { menu_setting_set_with_string_representation(setting, str); menu_setting_generic(setting, false); } else { uint32_t hash_label = menu_hash_calculate(label); switch (hash_label) { case MENU_LABEL_VIDEO_SHADER_PRESET_SAVE_AS: menu_shader_manager_save_preset(str, false); break; case MENU_LABEL_CHEAT_FILE_SAVE_AS: cheat_manager_save(global->cheat, str); break; } } } menu_input_key_end_line(); }
static void menu_action_setting_disp_set_label(file_list_t* list, unsigned *w, unsigned type, unsigned i, const char *label, char *s, size_t len, const char *entry_label, const char *path, char *s2, size_t len2) { global_t *global = global_get_ptr(); uint32_t hash_label = menu_hash_calculate(label); *s = '\0'; *w = 19; switch (hash_label) { case MENU_LABEL_PERFORMANCE_COUNTERS: case MENU_LABEL_LOAD_CONTENT_HISTORY: *w = strlen(label); break; } if (type >= MENU_SETTINGS_CORE_OPTION_START) strlcpy( s, core_option_get_val(global->system.core_options, type - MENU_SETTINGS_CORE_OPTION_START), len); else setting_get_label(list, s, len, w, type, label, entry_label, i); strlcpy(s2, path, len2); }
static void menu_action_setting_disp_set_label(file_list_t* list, unsigned *w, unsigned type, unsigned i, const char *label, char *s, size_t len, const char *entry_label, const char *path, char *s2, size_t len2) { rarch_system_info_t *system = rarch_system_info_get_ptr(); uint32_t hash_label = menu_hash_calculate(label); *s = '\0'; *w = 19; switch (hash_label) { case MENU_LABEL_LOAD_CONTENT_HISTORY: *w = strlen(label); break; case MENU_LABEL_SYSTEM_INFORMATION: *w = 2; break; case MENU_LABEL_DEBUG_INFORMATION: *w = 2; break; } if (type >= MENU_SETTINGS_CORE_OPTION_START) { const char *core_opt = NULL; if (!system) return; core_opt = core_option_get_val(system->core_options, type - MENU_SETTINGS_CORE_OPTION_START); strlcpy(s, core_opt ? core_opt : "", len); } else setting_get_label(list, s, len, w, type, label, entry_label, i); strlcpy(s2, path, len2); }
static int action_iterate_info(char *s, size_t len, const char *label) { uint32_t label_hash = 0; menu_file_list_cbs_t *cbs = NULL; menu_list_t *menu_list = menu_list_get_ptr(); menu_navigation_t *nav = menu_navigation_get_ptr(); size_t i = menu_navigation_get_selection(nav); if (!menu_list) return 0; cbs = menu_list_get_actiondata_at_offset(menu_list->selection_buf, i); if (cbs->setting) { char needle[PATH_MAX_LENGTH]; strlcpy(needle, cbs->setting->name, sizeof(needle)); label_hash = menu_hash_calculate(needle); } return menu_hash_get_help(label_hash, s, len); }
void menu_input_st_string_callback(void *userdata, const char *str) { menu_input_t *menu_input = menu_input_get_ptr(); if (!menu_input) return; if (str && *str) { global_t *global = global_get_ptr(); rarch_setting_t *current_setting = menu_setting_find(menu_input->keyboard.label_setting); if (current_setting) { setting_set_with_string_representation(current_setting, str); menu_setting_generic(current_setting, false); } else { uint32_t hash_label = menu_hash_calculate(menu_input->keyboard.label_setting); switch (hash_label) { case MENU_LABEL_VIDEO_SHADER_PRESET_SAVE_AS: menu_shader_manager_save_preset(str, false); break; case MENU_LABEL_REMAP_FILE_SAVE_AS: input_remapping_save_file(str); break; case MENU_LABEL_CHEAT_FILE_SAVE_AS: cheat_manager_save(global->cheat, str); break; } } } menu_input_key_end_line(); }
static void mui_render_label_value(mui_handle_t *mui, int y, unsigned width, unsigned height, uint64_t index, uint32_t color, bool selected, const char *label, const char *value, float *pure_white) { char label_str[PATH_MAX_LENGTH]; char value_str[PATH_MAX_LENGTH]; int value_len = strlen(value); int ticker_limit = 0; size_t usable_width = 0; uintptr_t texture_switch = 0; bool do_draw_text = false; uint32_t hash_value = 0; usable_width = width - (mui->margin * 2); if (value_len * mui->glyph_width > usable_width / 2) value_len = (usable_width/2) / mui->glyph_width; ticker_limit = (usable_width / mui->glyph_width) - (value_len + 2); menu_animation_ticker_str(label_str, ticker_limit, index, label, selected); menu_animation_ticker_str(value_str, value_len, index, value, selected); mui_blit_line(mui->margin, y + mui->line_height / 2, width, height, label_str, color, TEXT_ALIGN_LEFT); hash_value = menu_hash_calculate(value); if (string_is_equal(value, "disabled") || string_is_equal(value, "off")) { if (mui->textures.list[MUI_TEXTURE_SWITCH_OFF].id) texture_switch = mui->textures.list[MUI_TEXTURE_SWITCH_OFF].id; else do_draw_text = true; } else if (string_is_equal(value, "enabled") || string_is_equal(value, "on")) { if (mui->textures.list[MUI_TEXTURE_SWITCH_ON].id) texture_switch = mui->textures.list[MUI_TEXTURE_SWITCH_ON].id; else do_draw_text = true; } else { switch (hash_value) { case MENU_VALUE_COMP: break; case MENU_VALUE_MORE: break; case MENU_VALUE_CORE: break; case MENU_VALUE_RDB: break; case MENU_VALUE_CURSOR: break; case MENU_VALUE_FILE: break; case MENU_VALUE_DIR: break; case MENU_VALUE_MUSIC: break; case MENU_VALUE_IMAGE: break; case MENU_VALUE_MOVIE: break; case MENU_VALUE_ON: if (mui->textures.list[MUI_TEXTURE_SWITCH_ON].id) texture_switch = mui->textures.list[MUI_TEXTURE_SWITCH_ON].id; else do_draw_text = true; break; case MENU_VALUE_OFF: if (mui->textures.list[MUI_TEXTURE_SWITCH_OFF].id) texture_switch = mui->textures.list[MUI_TEXTURE_SWITCH_OFF].id; else do_draw_text = true; break; default: do_draw_text = true; break; } } if (do_draw_text) mui_blit_line(width - mui->margin, y + mui->line_height / 2, width, height, value_str, color, TEXT_ALIGN_RIGHT); if (texture_switch) mui_draw_icon(mui, texture_switch, width - mui->margin - mui->icon_size, y, width, height, 0, 1, &pure_white[0]); }
static int action_iterate_main(const char *label, unsigned action) { menu_entry_t entry; static bool did_messagebox = false; char msg[PATH_MAX_LENGTH] = {0}; enum action_iterate_type iterate_type; size_t selected; size_t *pop_selected = NULL; bool do_messagebox = false; bool do_pop_stack = false; bool do_post_iterate = false; bool do_render = false; int ret = 0; menu_handle_t *menu = menu_driver_get_ptr(); menu_navigation_t *nav = menu_navigation_get_ptr(); menu_display_t *disp = menu_display_get_ptr(); menu_list_t *menu_list = menu_list_get_ptr(); uint32_t hash = menu_hash_calculate(label); if (!menu || !menu_list) return 0; iterate_type = action_iterate_type(hash); switch (iterate_type) { case ITERATE_TYPE_HELP: ret = action_iterate_help(msg, sizeof(msg), label); pop_selected = NULL; do_messagebox = true; do_pop_stack = true; do_post_iterate = true; if (ret == 1) action = MENU_ACTION_OK; break; case ITERATE_TYPE_BIND: if (menu_input_bind_iterate()) menu_list_pop_stack(menu_list); break; case ITERATE_TYPE_VIEWPORT: ret = action_iterate_menu_viewport(msg, sizeof(msg), label, action, hash); break; case ITERATE_TYPE_INFO: ret = action_iterate_info(msg, sizeof(msg), label); pop_selected = &nav->selection_ptr; do_messagebox = true; do_pop_stack = true; do_post_iterate = true; break; case ITERATE_TYPE_MESSAGE: strlcpy(msg, disp->message_contents, sizeof(msg)); pop_selected = &nav->selection_ptr; do_messagebox = true; do_pop_stack = true; break; case ITERATE_TYPE_DEFAULT: selected = menu_navigation_get_current_selection(); /* FIXME: selected > selection_buf->list->size, i don't know why. */ selected = max(min(selected, menu_list_get_size(menu_list)-1), 0); menu_entry_get(&entry, selected, NULL, false); ret = menu_entry_action(&entry, selected, (enum menu_action)action); if (ret) return ret; do_post_iterate = true; do_render = true; /* Have to defer it so we let settings refresh. */ if (menu->push_help_screen) { menu_displaylist_info_t info = {0}; info.list = menu_list->menu_stack; strlcpy(info.label, menu_hash_to_str(MENU_LABEL_HELP), sizeof(info.label)); menu_displaylist_push_list(&info, DISPLAYLIST_HELP); } break; } did_messagebox = did_messagebox != do_messagebox; if (did_messagebox) menu_display_fb_set_dirty(); if (do_messagebox) menu_driver_render_messagebox(msg); if (do_pop_stack && action == MENU_ACTION_OK) menu_list_pop(menu_list->menu_stack, pop_selected); if (do_post_iterate) menu_input_post_iterate(&ret, action); if (do_render) menu_driver_render(); return ret; }
static int menu_cbs_init_bind_left_compare_label(menu_file_list_cbs_t *cbs, const char *label, uint32_t label_hash, uint32_t menu_label_hash, const char *elem0) { unsigned i; if (cbs->setting) { const char *parent_group = menu_setting_get_parent_group(cbs->setting); uint32_t parent_group_hash = menu_hash_calculate(parent_group); if ((parent_group_hash == MENU_VALUE_MAIN_MENU) && (menu_setting_get_type(cbs->setting) == ST_GROUP)) { BIND_ACTION_LEFT(cbs, action_left_mainmenu); return 0; } } for (i = 0; i < MAX_USERS; i++) { uint32_t label_setting_hash; char label_setting[PATH_MAX_LENGTH]; label_setting[0] = '\0'; snprintf(label_setting, sizeof(label_setting), "input_player%d_joypad_index", i + 1); label_setting_hash = menu_hash_calculate(label_setting); if (label_hash != label_setting_hash) continue; BIND_ACTION_LEFT(cbs, bind_left_generic); return 0; } if (strstr(label, "rdb_entry")) { BIND_ACTION_LEFT(cbs, action_left_scroll); } else { switch (label_hash) { case MENU_LABEL_VIDEO_SHADER_SCALE_PASS: BIND_ACTION_LEFT(cbs, action_left_shader_scale_pass); break; case MENU_LABEL_VIDEO_SHADER_FILTER_PASS: BIND_ACTION_LEFT(cbs, action_left_shader_filter_pass); break; case MENU_LABEL_VIDEO_SHADER_DEFAULT_FILTER: BIND_ACTION_LEFT(cbs, action_left_shader_filter_default); break; case MENU_LABEL_VIDEO_SHADER_NUM_PASSES: BIND_ACTION_LEFT(cbs, action_left_shader_num_passes); break; case MENU_LABEL_CHEAT_NUM_PASSES: BIND_ACTION_LEFT(cbs, action_left_cheat_num_passes); break; case MENU_LABEL_SCREEN_RESOLUTION: BIND_ACTION_LEFT(cbs, action_left_video_resolution); break; case MENU_LABEL_NO_PLAYLIST_ENTRIES_AVAILABLE: switch (menu_label_hash) { case MENU_VALUE_HORIZONTAL_MENU: case MENU_VALUE_MAIN_MENU: BIND_ACTION_LEFT(cbs, action_left_mainmenu); break; } default: return -1; } } return 0; }
void menu_cbs_init(void *data, menu_file_list_cbs_t *cbs, const char *path, const char *label, unsigned type, size_t idx) { menu_ctx_bind_t bind_info; char elem0[PATH_MAX_LENGTH]; char elem1[PATH_MAX_LENGTH]; const char *repr_label = NULL; struct string_list *str_list = NULL; const char *menu_label = NULL; uint32_t label_hash = 0; uint32_t menu_label_hash = 0; file_list_t *list = (file_list_t*)data; if (!list) return; elem0[0] = '\0'; elem1[0] = '\0'; menu_entries_get_last_stack(NULL, &menu_label, NULL, NULL); if (label) str_list = string_split(label, "|"); if (str_list && str_list->size > 0) strlcpy(elem0, str_list->elems[0].data, sizeof(elem0)); if (str_list && str_list->size > 1) strlcpy(elem1, str_list->elems[1].data, sizeof(elem1)); if (!label || !menu_label) goto error; label_hash = menu_hash_calculate(label); menu_label_hash = menu_hash_calculate(menu_label); #ifdef DEBUG_LOG RARCH_LOG("\n"); #endif repr_label = (!string_is_empty(label)) ? label : path; menu_cbs_init_bind_ok(cbs, path, label, type, idx, elem0, elem1, menu_label, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "OK", cbs->action_ok_ident); menu_cbs_init_bind_cancel(cbs, path, label, type, idx, elem0, elem1, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "CANCEL", cbs->action_cancel_ident); menu_cbs_init_bind_scan(cbs, path, label, type, idx, elem0, elem1, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "SCAN", cbs->action_scan_ident); menu_cbs_init_bind_start(cbs, path, label, type, idx, elem0, elem1, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "START", cbs->action_start_ident); menu_cbs_init_bind_select(cbs, path, label, type, idx, elem0, elem1, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "SELECT", cbs->action_select_ident); menu_cbs_init_bind_info(cbs, path, label, type, idx, elem0, elem1, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "INFO", cbs->action_info_ident); menu_cbs_init_bind_content_list_switch(cbs, path, label, type, idx, elem0, elem1, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "CONTENT SWITCH", cbs->action_content_list_switch_ident); menu_cbs_init_bind_up(cbs, path, label, type, idx, elem0, elem1, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "UP", cbs->action_up_ident); menu_cbs_init_bind_down(cbs, path, label, type, idx, elem0, elem1, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "DOWN", cbs->action_down_ident); menu_cbs_init_bind_left(cbs, path, label, type, idx, elem0, elem1, menu_label, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "LEFT", cbs->action_left_ident); menu_cbs_init_bind_right(cbs, path, label, type, idx, elem0, elem1, menu_label, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "RIGHT", cbs->action_right_ident); menu_cbs_init_bind_deferred_push(cbs, path, label, type, idx, elem0, elem1, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "DEFERRED PUSH", cbs->action_deferred_push_ident); menu_cbs_init_bind_refresh(cbs, path, label, type, idx, elem0, elem1, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "REFRESH", cbs->action_refresh_ident); menu_cbs_init_bind_get_string_representation(cbs, path, label, type, idx, elem0, elem1, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "GET VALUE", cbs->action_get_value_ident); menu_cbs_init_bind_title(cbs, path, label, type, idx, elem0, elem1, label_hash, menu_label_hash); menu_cbs_init_log(repr_label, "GET TITLE", cbs->action_get_title_ident); bind_info.cbs = cbs; bind_info.path = path; bind_info.label = label; bind_info.type = type; bind_info.idx = idx; bind_info.elem0 = elem0; bind_info.elem1 = elem1; bind_info.label_hash = label_hash; bind_info.menu_label_hash = menu_label_hash; menu_driver_ctl(RARCH_MENU_CTL_BIND_INIT, &bind_info); error: string_list_free(str_list); str_list = NULL; }
/** * menu_shader_manager_init: * * Initializes shader manager. **/ void menu_shader_manager_init(menu_handle_t *menu) { #ifdef HAVE_SHADER_MANAGER uint32_t ext_hash; char preset_path[PATH_MAX_LENGTH]; const char *ext = NULL; struct video_shader *shader = NULL; config_file_t *conf = NULL; const char *config_path = NULL; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); if (!menu) return; shader = (struct video_shader*)menu->shader; if (*global->path.core_specific_config && settings->core_specific_config) config_path = global->path.core_specific_config; else if (*global->path.config) config_path = global->path.config; /* In a multi-config setting, we can't have * conflicts on menu.cgp/menu.glslp. */ if (config_path) { fill_pathname_base(menu->default_glslp, config_path, sizeof(menu->default_glslp)); path_remove_extension(menu->default_glslp); strlcat(menu->default_glslp, ".glslp", sizeof(menu->default_glslp)); fill_pathname_base(menu->default_cgp, config_path, sizeof(menu->default_cgp)); path_remove_extension(menu->default_cgp); strlcat(menu->default_cgp, ".cgp", sizeof(menu->default_cgp)); } else { strlcpy(menu->default_glslp, "menu.glslp", sizeof(menu->default_glslp)); strlcpy(menu->default_cgp, "menu.cgp", sizeof(menu->default_cgp)); } ext = path_get_extension(settings->video.shader_path); ext_hash = menu_hash_calculate(ext); switch (ext_hash) { case MENU_VALUE_GLSLP: case MENU_VALUE_CGP: conf = config_file_new(settings->video.shader_path); if (conf) { if (video_shader_read_conf_cgp(conf, shader)) { video_shader_resolve_relative(shader, settings->video.shader_path); video_shader_resolve_parameters(conf, shader); } config_file_free(conf); } break; case MENU_VALUE_GLSL: case MENU_VALUE_CG: strlcpy(shader->pass[0].source.path, settings->video.shader_path, sizeof(shader->pass[0].source.path)); shader->passes = 1; break; default: { const char *shader_dir = *settings->video.shader_dir ? settings->video.shader_dir : settings->system_directory; fill_pathname_join(preset_path, shader_dir, "menu.glslp", sizeof(preset_path)); conf = config_file_new(preset_path); if (!conf) { fill_pathname_join(preset_path, shader_dir, "menu.cgp", sizeof(preset_path)); conf = config_file_new(preset_path); } if (conf) { if (video_shader_read_conf_cgp(conf, shader)) { video_shader_resolve_relative(shader, preset_path); video_shader_resolve_parameters(conf, shader); } config_file_free(conf); } } break; } #endif }
/** * menu_iterate: * @input : input sample for this frame * @old_input : input sample of the previous frame * @trigger_input : difference' input sample - difference * between 'input' and 'old_input' * * Runs RetroArch menu for one frame. * * Returns: 0 on success, -1 if we need to quit out of the loop. **/ int menu_iterate(bool render_this_frame, unsigned action) { menu_entry_t entry; enum action_iterate_type iterate_type; size_t selected; const char *label = NULL; int ret = 0; uint32_t hash = 0; menu_handle_t *menu = menu_driver_get_ptr(); menu_navigation_t *nav = menu_navigation_get_ptr(); menu_display_t *disp = menu_display_get_ptr(); menu_list_t *menu_list = menu_list_get_ptr(); if (render_this_frame) menu_animation_update_time(); menu_list_get_last_stack(menu_list, NULL, &label, NULL, NULL); if (!menu || !menu_list) return 0; menu->state.fb_is_dirty = false; menu->state.do_messagebox = false; menu->state.do_render = false; menu->state.do_pop_stack = false; menu->state.do_post_iterate = false; menu->state.pop_selected = NULL; menu->state.msg[0] = '\0'; hash = menu_hash_calculate(label); iterate_type = action_iterate_type(hash); if (action != MENU_ACTION_NOOP || menu_entries_needs_refresh() || menu_display_update_pending()) { if (render_this_frame) menu->state.fb_is_dirty = true; } switch (iterate_type) { case ITERATE_TYPE_HELP: ret = action_iterate_help(menu->state.msg, sizeof(menu->state.msg), label); if (render_this_frame) menu->state.do_render = true; menu->state.pop_selected = NULL; menu->state.do_messagebox = true; menu->state.do_pop_stack = true; menu->state.do_post_iterate = true; if (ret == 1) action = MENU_ACTION_OK; break; case ITERATE_TYPE_BIND: if (menu_input_bind_iterate(menu->state.msg, sizeof(menu->state.msg))) menu_list_pop_stack(menu_list, &nav->selection_ptr); else menu->state.do_messagebox = true; if (render_this_frame) menu->state.do_render = true; break; case ITERATE_TYPE_VIEWPORT: ret = action_iterate_menu_viewport(menu->state.msg, sizeof(menu->state.msg), label, action, hash); if (render_this_frame) menu->state.do_render = true; menu->state.do_messagebox = true; break; case ITERATE_TYPE_INFO: ret = action_iterate_info(menu->state.msg, sizeof(menu->state.msg), label); menu->state.pop_selected = &nav->selection_ptr; if (render_this_frame) menu->state.do_render = true; menu->state.do_messagebox = true; menu->state.do_pop_stack = true; menu->state.do_post_iterate = true; break; case ITERATE_TYPE_MESSAGE: strlcpy(menu->state.msg, disp->message_contents, sizeof(menu->state.msg)); menu->state.pop_selected = &nav->selection_ptr; menu->state.do_messagebox = true; menu->state.do_pop_stack = true; break; case ITERATE_TYPE_DEFAULT: selected = menu_navigation_get_selection(nav); /* FIXME: selected > selection_buf->list->size, i don't know why. */ selected = max(min(selected, menu_list_get_size(menu_list)-1), 0); menu_entry_get(&entry, selected, NULL, false); ret = menu_entry_action(&entry, selected, (enum menu_action)action); if (ret) goto end; menu->state.do_post_iterate = true; if (render_this_frame) menu->state.do_render = true; /* Have to defer it so we let settings refresh. */ if (menu->push_help_screen) { menu_displaylist_info_t info = {0}; info.list = menu_list->menu_stack; strlcpy(info.label, menu_hash_to_str(MENU_LABEL_HELP), sizeof(info.label)); menu_displaylist_push_list(&info, DISPLAYLIST_HELP); } break; } if (menu->state.do_pop_stack && action == MENU_ACTION_OK) menu_list_pop_stack(menu_list, menu->state.pop_selected); if (menu->state.do_post_iterate) menu_input_post_iterate(&ret, action); end: if (ret) return -1; return 0; }
static void menu_action_setting_disp_set_label(file_list_t* list, unsigned *w, unsigned type, unsigned i, const char *label, char *s, size_t len, const char *entry_label, const char *path, char *s2, size_t len2) { rarch_system_info_t *system = NULL; uint32_t hash_label = menu_hash_calculate(label); runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); *s = '\0'; *w = 19; switch (hash_label) { case MENU_LABEL_LOAD_CONTENT_HISTORY: *w = strlen(label); break; case MENU_LABEL_SYSTEM_INFORMATION: *w = 2; break; case MENU_LABEL_DEBUG_INFORMATION: *w = 2; break; case MENU_LABEL_ACHIEVEMENT_LIST: *w = 2; break; } if (type >= MENU_SETTINGS_PLAYLIST_ASSOCIATION_START) { char playlist_name_with_ext[PATH_MAX_LENGTH]; unsigned i; bool found_matching_core_association = false; settings_t *settings = config_get_ptr(); struct string_list *str_list = string_split(settings->playlist_names, ";"); struct string_list *str_list2 = string_split(settings->playlist_cores, ";"); strlcpy(playlist_name_with_ext, path, sizeof(playlist_name_with_ext)); strlcat(playlist_name_with_ext, ".lpl", sizeof(playlist_name_with_ext)); for (i = 0; i < str_list->size; i++) { if (!strcmp(str_list->elems[i].data, playlist_name_with_ext)) { if (str_list->size != str_list2->size) break; if (str_list2->elems[i].data == NULL) break; found_matching_core_association = true; strlcpy(s, str_list2->elems[i].data, len); } } string_list_free(str_list); string_list_free(str_list2); if (!strcmp(s, "DETECT") || !found_matching_core_association) strlcpy(s, "N/A", len); else { char buf[PATH_MAX_LENGTH]; core_info_list_t *list = NULL; runloop_ctl(RUNLOOP_CTL_CURRENT_CORE_LIST_GET, &list); if (core_info_list_get_display_name(list, s, buf, sizeof(buf))) strlcpy(s, buf, len); } } else if (type >= MENU_SETTINGS_CORE_OPTION_START) { const char *core_opt = NULL; if (!system) return; core_opt = core_option_get_val(system->core_options, type - MENU_SETTINGS_CORE_OPTION_START); strlcpy(s, "", len); if (core_opt) strlcpy(s, core_opt, len); } else menu_setting_get_label(list, s, len, w, type, label, entry_label, i); strlcpy(s2, path, len2); }
static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs, const char *label, uint32_t label_hash, const char *elem1) { if (cbs->setting) { const char *parent_group = menu_setting_get_parent_group(cbs->setting); uint32_t parent_group_hash = menu_hash_calculate(parent_group); if ((parent_group_hash == MENU_VALUE_MAIN_MENU) && menu_setting_get_type(cbs->setting) == ST_GROUP) { BIND_ACTION_GET_TITLE(cbs, action_get_title_group_settings); return 0; } } switch (label_hash) { case MENU_LABEL_DEFERRED_DATABASE_MANAGER_LIST: BIND_ACTION_GET_TITLE(cbs, action_get_title_deferred_database_manager_list); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST: BIND_ACTION_GET_TITLE(cbs, action_get_title_deferred_cursor_manager_list); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST_RDB_ENTRY_DEVELOPER: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_developer); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST_RDB_ENTRY_PUBLISHER: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_publisher); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST_RDB_ENTRY_ORIGIN: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_origin); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST_RDB_ENTRY_FRANCHISE: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_franchise); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST_RDB_ENTRY_EDGE_MAGAZINE_RATING: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_edge_magazine_rating); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST_RDB_ENTRY_EDGE_MAGAZINE_ISSUE: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_edge_magazine_issue); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST_RDB_ENTRY_RELEASEMONTH: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_releasedate_by_month); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST_RDB_ENTRY_RELEASEYEAR: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_releasedate_by_year); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST_RDB_ENTRY_ESRB_RATING: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_esrb_rating); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST_RDB_ENTRY_ELSPA_RATING: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_elspa_rating); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST_RDB_ENTRY_PEGI_RATING: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_pegi_rating); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST_RDB_ENTRY_CERO_RATING: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_cero_rating); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST_RDB_ENTRY_BBFC_RATING: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_bbfc_rating); break; case MENU_LABEL_DEFERRED_CURSOR_MANAGER_LIST_RDB_ENTRY_MAX_USERS: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_max_users); break; case MENU_LABEL_DEFERRED_RDB_ENTRY_DETAIL: BIND_ACTION_GET_TITLE(cbs, action_get_title_list_rdb_entry_database_info); break; case MENU_LABEL_DEFERRED_CORE_LIST: BIND_ACTION_GET_TITLE(cbs, action_get_title_deferred_core_list); break; case MENU_LABEL_CONFIGURATIONS: BIND_ACTION_GET_TITLE(cbs, action_get_title_configurations); break; case MENU_LABEL_JOYPAD_AUTOCONFIG_DIR: BIND_ACTION_GET_TITLE(cbs, action_get_title_autoconfig_directory); break; case MENU_LABEL_EXTRACTION_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_extraction_directory); break; case MENU_LABEL_SYSTEM_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_system_directory); break; case MENU_LABEL_ASSETS_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_assets_directory); break; case MENU_LABEL_SAVEFILE_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_savefile_directory); break; case MENU_LABEL_OVERLAY_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_overlay_directory); break; case MENU_LABEL_RGUI_BROWSER_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_browser_directory); break; case MENU_LABEL_PLAYLIST_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_playlist_directory); break; case MENU_LABEL_CONTENT_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_content_directory); break; case MENU_LABEL_SCREENSHOT_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_screenshot_directory); break; case MENU_LABEL_VIDEO_SHADER_DIR: BIND_ACTION_GET_TITLE(cbs, action_get_title_video_shader_directory); break; case MENU_LABEL_VIDEO_FILTER_DIR: BIND_ACTION_GET_TITLE(cbs, action_get_title_video_filter_directory); break; case MENU_LABEL_AUDIO_FILTER_DIR: BIND_ACTION_GET_TITLE(cbs, action_get_title_audio_filter_directory); break; case MENU_LABEL_CURSOR_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_cursor_directory); break; case MENU_LABEL_RECORDING_CONFIG_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_recording_config_directory); break; case MENU_LABEL_RECORDING_OUTPUT_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_recording_output_directory); break; case MENU_LABEL_OSK_OVERLAY_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_onscreen_overlay_keyboard_directory); break; case MENU_LABEL_INPUT_REMAPPING_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_input_remapping_directory); break; case MENU_LABEL_CONTENT_DATABASE_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_content_database_directory); break; case MENU_LABEL_SAVESTATE_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_savestate_directory); break; case MENU_LABEL_DYNAMIC_WALLPAPERS_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_dynamic_wallpapers_directory); break; case MENU_LABEL_CORE_ASSETS_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_core_assets_directory); break; case MENU_LABEL_RGUI_CONFIG_DIRECTORY: BIND_ACTION_GET_TITLE(cbs, action_get_title_config_directory); break; case MENU_LABEL_CORE_LIST: case MENU_LABEL_MANAGEMENT: case MENU_LABEL_ONLINE_UPDATER: case MENU_LABEL_SETTINGS: case MENU_LABEL_FRONTEND_COUNTERS: case MENU_LABEL_CORE_COUNTERS: case MENU_LABEL_LOAD_CONTENT_HISTORY: case MENU_LABEL_INFO_SCREEN: case MENU_LABEL_SYSTEM_INFORMATION: case MENU_LABEL_DEBUG_INFORMATION: case MENU_LABEL_CORE_INFORMATION: case MENU_LABEL_VIDEO_SHADER_PARAMETERS: case MENU_LABEL_VIDEO_SHADER_PRESET_PARAMETERS: case MENU_LABEL_DISK_OPTIONS: case MENU_LABEL_CORE_OPTIONS: case MENU_LABEL_SHADER_OPTIONS: case MENU_LABEL_CORE_CHEAT_OPTIONS: case MENU_LABEL_CORE_INPUT_REMAPPING_OPTIONS: case MENU_LABEL_DATABASE_MANAGER_LIST: case MENU_LABEL_CURSOR_MANAGER_LIST: case MENU_LABEL_DEFERRED_CORE_UPDATER_LIST: case MENU_LABEL_CONTENT_COLLECTION_LIST: case MENU_LABEL_INFORMATION_LIST: case MENU_LABEL_LOAD_CONTENT_LIST: case MENU_LABEL_CONTENT_SETTINGS: case MENU_LABEL_ADD_CONTENT_LIST: BIND_ACTION_GET_TITLE(cbs, action_get_title_action_generic); break; case MENU_LABEL_DISK_IMAGE_APPEND: BIND_ACTION_GET_TITLE(cbs, action_get_title_disk_image_append); break; case MENU_LABEL_VIDEO_SHADER_PRESET: BIND_ACTION_GET_TITLE(cbs, action_get_title_video_shader_preset); break; case MENU_LABEL_CHEAT_FILE_LOAD: BIND_ACTION_GET_TITLE(cbs, action_get_title_cheat_file_load); break; case MENU_LABEL_REMAP_FILE_LOAD: BIND_ACTION_GET_TITLE(cbs, action_get_title_remap_file_load); break; case MENU_LABEL_HELP: BIND_ACTION_GET_TITLE(cbs, action_get_title_help); break; case MENU_LABEL_HELP_LIST: BIND_ACTION_GET_TITLE(cbs, action_get_title_help_list); break; case MENU_LABEL_INPUT_OVERLAY: BIND_ACTION_GET_TITLE(cbs, action_get_title_overlay); break; case MENU_LABEL_VIDEO_FONT_PATH: BIND_ACTION_GET_TITLE(cbs, action_get_title_font_path); break; case MENU_LABEL_VIDEO_FILTER: BIND_ACTION_GET_TITLE(cbs, action_get_title_video_filter); break; case MENU_LABEL_AUDIO_DSP_PLUGIN: BIND_ACTION_GET_TITLE(cbs, action_get_title_audio_filter); break; case MENU_LABEL_CHEAT_DATABASE_PATH: BIND_ACTION_GET_TITLE(cbs, action_get_title_cheat_directory); break; case MENU_LABEL_LIBRETRO_DIR_PATH: BIND_ACTION_GET_TITLE(cbs, action_get_title_core_directory); break; case MENU_LABEL_LIBRETRO_INFO_PATH: BIND_ACTION_GET_TITLE(cbs, action_get_title_core_info_directory); break; default: return -1; } return 0; }
static int menu_cbs_init_bind_right_compare_label(menu_file_list_cbs_t *cbs, const char *label, uint32_t label_hash, uint32_t menu_label_hash, const char *elem0) { unsigned i; rarch_setting_t *setting = menu_setting_find(label); if (setting) { uint32_t parent_group_hash = menu_hash_calculate(setting->parent_group); if ((parent_group_hash == MENU_LABEL_SETTINGS) && (setting->type == ST_GROUP)) { cbs->action_right = action_right_scroll; return 0; } } for (i = 0; i < MAX_USERS; i++) { uint32_t label_setting_hash; char label_setting[PATH_MAX_LENGTH]; label_setting[0] = '\0'; snprintf(label_setting, sizeof(label_setting), "input_player%d_joypad_index", i + 1); label_setting_hash = menu_hash_calculate(label_setting); if (label_hash != label_setting_hash) continue; cbs->action_right = bind_right_generic; return 0; } if (strstr(label, "rdb_entry")) cbs->action_right = action_right_scroll; else { switch (label_hash) { case MENU_LABEL_SAVESTATE: case MENU_LABEL_LOADSTATE: cbs->action_right = action_right_save_state; break; case MENU_LABEL_VIDEO_SHADER_SCALE_PASS: cbs->action_right = action_right_shader_scale_pass; break; case MENU_LABEL_VIDEO_SHADER_FILTER_PASS: cbs->action_right = action_right_shader_filter_pass; break; case MENU_LABEL_VIDEO_SHADER_DEFAULT_FILTER: cbs->action_right = action_right_shader_filter_default; break; case MENU_LABEL_VIDEO_SHADER_NUM_PASSES: cbs->action_right = action_right_shader_num_passes; break; case MENU_LABEL_CHEAT_NUM_PASSES: cbs->action_right = action_right_cheat_num_passes; break; case MENU_LABEL_SCREEN_RESOLUTION: cbs->action_right = action_right_video_resolution; break; case MENU_LABEL_NO_PLAYLIST_ENTRIES_AVAILABLE: switch (menu_label_hash) { case MENU_VALUE_HORIZONTAL_MENU: case MENU_VALUE_MAIN_MENU: cbs->action_right = action_right_mainmenu; break; } default: return -1; } } return 0; }
/** * menu_iterate: * @input : input sample for this frame * @old_input : input sample of the previous frame * @trigger_input : difference' input sample - difference * between 'input' and 'old_input' * * Runs RetroArch menu for one frame. * * Returns: 0 on success, -1 if we need to quit out of the loop. **/ int generic_menu_iterate(enum menu_action action) { size_t selection; menu_entry_t entry; enum action_iterate_type iterate_type; const char *label = NULL; int ret = 0; uint32_t label_hash = 0; uint32_t hash = 0; menu_handle_t *menu = menu_driver_get_ptr(); file_list_t *menu_stack = menu_entries_get_menu_stack_ptr(); file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(); menu_entries_get_last_stack(NULL, &label, NULL, NULL); if (!menu) return 0; if (!menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SELECTION, &selection)) return 0; menu->menu_state.msg[0] = '\0'; hash = menu_hash_calculate(label); iterate_type = action_iterate_type(hash); if (action != MENU_ACTION_NOOP || menu_entries_needs_refresh() || menu_display_ctl(MENU_DISPLAY_CTL_UPDATE_PENDING, NULL)) { BIT64_SET(menu->state, MENU_STATE_RENDER_FRAMEBUFFER); } switch (iterate_type) { case ITERATE_TYPE_HELP: ret = action_iterate_help(menu->menu_state.msg, sizeof(menu->menu_state.msg), label); BIT64_SET(menu->state, MENU_STATE_RENDER_MESSAGEBOX); BIT64_SET(menu->state, MENU_STATE_POST_ITERATE); if (ret == 1 || action == MENU_ACTION_OK) BIT64_SET(menu->state, MENU_STATE_POP_STACK); break; case ITERATE_TYPE_BIND: if (menu_input_key_bind_iterate(menu->menu_state.msg, sizeof(menu->menu_state.msg))) { menu_entries_pop_stack(&selection); menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &selection); } else BIT64_SET(menu->state, MENU_STATE_RENDER_MESSAGEBOX); break; case ITERATE_TYPE_INFO: { menu_file_list_cbs_t *cbs = menu_entries_get_actiondata_at_offset(selection_buf, selection); rarch_setting_t *setting = cbs->setting; if (setting) { char needle[PATH_MAX_LENGTH]; strlcpy(needle, menu_setting_get_name(setting), sizeof(needle)); label_hash = menu_hash_calculate(needle); } ret = menu_hash_get_help(label_hash, menu->menu_state.msg, sizeof(menu->menu_state.msg)); } BIT64_SET(menu->state, MENU_STATE_RENDER_MESSAGEBOX); BIT64_SET(menu->state, MENU_STATE_POST_ITERATE); if (action == MENU_ACTION_OK) BIT64_SET(menu->state, MENU_STATE_POP_STACK); break; case ITERATE_TYPE_DEFAULT: /* FIXME: Crappy hack, needed for mouse controls to not be completely broken * in case we press back. * * We need to fix this entire mess, mouse controls should not rely on a * hack like this in order to work. */ selection = max(min(selection, (menu_entries_get_size() - 1)), 0); menu_entry_get(&entry, selection, NULL, false); ret = menu_entry_action(&entry, selection, (enum menu_action)action); if (ret) goto end; BIT64_SET(menu->state, MENU_STATE_POST_ITERATE); /* Have to defer it so we let settings refresh. */ if (menu->push_help_screen) { menu_displaylist_info_t info = {0}; info.list = menu_stack; strlcpy(info.label, menu_hash_to_str(MENU_LABEL_HELP), sizeof(info.label)); menu_displaylist_push_list(&info, DISPLAYLIST_HELP); } break; } BIT64_SET(menu->state, MENU_STATE_BLIT); if (BIT64_GET(menu->state, MENU_STATE_POP_STACK)) { size_t new_selection_ptr = selection; menu_entries_pop_stack(&new_selection_ptr); menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &selection); } if (BIT64_GET(menu->state, MENU_STATE_POST_ITERATE)) menu_input_post_iterate(&ret, action); end: if (ret) return -1; return 0; }