/* RetroArch - A frontend for libretro. * Copyright (C) 2011-2017 - Daniel De Matteis * Copyright (C) 2014-2017 - Jean-André Santoni * Copyright (C) 2016-2019 - Andrés Suárez * Copyright (C) 2016-2019 - Brad Parker * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- * ation, either version 3 of the License, or (at your option) any later version. * * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with RetroArch. * If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include "../config.h" #endif #ifdef HAVE_LIBRETRODB #include "../database_info.h" #endif #ifdef HAVE_CHEEVOS #include "../cheevos/cheevos.h" #include "../cheevos/cheevos_menu.h" #endif #ifdef HAVE_NETWORKING #include #include "../../network/netplay/netplay.h" #include "../core_updater_list.h" #endif #ifdef HAVE_LAKKA #include "../../lakka.h" #endif #ifdef HAVE_LIBNX #include #endif #if defined(HAVE_LIBNX) #include "../../switch_performance_profiles.h" #endif #if defined(__linux__) || (defined(BSD) && !defined(__MACH__)) #include "../frontend/drivers/platform_unix.h" #endif #if defined(ANDROID) #include "../play_feature_delivery/play_feature_delivery.h" #endif #ifdef IOS #include "JITSupport.h" #endif #ifdef HAVE_CDROM #include #include #endif #include "../audio/audio_driver.h" #include "../record/record_driver.h" #include "menu_cbs.h" #include "menu_driver.h" #include "menu_entries.h" #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) #include "menu_shader.h" #endif #if defined(HAVE_MATERIALUI) || defined(HAVE_XMB) || defined(HAVE_OZONE) #include "menu_screensaver.h" #endif #if defined(HAVE_FFMPEG) || defined(HAVE_MPV) #include "../../cores/internal_cores.h" #endif #include "../configuration.h" #include "../file_path_special.h" #include "../defaults.h" #include "../verbosity.h" #include "../version.h" #ifdef HAVE_CHEATS #include "../cheat_manager.h" #endif #include "../core_option_manager.h" #include "../paths.h" #include "../retroarch.h" #include "../runloop.h" #include "../core.h" #include "../frontend/frontend_driver.h" #include "../ui/ui_companion_driver.h" #include "../gfx/video_display_server.h" #ifdef HAVE_GFX_WIDGETS #include "../gfx/gfx_widgets.h" #endif #include "../config.features.h" #include "../version_git.h" #include "../list_special.h" #include "../performance_counters.h" #include "../core_info.h" #include "../bluetooth/bluetooth_driver.h" #if defined(HAVE_NETWORKING) && defined(HAVE_WIFI) #include "../network/wifi_driver.h" #endif #include "../tasks/task_content.h" #include "../tasks/tasks_internal.h" #include "../dynamic.h" #include "../runtime_file.h" #include "../manual_content_scan.h" #include "../core_backup.h" #include "../misc/cpufreq/cpufreq.h" #include "../input/input_remapping.h" #ifdef HAVE_MICROPHONE #include "../audio/microphone_driver.h" #endif #ifdef HAVE_MIST #include "../steam/steam.h" #endif /* Spacers used for ' - ' labels * in playlists */ #define PL_LABEL_SPACER_DEFAULT " | " #define PL_LABEL_SPACER_RGUI " | " #define PL_LABEL_SPACER_MAXLEN 8 #define BYTES_TO_MB(bytes) ((bytes) / 1024 / 1024) #define BYTES_TO_GB(bytes) (((bytes) / 1024) / 1024 / 1024) #if defined(HAVE_NETWORKING) && defined(HAVE_IFINFO) #include #endif /* TODO/FIXME - globals - need to find a way to * get rid of these */ struct menu_displaylist_state { enum filebrowser_enums filebrowser_types; }; static struct menu_displaylist_state menu_displist_st = { FILEBROWSER_NONE /* filebrowser_types */ }; extern struct key_desc key_descriptors[RARCH_MAX_KEYS]; enum filebrowser_enums filebrowser_get_type(void) { struct menu_displaylist_state *p_displist = &menu_displist_st; return p_displist->filebrowser_types; } void filebrowser_clear_type(void) { struct menu_displaylist_state *p_displist = &menu_displist_st; p_displist->filebrowser_types = FILEBROWSER_NONE; } void filebrowser_set_type(enum filebrowser_enums type) { struct menu_displaylist_state *p_displist = &menu_displist_st; p_displist->filebrowser_types = type; } static int filebrowser_parse( file_list_t *info_list, const char *path, const char *exts, const char *label, unsigned type_default, unsigned type_data, bool show_hidden_files, bool builtin_mediaplayer_enable, bool builtin_imageviewer_enable, bool filter_ext ) { size_t i, list_size; const struct retro_subsystem_info *subsystem = NULL; bool ret = false; struct string_list str_list = {0}; unsigned count = 0; enum menu_displaylist_ctl_state type = (enum menu_displaylist_ctl_state)type_data; enum filebrowser_enums filebrowser_type = filebrowser_get_type(); bool allow_parent_directory = true; bool path_is_compressed = !string_is_empty(path) ? path_is_compressed_file(path) : false; menu_search_terms_t *search_terms = menu_entries_search_get_terms(); #ifdef IOS char full_path[PATH_MAX_LENGTH]; fill_pathname_expand_special(full_path, path, sizeof(full_path)); #else const char *full_path = path; #endif if (path_is_compressed) { if (filebrowser_type == FILEBROWSER_SELECT_FILE_SUBSYSTEM) { runloop_state_t *runloop_st = runloop_state_get_ptr(); rarch_system_info_t *sys_info = &runloop_st->system; /* Core fully loaded, use the subsystem data */ if (sys_info->subsystem.data) subsystem = sys_info->subsystem.data + content_get_subsystem(); /* Core not loaded completely, use the data we peeked on load core */ else subsystem = runloop_st->subsystem_data + content_get_subsystem(); if (subsystem && runloop_st->subsystem_current_count > 0) ret = file_archive_get_file_list_noalloc(&str_list, path, subsystem->roms[ content_get_subsystem_rom_id()].valid_extensions); } else ret = file_archive_get_file_list_noalloc(&str_list, path, exts); } else if (!string_is_empty(path)) { if ( type_default == FILE_TYPE_SHADER_PRESET || type_default == FILE_TYPE_SHADER) filter_ext = true; if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_SCAN_FILE))) filter_ext = false; if ( string_is_equal(label, "database_manager_list") #if IOS || string_is_equal(label, "video_filter") || string_is_equal(label, "audio_dsp_plugin") #endif || string_is_equal(label, "cursor_manager_list")) allow_parent_directory = false; if (filebrowser_type == FILEBROWSER_SELECT_FILE_SUBSYSTEM) { runloop_state_t *runloop_st = runloop_state_get_ptr(); rarch_system_info_t *sys_info = &runloop_st->system; /* Core fully loaded, use the subsystem data */ if (sys_info->subsystem.data) subsystem = sys_info->subsystem.data + content_get_subsystem(); /* Core not loaded completely, use the data we peeked on load core */ else subsystem = runloop_st->subsystem_data + content_get_subsystem(); if ( subsystem && (runloop_st->subsystem_current_count > 0) && (content_get_subsystem_rom_id() < subsystem->num_roms)) ret = dir_list_initialize(&str_list, full_path, filter_ext ? subsystem->roms[content_get_subsystem_rom_id()].valid_extensions : NULL, true, show_hidden_files, true, false); } else if ((type_default == FILE_TYPE_MANUAL_SCAN_DAT) || (type_default == FILE_TYPE_SIDELOAD_CORE)) ret = dir_list_initialize(&str_list, full_path, exts, true, show_hidden_files, false, false); else ret = dir_list_initialize(&str_list, full_path, filter_ext ? exts : NULL, true, show_hidden_files, true, false); } switch (filebrowser_type) { case FILEBROWSER_SCAN_DIR: #ifdef HAVE_LIBRETRODB menu_entries_prepend(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCAN_THIS_DIRECTORY), msg_hash_to_str(MENU_ENUM_LABEL_SCAN_THIS_DIRECTORY), MENU_ENUM_LABEL_SCAN_THIS_DIRECTORY, FILE_TYPE_SCAN_DIRECTORY, 0 ,0); #endif break; case FILEBROWSER_MANUAL_SCAN_DIR: menu_entries_prepend(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCAN_THIS_DIRECTORY), msg_hash_to_str(MENU_ENUM_LABEL_SCAN_THIS_DIRECTORY), MENU_ENUM_LABEL_SCAN_THIS_DIRECTORY, FILE_TYPE_MANUAL_SCAN_DIRECTORY, 0 ,0); break; case FILEBROWSER_SELECT_DIR: menu_entries_prepend(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_USE_THIS_DIRECTORY), msg_hash_to_str(MENU_ENUM_LABEL_USE_THIS_DIRECTORY), MENU_ENUM_LABEL_USE_THIS_DIRECTORY, FILE_TYPE_USE_DIRECTORY, 0 ,0); break; default: break; } if (!ret) { const char *str = path_is_compressed ? msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UNABLE_TO_READ_COMPRESSED_FILE) : msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DIRECTORY_NOT_FOUND); menu_entries_append(info_list, str, "", MENU_ENUM_LABEL_VALUE_DIRECTORY_NOT_FOUND, 0, 0, 0, NULL); goto end; } dir_list_sort(&str_list, true); list_size = str_list.size; if (list_size > 0) { for (i = 0; i < list_size; i++) { enum msg_hash_enums enum_idx = MSG_UNKNOWN; enum rarch_content_type path_type = RARCH_CONTENT_NONE; enum msg_file_type file_type = FILE_TYPE_NONE; const char *file_path = str_list.elems[i].data; if (string_is_empty(file_path)) continue; if ( (str_list.elems[i].attr.i != RARCH_DIRECTORY) && ((filebrowser_type == FILEBROWSER_SELECT_DIR) || (filebrowser_type == FILEBROWSER_SCAN_DIR) || (filebrowser_type == FILEBROWSER_MANUAL_SCAN_DIR))) continue; if (!path_is_compressed) { file_path = path_basename_nocompression(file_path); if (string_is_empty(file_path)) continue; } /* Check whether entry matches search terms, * if required */ if (search_terms) { size_t j; bool skip_entry = false; for (j = 0; j < search_terms->size; j++) { const char *search_term = search_terms->terms[j]; if ( !string_is_empty(search_term) && !strcasestr(file_path, search_term)) { skip_entry = true; break; } } if (skip_entry) continue; } switch (str_list.elems[i].attr.i) { case RARCH_DIRECTORY: file_type = FILE_TYPE_DIRECTORY; count++; menu_entries_append(info_list, file_path, "", MENU_ENUM_LABEL_FILE_BROWSER_DIRECTORY, file_type, 0, 0, NULL); continue; case RARCH_COMPRESSED_ARCHIVE: file_type = FILE_TYPE_CARCHIVE; break; case RARCH_COMPRESSED_FILE_IN_ARCHIVE: file_type = FILE_TYPE_IN_CARCHIVE; break; case RARCH_PLAIN_FILE: default: if (filebrowser_type == FILEBROWSER_SELECT_VIDEO_FONT) file_type = FILE_TYPE_VIDEO_FONT; else file_type = (enum msg_file_type)type_default; switch (type) { /* in case of deferred_core_list we have to interpret * every archive as an archive to disallow instant loading */ case DISPLAYLIST_CORES_DETECTED: if (path_is_compressed_file(file_path)) file_type = FILE_TYPE_CARCHIVE; break; default: break; } break; } path_type = path_is_media_type(file_path); if (filebrowser_type == FILEBROWSER_SELECT_COLLECTION) file_type = FILE_TYPE_PLAYLIST_COLLECTION; if ( builtin_mediaplayer_enable || builtin_imageviewer_enable) { switch (path_type) { case RARCH_CONTENT_MUSIC: #if defined(HAVE_FFMPEG) || defined(HAVE_MPV) || defined(HAVE_AUDIOMIXER) if (builtin_mediaplayer_enable) file_type = FILE_TYPE_MUSIC; #endif break; case RARCH_CONTENT_MOVIE: #if defined(HAVE_FFMPEG) || defined(HAVE_MPV) if (builtin_mediaplayer_enable) file_type = FILE_TYPE_MOVIE; #endif break; case RARCH_CONTENT_IMAGE: #ifdef HAVE_IMAGEVIEWER if ( builtin_imageviewer_enable && (type != DISPLAYLIST_IMAGES)) file_type = FILE_TYPE_IMAGEVIEWER; else file_type = FILE_TYPE_IMAGE; #endif if (filebrowser_type == FILEBROWSER_SELECT_IMAGE) file_type = FILE_TYPE_IMAGE; break; default: break; } } switch (file_type) { case FILE_TYPE_MOVIE: enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_MOVIE_OPEN; break; case FILE_TYPE_MUSIC: enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_MUSIC_OPEN; break; case FILE_TYPE_IMAGE: enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_IMAGE; break; case FILE_TYPE_IMAGEVIEWER: enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_IMAGE_OPEN_WITH_VIEWER; break; case FILE_TYPE_PLAIN: default: break; } count++; menu_entries_append(info_list, file_path, "", enum_idx, file_type, 0, 0, NULL); } } dir_list_deinitialize(&str_list); if (count == 0) menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ITEMS), msg_hash_to_str(MENU_ENUM_LABEL_NO_ITEMS), MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_NO_ITEM, 0, 0, NULL); #ifdef IOS { /* Check if we're allowed to escape our sandbox */ struct string_list *str_list = string_list_new(); dir_list_append(str_list, "/private/var", NULL, true, false, false, false); if (str_list->size <= 0) { char dir[PATH_MAX_LENGTH]; fill_pathname_application_dir(dir, sizeof(dir)); if (string_ends_with(full_path, "/") && !string_ends_with(dir, "/")) strlcat(dir, "/", sizeof(dir)); if (string_is_equal(dir, full_path)) allow_parent_directory = false; else { size_t _len = fill_pathname_home_dir(dir, sizeof(dir)); if (string_ends_with(full_path, "/") && !string_ends_with(dir, "/")) strlcpy(dir + _len, "/", sizeof(dir) - _len); if (string_is_equal(dir, full_path)) allow_parent_directory = false; } } string_list_free(str_list); } #endif end: if (!path_is_compressed && allow_parent_directory) menu_entries_prepend(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PARENT_DIRECTORY), path, MENU_ENUM_LABEL_PARENT_DIRECTORY, FILE_TYPE_PARENT_DIRECTORY, 0, 0); return count; } static int menu_displaylist_parse_core_info( file_list_t *list, uint32_t info_type, const char *info_path, settings_t *settings) { char tmp[PATH_MAX_LENGTH]; #if IOS char shortened_path[PATH_MAX_LENGTH] = {0}; #endif unsigned i, count = 0; core_info_t *core_info = NULL; const char *core_path = NULL; const char *savestate_support = NULL; runloop_state_t *runloop_st = runloop_state_get_ptr(); bool kiosk_mode_enable = settings->bools.kiosk_mode_enable; #if defined(HAVE_DYNAMIC) enum menu_contentless_cores_display_type contentless_display_type = (enum menu_contentless_cores_display_type) settings->uints.menu_content_show_contentless_cores; #endif /* Check whether we are parsing information for a * core updater/manager entry or the currently loaded core */ if ( (info_type == FILE_TYPE_DOWNLOAD_CORE) || (info_type == MENU_SETTING_ACTION_CORE_MANAGER_OPTIONS)) { core_info_t *core_info_menu = NULL; core_path = info_path; /* Core updater entry - search for corresponding * core info */ if (core_info_find(core_path, &core_info_menu)) core_info = core_info_menu; } else if (core_info_get_current_core(&core_info) && core_info) core_path = core_info->path; if (!core_info || !core_info->has_info) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_CORE_INFORMATION_AVAILABLE), msg_hash_to_str(MENU_ENUM_LABEL_NO_CORE_INFORMATION_AVAILABLE), MENU_ENUM_LABEL_NO_CORE_INFORMATION_AVAILABLE, 0, 0, 0, NULL)) count++; goto end; } { runloop_state_t *runloop_st = runloop_state_get_ptr(); unsigned i; typedef struct menu_features_info { const char *name; enum msg_hash_enums msg; } menu_features_info_t; menu_features_info_t info_list[] = { {NULL, MENU_ENUM_LABEL_VALUE_CORE_INFO_CORE_NAME}, {NULL, MENU_ENUM_LABEL_VALUE_CORE_INFO_CORE_LABEL}, {NULL, MENU_ENUM_LABEL_VALUE_CORE_INFO_CORE_VERSION}, {NULL, MENU_ENUM_LABEL_VALUE_CORE_INFO_SYSTEM_NAME}, {NULL, MENU_ENUM_LABEL_VALUE_CORE_INFO_SYSTEM_MANUFACTURER}, }; info_list[0].name = core_info->core_name; info_list[1].name = core_info->display_name; info_list[2].name = (string_is_equal(runloop_st->current_library_name, core_info->core_name) && !string_is_empty(runloop_st->current_library_version)) ? runloop_st->current_library_version : core_info->display_version; info_list[3].name = core_info->systemname; info_list[4].name = core_info->system_manufacturer; for (i = 0; i < ARRAY_SIZE(info_list); i++) { size_t _len; if (!info_list[i].name) continue; _len = strlcpy(tmp, msg_hash_to_str(info_list[i].msg), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; strlcpy(tmp + _len, info_list[i].name, sizeof(tmp) - _len); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } } if (core_info->categories_list) { size_t _len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFO_CATEGORIES), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; string_list_join_concat(tmp, sizeof(tmp), core_info->categories_list, ", "); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } if (core_info->authors_list) { size_t _len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFO_AUTHORS), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; string_list_join_concat(tmp, sizeof(tmp), core_info->authors_list, ", "); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } if (core_info->permissions_list) { size_t _len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFO_PERMISSIONS), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; string_list_join_concat(tmp, sizeof(tmp), core_info->permissions_list, ", "); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } if (core_info->licenses_list) { size_t _len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFO_LICENSES), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; string_list_join_concat(tmp, sizeof(tmp), core_info->licenses_list, ", "); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } if (core_info->supported_extensions_list) { size_t _len = strlcpy(tmp, msg_hash_to_str( MENU_ENUM_LABEL_VALUE_CORE_INFO_SUPPORTED_EXTENSIONS), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; string_list_join_concat(tmp, sizeof(tmp), core_info->supported_extensions_list, ", "); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } if (core_info->required_hw_api) { size_t _len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFO_REQUIRED_HW_API), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; string_list_join_concat(tmp, sizeof(tmp), core_info->required_hw_api_list, ", "); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } switch (core_info->savestate_support_level) { case CORE_INFO_SAVESTATE_BASIC: savestate_support = msg_hash_to_str( MENU_ENUM_LABEL_VALUE_CORE_INFO_SAVESTATE_BASIC); break; case CORE_INFO_SAVESTATE_SERIALIZED: savestate_support = msg_hash_to_str( MENU_ENUM_LABEL_VALUE_CORE_INFO_SAVESTATE_SERIALIZED); break; case CORE_INFO_SAVESTATE_DETERMINISTIC: savestate_support = msg_hash_to_str( MENU_ENUM_LABEL_VALUE_CORE_INFO_SAVESTATE_DETERMINISTIC); break; default: if (core_info->savestate_support_level > CORE_INFO_SAVESTATE_DETERMINISTIC) savestate_support = msg_hash_to_str( MENU_ENUM_LABEL_VALUE_CORE_INFO_SAVESTATE_DETERMINISTIC); else savestate_support = msg_hash_to_str( MENU_ENUM_LABEL_VALUE_CORE_INFO_SAVESTATE_DISABLED); break; } { size_t _len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFO_SAVESTATE_SUPPORT_LEVEL), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; strlcpy(tmp + _len, savestate_support, sizeof(tmp) - _len); } if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; if (core_info->firmware_count > 0) { core_info_ctx_firmware_t firmware_info; uint8_t flags = content_get_flags(); bool update_missing_firmware = false; bool set_missing_firmware = false; bool systemfiles_in_content_dir = settings->bools.systemfiles_in_content_dir; bool content_is_inited = flags & CONTENT_ST_FLAG_IS_INITED; char tmp_path[PATH_MAX_LENGTH]; firmware_info.path = core_info->path; /* If 'System Files are in Content Directory' is enabled and content is inited, * adjust the path to check for firmware files */ if (systemfiles_in_content_dir && content_is_inited) { strlcpy(tmp_path, path_get(RARCH_PATH_CONTENT), sizeof(tmp_path)); path_basedir(tmp_path); /* If content path is empty, fall back to global system dir path */ if (string_is_empty(tmp_path)) firmware_info.directory.system = settings->paths.directory_system; else { size_t len = strlen(tmp_path); /* Removes trailing slash (unless root dir), doesn't really matter * but it's more consistent with how the path is stored and * displayed without 'System Files are in Content Directory' */ if ( string_count_occurrences_single_character(tmp_path, PATH_DEFAULT_SLASH_C()) > 1 && tmp_path[len - 1] == PATH_DEFAULT_SLASH_C()) tmp_path[len - 1] = '\0'; firmware_info.directory.system = tmp_path; } } else firmware_info.directory.system = settings->paths.directory_system; update_missing_firmware = core_info_list_update_missing_firmware(&firmware_info, &set_missing_firmware); if (set_missing_firmware) runloop_st->missing_bios = true; else runloop_st->missing_bios = false; if (update_missing_firmware) { const char *missing_optional = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MISSING_OPTIONAL); const char *missing_required = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MISSING_REQUIRED); const char *present_optional = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PRESENT_OPTIONAL); const char *present_required = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PRESENT_REQUIRED); const char *rdb_entry_name = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_NAME); size_t len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFO_FIRMWARE), sizeof(tmp)); tmp[ len] = ':'; tmp[++len] = ' '; tmp[++len] = '\0'; if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; /* If 'System Files are in Content Directory' is enabled, let's add a note about it. */ if (systemfiles_in_content_dir) { strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFO_FIRMWARE_IN_CONTENT_DIRECTORY), sizeof(tmp)); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } /* Show the path that was checked */ #ifdef IOS shortened_path[0] = '\0'; fill_pathname_abbreviate_special(shortened_path, firmware_info.directory.system, sizeof(shortened_path)); snprintf(tmp, sizeof(tmp), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFO_FIRMWARE_PATH), shortened_path); #else snprintf(tmp, sizeof(tmp), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFO_FIRMWARE_PATH), firmware_info.directory.system); #endif if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; len = strlcpy(tmp, "(!) ", sizeof(tmp)); /* FIXME: This looks hacky and probably * needs to be improved for good translation support. */ for (i = 0; i < core_info->firmware_count; i++) { if (!core_info->firmware[i].desc) continue; snprintf(tmp + len, sizeof(tmp) - len, "%s %s", core_info->firmware[i].missing ? ( core_info->firmware[i].optional ? missing_optional : missing_required) : ( core_info->firmware[i].optional ? present_optional : present_required), core_info->firmware[i].desc ? core_info->firmware[i].desc : rdb_entry_name ); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } } } if (core_info->notes) { for (i = 0; i < core_info->note_list->size; i++) { strlcpy(tmp, core_info->note_list->elems[i].data, sizeof(tmp)); if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } } if (core_path) { size_t _len; _len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFO_CORE_PATH), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; #if IOS shortened_path[0] = '\0'; fill_pathname_abbreviate_special(shortened_path, core_path, sizeof(shortened_path)); strlcpy(tmp + _len, shortened_path, sizeof(tmp) - _len); #else strlcpy(tmp + _len, core_path, sizeof(tmp) - _len); #endif if (menu_entries_append(list, tmp, "", MENU_ENUM_LABEL_CORE_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } end: if (!kiosk_mode_enable) { #if defined(HAVE_DYNAMIC) /* Exclude core from contentless cores menu */ if ((contentless_display_type == MENU_CONTENTLESS_CORES_DISPLAY_CUSTOM) && core_info && core_info->supports_no_game && !string_is_empty(core_path)) { /* Note: Have to set core_path as both the * 'path' and 'label' parameters (otherwise * cannot access it in menu_cbs_get_value.c * or menu_cbs_left/right.c), which means * entry name must be set as 'alt' text */ if (menu_entries_append(list, core_path, core_path, MENU_ENUM_LABEL_CORE_SET_STANDALONE_EXEMPT, MENU_SETTING_ACTION_CORE_SET_STANDALONE_EXEMPT, 0, 0, NULL)) { file_list_set_alt_at_offset(list, count, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_SET_STANDALONE_EXEMPT)); count++; } } #endif #if !defined(IOS) || !IOS /* should this be allowed on jailbroken iOS devices? */ if (!string_is_empty(core_path)) { /* Check whether core is currently locked */ bool core_locked = core_info_get_core_lock(core_path, true); #if defined(ANDROID) /* Play Store builds do not support * core locking */ if (!play_feature_delivery_enabled()) #endif { /* Lock core * > Note: Have to set core_path as both the * 'path' and 'label' parameters (otherwise * cannot access it in menu_cbs_get_value.c * or menu_cbs_left/right.c), which means * entry name must be set as 'alt' text */ if (menu_entries_append(list, core_path, core_path, MENU_ENUM_LABEL_CORE_LOCK, MENU_SETTING_ACTION_CORE_LOCK, 0, 0, NULL)) { file_list_set_alt_at_offset( list, count, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_LOCK)); count++; } } /* Backup core */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_CREATE_BACKUP), core_path, MENU_ENUM_LABEL_CORE_CREATE_BACKUP, MENU_SETTING_ACTION_CORE_CREATE_BACKUP, 0, 0, NULL)) count++; /* Restore core from backup */ if (!core_locked) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_RESTORE_BACKUP_LIST), core_path, MENU_ENUM_LABEL_CORE_RESTORE_BACKUP_LIST, MENU_SETTING_ACTION_CORE_RESTORE_BACKUP, 0, 0, NULL)) count++; /* Delete core backup */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_DELETE_BACKUP_LIST), core_path, MENU_ENUM_LABEL_CORE_DELETE_BACKUP_LIST, MENU_SETTING_ACTION_CORE_DELETE_BACKUP, 0, 0, NULL)) count++; /* Delete core * > Only add this option if online updater is * enabled/activated, otherwise user could end * up in a situation where a core cannot be * restored */ #if defined(HAVE_NETWORKING) && defined(HAVE_ONLINE_UPDATER) if (settings->bools.menu_show_core_updater && !core_locked) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_DELETE), core_path, MENU_ENUM_LABEL_CORE_DELETE, MENU_SETTING_ACTION_CORE_DELETE, 0, 0, NULL)) count++; #endif } #endif } return count; } /* Fetches a string representation of a backup * list entry timestamp. * Returns false in the event of an error */ static size_t core_backup_list_get_entry_timestamp_str( const core_backup_list_entry_t *entry, enum core_backup_date_separator_type date_separator, char *timestamp, size_t len) { const char *format_str = "%04u-%02u-%02u %02u:%02u:%02u"; /* Get time format string */ if (date_separator == CORE_BACKUP_DATE_SEPARATOR_SLASH) format_str = "%04u/%02u/%02u %02u:%02u:%02u"; else if (date_separator == CORE_BACKUP_DATE_SEPARATOR_PERIOD) format_str = "%04u.%02u.%02u %02u:%02u:%02u"; return snprintf(timestamp, len, format_str, entry->date.year, entry->date.month, entry->date.day, entry->date.hour, entry->date.minute, entry->date.second); } static unsigned menu_displaylist_parse_core_backup_list( file_list_t *list, const char *core_path, settings_t *settings, bool restore) { enum msg_hash_enums enum_idx; enum menu_settings_type settings_type; unsigned count = 0; core_backup_list_t *backup_list = NULL; const char *dir_core_assets = settings->paths.directory_core_assets; enum core_backup_date_separator_type date_separator = (enum core_backup_date_separator_type) settings->uints.menu_timedate_date_separator; if (restore) { enum_idx = MENU_ENUM_LABEL_CORE_RESTORE_BACKUP_ENTRY; settings_type = MENU_SETTING_ITEM_CORE_RESTORE_BACKUP; } else { /* If we're not restoring, we're deleting */ enum_idx = MENU_ENUM_LABEL_CORE_DELETE_BACKUP_ENTRY; settings_type = MENU_SETTING_ITEM_CORE_DELETE_BACKUP; } /* Get backup list */ backup_list = core_backup_list_init(core_path, dir_core_assets); if (backup_list) { size_t i; size_t menu_index = 0; for (i = 0; i < core_backup_list_size(backup_list); i++) { const core_backup_list_entry_t *entry = NULL; /* Ensure entry is valid */ if ( core_backup_list_get_index(backup_list, i, &entry) && entry && !string_is_empty(entry->backup_path)) { size_t _len; char timestamp[128]; timestamp[0] = '\0'; /* Get timestamp and crc strings */ _len = core_backup_list_get_entry_timestamp_str( entry, date_separator, timestamp, sizeof(timestamp)); /* Append 'auto backup' tag to timestamp, if required */ if (entry->backup_mode == CORE_BACKUP_MODE_AUTO) { _len += strlcpy(timestamp + _len, " ", sizeof(timestamp) - _len); strlcpy(timestamp + _len, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_BACKUP_MODE_AUTO), sizeof(timestamp) - _len); } /* Add menu entry */ if (menu_entries_append(list, timestamp, entry->backup_path, enum_idx, settings_type, 0, 0, NULL)) { char crc[16]; crc[0] = '\0'; snprintf(crc, sizeof(crc), "%08lx", (unsigned long)entry->crc); /* We need to set backup path, timestamp and crc * > Only have 2 useable fields as standard * ('path' and 'label'), so have to set the * crc as 'alt' text */ file_list_set_alt_at_offset(list, menu_index, crc); menu_index++; count++; } } } core_backup_list_free(backup_list); } /* Fallback, in case no backups are found */ if (count == 0) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_CORE_BACKUPS_AVAILABLE), msg_hash_to_str(MENU_ENUM_LABEL_NO_CORE_BACKUPS_AVAILABLE), MENU_ENUM_LABEL_NO_CORE_BACKUPS_AVAILABLE, 0, 0, 0, NULL)) count++; return count; } static unsigned menu_displaylist_parse_core_manager_list(file_list_t *list, settings_t *settings) { unsigned count = 0; core_info_list_t *core_info_list = NULL; /* Get core list */ core_info_get_list(&core_info_list); if (core_info_list) { size_t i; size_t menu_index = 0; menu_search_terms_t *search_terms= menu_entries_search_get_terms(); /* Sort cores alphabetically */ core_info_qsort(core_info_list, CORE_INFO_LIST_SORT_DISPLAY_NAME); /* Loop through cores */ for (i = 0; i < core_info_list->count; i++) { core_info_t *core_info = core_info_get(core_info_list, i); if (core_info) { /* If a search is active, skip non-matching * entries */ if (search_terms) { bool entry_valid = true; size_t j; for (j = 0; j < search_terms->size; j++) { const char *search_term = search_terms->terms[j]; if ( !string_is_empty(search_term) && !string_is_empty(core_info->display_name) && !strcasestr(core_info->display_name, search_term)) { entry_valid = false; break; } } if (!entry_valid) continue; } if (menu_entries_append(list, core_info->path, "", MENU_ENUM_LABEL_CORE_MANAGER_ENTRY, MENU_SETTING_ACTION_CORE_MANAGER_OPTIONS, 0, 0, NULL)) { file_list_set_alt_at_offset(list, menu_index, core_info->display_name); menu_index++; count++; } } } } #ifndef IOS /* Add 'sideload core' entry */ if (!settings->bools.kiosk_mode_enable) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SIDELOAD_CORE_LIST), msg_hash_to_str(MENU_ENUM_LABEL_SIDELOAD_CORE_LIST), MENU_ENUM_LABEL_SIDELOAD_CORE_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif return count; } #ifdef HAVE_MIST static unsigned menu_displaylist_parse_core_manager_steam_list( file_list_t *list, settings_t *settings) { size_t i; steam_core_dlc_list_t *dlc_list; unsigned count = 0; MistResult result = steam_get_core_dlcs(&dlc_list, false); if (MIST_IS_ERROR(result)) { /* TODO/FIXME: Send error notification */ RARCH_ERR("[Steam] Error enumerating core dlcs for core manager (%d-%d)\n", MIST_UNPACK_RESULT(result)); return 0; } for (i = 0; i < dlc_list->count; i++) { steam_core_dlc_t *dlc_info = steam_core_dlc_list_get(dlc_list, i); if (menu_entries_append(list, dlc_info->name, "", MENU_ENUM_LABEL_CORE_MANAGER_STEAM_ENTRY, MENU_SETTING_ACTION_CORE_MANAGER_STEAM_OPTIONS, 0, 0, NULL)) count++; } return count; } static unsigned menu_displaylist_parse_core_information_steam( file_list_t *info_list, const char *info_path, settings_t *settings) { steam_core_dlc_list_t *dlc_list; unsigned count = 0; steam_core_dlc_t *core_dlc = NULL; bool installed = false; MistResult result = steam_get_core_dlcs(&dlc_list, false); if (MIST_IS_ERROR(result)) goto error; /* Get the core dlc information */ if (!(core_dlc = steam_get_core_dlc_by_name(dlc_list, info_path))) return 0; /* Check if installed */ result = mist_steam_apps_is_dlc_installed(core_dlc->app_id, &installed); if (MIST_IS_ERROR(result)) goto error; if (installed) { if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_STEAM_UNINSTALL), core_dlc->name, MENU_ENUM_LABEL_CORE_STEAM_UNINSTALL, MENU_SETTING_ACTION_CORE_STEAM_UNINSTALL, 0, 0, NULL)) count++; } else { if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_STEAM_INSTALL), core_dlc->name, MENU_ENUM_LABEL_CORE_STEAM_INSTALL, MENU_SETTING_ACTION_CORE_STEAM_INSTALL, 0, 0, NULL)) count++; } return count; error: /* TODO: Send error notification */ RARCH_ERR("[Steam] Error getting core information (%d-%d)\n", MIST_UNPACK_RESULT(result)); return count; } #endif static unsigned menu_displaylist_parse_core_option_dropdown_list( file_list_t *info_list, const char *info_path) { int j; char val_d[8]; unsigned count = 0; unsigned option_index = 0; unsigned checked = 0; bool checked_found = false; core_option_manager_t *coreopts = NULL; struct core_option *option = NULL; const char *val = NULL; const char *lbl_enabled = NULL; const char *lbl_disabled = NULL; const char *val_on_str = NULL; const char *val_off_str = NULL; const char *opt = NULL; /* Fetch options */ retroarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts); if (!coreopts) return 0; /* Path string has the format core_option_ * > Extract option index */ if (string_is_empty(info_path)) return 0; if (!(opt = strrchr(info_path, '_'))) return 0; option_index = string_to_unsigned(opt+1); val_d[0] = '\0'; snprintf(val_d, sizeof(val_d), "%d", option_index); /* Get option itself + current value */ option = (struct core_option*)&coreopts->opts[option_index]; val = core_option_manager_get_val(coreopts, option_index); if (!option || string_is_empty(val)) return 0; lbl_enabled = msg_hash_to_str(MENU_ENUM_LABEL_ENABLED); lbl_disabled = msg_hash_to_str(MENU_ENUM_LABEL_DISABLED); val_on_str = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON); val_off_str = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF); /* Loop over all option values */ for (j = 0; j < (int)option->vals->size; j++) { const char *val_str = option->vals->elems[j].data; const char *val_label_str = option->val_labels->elems[j].data; if (!string_is_empty(val_label_str)) { if (string_is_equal(val_label_str, lbl_enabled)) val_label_str = val_on_str; else if (string_is_equal(val_label_str, lbl_disabled)) val_label_str = val_off_str; if (menu_entries_append(info_list, val_label_str, val_d, MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_DROPDOWN_SETTING_CORE_OPTIONS_ITEM, j, 0, NULL)) count++; if (!checked_found && string_is_equal(val_str, val)) { checked = j; checked_found = true; } } } if (checked_found) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*) info_list->list[checked].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = checked; } return count; } static unsigned menu_displaylist_parse_core_option_override_list(file_list_t *list, settings_t *settings) { unsigned count = 0; runloop_state_t *runloop_st = runloop_state_get_ptr(); uint32_t flags = runloop_get_flags(); bool core_has_options = !retroarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL) && (runloop_st->core_options); bool game_options_active = (flags & RUNLOOP_FLAG_GAME_OPTIONS_ACTIVE) ? true : false; bool folder_options_active = (flags & RUNLOOP_FLAG_FOLDER_OPTIONS_ACTIVE) ? true : false; bool show_core_options_flush = settings ? settings->bools.quick_menu_show_core_options_flush : false; /* Sanity check - cannot handle core option * overrides if: * - Core is 'dummy' * - Core has no options * - No content has been loaded */ if ( !core_has_options || string_is_empty(path_get(RARCH_PATH_CONTENT))) goto end; /* Show currently active core options file */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_OPTION_OVERRIDE_INFO), msg_hash_to_str(MENU_ENUM_LABEL_CORE_OPTION_OVERRIDE_INFO), MENU_ENUM_LABEL_CORE_OPTION_OVERRIDE_INFO, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; /* Save core option overrides */ if (!game_options_active) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GAME_SPECIFIC_CORE_OPTIONS_CREATE), msg_hash_to_str(MENU_ENUM_LABEL_GAME_SPECIFIC_CORE_OPTIONS_CREATE), MENU_ENUM_LABEL_GAME_SPECIFIC_CORE_OPTIONS_CREATE, MENU_SETTING_ACTION_GAME_SPECIFIC_CORE_OPTIONS_CREATE, 0, 0, NULL)) count++; } else { /* Remove core option overrides */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GAME_SPECIFIC_CORE_OPTIONS_REMOVE), msg_hash_to_str(MENU_ENUM_LABEL_GAME_SPECIFIC_CORE_OPTIONS_REMOVE), MENU_ENUM_LABEL_GAME_SPECIFIC_CORE_OPTIONS_REMOVE, MENU_SETTING_ACTION_GAME_SPECIFIC_CORE_OPTIONS_REMOVE, 0, 0, NULL)) count++; } if (folder_options_active) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FOLDER_SPECIFIC_CORE_OPTIONS_REMOVE), msg_hash_to_str(MENU_ENUM_LABEL_FOLDER_SPECIFIC_CORE_OPTIONS_REMOVE), MENU_ENUM_LABEL_FOLDER_SPECIFIC_CORE_OPTIONS_REMOVE, MENU_SETTING_ACTION_FOLDER_SPECIFIC_CORE_OPTIONS_REMOVE, 0, 0, NULL)) count++; } else { if (!game_options_active) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FOLDER_SPECIFIC_CORE_OPTIONS_CREATE), msg_hash_to_str(MENU_ENUM_LABEL_FOLDER_SPECIFIC_CORE_OPTIONS_CREATE), MENU_ENUM_LABEL_FOLDER_SPECIFIC_CORE_OPTIONS_CREATE, MENU_SETTING_ACTION_FOLDER_SPECIFIC_CORE_OPTIONS_CREATE, 0, 0, NULL)) count++; } end: if (core_has_options) { /* Flush core options to disk */ if (show_core_options_flush) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_OPTIONS_FLUSH), msg_hash_to_str(MENU_ENUM_LABEL_CORE_OPTIONS_FLUSH), MENU_ENUM_LABEL_CORE_OPTIONS_FLUSH, MENU_SETTING_ACTION_CORE_OPTIONS_FLUSH, 0, 0, NULL)) count++; /* Reset core options */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_OPTIONS_RESET), msg_hash_to_str(MENU_ENUM_LABEL_CORE_OPTIONS_RESET), MENU_ENUM_LABEL_CORE_OPTIONS_RESET, MENU_SETTING_ACTION_CORE_OPTIONS_RESET, 0, 0, NULL)) count++; } return count; } static unsigned menu_displaylist_parse_remap_file_manager_list(file_list_t *list, settings_t *settings) { unsigned count = 0; uint32_t flags = runloop_get_flags(); bool has_content = !string_is_empty(path_get(RARCH_PATH_CONTENT)); bool core_remap_active = (flags & RUNLOOP_FLAG_REMAPS_CORE_ACTIVE) ? true : false; bool content_dir_remap_active = (flags & RUNLOOP_FLAG_REMAPS_CONTENT_DIR_ACTIVE) ? true : false; bool game_remap_active = (flags & RUNLOOP_FLAG_REMAPS_GAME_ACTIVE) ? true : false; bool remap_save_on_exit = settings->bools.remap_save_on_exit; /* Sanity check - cannot handle remap files * unless a valid core is running */ if ( !(flags & RUNLOOP_FLAG_CORE_RUNNING) || retroarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) return 0; /* Show currently 'active' remap file */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMAP_FILE_INFO), msg_hash_to_str(MENU_ENUM_LABEL_REMAP_FILE_INFO), MENU_ENUM_LABEL_REMAP_FILE_INFO, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; /* Load remap file */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMAP_FILE_LOAD), msg_hash_to_str(MENU_ENUM_LABEL_REMAP_FILE_LOAD), MENU_ENUM_LABEL_REMAP_FILE_LOAD, MENU_SETTING_ACTION_REMAP_FILE_LOAD, 0, 0, NULL)) count++; /* Save as */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMAP_FILE_SAVE_AS), msg_hash_to_str(MENU_ENUM_LABEL_REMAP_FILE_SAVE_AS), MENU_ENUM_LABEL_REMAP_FILE_SAVE_AS, MENU_SETTING_ACTION_REMAP_FILE_SAVE_AS, 0, 0, NULL)) count++; if (!game_remap_active) { /* Save remap files */ if (has_content) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMAP_FILE_SAVE_GAME), msg_hash_to_str(MENU_ENUM_LABEL_REMAP_FILE_SAVE_GAME), MENU_ENUM_LABEL_REMAP_FILE_SAVE_GAME, MENU_SETTING_ACTION_REMAP_FILE_SAVE_GAME, 0, 0, NULL)) count++; } if (!content_dir_remap_active) { if (has_content && menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMAP_FILE_SAVE_CONTENT_DIR), msg_hash_to_str(MENU_ENUM_LABEL_REMAP_FILE_SAVE_CONTENT_DIR), MENU_ENUM_LABEL_REMAP_FILE_SAVE_CONTENT_DIR, MENU_SETTING_ACTION_REMAP_FILE_SAVE_CONTENT_DIR, 0, 0, NULL)) count++; if ( !core_remap_active && menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMAP_FILE_SAVE_CORE), msg_hash_to_str(MENU_ENUM_LABEL_REMAP_FILE_SAVE_CORE), MENU_ENUM_LABEL_REMAP_FILE_SAVE_CORE, MENU_SETTING_ACTION_REMAP_FILE_SAVE_CORE, 0, 0, NULL)) count++; } } /* Remove remap files */ if (has_content) { if (game_remap_active && menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMAP_FILE_REMOVE_GAME), msg_hash_to_str(MENU_ENUM_LABEL_REMAP_FILE_REMOVE_GAME), MENU_ENUM_LABEL_REMAP_FILE_REMOVE_GAME, MENU_SETTING_ACTION_REMAP_FILE_REMOVE_GAME, 0, 0, NULL)) count++; if (content_dir_remap_active && menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMAP_FILE_REMOVE_CONTENT_DIR), msg_hash_to_str(MENU_ENUM_LABEL_REMAP_FILE_REMOVE_CONTENT_DIR), MENU_ENUM_LABEL_REMAP_FILE_REMOVE_CONTENT_DIR, MENU_SETTING_ACTION_REMAP_FILE_REMOVE_CONTENT_DIR, 0, 0, NULL)) count++; } if (core_remap_active && menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMAP_FILE_REMOVE_CORE), msg_hash_to_str(MENU_ENUM_LABEL_REMAP_FILE_REMOVE_CORE), MENU_ENUM_LABEL_REMAP_FILE_REMOVE_CORE, MENU_SETTING_ACTION_REMAP_FILE_REMOVE_CORE, 0, 0, NULL)) count++; /* Reset input remaps */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMAP_FILE_RESET), msg_hash_to_str(MENU_ENUM_LABEL_REMAP_FILE_RESET), MENU_ENUM_LABEL_REMAP_FILE_RESET, MENU_SETTING_ACTION_REMAP_FILE_RESET, 0, 0, NULL)) count++; /* Flush input remaps to disk */ if ( !remap_save_on_exit && (core_remap_active || content_dir_remap_active || game_remap_active) && menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMAP_FILE_FLUSH), msg_hash_to_str(MENU_ENUM_LABEL_REMAP_FILE_FLUSH), MENU_ENUM_LABEL_REMAP_FILE_FLUSH, MENU_SETTING_ACTION_REMAP_FILE_FLUSH, 0, 0, NULL)) count++; return count; } static unsigned menu_displaylist_parse_supported_cores(menu_displaylist_info_t *info, settings_t *settings, const char *content_path, enum msg_hash_enums core_enum_label, enum msg_hash_enums current_core_enum_label) { unsigned count = 0; core_info_list_t *core_info_list = NULL; bool core_available = false; const char *core_path_current = path_get(RARCH_PATH_CORE); #if defined(HAVE_DYNAMIC) bool enable_load_with_current = !string_is_empty(core_path_current); #else bool enable_load_with_current = !string_is_empty(core_path_current) && !settings->bools.always_reload_core_on_run_content; #endif /* Get core list */ if (core_info_get_list(&core_info_list) && core_info_list) { const char *detect_core_str = NULL; const core_info_t *core_infos = NULL; size_t core_infos_size = 0; size_t core_idx = 0; size_t entry_idx = 0; const char *pending_core_path = NULL; const char *pending_core_name = NULL; bool core_is_pending = false; /* Get list of supported cores */ core_info_list_get_supported_cores(core_info_list, content_path, &core_infos, &core_infos_size); detect_core_str = msg_hash_to_str( MENU_ENUM_LABEL_VALUE_DETECT_CORE_LIST_OK_CURRENT_CORE); for (core_idx = 0; core_idx < core_infos_size; core_idx++) { const core_info_t *core_info = (const core_info_t*)&core_infos[core_idx]; const char *core_path = core_info->path; const char *core_name = core_info->display_name; if ( string_is_empty(core_path) || string_is_empty(core_name)) continue; /* If the content is supported by the currently * loaded core, add a 'special' entry which * (a) highlights this fact and (b) allows * special handling of the the content (e.g. * allow it to be launched without a core reload) * > This functionality is disabled on static platforms * when 'always_reload_core_on_run_content' is enabled */ if ( enable_load_with_current && string_is_equal(core_path, core_path_current)) { /* This is a 'pending' entry. It will be * prepended to the displaylist once all * other cores have been added */ pending_core_path = core_path; pending_core_name = core_name; core_is_pending = true; } else if (menu_entries_append(info->list, core_path, msg_hash_to_str(core_enum_label), core_enum_label, FILE_TYPE_CORE, 0, 0, NULL)) { file_list_set_alt_at_offset(info->list, entry_idx, core_name); core_available = true; entry_idx++; count++; } } /* If cores were found, sort the displaylist now */ if (core_available) file_list_sort_on_alt(info->list); /* If we have a 'pending' entry, prepended it * to the displaylist */ if (core_is_pending) { char entry_alt_text[256]; size_t _len = strlcpy(entry_alt_text, detect_core_str, sizeof(entry_alt_text)); entry_alt_text[ _len] = ' '; entry_alt_text[++_len] = '('; entry_alt_text[++_len] = '\0'; _len += strlcpy(entry_alt_text + _len, pending_core_name, sizeof(entry_alt_text) - _len); entry_alt_text[ _len] = ')'; entry_alt_text[++_len] = '\0'; menu_entries_prepend(info->list, pending_core_path, msg_hash_to_str(current_core_enum_label), current_core_enum_label, FILE_TYPE_CORE, 0, 0); file_list_set_alt_at_offset(info->list, 0, entry_alt_text); core_available = true; count++; } } /* Fallback */ if (!core_available) { /* We have to handle an annoying special case here. * Some RetroArch ports (e.g. emscripten) are 'broken' * by design - they do not handle cores correctly, * resulting in empty core_info lists and thus no * concept of supported content. These builds are * typically static, such that the currently running * core is the only one available. To enable the * loading of *any* content on these troublesome * platforms, we therefore have to: * 1) Detect the presence of a running core * 2) Blindly add a menu entry enabling the * selection of this core * 3) Hope that the user does not attempt to * load unsupported content... */ char exts[16]; /* Attempt to identify 'broken' platforms by fetching * the core file extension - if there is none, then * it is impossible for RetroArch to populate a * core_info list */ #if !defined(LOAD_WITHOUT_CORE_INFO) if ( !frontend_driver_get_core_extension(exts, sizeof(exts)) || string_is_empty(exts)) #endif { struct retro_system_info *sysinfo = &runloop_state_get_ptr()->system.info; const char *core_path = core_path_current; const char *core_name = sysinfo ? sysinfo->library_name : NULL; if (!string_is_empty(core_path)) { /* If we have a valid 'currently running' core * path, add an entry for this core to the list */ if (menu_entries_append(info->list, core_path, msg_hash_to_str(current_core_enum_label), current_core_enum_label, FILE_TYPE_DIRECT_LOAD, 0, 0, NULL)) { if (!string_is_empty(core_name)) file_list_set_alt_at_offset(info->list, 0, core_name); core_available = true; count++; } } else if (!string_is_empty(core_name)) { /* If we have a valid core name, but no core * path, then RetroArch on this platform is * likely to be unusable. But this legacy code * path has existed for many years, and since * we do not know who added it, or why, we * shall continue to include it lest we break * an unknown platform... */ if (menu_entries_append(info->list, core_name, msg_hash_to_str(current_core_enum_label), current_core_enum_label, FILE_TYPE_DIRECT_LOAD, 0, 0, NULL)) { core_available = true; count++; } } } if (!core_available) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_CORES_AVAILABLE), msg_hash_to_str(MENU_ENUM_LABEL_NO_CORES_AVAILABLE), MENU_ENUM_LABEL_NO_CORES_AVAILABLE, 0, 0, 0, NULL)) count++; info->flags |= MD_FLAG_DOWNLOAD_CORE; } } return count; } static unsigned menu_displaylist_parse_system_info(file_list_t *list) { char entry[256]; char tmp[128]; unsigned count = 0; /* RetroArch Version */ size_t _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RETROARCH_VERSION), sizeof(entry)); entry[ _len] = ':'; entry[++_len] = ' '; entry[++_len] = '\0'; strlcpy(entry + _len, PACKAGE_VERSION, sizeof(entry) - _len); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; #ifdef HAVE_GIT_VERSION /* Git Version */ _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_GIT_VERSION), sizeof(entry)); entry[ _len] = ':'; entry[++_len] = ' '; entry[++_len] = '\0'; strlcpy(entry + _len, retroarch_git_version, sizeof(entry) - _len); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; #endif /* Build Date */ _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_BUILD_DATE), sizeof(entry)); entry[ _len] = ':'; entry[++_len] = ' '; entry[++_len] = '\0'; strlcpy(entry + _len, __DATE__, sizeof(entry) - _len); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; /* Compiler */ retroarch_get_capabilities(RARCH_CAPABILITIES_COMPILER, entry, sizeof(entry)); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; #ifdef ANDROID /* Internal Storage Status */ { bool perms = test_permissions(internal_storage_path); strlcpy(entry, perms ? msg_hash_to_str(MSG_READ_WRITE) : msg_hash_to_str(MSG_READ_ONLY), sizeof(tmp)); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } #endif /* CPU Model */ { /* TODO: this API is prone to leaking memory! */ const char *cpu_model = frontend_driver_get_cpu_model_name(); _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_CPU_MODEL), sizeof(entry)); entry[ _len] = ':'; entry[++_len] = ' '; entry[++_len] = '\0'; if (string_is_empty(cpu_model)) strlcpy(entry + _len, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE), sizeof(entry) - _len); else strlcpy(entry + _len, cpu_model, sizeof(entry) - _len); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } /* CPU Features */ retroarch_get_capabilities(RARCH_CAPABILITIES_CPU, tmp, sizeof(tmp)); _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_CPU_FEATURES), sizeof(entry)); entry[ _len] = ':'; entry[++_len] = ' '; entry[++_len] = '\0'; strlcpy(entry + _len, tmp, sizeof(entry) - _len); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; /* CPU Architecture */ _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CPU_ARCHITECTURE), sizeof(entry)); entry[ _len] = ':'; entry[++_len] = ' '; entry[++_len] = '\0'; frontend_driver_get_cpu_architecture_str(entry + _len, sizeof(entry) - _len); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_CPU_ARCHITECTURE, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; /* CPU Cores */ { unsigned cores = cpu_features_get_core_amount(); size_t _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CPU_CORES), sizeof(entry)); snprintf(entry + _len, sizeof(entry) - _len, ": %u", cores); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_CPU_CORES, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } #ifdef IOS { const char *val_yes_str = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_YES); const char *val_no_str = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO); size_t _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_JIT_AVAILABLE), sizeof(entry)); entry[ _len] = ':'; entry[++_len] = ' '; entry[++_len] = '\0'; if (jit_available()) strlcpy(entry + _len, val_yes_str, sizeof(entry) - _len); else strlcpy(entry + _len, val_no_str, sizeof(entry) - _len); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } #endif /* Input devices */ { const char *menu_driver = menu_driver_ident(); unsigned controller; for (controller = 0; controller < MAX_USERS; controller++) { if (input_config_get_device_autoconfigured(controller)) { /* Port and Device Name: s (#n) */ snprintf(entry, sizeof(entry), /* Note: format string below */ msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PORT_DEVICE_NAME), controller + 1, input_config_get_device_name(controller), input_config_get_device_name_index(controller)); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_CONTROLLER_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; #ifdef HAVE_RGUI if (string_is_equal(menu_driver, "rgui")) { /* Device Display Name */ snprintf(entry, sizeof(entry), /* TODO/FIXME: localize */ "- Device Display Name: %s", input_config_get_device_display_name(controller) ? input_config_get_device_display_name(controller) : msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE)); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_CONTROLLER_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; /* Device Config Name */ snprintf(entry, sizeof(entry), /* TODO: localize */ "- Device Config Name: %s", input_config_get_device_config_name(controller) ? input_config_get_device_config_name(controller) : msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE)); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_CONTROLLER_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; /* Device VID/PID */ snprintf(entry, sizeof(entry), /* TODO: localize */ "- Device VID/PID: %d/%d", input_config_get_device_vid(controller), input_config_get_device_pid(controller)); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_CONTROLLER_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } #endif } } } { const frontend_ctx_driver_t *frontend = frontend_get_ptr(); if (frontend) { /* Frontend Identifier */ _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FRONTEND_IDENTIFIER), sizeof(entry)); entry[ _len] = ':'; entry[++_len] = ' '; entry[++_len] = '\0'; strlcpy(entry + _len, frontend->ident, sizeof(entry) - _len); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; /* Lakka Version */ if (frontend->get_lakka_version) { char lakka_ver[64]; frontend->get_lakka_version(lakka_ver, sizeof(lakka_ver)); _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LAKKA_VERSION), sizeof(entry)); entry[ _len] = ':'; entry[++_len] = ' '; entry[++_len] = '\0'; strlcpy(entry + _len, lakka_ver, sizeof(entry) - _len); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } /* Frontend name */ if (frontend->get_name) { char frontend_name[64]; frontend->get_name(frontend_name, sizeof(frontend_name)); _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FRONTEND_NAME), sizeof(entry)); entry[ _len] = ':'; entry[++_len] = ' '; entry[++_len] = '\0'; strlcpy(entry + _len, frontend_name, sizeof(entry) - _len); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } /* Frontend OS */ if (frontend->get_os) { char os_ver[64]; int major = 0; int minor = 0; frontend->get_os(os_ver, sizeof(os_ver), &major, &minor); _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FRONTEND_OS), sizeof(entry)); entry[ _len] = ':'; entry[++_len] = ' '; entry[++_len] = '\0'; _len += strlcpy (entry + _len, os_ver, sizeof(entry) - _len); snprintf(entry + _len, sizeof(entry) - _len, " (v%d.%d)", major, minor); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } /* RetroRating Level */ if (frontend->get_rating) { snprintf(entry, sizeof(entry), "%s: %d", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RETRORATING_LEVEL), frontend->get_rating()); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } /* Memory */ { uint64_t memory_total = frontend_driver_get_total_memory(); uint64_t memory_used = memory_total - frontend_driver_get_free_memory(); if (memory_used != 0 && memory_total != 0) { _len = strlcpy(entry, msg_hash_to_str(MSG_MEMORY), sizeof(entry)); snprintf(entry + _len, sizeof(entry) - _len, ": %" PRIu64 "/%" PRIu64 " MB", BYTES_TO_MB(memory_used), BYTES_TO_MB(memory_total)); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } } /* Power Source */ if (frontend->get_powerstate) { size_t _len; int seconds = 0; int percent = 0; enum frontend_powerstate state = frontend->get_powerstate(&seconds, &percent); /* N/A */ if (state == FRONTEND_POWERSTATE_NONE) strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE), sizeof(tmp)); /* n% (No Source) */ else if (state == FRONTEND_POWERSTATE_NO_SOURCE) snprintf(tmp, sizeof(tmp), "%d%% (%s)", percent, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE_NO_SOURCE)); /* n% (Charging) */ else if (state == FRONTEND_POWERSTATE_CHARGING) snprintf(tmp, sizeof(tmp), "%d%% (%s)", percent, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE_CHARGING)); /* n% (Charged) */ else if (state == FRONTEND_POWERSTATE_CHARGED) snprintf(tmp, sizeof(tmp), "%d%% (%s)", percent, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE_CHARGED)); /* n% (Discharging) */ else if (state == FRONTEND_POWERSTATE_ON_POWER_SOURCE) snprintf(tmp, sizeof(tmp), "%d%% (%s)", percent, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE_DISCHARGING)); /* Power Source */ _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_POWER_SOURCE), sizeof(entry)); entry[ _len] = ':'; entry[++_len] = ' '; entry[++_len] = '\0'; strlcpy(entry + _len, tmp, sizeof(entry) - _len); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } } } #if defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || \ defined(HAVE_OPENGLES) || defined(HAVE_OPENGL_CORE) { gfx_ctx_ident_t ident_info; video_context_driver_get_ident(&ident_info); /* Video Context Driver */ snprintf(entry, sizeof(entry), "%s: %s", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_VIDEO_CONTEXT_DRIVER), string_is_empty(ident_info.ident) ? msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE) : ident_info.ident); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; { gfx_ctx_metrics_t metrics; float val = 0.0f; metrics.value = &val; /* Display Width (mm) */ metrics.type = DISPLAY_METRIC_MM_WIDTH; if (video_context_driver_get_metrics(&metrics)) { _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DISPLAY_METRIC_MM_WIDTH), sizeof(entry)); snprintf(entry + _len, sizeof(entry) - _len, ": %.2f", val); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } /* Display Height (mm) */ metrics.type = DISPLAY_METRIC_MM_HEIGHT; if (video_context_driver_get_metrics(&metrics)) { _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DISPLAY_METRIC_MM_HEIGHT), sizeof(entry)); snprintf(entry + _len, sizeof(entry) - _len, ": %.2f", val); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } /* DPI */ metrics.type = DISPLAY_METRIC_DPI; if (video_context_driver_get_metrics(&metrics)) { _len = strlcpy(entry, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DISPLAY_METRIC_DPI), sizeof(entry)); snprintf(entry + _len, sizeof(entry) - _len, ": %.2f", val); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } } } #endif /* Supports %s: yes/no */ { struct menu_features_info { bool enabled; enum msg_hash_enums msg; } info_list[] = { {SUPPORTS_LIBRETRODB, MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LIBRETRODB_SUPPORT}, {SUPPORTS_OVERLAY, MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OVERLAY_SUPPORT}, {SUPPORTS_COMMAND, MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_COMMAND_IFACE_SUPPORT}, {SUPPORTS_NETWORK_COMMAND, MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_NETWORK_COMMAND_IFACE_SUPPORT}, {SUPPORTS_NETWORK_GAMEPAD, MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_NETWORK_REMOTE_SUPPORT}, {SUPPORTS_COCOA , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_COCOA_SUPPORT}, {SUPPORTS_RPNG , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RPNG_SUPPORT}, {SUPPORTS_RJPEG , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RJPEG_SUPPORT}, {SUPPORTS_RBMP , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RBMP_SUPPORT}, {SUPPORTS_RTGA , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RTGA_SUPPORT}, {SUPPORTS_SDL , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_SDL_SUPPORT}, {SUPPORTS_SDL2 , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_SDL2_SUPPORT}, {SUPPORTS_VULKAN , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_VULKAN_SUPPORT}, {SUPPORTS_METAL , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_METAL_SUPPORT}, {SUPPORTS_OPENGL , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENGL_SUPPORT}, {SUPPORTS_OPENGLES , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENGLES_SUPPORT}, {SUPPORTS_THREAD , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_THREADING_SUPPORT}, {SUPPORTS_KMS , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_KMS_SUPPORT}, {SUPPORTS_UDEV , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_UDEV_SUPPORT}, {SUPPORTS_VG , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENVG_SUPPORT}, {SUPPORTS_EGL , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_EGL_SUPPORT}, {SUPPORTS_X11 , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_X11_SUPPORT}, {SUPPORTS_WAYLAND , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_WAYLAND_SUPPORT}, {SUPPORTS_XVIDEO , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_XVIDEO_SUPPORT}, {SUPPORTS_ALSA , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_ALSA_SUPPORT}, {SUPPORTS_OSS , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OSS_SUPPORT}, {SUPPORTS_AL , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENAL_SUPPORT}, {SUPPORTS_SL , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_OPENSL_SUPPORT}, {SUPPORTS_RSOUND , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_RSOUND_SUPPORT}, {SUPPORTS_ROAR , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_ROARAUDIO_SUPPORT}, {SUPPORTS_JACK , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_JACK_SUPPORT}, {SUPPORTS_PULSE , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_PULSEAUDIO_SUPPORT}, {SUPPORTS_COREAUDIO , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_COREAUDIO_SUPPORT}, {SUPPORTS_COREAUDIO3 , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_COREAUDIO3_SUPPORT}, {SUPPORTS_DSOUND , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DSOUND_SUPPORT}, {SUPPORTS_WASAPI , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_WASAPI_SUPPORT}, {SUPPORTS_XAUDIO , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_XAUDIO2_SUPPORT}, {SUPPORTS_ZLIB , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_ZLIB_SUPPORT}, {SUPPORTS_7ZIP , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_7ZIP_SUPPORT}, {SUPPORTS_DYLIB , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DYLIB_SUPPORT}, {SUPPORTS_DYNAMIC , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DYNAMIC_SUPPORT}, {SUPPORTS_CG , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_CG_SUPPORT}, {SUPPORTS_GLSL , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_GLSL_SUPPORT}, {SUPPORTS_HLSL , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_HLSL_SUPPORT}, {SUPPORTS_SDL_IMAGE , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_SDL_IMAGE_SUPPORT}, {SUPPORTS_FFMPEG , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FFMPEG_SUPPORT}, {SUPPORTS_MPV , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT}, {SUPPORTS_CORETEXT , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_CORETEXT_SUPPORT}, {SUPPORTS_FREETYPE , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_FREETYPE_SUPPORT}, {SUPPORTS_STBFONT , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_STB_TRUETYPE_SUPPORT}, {SUPPORTS_NETPLAY , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_NETPLAY_SUPPORT}, {SUPPORTS_V4L2 , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_V4L2_SUPPORT}, {SUPPORTS_LIBUSB , MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_LIBUSB_SUPPORT}, }; unsigned info_idx; const char *val_yes_str = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_YES); const char *val_no_str = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO); for (info_idx = 0; info_idx < ARRAY_SIZE(info_list); info_idx++) { size_t _len = strlcpy(entry, msg_hash_to_str(info_list[info_idx].msg), sizeof(entry)); entry[ _len] = ':'; entry[++_len] = ' '; entry[++_len] = '\0'; if (info_list[info_idx].enabled) strlcpy(entry + _len, val_yes_str, sizeof(entry) - _len); else strlcpy(entry + _len, val_no_str, sizeof(entry) - _len); if (menu_entries_append(list, entry, "", MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } } return count; } static int menu_displaylist_parse_playlist( file_list_t *info_list, const char *info_path, playlist_t *playlist, settings_t *settings, const char *path_playlist, size_t path_playlist_size, bool is_collection) { unsigned i; char label_spacer[PL_LABEL_SPACER_MAXLEN]; size_t list_size = playlist_size(playlist); bool show_inline_core_name = false; struct menu_state *menu_st = menu_state_get_ptr(); const char *menu_driver = menu_driver_ident(); menu_search_terms_t *search_terms = menu_entries_search_get_terms(); unsigned pl_show_inline_core_name = settings->uints.playlist_show_inline_core_name; bool pl_show_sublabels = settings->bools.playlist_show_sublabels; void (*sanitization)(char*) = NULL; unsigned count = 0; if (list_size == 0) return 0; /* Check whether core name should be added to playlist entries */ if ( !string_is_equal(menu_driver, "ozone") && !pl_show_sublabels && ((pl_show_inline_core_name == PLAYLIST_INLINE_CORE_DISPLAY_ALWAYS) || (!is_collection && !(pl_show_inline_core_name == PLAYLIST_INLINE_CORE_DISPLAY_NEVER)))) { show_inline_core_name = true; #ifdef HAVE_RGUI /* Get spacer for menu entry labels () * > Note: Only required when showing inline core names */ if (string_is_equal(menu_driver, "rgui")) strlcpy(label_spacer, PL_LABEL_SPACER_RGUI, sizeof(label_spacer)); else #endif strlcpy(label_spacer, PL_LABEL_SPACER_DEFAULT, sizeof(label_spacer)); } { /* Inform menu driver of current system name * > Note: history, favorites and images_history * require special treatment here, since info_path * is nonsensical in these cases (and we *do* need * to call set_thumbnail_system() in these cases, * since all three playlist types have thumbnail * support) * EDIT: For correct operation of the quick menu * 'download thumbnails' option, we must also extend * this to music_history and video_history */ if ( string_is_equal(path_playlist, "history") || string_is_equal(path_playlist, "favorites") || string_ends_with_size(path_playlist, "_history", path_playlist_size, STRLEN_CONST("_history"))) { char system_name[15]; strlcpy(system_name, path_playlist, sizeof(system_name)); menu_driver_set_thumbnail_system( menu_st->userdata, system_name, sizeof(system_name)); } else if (!string_is_empty(info_path)) { char lpl_basename[256]; fill_pathname_base(lpl_basename, info_path, sizeof(lpl_basename)); path_remove_extension(lpl_basename); menu_driver_set_thumbnail_system( menu_st->userdata, lpl_basename, sizeof(lpl_basename)); } } /* Preallocate the file list */ file_list_reserve(info_list, list_size); switch (playlist_get_label_display_mode(playlist)) { case LABEL_DISPLAY_MODE_REMOVE_PARENTHESES : sanitization = &label_remove_parens; break; case LABEL_DISPLAY_MODE_REMOVE_BRACKETS : sanitization = &label_remove_brackets; break; case LABEL_DISPLAY_MODE_REMOVE_PARENTHESES_AND_BRACKETS : sanitization = &label_remove_parens_and_brackets; break; case LABEL_DISPLAY_MODE_KEEP_DISC_INDEX : sanitization = &label_keep_disc; break; case LABEL_DISPLAY_MODE_KEEP_REGION : sanitization = &label_keep_region; break; case LABEL_DISPLAY_MODE_KEEP_REGION_AND_DISC_INDEX : sanitization = &label_keep_region_and_disc; break; default : break; } for (i = 0; i < list_size; i++) { char menu_entry_label[256]; const struct playlist_entry *entry = NULL; const char *entry_path = NULL; bool entry_valid = true; /* Read playlist entry */ playlist_get_index(playlist, i, &entry); if (!string_is_empty(entry->path)) { size_t _len; /* Standard playlist entry * > Base menu entry label is always playlist label * > If playlist label is NULL, fallback to playlist entry file name * > If required, add currently associated core (if any), otherwise * no further action is necessary */ if (string_is_empty(entry->label)) _len = fill_pathname(menu_entry_label, path_basename(entry->path), "", sizeof(menu_entry_label)); else _len = strlcpy(menu_entry_label, entry->label, sizeof(menu_entry_label)); if (sanitization) (*sanitization)(menu_entry_label); if (show_inline_core_name) { /* Both core name and core path must be valid */ if ( !string_is_empty(entry->core_name) && !string_is_equal(entry->core_name, "DETECT") && !string_is_empty(entry->core_path) && !string_is_equal(entry->core_path, "DETECT")) { _len += strlcpy( menu_entry_label + _len, label_spacer, sizeof(menu_entry_label) - _len); strlcpy(menu_entry_label + _len, entry->core_name, sizeof(menu_entry_label) - _len); } } entry_path = entry->path; } else { /* Playlist entry without content... * This is useless/broken, but have to include * it otherwise synchronisation between the menu * and the underlying playlist will be lost... * > Use label if available, otherwise core name * > If both are missing, add an empty menu entry */ if (!string_is_empty(entry->label)) strlcpy(menu_entry_label, entry->label, sizeof(menu_entry_label)); else if (!string_is_empty(entry->core_name)) strlcpy(menu_entry_label, entry->core_name, sizeof(menu_entry_label)); entry_path = path_playlist; } /* Check whether entry matches search terms, * if required */ if (search_terms) { size_t j; for (j = 0; j < search_terms->size; j++) { const char *search_term = search_terms->terms[j]; if ( !string_is_empty(search_term) && !strcasestr(menu_entry_label, search_term)) { entry_valid = false; break; } } } /* Add menu entry */ if (entry_valid && menu_entries_append(info_list, menu_entry_label, entry_path, MENU_ENUM_LABEL_PLAYLIST_ENTRY, FILE_TYPE_RPL_ENTRY, 0, i, NULL)) count++; } return count; } #ifdef HAVE_LIBRETRODB static int create_string_list_rdb_entry_string( enum msg_hash_enums enum_idx, const char *desc, const char *label, const char *actual_string, const char *path, size_t path_len, file_list_t *list) { size_t _len; char tmp[128]; char *out_lbl = NULL; size_t str_len = (strlen(label) + 1) + (strlen(actual_string) + 1) + (path_len + 1); if (!(out_lbl = (char*)calloc(str_len, sizeof(char)))) return -1; _len = strlcpy(out_lbl, label, str_len); out_lbl[ _len] = '|'; out_lbl[++_len] = '\0'; _len += strlcpy(out_lbl + _len, actual_string, str_len - _len); out_lbl[ _len] = '|'; out_lbl[++_len] = '\0'; strlcpy(out_lbl + _len, path, str_len - _len); _len = strlcpy(tmp, desc, sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; strlcpy(tmp + _len, actual_string, sizeof(tmp) - _len); menu_entries_append(list, tmp, out_lbl, enum_idx, 0, 0, 0, NULL); free(out_lbl); return 0; } static int create_string_list_rdb_entry_int( enum msg_hash_enums enum_idx, const char *desc, const char *label, int actual_int, const char *path, size_t path_len, file_list_t *list) { size_t _len; char str[16]; char tmp[128]; char out_lbl[PATH_MAX_LENGTH]; str[0] = '\0'; out_lbl[0] = '\0'; snprintf(str, sizeof(str), "%d", actual_int); _len = strlcpy(out_lbl, label, sizeof(out_lbl)); out_lbl[ _len] = '|'; out_lbl[++_len] = '\0'; _len += strlcpy(out_lbl + _len, str, sizeof(out_lbl) - _len); out_lbl[ _len] = '|'; out_lbl[++_len] = '\0'; strlcpy(out_lbl + _len, path, sizeof(out_lbl) - _len); _len = strlcpy(tmp, desc, sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; strlcpy(tmp + _len, str, sizeof(tmp) - _len); menu_entries_append(list, tmp, out_lbl, enum_idx, 0, 0, 0, NULL); return 0; } static enum msg_file_type extension_to_file_hash_type(const char *ext) { if ( ext[0] == 's' && ext[1] == 'h' && ext[2] == 'a' && ext[3] == '1' && ext[4] == '\0') return FILE_TYPE_SHA1; else if ( ext[0] == 'c' && ext[1] == 'r' && ext[2] == 'c' && ext[3] == '\0') return FILE_TYPE_CRC; else if ( ext[0] == 'm' && ext[1] == 'd' && ext[2] == '5' && ext[3] == '\0') return FILE_TYPE_MD5; return FILE_TYPE_NONE; } static int menu_displaylist_parse_database_entry(menu_handle_t *menu, settings_t *settings, menu_displaylist_info_t *info) { size_t path_len; unsigned i, j, k; char query[256]; char path_playlist[PATH_MAX_LENGTH]; char path_base[NAME_MAX_LENGTH]; playlist_config_t playlist_config; playlist_t *playlist = NULL; database_info_list_t *db_info = NULL; struct menu_state *menu_st = menu_state_get_ptr(); bool show_advanced_settings = settings->bools.menu_show_advanced_settings; const char *dir_playlist = settings->paths.directory_playlist; playlist_config.capacity = COLLECTION_SIZE; playlist_config.old_format = settings->bools.playlist_use_old_format; playlist_config.compress = settings->bools.playlist_compression; playlist_config.fuzzy_archive_match = settings->bools.playlist_fuzzy_archive_match; playlist_config_set_base_content_directory(&playlist_config, settings->bools.playlist_portable_paths ? settings->paths.directory_menu_content : NULL); database_info_build_query_enum(query, sizeof(query), DATABASE_QUERY_ENTRY, info->path_b); if (!(db_info = database_info_list_new(info->path, query))) return -1; fill_pathname(path_base, path_basename(info->path), "", sizeof(path_base)); path_remove_extension(path_base); menu_driver_set_thumbnail_system( menu_st->userdata, path_base, sizeof(path_base)); strlcat(path_base, ".lpl", sizeof(path_base)); fill_pathname_join_special(path_playlist, dir_playlist, path_base, sizeof(path_playlist)); playlist_config_set_path(&playlist_config, path_playlist); if ((playlist = playlist_init(&playlist_config))) strlcpy(menu->db_playlist_file, path_playlist, sizeof(menu->db_playlist_file)); for (i = 0; i < db_info->count; i++) { char crc_str[20]; char tmp[PATH_MAX_LENGTH]; database_info_t *db_info_entry = &db_info->list[i]; crc_str[0] = tmp[0] = '\0'; snprintf(crc_str, sizeof(crc_str), "%08lX", (unsigned long)db_info_entry->crc32); if (playlist) { for (j = 0; j < playlist_size(playlist); j++) { const struct playlist_entry *entry = NULL; bool match_found = false; playlist_get_index(playlist, j, &entry); if (entry->crc32) { char *elem0 = NULL; char *save = NULL; char *entry_crc32_cpy = strdup(entry->crc32); const char *con = strtok_r(entry_crc32_cpy, "|", &save); if (con) { elem0 = strdup(con); if ((con = strtok_r(NULL, "|", &save))) { switch (extension_to_file_hash_type(con)) { case FILE_TYPE_CRC: if (string_is_equal(crc_str, elem0)) match_found = true; break; case FILE_TYPE_SHA1: if (string_is_equal(db_info_entry->sha1, elem0)) match_found = true; break; case FILE_TYPE_MD5: if (string_is_equal(db_info_entry->md5, elem0)) match_found = true; break; default: break; } } free(elem0); } free(entry_crc32_cpy); } if (!match_found) continue; menu->scratchpad.unsigned_var = j; } } if (db_info_entry->name) { size_t _len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_NAME), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; strlcpy(tmp + _len, db_info_entry->name, sizeof(tmp) - _len); menu_entries_append(info->list, tmp, msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_NAME), MENU_ENUM_LABEL_RDB_ENTRY_NAME, 0, 0, 0, NULL); } if (db_info_entry->description) { size_t _len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_DESCRIPTION), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; strlcpy(tmp + _len, db_info_entry->description, sizeof(tmp) - _len); menu_entries_append(info->list, tmp, msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_DESCRIPTION), MENU_ENUM_LABEL_RDB_ENTRY_DESCRIPTION, 0, 0, 0, NULL); } if (db_info_entry->genre) { size_t _len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_GENRE), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; strlcpy(tmp + _len, db_info_entry->genre, sizeof(tmp) - _len); menu_entries_append(info->list, tmp, msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_GENRE), MENU_ENUM_LABEL_RDB_ENTRY_GENRE, 0, 0, 0, NULL); } path_len = strlen(info->path); if (db_info_entry->publisher) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_PUBLISHER, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_PUBLISHER), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_PUBLISHER), db_info_entry->publisher, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->category) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_CATEGORY, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_CATEGORY), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_CATEGORY), db_info_entry->category, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->language) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_LANGUAGE, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_LANGUAGE), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_LANGUAGE), db_info_entry->language, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->region) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_REGION, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_REGION), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_REGION), db_info_entry->region, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->score) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_SCORE, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_SCORE), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_SCORE), db_info_entry->score, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->media) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_MEDIA, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_MEDIA), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_MEDIA), db_info_entry->media, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->controls) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_CONTROLS, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_CONTROLS), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_CONTROLS), db_info_entry->controls, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->artstyle) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_ARTSTYLE, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_ARTSTYLE), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_ARTSTYLE), db_info_entry->artstyle, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->gameplay) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_GAMEPLAY, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_GAMEPLAY), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_GAMEPLAY), db_info_entry->gameplay, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->narrative) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_NARRATIVE, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_NARRATIVE), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_NARRATIVE), db_info_entry->narrative, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->pacing) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_PACING, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_PACING), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_PACING), db_info_entry->pacing, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->perspective) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_PERSPECTIVE, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_PERSPECTIVE), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_PERSPECTIVE), db_info_entry->perspective, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->setting) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_SETTING, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_SETTING), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_SETTING), db_info_entry->setting, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->visual) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_VISUAL, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_VISUAL), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_VISUAL), db_info_entry->visual, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->vehicular) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_VEHICULAR, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_VEHICULAR), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_VEHICULAR), db_info_entry->vehicular, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->developer) { const char *val_rdb_entry_dev = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_DEVELOPER); const char *rdb_entry_dev = msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_DEVELOPER); for (k = 0; k < db_info_entry->developer->size; k++) { if (db_info_entry->developer->elems[k].data) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_DEVELOPER, val_rdb_entry_dev, rdb_entry_dev, db_info_entry->developer->elems[k].data, info->path, path_len, info->list) == -1) goto error; } } } if (db_info_entry->origin) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_ORIGIN, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_ORIGIN), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_ORIGIN), db_info_entry->origin, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->franchise) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_FRANCHISE, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_FRANCHISE), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_FRANCHISE), db_info_entry->franchise, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->max_users) { if (create_string_list_rdb_entry_int( MENU_ENUM_LABEL_RDB_ENTRY_MAX_USERS, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_MAX_USERS), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_MAX_USERS), db_info_entry->max_users, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->tgdb_rating) { if (create_string_list_rdb_entry_int( MENU_ENUM_LABEL_RDB_ENTRY_TGDB_RATING, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_TGDB_RATING), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_TGDB_RATING), db_info_entry->tgdb_rating, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->famitsu_magazine_rating) { if (create_string_list_rdb_entry_int( MENU_ENUM_LABEL_RDB_ENTRY_FAMITSU_MAGAZINE_RATING, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_FAMITSU_MAGAZINE_RATING), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_FAMITSU_MAGAZINE_RATING), db_info_entry->famitsu_magazine_rating, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->edge_magazine_review) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_EDGE_MAGAZINE_REVIEW, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_EDGE_MAGAZINE_REVIEW), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_EDGE_MAGAZINE_REVIEW), db_info_entry->edge_magazine_review, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->edge_magazine_rating) { if (create_string_list_rdb_entry_int( MENU_ENUM_LABEL_RDB_ENTRY_EDGE_MAGAZINE_RATING, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_EDGE_MAGAZINE_RATING), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_EDGE_MAGAZINE_RATING), db_info_entry->edge_magazine_rating, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->edge_magazine_issue) { if (create_string_list_rdb_entry_int( MENU_ENUM_LABEL_RDB_ENTRY_EDGE_MAGAZINE_ISSUE, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_EDGE_MAGAZINE_ISSUE), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_EDGE_MAGAZINE_ISSUE), db_info_entry->edge_magazine_issue, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->releasemonth) { if (create_string_list_rdb_entry_int( MENU_ENUM_LABEL_RDB_ENTRY_RELEASE_MONTH, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_RELEASE_MONTH), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_RELEASE_MONTH), db_info_entry->releasemonth, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->releaseyear) { if (create_string_list_rdb_entry_int( MENU_ENUM_LABEL_RDB_ENTRY_RELEASE_YEAR, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_RELEASE_YEAR), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_RELEASE_YEAR), db_info_entry->releaseyear, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->bbfc_rating) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_BBFC_RATING, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_BBFC_RATING), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_BBFC_RATING), db_info_entry->bbfc_rating, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->esrb_rating) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_ESRB_RATING, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_ESRB_RATING), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_ESRB_RATING), db_info_entry->esrb_rating, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->elspa_rating) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_ELSPA_RATING, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_ELSPA_RATING), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_ELSPA_RATING), db_info_entry->elspa_rating, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->pegi_rating) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_PEGI_RATING, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_PEGI_RATING), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_PEGI_RATING), db_info_entry->pegi_rating, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->enhancement_hw) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_ENHANCEMENT_HW, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_ENHANCEMENT_HW), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_ENHANCEMENT_HW), db_info_entry->enhancement_hw, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->cero_rating) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_CERO_RATING, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_CERO_RATING), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_CERO_RATING), db_info_entry->cero_rating, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->serial) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_SERIAL, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_SERIAL), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_SERIAL), db_info_entry->serial, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->analog_supported == 1) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_ANALOG, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_ANALOG), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_ANALOG), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_TRUE), info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->rumble_supported == 1) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_RUMBLE, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_RUMBLE), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_RUMBLE), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_TRUE), info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->coop_supported == 1) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_COOP, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_COOP), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_COOP), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_TRUE), info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->achievements == 1) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_ACHIEVEMENTS, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_ACHIEVEMENTS), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_ACHIEVEMENTS), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_TRUE), info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->console_exclusive == 1) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_CONSOLE_EXCLUSIVE, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_CONSOLE_EXCLUSIVE), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_CONSOLE_EXCLUSIVE), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_TRUE), info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->platform_exclusive == 1) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_PLATFORM_EXCLUSIVE, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_PLATFORM_EXCLUSIVE), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_PLATFORM_EXCLUSIVE), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_TRUE), info->path, path_len, info->list) == -1) goto error; } if (!show_advanced_settings) continue; if (db_info_entry->crc32) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_CRC32, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_CRC32), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_CRC32), crc_str, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->sha1) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_SHA1, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_SHA1), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_SHA1), db_info_entry->sha1, info->path, path_len, info->list) == -1) goto error; } if (db_info_entry->md5) { if (create_string_list_rdb_entry_string( MENU_ENUM_LABEL_RDB_ENTRY_MD5, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_MD5), msg_hash_to_str(MENU_ENUM_LABEL_RDB_ENTRY_MD5), db_info_entry->md5, info->path, path_len, info->list) == -1) goto error; } } if (db_info->count < 1) info->flags |= MD_FLAG_NEED_PUSH_NO_PLAYLIST_ENTRIES; playlist_free(playlist); database_info_list_free(db_info); free(db_info); return 0; error: if (db_info) { database_info_list_free(db_info); free(db_info); } playlist_free(playlist); return -1; } #endif int menu_displaylist_parse_settings_enum( file_list_t *info_list, enum menu_displaylist_parse_type parse_type, bool add_empty_entry, rarch_setting_t *setting, unsigned entry_type, bool is_enum ) { static enum setting_type precond_lut[] = { ST_END_GROUP, /* PARSE_NONE */ ST_NONE, /* PARSE_GROUP */ ST_ACTION, /* PARSE_ACTION */ ST_INT, /* PARSE_ONLY_INT */ ST_UINT, /* PARSE_ONLY_UINT */ ST_BOOL, /* PARSE_ONLY_BOOL */ ST_FLOAT, /* PARSE_ONLY_FLOAT */ ST_BIND, /* PARSE_ONLY_BIND */ ST_END_GROUP, /* PARSE_ONLY_GROUP */ ST_STRING, /* PARSE_ONLY_STRING */ ST_PATH, /* PARSE_ONLY_PATH */ ST_STRING_OPTIONS, /* PARSE_ONLY_STRING_OPTIONS */ ST_DIR, /* PARSE_ONLY_DIR */ ST_NONE, /* PARSE_SUB_GROUP */ ST_SIZE, /* PARSE_ONLY_SIZE */ }; uint32_t flags; enum setting_type precond = precond_lut[parse_type]; size_t count = 0; if (!setting) return -1; flags = setting->flags; #ifdef HAVE_LAKKA if (flags & (SD_FLAG_ADVANCED | SD_FLAG_LAKKA_ADVANCED)) #else if (flags & (SD_FLAG_ADVANCED)) #endif { settings_t *settings = config_get_ptr(); bool show_advanced_settings = settings->bools.menu_show_advanced_settings; if (!show_advanced_settings) goto end; } for (;;) { bool time_to_exit = false; const char *short_description = setting->short_description; const char *name = setting->name; enum setting_type type = setting->type; rarch_setting_t **list = &setting; int type_flags = 0; switch (parse_type) { case PARSE_NONE: switch (type) { case ST_GROUP: case ST_END_GROUP: case ST_SUB_GROUP: case ST_END_SUB_GROUP: goto loop; default: break; } break; case PARSE_GROUP: case PARSE_ONLY_GROUP: if (type == ST_GROUP) break; goto loop; case PARSE_SUB_GROUP: break; case PARSE_ACTION: case PARSE_ONLY_INT: case PARSE_ONLY_UINT: case PARSE_ONLY_SIZE: case PARSE_ONLY_BIND: case PARSE_ONLY_BOOL: case PARSE_ONLY_FLOAT: case PARSE_ONLY_STRING: case PARSE_ONLY_PATH: case PARSE_ONLY_DIR: case PARSE_ONLY_STRING_OPTIONS: if (type == precond) break; goto loop; } switch (type) { case ST_STRING_OPTIONS: type_flags = MENU_SETTING_STRING_OPTIONS; break; case ST_ACTION: type_flags = MENU_SETTING_ACTION; break; case ST_PATH: type_flags = FILE_TYPE_PATH; break; case ST_GROUP: type_flags = MENU_SETTING_GROUP; break; case ST_SUB_GROUP: type_flags = MENU_SETTING_SUBGROUP; break; default: break; } if (is_enum) menu_entries_append(info_list, short_description, name, (enum msg_hash_enums)entry_type, type_flags, 0, 0, NULL); else { if ( (entry_type >= MENU_SETTINGS_INPUT_BEGIN) && (entry_type < MENU_SETTINGS_INPUT_END) ) entry_type = (unsigned)(MENU_SETTINGS_INPUT_BEGIN + count); if (entry_type == 0) entry_type = type_flags; menu_entries_append(info_list, short_description, name, MSG_UNKNOWN, entry_type, 0, 0, menu_setting_find(name)); } count++; loop: switch (parse_type) { case PARSE_NONE: case PARSE_GROUP: case PARSE_ONLY_GROUP: case PARSE_SUB_GROUP: if (setting->type == precond) time_to_exit = true; break; case PARSE_ONLY_BIND: case PARSE_ONLY_FLOAT: case PARSE_ONLY_BOOL: case PARSE_ONLY_INT: case PARSE_ONLY_UINT: case PARSE_ONLY_SIZE: case PARSE_ONLY_PATH: case PARSE_ONLY_DIR: case PARSE_ONLY_STRING: case PARSE_ONLY_STRING_OPTIONS: case PARSE_ACTION: time_to_exit = true; break; } if (time_to_exit) break; (*list = *list + 1); } end: if (count == 0) { if (add_empty_entry) menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND), msg_hash_to_str(MENU_ENUM_LABEL_NO_SETTINGS_FOUND), MENU_ENUM_LABEL_NO_SETTINGS_FOUND, 0, 0, 0, NULL); return -1; } return 0; } static void menu_displaylist_set_new_playlist( menu_handle_t *menu, settings_t *settings, const char *path, bool sort_enabled) { playlist_config_t playlist_config; const char *playlist_file_name = path_basename_nocompression(path); int content_favorites_size = settings->ints.content_favorites_size; unsigned content_history_size = settings->uints.content_history_size; bool playlist_sort_alphabetical = settings->bools.playlist_sort_alphabetical; playlist_config_set_path(&playlist_config, path); playlist_config.capacity = COLLECTION_SIZE; playlist_config.old_format = settings->bools.playlist_use_old_format; playlist_config.compress = settings->bools.playlist_compression; playlist_config.fuzzy_archive_match = settings->bools.playlist_fuzzy_archive_match; playlist_config_set_base_content_directory(&playlist_config, settings->bools.playlist_portable_paths ? settings->paths.directory_menu_content : NULL); menu->db_playlist_file[0] = '\0'; if (playlist_get_cached()) playlist_free_cached(); /* Get proper playlist capacity */ if (!string_is_empty(playlist_file_name)) { if (string_ends_with_size(playlist_file_name, "_history.lpl", strlen(playlist_file_name), STRLEN_CONST("_history.lpl"))) playlist_config.capacity = content_history_size; else if (string_is_equal(playlist_file_name, FILE_PATH_CONTENT_FAVORITES) && (content_favorites_size >= 0)) playlist_config.capacity = (unsigned)content_favorites_size; } if (playlist_init_cached(&playlist_config)) { playlist_t *playlist = playlist_get_cached(); enum playlist_sort_mode current_sort_mode = playlist_get_sort_mode(playlist); /* Sort playlist, if required */ if ( sort_enabled && ((playlist_sort_alphabetical && (current_sort_mode == PLAYLIST_SORT_MODE_DEFAULT)) || (current_sort_mode == PLAYLIST_SORT_MODE_ALPHABETICAL))) playlist_qsort(playlist); strlcpy(menu->db_playlist_file, path, sizeof(menu->db_playlist_file)); } } static int menu_displaylist_parse_horizontal_list( menu_handle_t *menu, struct menu_state *menu_st, settings_t *settings, menu_displaylist_info_t *info) { struct item_file *item = NULL; const menu_ctx_driver_t *driver_ctx = menu_st->driver_ctx; size_t selection = driver_ctx->list_get_selection ? driver_ctx->list_get_selection(menu_st->userdata) : 0; size_t size = driver_ctx->list_get_size ? driver_ctx->list_get_size(menu_st->userdata, MENU_LIST_TABS) : 0; if (!driver_ctx->list_get_entry) return -1; if (!(item = (struct item_file*)driver_ctx->list_get_entry(menu_st->userdata, MENU_LIST_HORIZONTAL, (unsigned)(selection - (size +1))))) return -1; /* When opening a saved view the explore menu will handle the list */ if (item->type == MENU_EXPLORE_TAB) menu_displaylist_ctl(DISPLAYLIST_EXPLORE, info, settings); else { struct menu_state *menu_st = menu_state_get_ptr(); playlist_t *playlist = NULL; if (!string_is_empty(item->path)) { char lpl_basename[256]; char path_playlist[PATH_MAX_LENGTH]; const char *dir_playlist = settings->paths.directory_playlist; fill_pathname_join_special(path_playlist, dir_playlist, item->path, sizeof(path_playlist)); /* Horizontal lists are always 'collections' * > Enable sorting (if allowed by user config) */ menu_displaylist_set_new_playlist(menu, settings, path_playlist, true); /* Thumbnail system must be set *after* playlist * is loaded/cached */ fill_pathname_base(lpl_basename, item->path, sizeof(lpl_basename)); path_remove_extension(lpl_basename); menu_driver_set_thumbnail_system( menu_st->userdata, lpl_basename, sizeof(lpl_basename)); } if ((playlist = playlist_get_cached())) { const char *_msg = msg_hash_to_str(MENU_ENUM_LABEL_COLLECTION); if (menu_displaylist_parse_playlist(info->list, info->path, playlist, settings, _msg, strlen(_msg), true) == 0) info->flags |= MD_FLAG_NEED_PUSH_NO_PLAYLIST_ENTRIES; } } return 0; } static int menu_displaylist_parse_load_content_settings( file_list_t *list, settings_t *settings, bool horizontal) { unsigned count = 0; if (!retroarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) { #ifdef HAVE_LAKKA bool show_advanced_settings = settings->bools.menu_show_advanced_settings; #endif bool quickmenu_show_resume_content = settings->bools.quick_menu_show_resume_content; bool quickmenu_show_restart_content = settings->bools.quick_menu_show_restart_content; bool savestates_enabled = core_info_current_supports_savestate(); rarch_system_info_t *sys_info = &runloop_state_get_ptr()->system; if (quickmenu_show_resume_content) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RESUME_CONTENT), msg_hash_to_str(MENU_ENUM_LABEL_RESUME_CONTENT), MENU_ENUM_LABEL_RESUME_CONTENT, MENU_SETTING_ACTION_RUN, 0, 0, NULL)) count++; if (quickmenu_show_restart_content) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RESTART_CONTENT), msg_hash_to_str(MENU_ENUM_LABEL_RESTART_CONTENT), MENU_ENUM_LABEL_RESTART_CONTENT, MENU_SETTING_ACTION_RUN, 0, 0, NULL)) count++; /* Note: Entry type depends on whether quick menu * was accessed via a playlist ('horizontal content') * or the main menu * > This allows us to identify a close content event * triggered via 'Main Menu > Quick Menu', which * subsequently requires the menu stack to be flushed * in order to prevent the display of an empty * 'No items' menu */ if (settings->bools.quick_menu_show_close_content) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CLOSE_CONTENT), msg_hash_to_str(MENU_ENUM_LABEL_CLOSE_CONTENT), MENU_ENUM_LABEL_CLOSE_CONTENT, horizontal ? MENU_SETTING_ACTION_CLOSE_HORIZONTAL : MENU_SETTING_ACTION_CLOSE, 0, 0, NULL)) count++; if ( savestates_enabled && settings->bools.quick_menu_show_savestate_submenu) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SAVESTATE_LIST), msg_hash_to_str(MENU_ENUM_LABEL_SAVESTATE_LIST), MENU_ENUM_LABEL_SAVESTATE_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } else if (savestates_enabled) { if (settings->bools.quick_menu_show_save_load_state) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_STATE_SLOT, PARSE_ONLY_INT, true) == 0) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SAVE_STATE), msg_hash_to_str(MENU_ENUM_LABEL_SAVE_STATE), MENU_ENUM_LABEL_SAVE_STATE, MENU_SETTING_ACTION_SAVESTATE, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_LOAD_STATE), msg_hash_to_str(MENU_ENUM_LABEL_LOAD_STATE), MENU_ENUM_LABEL_LOAD_STATE, MENU_SETTING_ACTION_LOADSTATE, 0, 0, NULL)) count++; if (settings->bools.quick_menu_show_undo_save_load_state) { #ifdef HAVE_CHEEVOS if (!rcheevos_hardcore_active()) #endif { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UNDO_LOAD_STATE), msg_hash_to_str(MENU_ENUM_LABEL_UNDO_LOAD_STATE), MENU_ENUM_LABEL_UNDO_LOAD_STATE, MENU_SETTING_ACTION_LOADSTATE, 0, 0, NULL)) count++; } if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UNDO_SAVE_STATE), msg_hash_to_str(MENU_ENUM_LABEL_UNDO_SAVE_STATE), MENU_ENUM_LABEL_UNDO_SAVE_STATE, MENU_SETTING_ACTION_LOADSTATE, 0, 0, NULL)) count++; } } } if (!settings->bools.kiosk_mode_enable) { if (settings->bools.quick_menu_show_options) { /* Empty 'path' string signifies top level * core options menu */ if (menu_entries_append(list, "", msg_hash_to_str(MENU_ENUM_LABEL_CORE_OPTIONS), MENU_ENUM_LABEL_CORE_OPTIONS, MENU_SETTING_ACTION_CORE_OPTIONS, 0, 0, NULL)) count++; } if (settings->bools.quick_menu_show_controls) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INPUT_REMAPPING_OPTIONS), msg_hash_to_str(MENU_ENUM_LABEL_CORE_INPUT_REMAPPING_OPTIONS), MENU_ENUM_LABEL_CORE_INPUT_REMAPPING_OPTIONS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } } if ((!retroarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) && disk_control_enabled(&sys_info->disk_control)) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISK_OPTIONS), msg_hash_to_str(MENU_ENUM_LABEL_DISK_OPTIONS), MENU_ENUM_LABEL_DISK_OPTIONS, MENU_SETTING_ACTION_CORE_DISK_OPTIONS, 0, 0, NULL)) count++; #ifdef HAVE_SCREENSHOTS if (settings->bools.quick_menu_show_take_screenshot) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_TAKE_SCREENSHOT), msg_hash_to_str(MENU_ENUM_LABEL_TAKE_SCREENSHOT), MENU_ENUM_LABEL_TAKE_SCREENSHOT, MENU_SETTING_ACTION_SCREENSHOT, 0, 0, NULL)) count++; } #endif if (string_is_not_equal(settings->arrays.record_driver, "null")) { recording_state_t *recording_st = recording_state_get_ptr(); if (!recording_st->enable) { if (!settings->bools.kiosk_mode_enable) { if (settings->bools.quick_menu_show_start_recording) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QUICK_MENU_START_RECORDING), msg_hash_to_str(MENU_ENUM_LABEL_QUICK_MENU_START_RECORDING), MENU_ENUM_LABEL_QUICK_MENU_START_RECORDING, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } if (settings->bools.quick_menu_show_start_streaming) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QUICK_MENU_START_STREAMING), msg_hash_to_str(MENU_ENUM_LABEL_QUICK_MENU_START_STREAMING), MENU_ENUM_LABEL_QUICK_MENU_START_STREAMING, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } } } else { recording_state_t *recording_st = recording_state_get_ptr(); if (recording_st->streaming_enable) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QUICK_MENU_STOP_STREAMING), msg_hash_to_str(MENU_ENUM_LABEL_QUICK_MENU_STOP_STREAMING), MENU_ENUM_LABEL_QUICK_MENU_STOP_STREAMING, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } else { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QUICK_MENU_STOP_RECORDING), msg_hash_to_str(MENU_ENUM_LABEL_QUICK_MENU_STOP_RECORDING), MENU_ENUM_LABEL_QUICK_MENU_STOP_RECORDING, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } } } #ifdef HAVE_BSV_MOVIE if ( savestates_enabled && !settings->bools.quick_menu_show_savestate_submenu && settings->bools.quick_menu_show_replay) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_REPLAY_SLOT, PARSE_ONLY_INT, true) == 0) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RECORD_REPLAY), msg_hash_to_str(MENU_ENUM_LABEL_RECORD_REPLAY), MENU_ENUM_LABEL_RECORD_REPLAY, MENU_SETTING_ACTION_RECORDREPLAY, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAY_REPLAY), msg_hash_to_str(MENU_ENUM_LABEL_PLAY_REPLAY), MENU_ENUM_LABEL_PLAY_REPLAY, MENU_SETTING_ACTION_PLAYREPLAY, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_HALT_REPLAY), msg_hash_to_str(MENU_ENUM_LABEL_HALT_REPLAY), MENU_ENUM_LABEL_HALT_REPLAY, MENU_SETTING_ACTION_HALTREPLAY, 0, 0, NULL)) count++; } #endif if ( settings->bools.quick_menu_show_add_to_favorites && settings->bools.menu_content_show_favorites ) { bool add_to_favorites_enabled = true; /* Skip 'Add to Favourites' if we are currently * viewing an entry of the favourites playlist */ if (horizontal) { playlist_t *playlist = playlist_get_cached(); const char *playlist_path = playlist_get_conf_path(playlist); const char *playlist_file = NULL; if (!string_is_empty(playlist_path)) playlist_file = path_basename_nocompression(playlist_path); if ( !string_is_empty(playlist_file) && string_is_equal(playlist_file, FILE_PATH_CONTENT_FAVORITES)) add_to_favorites_enabled = false; } if ( add_to_favorites_enabled && menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_TO_FAVORITES), msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_FAVORITES), MENU_ENUM_LABEL_ADD_TO_FAVORITES, FILE_TYPE_PLAYLIST_ENTRY, 0, 0, NULL)) count++; } if (settings->bools.quick_menu_show_add_to_playlist) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_TO_PLAYLIST), msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_PLAYLIST), MENU_ENUM_LABEL_ADD_TO_PLAYLIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } if (!settings->bools.kiosk_mode_enable) { if (settings->bools.menu_show_overlays) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ONSCREEN_OVERLAY_SETTINGS), msg_hash_to_str(MENU_ENUM_LABEL_ONSCREEN_OVERLAY_SETTINGS), MENU_ENUM_LABEL_ONSCREEN_OVERLAY_SETTINGS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } if (settings->bools.menu_show_latency) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_LATENCY_SETTINGS), msg_hash_to_str(MENU_ENUM_LABEL_LATENCY_SETTINGS), MENU_ENUM_LABEL_LATENCY_SETTINGS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } #ifdef HAVE_REWIND if ( settings->bools.menu_show_rewind && core_info_current_supports_rewind()) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REWIND_SETTINGS), msg_hash_to_str(MENU_ENUM_LABEL_REWIND_SETTINGS), MENU_ENUM_LABEL_REWIND_SETTINGS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } #endif if ( (settings->bools.quick_menu_show_save_core_overrides || settings->bools.quick_menu_show_save_content_dir_overrides || settings->bools.quick_menu_show_save_game_overrides)) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QUICK_MENU_OVERRIDE_OPTIONS), msg_hash_to_str(MENU_ENUM_LABEL_QUICK_MENU_OVERRIDE_OPTIONS), MENU_ENUM_LABEL_QUICK_MENU_OVERRIDE_OPTIONS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } } #ifdef HAVE_CHEEVOS if (settings->bools.cheevos_enable) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_LIST), msg_hash_to_str(MENU_ENUM_LABEL_ACHIEVEMENT_LIST), MENU_ENUM_LABEL_ACHIEVEMENT_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } #endif #ifdef HAVE_CHEATS if (settings->bools.quick_menu_show_cheats) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_CHEAT_OPTIONS), msg_hash_to_str(MENU_ENUM_LABEL_CORE_CHEAT_OPTIONS), MENU_ENUM_LABEL_CORE_CHEAT_OPTIONS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } #endif #if 0 if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_SETTINGS), msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_SETTINGS), MENU_ENUM_LABEL_NETPLAY_SETTINGS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) if (video_shader_any_supported()) { if (settings->bools.quick_menu_show_shaders && !settings->bools.kiosk_mode_enable) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER_OPTIONS), msg_hash_to_str(MENU_ENUM_LABEL_SHADER_OPTIONS), MENU_ENUM_LABEL_SHADER_OPTIONS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } } #endif if (settings->bools.quick_menu_show_information) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INFORMATION), msg_hash_to_str(MENU_ENUM_LABEL_INFORMATION), MENU_ENUM_LABEL_INFORMATION, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } } return count; } static int menu_displaylist_parse_horizontal_content_actions( menu_handle_t *menu, settings_t *settings, file_list_t *list) { bool content_loaded = false; playlist_t *playlist = playlist_get_cached(); const char *fullpath = path_get(RARCH_PATH_CONTENT); unsigned idx = menu->rpl_entry_selection_ptr; const struct playlist_entry *entry = NULL; if (playlist) playlist_get_index(playlist, idx, &entry); content_loaded = !retroarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL) && string_is_equal(menu->deferred_path, fullpath); if (content_loaded) { if (menu_displaylist_parse_load_content_settings(list, settings, true) == 0) menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ITEMS), msg_hash_to_str(MENU_ENUM_LABEL_NO_ITEMS), MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_NO_ITEM, 0, 0, NULL); } else { const char *playlist_path = NULL; const char *playlist_file = NULL; #ifdef HAVE_AUDIOMIXER const char *ext = NULL; if (entry && !string_is_empty(entry->path)) ext = path_get_extension(entry->path); if ( !string_is_empty(ext) && audio_driver_mixer_extension_supported(ext)) { menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER), msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_MIXER), MENU_ENUM_LABEL_ADD_TO_MIXER, FILE_TYPE_PLAYLIST_ENTRY, 0, idx, NULL); menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER_AND_PLAY), msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_MIXER_AND_PLAY), MENU_ENUM_LABEL_ADD_TO_MIXER_AND_PLAY, FILE_TYPE_PLAYLIST_ENTRY, 0, idx, NULL); } #endif playlist_path = playlist_get_conf_path(playlist); if (!string_is_empty(playlist_path)) playlist_file = path_basename_nocompression(playlist_path); menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RUN), msg_hash_to_str(MENU_ENUM_LABEL_RUN), MENU_ENUM_LABEL_RUN, FILE_TYPE_PLAYLIST_ENTRY, 0, idx, NULL); if (!settings->bools.kiosk_mode_enable) { bool remove_entry_enabled = false; if (settings->bools.playlist_entry_rename) menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RENAME_ENTRY), msg_hash_to_str(MENU_ENUM_LABEL_RENAME_ENTRY), MENU_ENUM_LABEL_RENAME_ENTRY, FILE_TYPE_PLAYLIST_ENTRY, 0, idx, NULL); switch (settings->uints.playlist_entry_remove_enable) { case PLAYLIST_ENTRY_REMOVE_ENABLE_ALL: remove_entry_enabled = true; break; case PLAYLIST_ENTRY_REMOVE_ENABLE_HIST_FAV: { char sys_thumb[64]; struct menu_state *menu_st = menu_state_get_ptr(); size_t sys_len = menu_driver_get_thumbnail_system( menu_st->userdata, sys_thumb, sizeof(sys_thumb)); if (!string_is_empty(sys_thumb)) remove_entry_enabled = string_is_equal(sys_thumb, "history") || string_is_equal(sys_thumb, "favorites") || string_ends_with_size(sys_thumb, "_history", sys_len, STRLEN_CONST("_history")); /* An annoyance: if the user navigates to the information menu, * then to the database entry, the thumbnail system will be changed. * This breaks the above 'remove_entry_enabled' check for the * history and favorites playlists. We therefore have to check * the playlist file name as well... */ if ( !remove_entry_enabled && settings->bools.quick_menu_show_information && !string_is_empty(playlist_file)) remove_entry_enabled = string_is_equal(playlist_file, FILE_PATH_CONTENT_HISTORY) || string_is_equal(playlist_file, FILE_PATH_CONTENT_FAVORITES); } break; } /* Remove 'Remove' from Explore lists for now since it does not work correctly */ if (remove_entry_enabled) { struct menu_state *menu_st = menu_state_get_ptr(); menu_list_t *menu_list = menu_st->entries.list; file_list_t *menu_stack = MENU_LIST_GET(menu_list, 0); struct item_file *stack_top = menu_stack->list; size_t depth = menu_stack->size; unsigned current_type = (depth > 0 ? stack_top[depth - 1].type : 0); if (current_type) remove_entry_enabled = false; } if (remove_entry_enabled) menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DELETE_ENTRY), msg_hash_to_str(MENU_ENUM_LABEL_DELETE_ENTRY), MENU_ENUM_LABEL_DELETE_ENTRY, MENU_SETTING_ACTION_DELETE_ENTRY, 0, 0, NULL); } /* Skip 'Add to Favourites' if we are currently * viewing an entry of the favourites playlist */ if ( settings->bools.quick_menu_show_add_to_favorites && settings->bools.menu_content_show_favorites && !(!string_is_empty(playlist_file) && string_is_equal(playlist_file, FILE_PATH_CONTENT_FAVORITES)) ) { menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_TO_FAVORITES_PLAYLIST), msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_FAVORITES_PLAYLIST), MENU_ENUM_LABEL_ADD_TO_FAVORITES_PLAYLIST, FILE_TYPE_PLAYLIST_ENTRY, 0, 0, NULL); } if (settings->bools.quick_menu_show_add_to_playlist) { menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_TO_PLAYLIST), msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_PLAYLIST), MENU_ENUM_LABEL_ADD_TO_PLAYLIST, MENU_SETTING_ACTION, 0, 0, NULL); } if (!settings->bools.kiosk_mode_enable) { if (settings->bools.quick_menu_show_set_core_association) { menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SET_CORE_ASSOCIATION), msg_hash_to_str(MENU_ENUM_LABEL_SET_CORE_ASSOCIATION), MENU_ENUM_LABEL_SET_CORE_ASSOCIATION, FILE_TYPE_PLAYLIST_ENTRY, 0, 0, NULL); } if (settings->bools.quick_menu_show_reset_core_association) { menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RESET_CORE_ASSOCIATION), msg_hash_to_str(MENU_ENUM_LABEL_RESET_CORE_ASSOCIATION), MENU_ENUM_LABEL_RESET_CORE_ASSOCIATION, FILE_TYPE_PLAYLIST_ENTRY, 0, 0, NULL); } #ifdef HAVE_NETWORKING if (settings->bools.quick_menu_show_download_thumbnails) { bool download_enabled = true; if (download_enabled) { char sys_thumb[64]; struct menu_state *menu_st = menu_state_get_ptr(); /* Only show 'Download Thumbnails' on supported playlists */ size_t sys_len = menu_driver_get_thumbnail_system( menu_st->userdata, sys_thumb, sizeof(sys_thumb)); if (!string_is_empty(sys_thumb)) download_enabled = !string_ends_with_size( sys_thumb, "_history", sys_len, STRLEN_CONST("_history")); else download_enabled = false; } if (settings->bools.network_on_demand_thumbnails) download_enabled = false; if (download_enabled) menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWNLOAD_PL_ENTRY_THUMBNAILS), msg_hash_to_str(MENU_ENUM_LABEL_DOWNLOAD_PL_ENTRY_THUMBNAILS), MENU_ENUM_LABEL_DOWNLOAD_PL_ENTRY_THUMBNAILS, FILE_TYPE_PLAYLIST_ENTRY, 0, 0, NULL); } #endif } if (settings->bools.quick_menu_show_information) menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INFORMATION), msg_hash_to_str(MENU_ENUM_LABEL_INFORMATION), MENU_ENUM_LABEL_INFORMATION, MENU_SETTING_ACTION, 0, 0, NULL); } return 0; } static unsigned menu_displaylist_parse_information_list(file_list_t *info_list) { unsigned count = 0; core_info_t *core_info = NULL; struct retro_system_info *sysinfo = &runloop_state_get_ptr()->system.info; core_info_get_current_core(&core_info); if ( sysinfo && (!string_is_empty(sysinfo->library_name) && !string_is_equal(sysinfo->library_name, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_CORE)) ) && core_info && core_info->has_info ) if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_INFORMATION), msg_hash_to_str(MENU_ENUM_LABEL_CORE_INFORMATION), MENU_ENUM_LABEL_CORE_INFORMATION, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #ifdef HAVE_CDROM { struct string_list *drive_list = cdrom_get_available_drives(); if (drive_list) { if (drive_list->size) { if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISC_INFORMATION), msg_hash_to_str(MENU_ENUM_LABEL_DISC_INFORMATION), MENU_ENUM_LABEL_DISC_INFORMATION, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } string_list_free(drive_list); } } #endif if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFORMATION), msg_hash_to_str(MENU_ENUM_LABEL_SYSTEM_INFORMATION), MENU_ENUM_LABEL_SYSTEM_INFORMATION, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #if defined(HAVE_NETWORKING) && defined(HAVE_IFINFO) if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETWORK_INFORMATION), msg_hash_to_str(MENU_ENUM_LABEL_NETWORK_INFORMATION), MENU_ENUM_LABEL_NETWORK_INFORMATION, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif #ifdef HAVE_LIBRETRODB if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DATABASE_MANAGER), msg_hash_to_str(MENU_ENUM_LABEL_DATABASE_MANAGER_LIST), MENU_ENUM_LABEL_DATABASE_MANAGER_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif if (retroarch_ctl(RARCH_CTL_IS_PERFCNT_ENABLE, NULL)) { if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FRONTEND_COUNTERS), msg_hash_to_str(MENU_ENUM_LABEL_FRONTEND_COUNTERS), MENU_ENUM_LABEL_FRONTEND_COUNTERS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_COUNTERS), msg_hash_to_str(MENU_ENUM_LABEL_CORE_COUNTERS), MENU_ENUM_LABEL_CORE_COUNTERS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } return count; } static unsigned menu_displaylist_parse_playlists( file_list_t *info_list, unsigned type_default, const char *path, settings_t *settings, bool horizontal) { size_t i, list_size; struct string_list str_list = {0}; unsigned count = 0; unsigned content_count = 0; bool show_hidden_files = settings->bools.show_hidden_files; if (string_is_empty(path)) { int ret = frontend_driver_parse_drive_list(info_list, true); /* TODO/FIXME - we need to know the actual count number here */ if (ret == 0) count++; else if (menu_entries_append(info_list, "/", "", MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR, FILE_TYPE_DIRECTORY, 0, 0, NULL)) count++; return count; } if (!horizontal) { bool show_add_content = false; #if defined(HAVE_XMB) || defined(HAVE_OZONE) const char *menu_ident = menu_driver_ident(); if ( string_is_equal(menu_ident, "xmb") || string_is_equal(menu_ident, "ozone")) show_add_content = settings->bools.menu_content_show_add; else #endif show_add_content = (settings->uints.menu_content_show_add_entry == MENU_ADD_CONTENT_ENTRY_DISPLAY_PLAYLISTS_TAB); if (show_add_content) if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_CONTENT_LIST), msg_hash_to_str(MENU_ENUM_LABEL_ADD_CONTENT_LIST), MENU_ENUM_LABEL_ADD_CONTENT_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (settings->bools.menu_content_show_favorites) if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_FAVORITES), msg_hash_to_str(MENU_ENUM_LABEL_GOTO_FAVORITES), MENU_ENUM_LABEL_GOTO_FAVORITES, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (settings->bools.menu_content_show_images) if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_IMAGES), msg_hash_to_str(MENU_ENUM_LABEL_GOTO_IMAGES), MENU_ENUM_LABEL_GOTO_IMAGES, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (settings->bools.menu_content_show_music) if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_MUSIC), msg_hash_to_str(MENU_ENUM_LABEL_GOTO_MUSIC), MENU_ENUM_LABEL_GOTO_MUSIC, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #if defined(HAVE_FFMPEG) || defined(HAVE_MPV) if (settings->bools.menu_content_show_video) if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_VIDEO), msg_hash_to_str(MENU_ENUM_LABEL_GOTO_VIDEO), MENU_ENUM_LABEL_GOTO_VIDEO, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif #if defined(HAVE_DYNAMIC) if (settings->uints.menu_content_show_contentless_cores != MENU_CONTENTLESS_CORES_DISPLAY_NONE) if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_CONTENTLESS_CORES), msg_hash_to_str(MENU_ENUM_LABEL_GOTO_CONTENTLESS_CORES), MENU_ENUM_LABEL_GOTO_CONTENTLESS_CORES, MENU_CONTENTLESS_CORES_TAB, 0, 0, NULL)) count++; #endif #if defined(HAVE_LIBRETRODB) if (settings->bools.menu_content_show_explore) if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_EXPLORE), msg_hash_to_str(MENU_ENUM_LABEL_GOTO_EXPLORE), MENU_ENUM_LABEL_GOTO_EXPLORE, MENU_EXPLORE_TAB, 0, 0, NULL)) count++; #endif } if (!dir_list_initialize(&str_list, path, NULL, true, show_hidden_files, true, false)) return count; content_count = count; dir_list_sort_ignore_ext(&str_list, true); list_size = str_list.size; #if defined(HAVE_LIBRETRODB) if (settings->bools.menu_content_show_explore) { char label[512]; size_t _len = strlcpy(label, msg_hash_to_str(MENU_ENUM_LABEL_EXPLORE_VIEW), sizeof(label)); /* List any custom explore views above playlists */ for (i = 0; i < list_size; i++) { const char *path = str_list.elems[i].data; const char *fname = path_basename(path); const char *fext = path_get_extension(fname); if (!string_is_equal_noncase(fext, "lvw")) continue; snprintf(label + _len, sizeof(label) - _len, ": %.*s", (int)(fext - 1 - fname), fname); if (menu_entries_append(info_list, label, path, MENU_ENUM_LABEL_GOTO_EXPLORE, MENU_EXPLORE_TAB, 0, (count - content_count), NULL)) { menu_file_list_cbs_t *cbs = ((menu_file_list_cbs_t*)info_list->list[info_list->size-1].actiondata); cbs->action_sublabel = NULL; count++; } } } #endif for (i = 0; i < list_size; i++) { const char *path = str_list.elems[i].data; const char *playlist_file = NULL; enum msg_file_type file_type = FILE_TYPE_NONE; switch (str_list.elems[i].attr.i) { case RARCH_DIRECTORY: file_type = FILE_TYPE_DIRECTORY; break; case RARCH_PLAIN_FILE: default: file_type = (enum msg_file_type)type_default; break; } if (file_type == FILE_TYPE_DIRECTORY) continue; if (string_is_empty(path)) continue; playlist_file = path_basename_nocompression(path); if (string_is_empty(playlist_file)) continue; /* Ignore non-playlist files */ if (!string_is_equal_noncase(path_get_extension(playlist_file), "lpl")) continue; /* Ignore history/favourites */ if ( string_ends_with_size(path, "_history.lpl", strlen(path), STRLEN_CONST("_history.lpl")) || string_is_equal(playlist_file, FILE_PATH_CONTENT_FAVORITES)) continue; file_type = FILE_TYPE_PLAYLIST_COLLECTION; if (horizontal) path = playlist_file; if (menu_entries_append(info_list, path, "", MENU_ENUM_LABEL_PLAYLIST_COLLECTION_ENTRY, file_type, 0, (count - content_count), NULL)) count++; } dir_list_deinitialize(&str_list); return count; } static unsigned menu_displaylist_parse_cores( menu_handle_t *menu, settings_t *settings, menu_displaylist_info_t *info) { size_t i, list_size; char out_dir[PATH_MAX_LENGTH]; struct string_list *str_list = NULL; unsigned count = 0; const char *path = info->path; bool ok = false; bool show_hidden_files = settings->bools.show_hidden_files; if (string_is_empty(path)) { if (frontend_driver_parse_drive_list(info->list, true) != 0) menu_entries_append(info->list, "/", "", MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR, FILE_TYPE_DIRECTORY, 0, 0, NULL); count++; return count; } str_list = string_list_new(); ok = dir_list_append(str_list, path, info->exts, true, show_hidden_files, false, false); #if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP /* UWP: browse the optional packages for additional cores */ struct string_list *core_packages = string_list_new(); uwp_fill_installed_core_packages(core_packages); for (i = 0; i < core_packages->size; i++) dir_list_append(str_list, core_packages->elems[i].data, info->exts, true, show_hidden_files, true, false); string_list_free(core_packages); #else /* Keep the old 'directory not found' behavior */ if (!ok) { string_list_free(str_list); str_list = NULL; } #endif fill_pathname_parent_dir(out_dir, path, sizeof(out_dir)); if (string_is_empty(out_dir)) menu_entries_prepend(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PARENT_DIRECTORY), path, MENU_ENUM_LABEL_PARENT_DIRECTORY, FILE_TYPE_PARENT_DIRECTORY, 0, 0); if (!str_list) { const char *str = msg_hash_to_str( MENU_ENUM_LABEL_VALUE_DIRECTORY_NOT_FOUND); menu_entries_append(info->list, str, "", MENU_ENUM_LABEL_VALUE_DIRECTORY_NOT_FOUND, 0, 0, 0, NULL); count++; return count; } if (string_is_equal(info->label, msg_hash_to_str(MENU_ENUM_LABEL_CORE_LIST))) info->flags |= MD_FLAG_DOWNLOAD_CORE; dir_list_sort(str_list, true); list_size = str_list->size; if (list_size == 0) { string_list_free(str_list); return 0; } for (i = 0; i < list_size; i++) { char label[64]; #ifndef HAVE_DYNAMIC bool is_dir = false; #endif const char *path = NULL; enum msg_hash_enums enum_idx = MSG_UNKNOWN; enum msg_file_type file_type = FILE_TYPE_NONE; /* TODO/FIXME - empty label */ label[0] = '\0'; switch (str_list->elems[i].attr.i) { case RARCH_DIRECTORY: file_type = FILE_TYPE_DIRECTORY; enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_DIRECTORY; #ifndef HAVE_DYNAMIC is_dir = true; #endif break; case RARCH_COMPRESSED_ARCHIVE: case RARCH_COMPRESSED_FILE_IN_ARCHIVE: /* Compressed cores are unsupported */ continue; case RARCH_PLAIN_FILE: default: file_type = FILE_TYPE_CORE; enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_CORE; break; } /* Need to preserve slash first time. */ path = str_list->elems[i].data; if (!string_is_empty(path)) path = path_basename_nocompression(path); #ifndef HAVE_DYNAMIC if (frontend_driver_has_fork()) { char salamander_name[PATH_MAX_LENGTH]; salamander_name[0] = '\0'; if (frontend_driver_get_salamander_basename( salamander_name, sizeof(salamander_name))) { if (string_is_equal_noncase(path, salamander_name)) continue; } if (is_dir) continue; } #endif #ifdef IOS /* For various reasons on iOS/tvOS, MoltenVK shows up * in the cores directory; exclude it here */ if (string_starts_with(path, "MoltenVK")) continue; #endif count++; menu_entries_append(info->list, path, label, enum_idx, file_type, 0, 0, NULL); } string_list_free(str_list); if (count == 0) return 0; { core_info_list_t *list = NULL; const char *dir = NULL; core_info_get_list(&list); menu_entries_get_last_stack(&dir, NULL, NULL, NULL, NULL); list_size = info->list->size; for (i = 0; i < list_size; i++) { const char *path = info->list->list[i].path; unsigned type = info->list->list[i].type; if (type == FILE_TYPE_CORE) { char core_path[PATH_MAX_LENGTH]; char display_name[256]; display_name[0] = '\0'; fill_pathname_join_special(core_path, dir, path, sizeof(core_path)); if (core_info_list_get_display_name(list, core_path, display_name, sizeof(display_name))) file_list_set_alt_at_offset(info->list, i, display_name); } } info->flags |= MD_FLAG_NEED_SORT; } return count; } static unsigned menu_displaylist_parse_add_to_playlist_list( file_list_t *list, settings_t *settings) { unsigned count = 0; const char *dir_playlist = settings->paths.directory_playlist; bool show_hidden_files = settings->bools.show_hidden_files; char playlist_display_name[PATH_MAX_LENGTH]; struct string_list *str_list = dir_list_new_special( dir_playlist, DIR_LIST_COLLECTIONS, NULL, show_hidden_files); if (str_list && str_list->size) { unsigned i; dir_list_sort(str_list, true); for (i = 0; i < str_list->size; i++) { const char *path = str_list->elems[i].data; const char *playlist_file = NULL; if (str_list->elems[i].attr.i == FILE_TYPE_DIRECTORY) continue; if (string_is_empty(path)) continue; playlist_file = path_basename_nocompression(path); if (string_is_empty(playlist_file)) continue; /* Ignore non-playlist files */ if (!string_is_equal_noncase(path_get_extension(playlist_file), "lpl")) continue; /* Ignore history/favourites * > content_history + favorites are handled separately * > music/video/image_history are ignored */ if ( string_ends_with_size(path, "_history.lpl", strlen(path), STRLEN_CONST("_history.lpl")) || string_is_equal(playlist_file, FILE_PATH_CONTENT_FAVORITES)) continue; strlcpy(playlist_display_name, playlist_file, sizeof(playlist_display_name)); path_remove_extension(playlist_display_name); menu_entries_append(list, playlist_display_name, path, MENU_ENUM_LABEL_ADD_ENTRY_TO_PLAYLIST, MENU_SETTING_ACTION, 0, 0, NULL); count++; } } /* Not necessary to check for NULL here */ string_list_free(str_list); return count; } static unsigned menu_displaylist_parse_playlist_manager_list( file_list_t *list, settings_t *settings) { unsigned count = 0; const char *dir_playlist = settings->paths.directory_playlist; bool show_hidden_files = settings->bools.show_hidden_files; bool history_list_enable = settings->bools.history_list_enable; struct string_list *str_list = dir_list_new_special( dir_playlist, DIR_LIST_COLLECTIONS, NULL, show_hidden_files); if (str_list && str_list->size) { unsigned i; dir_list_sort(str_list, true); for (i = 0; i < str_list->size; i++) { const char *path = str_list->elems[i].data; const char *playlist_file = NULL; if (str_list->elems[i].attr.i == FILE_TYPE_DIRECTORY) continue; if (string_is_empty(path)) continue; playlist_file = path_basename_nocompression(path); if (string_is_empty(playlist_file)) continue; /* Ignore non-playlist files */ if (!string_is_equal_noncase(path_get_extension(playlist_file), "lpl")) continue; /* Ignore history/favourites * > content_history + favorites are handled separately * > music/video/image_history are ignored */ if ( string_ends_with_size(path, "_history.lpl", strlen(path), STRLEN_CONST("_history.lpl")) || string_is_equal(playlist_file, FILE_PATH_CONTENT_FAVORITES)) continue; menu_entries_append(list, path, "", MENU_ENUM_LABEL_PLAYLIST_MANAGER_SETTINGS, MENU_SETTING_ACTION, 0, 0, NULL); count++; } } /* Not necessary to check for NULL here */ string_list_free(str_list); /* Add content history */ if (history_list_enable) if (g_defaults.content_history) if (playlist_size(g_defaults.content_history) > 0) if (menu_entries_append(list, playlist_get_conf_path(g_defaults.content_history), "", MENU_ENUM_LABEL_PLAYLIST_MANAGER_SETTINGS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; /* Add favourites */ if (g_defaults.content_favorites) if (playlist_size(g_defaults.content_favorites) > 0) if (menu_entries_append(list, playlist_get_conf_path(g_defaults.content_favorites), "", MENU_ENUM_LABEL_PLAYLIST_MANAGER_SETTINGS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; return count; } static bool menu_displaylist_parse_playlist_manager_settings( menu_handle_t *menu, settings_t *settings, file_list_t *list, const char *playlist_path) { bool is_content_history; enum msg_hash_enums right_thumbnail_label_value; enum msg_hash_enums left_thumbnail_label_value; const char *playlist_file = NULL; playlist_t *playlist = NULL; const char *menu_driver = menu_driver_ident(); if (string_is_empty(playlist_path)) return false; playlist_file = path_basename_nocompression(playlist_path); if (string_is_empty(playlist_file)) return false; /* Note: We are caching the current playlist * here so we can get its path and/or modify * its metadata when performing management * tasks. We *don't* care about entry order * at this stage, so we can save a few clock * cycles by disabling sorting */ menu_displaylist_set_new_playlist(menu, settings, playlist_path, false); if (!(playlist = playlist_get_cached())) return false; /* Check whether this is a content history playlist */ is_content_history = string_ends_with_size( playlist_path, "_history.lpl", strlen(playlist_path), STRLEN_CONST("_history.lpl")); /* Label display mode */ menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE), msg_hash_to_str(MENU_ENUM_LABEL_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE), MENU_ENUM_LABEL_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE, MENU_SETTING_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE, 0, 0, NULL); /* Thumbnail modes */ right_thumbnail_label_value = MENU_ENUM_LABEL_VALUE_THUMBNAILS; left_thumbnail_label_value = MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS; /* > Get label values */ #ifdef HAVE_RGUI if (string_is_equal(menu_driver, "rgui")) { right_thumbnail_label_value = MENU_ENUM_LABEL_VALUE_THUMBNAILS_RGUI; left_thumbnail_label_value = MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS_RGUI; } #endif #ifdef HAVE_OZONE if (string_is_equal(menu_driver, "ozone")) { right_thumbnail_label_value = MENU_ENUM_LABEL_VALUE_THUMBNAILS; left_thumbnail_label_value = MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS_OZONE; } #endif #ifdef HAVE_MATERIALUI if (string_is_equal(menu_driver, "glui")) { right_thumbnail_label_value = MENU_ENUM_LABEL_VALUE_THUMBNAILS_MATERIALUI; left_thumbnail_label_value = MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS_MATERIALUI; } #endif /* > Right thumbnail mode */ menu_entries_append(list, msg_hash_to_str(right_thumbnail_label_value), msg_hash_to_str(MENU_ENUM_LABEL_PLAYLIST_MANAGER_RIGHT_THUMBNAIL_MODE), MENU_ENUM_LABEL_PLAYLIST_MANAGER_RIGHT_THUMBNAIL_MODE, MENU_SETTING_PLAYLIST_MANAGER_RIGHT_THUMBNAIL_MODE, 0, 0, NULL); /* > Left thumbnail mode */ menu_entries_append(list, msg_hash_to_str(left_thumbnail_label_value), msg_hash_to_str(MENU_ENUM_LABEL_PLAYLIST_MANAGER_LEFT_THUMBNAIL_MODE), MENU_ENUM_LABEL_PLAYLIST_MANAGER_LEFT_THUMBNAIL_MODE, MENU_SETTING_PLAYLIST_MANAGER_LEFT_THUMBNAIL_MODE, 0, 0, NULL); /* Sorting mode * > Not relevant for history playlists */ if (!is_content_history) menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_SORT_MODE), msg_hash_to_str(MENU_ENUM_LABEL_PLAYLIST_MANAGER_SORT_MODE), MENU_ENUM_LABEL_PLAYLIST_MANAGER_SORT_MODE, MENU_SETTING_PLAYLIST_MANAGER_SORT_MODE, 0, 0, NULL); /* Default core association * > This is only shown for collection playlists * (i.e. it is not relevant for history/favourites) */ if ( !is_content_history && !string_is_equal(playlist_file, FILE_PATH_CONTENT_FAVORITES)) menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_DEFAULT_CORE), msg_hash_to_str(MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE), MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE, MENU_SETTING_PLAYLIST_MANAGER_DEFAULT_CORE, 0, 0, NULL); /* Reset core associations */ menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_RESET_CORES), msg_hash_to_str(MENU_ENUM_LABEL_PLAYLIST_MANAGER_RESET_CORES), MENU_ENUM_LABEL_PLAYLIST_MANAGER_RESET_CORES, MENU_SETTING_ACTION_PLAYLIST_MANAGER_RESET_CORES, 0, 0, NULL); /* Refresh playlist */ if (playlist_scan_refresh_enabled(playlist)) menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_REFRESH_PLAYLIST), msg_hash_to_str(MENU_ENUM_LABEL_PLAYLIST_MANAGER_REFRESH_PLAYLIST), MENU_ENUM_LABEL_PLAYLIST_MANAGER_REFRESH_PLAYLIST, MENU_SETTING_ACTION_PLAYLIST_MANAGER_REFRESH_PLAYLIST, 0, 0, NULL); /* Clean playlist */ menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_CLEAN_PLAYLIST), msg_hash_to_str(MENU_ENUM_LABEL_PLAYLIST_MANAGER_CLEAN_PLAYLIST), MENU_ENUM_LABEL_PLAYLIST_MANAGER_CLEAN_PLAYLIST, MENU_SETTING_ACTION_PLAYLIST_MANAGER_CLEAN_PLAYLIST, 0, 0, NULL); /* Delete playlist */ menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DELETE_PLAYLIST), msg_hash_to_str(MENU_ENUM_LABEL_DELETE_PLAYLIST), MENU_ENUM_LABEL_DELETE_PLAYLIST, MENU_SETTING_ACTION_DELETE_PLAYLIST, 0, 0, NULL); return true; } #ifdef HAVE_NETWORKING static unsigned menu_displaylist_parse_pl_thumbnail_download_list( file_list_t *list, settings_t *settings) { unsigned count = 0; const char *dir_playlist = settings->paths.directory_playlist; bool show_hidden_files = settings->bools.show_hidden_files; struct string_list *str_list = dir_list_new_special( dir_playlist, DIR_LIST_COLLECTIONS, NULL, show_hidden_files); if (str_list && str_list->size) { unsigned i; dir_list_sort(str_list, true); for (i = 0; i < str_list->size; i++) { char path_base[PATH_MAX_LENGTH]; const char *path; if (str_list->elems[i].attr.i == FILE_TYPE_DIRECTORY) continue; path = path_basename(str_list->elems[i].data); if ( string_is_empty(path) || !string_is_equal_noncase(path_get_extension(path), "lpl")) continue; strlcpy(path_base, path, sizeof(path_base)); path_remove_extension(path_base); menu_entries_append(list, path_base, path, MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_ENTRY, FILE_TYPE_DOWNLOAD_PL_THUMBNAIL_CONTENT, 0, 0, NULL); count++; } } /* Not necessary to check for NULL here */ string_list_free(str_list); return count; } #endif static unsigned menu_displaylist_parse_content_information( menu_handle_t *menu, settings_t *settings, file_list_t *info_list) { char tmp[8192]; char core_name[256]; char content_label[256]; playlist_t *playlist = playlist_get_cached(); unsigned idx = menu->rpl_entry_selection_ptr; const struct playlist_entry *entry = NULL; const char *loaded_content_path = path_get(RARCH_PATH_CONTENT); const char *loaded_core_path = path_get(RARCH_PATH_CORE); const char *content_path = NULL; const char *core_path = NULL; const char *db_name = NULL; bool playlist_origin = true; bool playlist_valid = false; const char *origin_label = NULL; struct menu_state *menu_st = menu_state_get_ptr(); file_list_t *list = NULL; unsigned count = 0; bool content_loaded = !retroarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL) && !string_is_empty(loaded_content_path) && string_is_equal(menu->deferred_path, loaded_content_path); bool core_supports_no_game = false; core_name[0] = '\0'; content_label[0] = '\0'; /* Check the origin menu from which the information * entry was selected * > Can only assume a valid playlist if the origin * was an actual playlist - i.e. cached playlist is * dubious if information was selected from * 'Main Menu > Quick Menu' or 'Contentless Cores > * Quick Menu' */ if (menu_st->entries.list) list = MENU_LIST_GET(menu_st->entries.list, 0); if (list && (list->size > 2)) { origin_label = list->list[list->size - 3].label; if ( string_is_equal(origin_label, msg_hash_to_str(MENU_ENUM_LABEL_MAIN_MENU)) || string_is_equal(origin_label, msg_hash_to_str(MENU_ENUM_LABEL_CONTENTLESS_CORES_TAB)) || string_is_equal(origin_label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_CONTENTLESS_CORES_LIST))) playlist_origin = false; } /* If origin menu was a playlist, may rely on * return value from playlist_get_cached() */ if (playlist_origin) playlist_valid = !!playlist; else { /* If origin menu was not a playlist, then * check currently loaded content against * last cached playlist */ if (content_loaded && !string_is_empty(loaded_core_path)) playlist_valid = playlist_index_is_valid( playlist, idx, loaded_content_path, loaded_core_path); } if (playlist_valid) { /* If playlist is valid, all information is readily available */ playlist_get_index(playlist, idx, &entry); if (entry) { content_path = entry->path; core_path = entry->core_path; db_name = entry->db_name; if (!string_is_empty(entry->label)) strlcpy(content_label, entry->label, sizeof(content_label)); else if (!string_is_empty(content_path)) { /* Create content label from the path */ strlcpy(content_label, path_basename(content_path), sizeof(content_label)); path_remove_extension(content_label); } /* Only display core name if both core name and * core path are valid */ if ( !string_is_empty(entry->core_name) && !string_is_empty(core_path) && !string_is_equal(core_path, "DETECT")) strlcpy(core_name, entry->core_name, sizeof(core_name)); } } else { core_info_t *core_info = NULL; /* No playlist - just extract what we can... */ content_path = loaded_content_path; core_path = loaded_core_path; /* Create content label from the path */ strlcpy(content_label, path_basename(content_path), sizeof(content_label)); path_remove_extension(content_label); if (core_info_find(core_path, &core_info)) { core_supports_no_game = core_info->supports_no_game; if (!string_is_empty(core_info->display_name)) strlcpy(core_name, core_info->display_name, sizeof(core_name)); } } #ifdef HAVE_LIBRETRODB /* Database entry */ if ( !string_is_empty(content_label) && !string_is_empty(db_name)) { char db_path[PATH_MAX_LENGTH]; fill_pathname_join_special(db_path, settings->paths.path_content_database, db_name, sizeof(db_path)); path_remove_extension(db_path); strlcat(db_path, ".rdb", sizeof(db_path)); if (path_is_valid(db_path)) if (menu_entries_append(info_list, content_label, db_path, MENU_ENUM_LABEL_RDB_ENTRY_DETAIL, FILE_TYPE_RDB_ENTRY, 0, 0, NULL)) count++; } #endif /* Database */ if (!string_is_empty(db_name)) { char *db_name_no_ext = NULL; char db_name_no_ext_buff[PATH_MAX_LENGTH]; /* Remove .lpl extension * > path_remove_extension() requires a char * (not const) * so have to use a temporary buffer... */ strlcpy(db_name_no_ext_buff, db_name, sizeof(db_name_no_ext_buff)); db_name_no_ext = path_remove_extension(db_name_no_ext_buff); if (!string_is_empty(db_name_no_ext)) { size_t _len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CONTENT_INFO_DATABASE), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; strlcpy(tmp + _len, db_name_no_ext, sizeof(tmp) - _len); if (menu_entries_append(info_list, tmp, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_INFO_DATABASE), MENU_ENUM_LABEL_CONTENT_INFO_DATABASE, 0, 0, 0, NULL)) count++; } } /* If content path is empty and core supports * contentless operation, skip label/path entries */ if ( !(core_supports_no_game && string_is_empty(content_path))) { /* Content label */ size_t _len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CONTENT_INFO_LABEL), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; strlcpy(tmp + _len, !string_is_empty(content_label) ? content_label : msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE), sizeof(tmp) - _len); if (menu_entries_append(info_list, tmp, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_INFO_LABEL), MENU_ENUM_LABEL_CONTENT_INFO_LABEL, 0, 0, 0, NULL)) count++; /* Content path */ _len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CONTENT_INFO_PATH), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; strlcpy(tmp + _len, !string_is_empty(content_path) ? content_path : msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE), sizeof(tmp) - _len); if (menu_entries_append(info_list, tmp, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_INFO_PATH), MENU_ENUM_LABEL_CONTENT_INFO_PATH, 0, 0, 0, NULL)) count++; } /* Core name */ if ( !string_is_empty(core_name) && !string_is_equal(core_name, "DETECT")) { size_t _len = strlcpy(tmp, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CONTENT_INFO_CORE_NAME), sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\0'; strlcpy(tmp + _len, core_name, sizeof(tmp) - _len); if (menu_entries_append(info_list, tmp, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_INFO_CORE_NAME), MENU_ENUM_LABEL_CORE_INFORMATION, /* Shortcut to core info */ 0, 0, 0, NULL)) count++; } /* Runtime */ if (((settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_PER_CORE) && settings->bools.content_runtime_log) || ((settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_AGGREGATE) && !settings->bools.content_runtime_log_aggregate)) { runtime_log_t *runtime_log = runtime_log_init( content_path, core_path, settings->paths.directory_runtime_log, settings->paths.directory_playlist, (settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_PER_CORE)); if (runtime_log) { if (runtime_log_has_runtime(runtime_log)) { /* Play time */ tmp[0] = '\0'; runtime_log_get_runtime_str(runtime_log, tmp, sizeof(tmp)); if (!string_is_empty(tmp)) if (menu_entries_append(info_list, tmp, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_INFO_RUNTIME), MENU_ENUM_LABEL_CONTENT_INFO_RUNTIME, 0, 0, 0, NULL)) count++; /* Last Played */ tmp[0] = '\0'; runtime_log_get_last_played_str(runtime_log, tmp, sizeof(tmp), (enum playlist_sublabel_last_played_style_type)settings->uints.playlist_sublabel_last_played_style, (enum playlist_sublabel_last_played_date_separator_type)settings->uints.menu_timedate_date_separator); if (!string_is_empty(tmp)) if (menu_entries_append(info_list, tmp, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_INFO_LAST_PLAYED), MENU_ENUM_LABEL_CONTENT_INFO_LAST_PLAYED, 0, 0, 0, NULL)) count++; } free(runtime_log); } } #ifdef HAVE_CHEEVOS /* RetroAchievements Hash */ if ( settings->bools.cheevos_enable && settings->arrays.cheevos_token[0] && !string_is_empty(loaded_content_path)) { const char *cheevos_hash_str = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CONTENT_INFO_CHEEVOS_HASH); size_t _len = strlcpy(tmp, cheevos_hash_str, sizeof(tmp)); tmp[ _len] = ':'; tmp[++_len] = ' '; tmp[++_len] = '\n'; tmp[++_len] = '\0'; strlcpy(tmp + _len, rcheevos_get_hash(), sizeof(tmp) - _len); if (menu_entries_append(info_list, tmp, cheevos_hash_str, MENU_ENUM_LABEL_VALUE_CONTENT_INFO_CHEEVOS_HASH, 0, 0, 0, NULL)) count++; } #endif return count; } static unsigned menu_displaylist_parse_disk_options(file_list_t *list) { unsigned count = 0; rarch_system_info_t *sys_info = &runloop_state_get_ptr()->system; bool disk_ejected = false; /* Sanity Check */ if (!sys_info) return 0; if (!disk_control_enabled(&sys_info->disk_control)) return 0; /* Check whether disk is currently ejected */ disk_ejected = disk_control_get_eject_state(&sys_info->disk_control); /* Always show a 'DISK_CYCLE_TRAY_STATUS' entry * > These perform the same function, but just have * different labels/sublabels */ if (disk_ejected) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISK_TRAY_INSERT), msg_hash_to_str(MENU_ENUM_LABEL_DISK_TRAY_INSERT), MENU_ENUM_LABEL_DISK_TRAY_INSERT, MENU_SETTINGS_CORE_DISK_OPTIONS_DISK_CYCLE_TRAY_STATUS, 0, 0, NULL)) count++; /* Only show disk index if disk is currently ejected */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISK_INDEX), msg_hash_to_str(MENU_ENUM_LABEL_DISK_INDEX), MENU_ENUM_LABEL_DISK_INDEX, MENU_SETTINGS_CORE_DISK_OPTIONS_DISK_INDEX, 0, 0, NULL)) count++; } else if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISK_TRAY_EJECT), msg_hash_to_str(MENU_ENUM_LABEL_DISK_TRAY_EJECT), MENU_ENUM_LABEL_DISK_TRAY_EJECT, MENU_SETTINGS_CORE_DISK_OPTIONS_DISK_CYCLE_TRAY_STATUS, 0, 0, NULL)) count++; /* If core does not support appending images, * can stop here */ if (!disk_control_append_enabled(&sys_info->disk_control)) return count; /* Always show a 'DISK_IMAGE_APPEND' entry * > If tray is currently shut, this will: * - Open tray * - Append disk image * - Close tray * > If tray is currently open, this will * only append a disk image */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISK_IMAGE_APPEND), msg_hash_to_str(MENU_ENUM_LABEL_DISK_IMAGE_APPEND), MENU_ENUM_LABEL_DISK_IMAGE_APPEND, MENU_SETTINGS_CORE_DISK_OPTIONS_DISK_IMAGE_APPEND, 0, 0, NULL)) count++; return count; } static int menu_displaylist_parse_audio_device_list( file_list_t *info_list, const char *info_path, settings_t *settings) { enum msg_hash_enums enum_idx = (enum msg_hash_enums)atoi(info_path); rarch_setting_t *setting = menu_setting_find_enum(enum_idx); size_t menu_index = 0; unsigned count = 0; int i = -1; int audio_device_index = -1; struct string_list *ptr = NULL; if (!settings || !setting) return 0; if (!audio_driver_get_devices_list((void**)&ptr)) return 0; if (!ptr) return 0; /* Get index in the string list */ audio_device_index = string_list_find_elem(ptr, setting->value.target.string) - 1; /* Add "Default" */ if (i == -1) { bool add = false; if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DONT_CARE), "", MENU_ENUM_LABEL_AUDIO_DEVICE_LIST, MENU_SETTING_DROPDOWN_ITEM_AUDIO_DEVICE, 0, i, NULL)) add = true; if (add) { /* Add checkmark if input is currently * mapped to this entry */ if (audio_device_index == i) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info_list->list[menu_index].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = menu_index; } count++; menu_index++; } } for (i = 0; i < (int)ptr->size; i++) { bool add = false; /* Add menu entry */ if (menu_entries_append(info_list, ptr->elems[i].data, ptr->elems[i].data, MENU_ENUM_LABEL_AUDIO_DEVICE_LIST, MENU_SETTING_DROPDOWN_ITEM_AUDIO_DEVICE, 0, i, NULL)) add = true; if (add) { /* Add checkmark if input is currently * mapped to this entry */ if (audio_device_index == i) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info_list->list[menu_index].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = menu_index; } count++; menu_index++; } } return count; } #ifdef HAVE_MICROPHONE static int menu_displaylist_parse_microphone_device_list( file_list_t *info_list, const char *info_path, settings_t *settings) { enum msg_hash_enums enum_idx = (enum msg_hash_enums)atoi(info_path); rarch_setting_t *setting = menu_setting_find_enum(enum_idx); size_t menu_index = 0; unsigned count = 0; int i = -1; int mic_device_index = -1; struct string_list *ptr = NULL; if (!settings || !setting) return 0; if (!microphone_driver_get_devices_list((void**)&ptr)) return 0; if (!ptr) return 0; /* Get index in the string list */ mic_device_index = string_list_find_elem(ptr, setting->value.target.string) - 1; /* Add "Default" */ if (i == -1) { bool add = false; if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DONT_CARE), "", MENU_ENUM_LABEL_MICROPHONE_DEVICE_LIST, MENU_SETTING_DROPDOWN_ITEM_MICROPHONE_DEVICE, 0, i, NULL)) add = true; if (add) { /* Add checkmark if input is currently * mapped to this entry */ if (mic_device_index == i) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info_list->list[menu_index].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = menu_index; } count++; menu_index++; } } for (i = 0; i < (int)ptr->size; i++) { bool add = false; /* Add menu entry */ if (menu_entries_append(info_list, ptr->elems[i].data, ptr->elems[i].data, MENU_ENUM_LABEL_MICROPHONE_DEVICE_LIST, MENU_SETTING_DROPDOWN_ITEM_MICROPHONE_DEVICE, 0, i, NULL)) add = true; if (add) { /* Add checkmark if input is currently * mapped to this entry */ if (mic_device_index == i) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info_list->list[menu_index].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = menu_index; } count++; menu_index++; } } return count; } #endif static int menu_displaylist_parse_input_device_type_list( file_list_t *info_list, const char *info_path, settings_t *settings) { const struct retro_controller_description *desc = NULL; const char *name = NULL; const char *val_none = NULL; const char *val_retropad = NULL; const char *val_retropad_an = NULL; const char *val_unknown = NULL; rarch_system_info_t *sys_info= &runloop_state_get_ptr()->system; enum msg_hash_enums enum_idx = (enum msg_hash_enums)atoi(info_path); rarch_setting_t *setting = menu_setting_find_enum(enum_idx); size_t menu_index = 0; unsigned count = 0; unsigned i = 0; unsigned types = 0; unsigned port = 0; unsigned current_device = 0; unsigned devices[128] = {0}; char device_id[10]; device_id[0] = '\0'; if (!sys_info || !settings || !setting) return 0; port = setting->index_offset; if (port >= MAX_USERS) return 0; types = libretro_device_get_size(devices, ARRAY_SIZE(devices), port); current_device = input_config_get_device(port); val_none = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NONE); val_retropad = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RETROPAD); val_retropad_an= msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RETROPAD_WITH_ANALOG); val_unknown = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UNKNOWN); for (i = 0; i < types; i++) { snprintf(device_id, sizeof(device_id), "%d", devices[i]); desc = NULL; name = NULL; if (sys_info && port < sys_info->ports.size) desc = libretro_find_controller_description( &sys_info->ports.data[port], devices[i]); if (desc) name = desc->desc; if (!name) { /* Find generic name. */ switch (devices[i]) { case RETRO_DEVICE_NONE: name = val_none; break; case RETRO_DEVICE_JOYPAD: name = val_retropad; break; case RETRO_DEVICE_ANALOG: name = val_retropad_an; break; default: name = val_unknown; break; } } /* Add menu entry */ if (menu_entries_append(info_list, name, device_id, MENU_ENUM_LABEL_INPUT_BIND_DEVICE_TYPE, MENU_SETTING_DROPDOWN_ITEM_INPUT_DEVICE_TYPE, 0, i, NULL)) { /* Add checkmark if input is currently * mapped to this entry */ if (current_device == devices[i]) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info_list->list[menu_index].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = menu_index; } count++; menu_index++; } } return count; } static int menu_displaylist_parse_input_select_reserved_device_list( file_list_t *info_list, const char *info_path, settings_t *settings) { char device_label[256]; const char *val_disabled = NULL; enum msg_hash_enums enum_idx = (enum msg_hash_enums)atoi(info_path); struct menu_state *menu_st = menu_state_get_ptr(); rarch_setting_t *setting = menu_setting_find_enum(enum_idx); size_t menu_index = 0; unsigned count = 0; int i = 0; char reserved_device_name[sizeof(settings->arrays.input_reserved_devices[0])]; bool device_added = false; device_label[0] = '\0'; if (!settings || !setting) return 0; val_disabled = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NONE); if (string_is_empty(settings->arrays.input_reserved_devices[enum_idx - MENU_ENUM_LABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME])) strlcpy(reserved_device_name, val_disabled, sizeof(reserved_device_name)); else strlcpy(reserved_device_name, settings->arrays.input_reserved_devices[enum_idx - MENU_ENUM_LABEL_INPUT_DEVICE_RESERVED_DEVICE_NAME], sizeof(reserved_device_name)); /* List elements: none/disabled, all existing reservations, all existing devices */ for (i = MAX_INPUT_DEVICES+MAX_USERS; i >= 0; --i) { device_label[0] = '\0'; if (i == MAX_INPUT_DEVICES + MAX_USERS) strlcpy(device_label, val_disabled, sizeof(device_label)); else if (i < MAX_INPUT_DEVICES) { const char *device_name = input_config_get_device_display_name(i) ? input_config_get_device_display_name(i) : input_config_get_device_name(i); if (!string_is_empty(device_name)) { unsigned idx = input_config_get_device_name_index(i); size_t _len = strlcpy(device_label, device_name, sizeof(device_label)); /* If idx is non-zero, it's part of a set*/ if (idx > 0) snprintf(device_label + _len, sizeof(device_label) - _len, " (#%u)", idx); } } else { if (!string_is_empty(settings->arrays.input_reserved_devices[i-MAX_INPUT_DEVICES])) { unsigned int vendor_id; unsigned int product_id; if (sscanf(settings->arrays.input_reserved_devices[i-MAX_INPUT_DEVICES], "%04x:%04x ", &vendor_id, &product_id) != 2) strlcpy(device_label, settings->arrays.input_reserved_devices[i-MAX_INPUT_DEVICES], sizeof(reserved_device_name)); else /* If the vendor_id:product_id is encoded in the name, ignore them. */ strlcpy(device_label, &settings->arrays.input_reserved_devices[i-MAX_INPUT_DEVICES][10], sizeof(reserved_device_name)); } } if (!string_is_empty(device_label)) { size_t previous_position; if (file_list_search(info_list, device_label, &previous_position)) continue; /* Add menu entry */ if (menu_entries_append(info_list, device_label, device_label, MSG_UNKNOWN, MENU_SETTING_DROPDOWN_ITEM_INPUT_SELECT_RESERVED_DEVICE, 0, menu_index, NULL)) { /* Add checkmark if input is currently * mapped to this entry */ if (string_is_equal(device_label, reserved_device_name)) { menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info_list->list[menu_index].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = menu_index; device_added = true; } count++; menu_index++; } } } /* if nothing is configured, select None by default */ if (!device_added) { menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info_list->list[0].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = 0; } return count; } #ifdef ANDROID static int menu_displaylist_parse_input_select_physical_keyboard_list( file_list_t *info_list, const char *info_path, settings_t *settings) { char device_label[128]; const char *val_disabled = NULL; enum msg_hash_enums enum_idx = (enum msg_hash_enums)atoi(info_path); struct menu_state *menu_st = menu_state_get_ptr(); rarch_setting_t *setting = menu_setting_find_enum(enum_idx); size_t menu_index = 0; unsigned count = 0; int i = 0; char keyboard[sizeof(settings->arrays.input_android_physical_keyboard)]; /* TODO/FIXME - C99 VLA */ bool keyboard_added = false; input_driver_state_t *st = input_state_get_ptr(); input_driver_t *current_input = st->current_driver; bool is_android_driver = string_is_equal(current_input->ident, "android"); device_label[0] = '\0'; if (!settings || !setting || !is_android_driver) return 0; val_disabled = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NONE); if (string_is_empty(settings->arrays.input_android_physical_keyboard)) strlcpy(keyboard, val_disabled, sizeof(keyboard)); else { unsigned int vendor_id; unsigned int product_id; if (sscanf(settings->arrays.input_android_physical_keyboard, "%04x:%04x ", &vendor_id, &product_id) != 2) strlcpy(keyboard, settings->arrays.input_android_physical_keyboard, sizeof(keyboard)); else /* If the vendor_id:product_id is encoded in the name, ignore them. */ strlcpy(keyboard, &settings->arrays.input_android_physical_keyboard[10], sizeof(keyboard)); } for (i = MAX_INPUT_DEVICES; i >= -1; --i) { device_label[0] = '\0'; if (i < 0) strlcpy(device_label, keyboard, sizeof(device_label)); else if (i == MAX_INPUT_DEVICES) strlcpy(device_label, val_disabled, sizeof(device_label)); else if (i < MAX_INPUT_DEVICES) { /* * Skip devices that do not look like keyboards */ if (!android_input_can_be_keyboard(st->current_data, i)) continue; const char *device_name = input_config_get_device_display_name(i) ? input_config_get_device_display_name(i) : input_config_get_device_name(i); if (!string_is_empty(device_name)) { unsigned idx = input_config_get_device_name_index(i); size_t _len = strlcpy(device_label, device_name, sizeof(device_label)); /* If idx is non-zero, it's part of a set*/ if (idx > 0) snprintf(device_label + _len, sizeof(device_label) - _len, " (#%u)", idx); } } if (!string_is_empty(device_label)) { size_t previous_position; if (file_list_search(info_list, device_label, &previous_position)) continue; /* Add menu entry */ if (menu_entries_append(info_list, device_label, device_label, MSG_UNKNOWN, MENU_SETTING_DROPDOWN_ITEM_INPUT_SELECT_PHYSICAL_KEYBOARD, 0, menu_index, NULL)) { /* Add checkmark if input is currently * mapped to this entry */ if (string_is_equal(device_label, keyboard)) { menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info_list->list[menu_index].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = menu_index; keyboard_added = true; } count++; menu_index++; } } } /* if nothing is configured, select None by default */ if (!keyboard_added) { menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info_list->list[0].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = 0; } return count; } #endif static int menu_displaylist_parse_input_description_list( menu_displaylist_info_t *info, settings_t *settings) { unsigned count = 0; rarch_system_info_t *sys_info = &runloop_state_get_ptr()->system; size_t menu_index = 0; bool current_input_mapped = false; unsigned user_idx; unsigned btn_idx; unsigned current_remap_idx; unsigned mapped_port; size_t i, j; char entry_label[21]; entry_label[0] = '\0'; if (!settings) return 0; /* Determine user/button indices */ user_idx = (info->type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (RARCH_FIRST_CUSTOM_BIND + 8); btn_idx = (info->type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (RARCH_FIRST_CUSTOM_BIND + 8) * user_idx; if ( (user_idx >= MAX_USERS) || (btn_idx >= RARCH_CUSTOM_BIND_LIST_END)) return 0; mapped_port = settings->uints.input_remap_ports[user_idx]; if (mapped_port >= MAX_USERS) return 0; /* Get current mapping for selected button */ current_remap_idx = settings->uints.input_remap_ids[user_idx][btn_idx]; if (current_remap_idx >= RARCH_CUSTOM_BIND_LIST_END) current_remap_idx = RARCH_UNMAPPED; /* An annoyance: Menu entries do not have * enough parameters to pass on all the information * required to interpret a remap selection without * adding workarounds... * We need to record the current user/button indices, * and so have to convert 'info->type' to a string * and pass it as the entry label... */ snprintf(entry_label, sizeof(entry_label), "%u", info->type); /* Loop over core input definitions */ for (j = 0; j < RARCH_CUSTOM_BIND_LIST_END; j++) { const char *input_desc_btn; i = (j < RARCH_ANALOG_BIND_LIST_END) ? input_config_bind_order[j] : j; input_desc_btn = sys_info->input_desc_btn[mapped_port][i]; /* Check whether an input is defined for * this button */ if (!string_is_empty(input_desc_btn)) { char input_description[256]; /* > Up to RARCH_FIRST_CUSTOM_BIND, inputs * are buttons - description can be used * directly * > Above RARCH_FIRST_CUSTOM_BIND, inputs * are analog axes - have to add +/- * indicators */ size_t _len = strlcpy(input_description, input_desc_btn, sizeof(input_description)); if (i >= RARCH_FIRST_CUSTOM_BIND) { input_description [ _len] = ' '; if ((i % 2) == 0) input_description[++_len] = '+'; else input_description[++_len] = '-'; input_description [++_len] = '\0'; } if (string_is_empty(input_description)) continue; /* Add menu entry */ if (menu_entries_append(info->list, input_description, entry_label, MENU_ENUM_LABEL_INPUT_DESCRIPTION, MENU_SETTING_DROPDOWN_ITEM_INPUT_DESCRIPTION, 0, i, NULL)) { /* Add checkmark if input is currently * mapped to this entry */ if (current_remap_idx == i) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[menu_index].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = menu_index; current_input_mapped = true; } count++; menu_index++; } } } /* Add 'unmapped' entry at end of list */ if (menu_entries_append(info->list, "---", entry_label, MENU_ENUM_LABEL_INPUT_DESCRIPTION, MENU_SETTING_DROPDOWN_ITEM_INPUT_DESCRIPTION, 0, RARCH_UNMAPPED, NULL)) { /* Add checkmark if input is currently unmapped */ if (!current_input_mapped) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[menu_index].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = menu_index; } count++; menu_index++; } return count; } #ifdef HAVE_NETWORKING static unsigned menu_displaylist_parse_netplay_mitm_server_list( file_list_t *info_list, settings_t *settings) { size_t i; unsigned count = 0; const char *netplay_mitm_server = settings->arrays.netplay_mitm_server; for (i = 0; i < ARRAY_SIZE(netplay_mitm_server_list); i++) { const mitm_server_t *server = &netplay_mitm_server_list[i]; if (menu_entries_append(info_list, msg_hash_to_str(server->description), server->name, MENU_ENUM_LABEL_NETPLAY_MITM_SERVER_LOCATION, MENU_SETTING_DROPDOWN_ITEM_NETPLAY_MITM_SERVER, 0, i, NULL)) { if (string_is_equal(server->name, netplay_mitm_server)) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info_list->list[count].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = count; } count++; } } return count; } #endif static int menu_displaylist_parse_input_description_kbd_list( file_list_t *info_list, unsigned info_type, settings_t *settings) { size_t i; unsigned user_idx; unsigned btn_idx; unsigned current_key_id; char entry_label[21]; unsigned count = 0; size_t menu_index = 0; entry_label[0] = '\0'; if (!settings) return 0; /* Determine user/button indices */ user_idx = (info_type - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN) / RARCH_ANALOG_BIND_LIST_END; btn_idx = (info_type - MENU_SETTINGS_INPUT_DESC_KBD_BEGIN) - RARCH_ANALOG_BIND_LIST_END * user_idx; if ( (user_idx >= MAX_USERS) || (btn_idx >= RARCH_CUSTOM_BIND_LIST_END)) return 0; /* Get current mapping for selected button */ current_key_id = settings->uints.input_keymapper_ids[user_idx][btn_idx]; if (current_key_id >= (RARCH_MAX_KEYS + MENU_SETTINGS_INPUT_DESC_KBD_BEGIN)) current_key_id = RETROK_FIRST; /* An annoyance: Menu entries do not have * enough parameters to pass on all the information * required to interpret a remap selection without * adding workarounds... * We need to record the current user/button indices, * and so have to convert 'info_type' to a string * and pass it as the entry label... */ snprintf(entry_label, sizeof(entry_label), "%u", info_type); /* Loop over keyboard keys */ for (i = 0; i < RARCH_MAX_KEYS; i++) { char input_description[256]; unsigned key_id = key_descriptors[i].key; const char *key_label = key_descriptors[i].desc; if (string_is_empty(key_label)) continue; if (key_id == RETROK_FIRST) { input_description[0] = '-'; input_description[1] = '-'; input_description[2] = '-'; input_description[3] = '\0'; } else { /* TODO/FIXME: Localize 'Keyboard' */ size_t _len = strlcpy(input_description, "Keyboard ", sizeof(input_description)); strlcpy(input_description + _len, key_label, sizeof(input_description) - _len); } /* Add menu entry */ if (menu_entries_append(info_list, input_description, entry_label, MENU_ENUM_LABEL_INPUT_DESCRIPTION_KBD, MENU_SETTING_DROPDOWN_ITEM_INPUT_DESCRIPTION_KBD, 0, key_id, NULL)) { /* Add checkmark if input is currently * mapped to this entry */ if (current_key_id == key_id) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info_list->list[menu_index].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = menu_index; } count++; menu_index++; } } return count; } static int menu_displaylist_parse_playlist_generic( menu_handle_t *menu, menu_displaylist_info_t *info, settings_t *settings, const char *playlist_name, size_t playlist_name_size, const char *playlist_path, bool is_collection, bool sort_enabled, int *ret) { unsigned count = 0; playlist_t *playlist = NULL; menu_displaylist_set_new_playlist(menu, settings, playlist_path, sort_enabled); if ((playlist = playlist_get_cached())) { if ((count = menu_displaylist_parse_playlist(info->list, info->path, playlist, settings, playlist_name, playlist_name_size, is_collection)) == 0) info->flags |= MD_FLAG_NEED_PUSH_NO_PLAYLIST_ENTRIES; *ret = 0; } return count; } #ifdef HAVE_BLUETOOTH static void bluetooth_scan_callback(retro_task_t *task, void *task_data, void *user_data, const char *error) { unsigned i; struct string_list *device_list = NULL; const char *msg_connect_bluetooth = msg_hash_to_str(MENU_ENUM_LABEL_CONNECT_BLUETOOTH); const char *path = NULL; const char *label = NULL; unsigned menu_type = 0; struct menu_state *menu_st = menu_state_get_ptr(); menu_list_t *menu_list = menu_st->entries.list; file_list_t *selection_buf = menu_list ? MENU_LIST_GET_SELECTION(menu_list, 0) : NULL; menu_entries_get_last_stack(&path, &label, &menu_type, NULL, NULL); /* Don't push the results if we left the bluetooth menu */ if (!string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_BLUETOOTH_SETTINGS_LIST))) return; menu_entries_clear(selection_buf); device_list = string_list_new(); driver_bluetooth_get_devices(device_list); for (i = 0; i < device_list->size; i++) { const char *device = device_list->elems[i].data; menu_entries_append(selection_buf, device, msg_connect_bluetooth, MENU_ENUM_LABEL_CONNECT_BLUETOOTH, MENU_BLUETOOTH, 0, 0, NULL); } string_list_free(device_list); } #endif #if defined(HAVE_NETWORKING) && defined(HAVE_WIFI) static void wifi_scan_callback(retro_task_t *task, void *task_data, void *user_data, const char *error) { struct menu_state *menu_st = menu_state_get_ptr(); menu_st->flags |= MENU_ST_FLAG_PREVENT_POPULATE | MENU_ST_FLAG_ENTRIES_NEED_REFRESH; } #endif /** * Before a refresh, we could have deleted a * file on disk, causing selection_ptr to * suddendly be out of range. * * Ensure it doesn't overflow. **/ static bool menu_displaylist_refresh(struct menu_state *menu_st, file_list_t *list) { size_t list_size = 0; if (list->size) menu_entries_build_scroll_indices(menu_st, list); if (menu_st->entries.list) list_size = MENU_LIST_GET_SELECTION(menu_st->entries.list, 0)->size; if (list_size) { size_t selection = menu_st->selection_ptr; if (selection >= list_size) { size_t idx = list_size - 1; menu_st->selection_ptr = idx; if (menu_st->driver_ctx->navigation_set) menu_st->driver_ctx->navigation_set(menu_st->userdata, true); } } else { bool pending_push = true; menu_driver_ctl(MENU_NAVIGATION_CTL_CLEAR, &pending_push); } return true; } bool menu_displaylist_process(menu_displaylist_info_t *info) { #ifdef HAVE_NETWORKING settings_t *settings = config_get_ptr(); #endif struct menu_state *menu_st = menu_state_get_ptr(); uint32_t info_flags = info->flags; file_list_t *info_list = info->list; if (info_flags & MD_FLAG_NEED_NAVIGATION_CLEAR) { bool pending_push = true; menu_driver_ctl(MENU_NAVIGATION_CTL_CLEAR, &pending_push); } if (info_flags & MD_FLAG_NEED_ENTRIES_REFRESH) menu_st->flags |= MENU_ST_FLAG_ENTRIES_NEED_REFRESH; if (info_flags & MD_FLAG_NEED_SORT) file_list_sort_on_alt(info_list); #ifdef HAVE_NETWORKING if ( settings->bools.menu_show_core_updater && !settings->bools.kiosk_mode_enable) { if (info_flags & MD_FLAG_DOWNLOAD_CORE) { #ifdef HAVE_UPDATE_CORES menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE), msg_hash_to_str(MENU_ENUM_LABEL_CORE_UPDATER_LIST), MENU_ENUM_LABEL_CORE_UPDATER_LIST, MENU_SETTING_ACTION, 0, 0, NULL); #endif #ifndef IOS menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SIDELOAD_CORE_LIST), msg_hash_to_str(MENU_ENUM_LABEL_SIDELOAD_CORE_LIST), MENU_ENUM_LABEL_SIDELOAD_CORE_LIST, MENU_SETTING_ACTION, 0, 0, NULL); #endif } } #endif if (info_flags & MD_FLAG_PUSH_BUILTIN_CORES) { #if defined(HAVE_VIDEOPROCESSOR) menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_START_VIDEO_PROCESSOR), msg_hash_to_str(MENU_ENUM_LABEL_START_VIDEO_PROCESSOR), MENU_ENUM_LABEL_START_VIDEO_PROCESSOR, MENU_SETTING_ACTION, 0, 0, NULL); #endif #if defined(HAVE_NETWORKING) && defined(HAVE_NETWORKGAMEPAD) menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_START_NET_RETROPAD), msg_hash_to_str(MENU_ENUM_LABEL_START_NET_RETROPAD), MENU_ENUM_LABEL_START_NET_RETROPAD, MENU_SETTING_ACTION, 0, 0, NULL); #endif } if (info_flags & MD_FLAG_NEED_REFRESH) menu_displaylist_refresh(menu_st, info_list); if (info_flags & MD_FLAG_NEED_CLEAR) menu_st->selection_ptr = 0; if (info_flags & MD_FLAG_NEED_PUSH) { if (info_flags & MD_FLAG_NEED_PUSH_NO_PLAYLIST_ENTRIES) menu_entries_append(info_list, msg_hash_to_str( MENU_ENUM_LABEL_VALUE_NO_PLAYLIST_ENTRIES_AVAILABLE), msg_hash_to_str( MENU_ENUM_LABEL_NO_PLAYLIST_ENTRIES_AVAILABLE), MENU_ENUM_LABEL_NO_PLAYLIST_ENTRIES_AVAILABLE, MENU_INFO_MESSAGE, 0, 0, NULL); if (menu_st->driver_ctx && menu_st->driver_ctx->populate_entries) menu_st->driver_ctx->populate_entries( menu_st->userdata, info->path, info->label, info->type); } return true; } void menu_displaylist_info_free(menu_displaylist_info_t *info) { if (!info) return; if (info->exts) free(info->exts); if (info->path_b) free(info->path_b); if (info->path_c) free(info->path_c); if (info->label) free(info->label); if (info->path) free(info->path); info->exts = NULL; info->path_b = NULL; info->path_c = NULL; info->label = NULL; info->path = NULL; } void menu_displaylist_info_init(menu_displaylist_info_t *info) { if (!info) return; info->enum_idx = MSG_UNKNOWN; info->type = 0; info->type_default = 0; info->flags = 0; info->directory_ptr = 0; info->label = NULL; info->path = NULL; info->path_b = NULL; info->path_c = NULL; info->exts = NULL; info->list = NULL; info->setting = NULL; } typedef struct menu_displaylist_build_info { enum msg_hash_enums enum_idx; enum menu_displaylist_parse_type parse_type; } menu_displaylist_build_info_t; typedef struct menu_displaylist_build_info_selective { enum msg_hash_enums enum_idx; enum menu_displaylist_parse_type parse_type; bool checked; } menu_displaylist_build_info_selective_t; static unsigned populate_playlist_thumbnail_mode_dropdown_list( file_list_t *list, enum playlist_thumbnail_id thumbnail_id) { unsigned count = 0; playlist_t *playlist = playlist_get_cached(); if (list && playlist) { size_t i; /* Get currently selected thumbnail mode */ enum playlist_thumbnail_mode current_thumbnail_mode = playlist_get_thumbnail_mode(playlist, thumbnail_id); /* Get appropriate menu_settings_type (right/left) */ enum menu_settings_type settings_type = (thumbnail_id == PLAYLIST_THUMBNAIL_RIGHT) ? MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_RIGHT_THUMBNAIL_MODE : MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_LEFT_THUMBNAIL_MODE; /* Loop over all thumbnail modes */ for (i = 0; i <= (unsigned)PLAYLIST_THUMBNAIL_MODE_BOXARTS; i++) { enum msg_hash_enums label_value; enum playlist_thumbnail_mode thumbnail_mode = (enum playlist_thumbnail_mode)i; /* Get appropriate entry label */ switch (thumbnail_mode) { case PLAYLIST_THUMBNAIL_MODE_OFF: label_value = MENU_ENUM_LABEL_VALUE_OFF; break; case PLAYLIST_THUMBNAIL_MODE_SCREENSHOTS: label_value = MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_SCREENSHOTS; break; case PLAYLIST_THUMBNAIL_MODE_TITLE_SCREENS: label_value = MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_TITLE_SCREENS; break; case PLAYLIST_THUMBNAIL_MODE_BOXARTS: label_value = MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_BOXARTS; break; default: /* PLAYLIST_THUMBNAIL_MODE_DEFAULT */ label_value = MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_THUMBNAIL_MODE_DEFAULT; break; } /* Add entry */ if (menu_entries_append(list, msg_hash_to_str(label_value), "", MENU_ENUM_LABEL_NO_ITEMS, settings_type, 0, 0, NULL)) count++; /* Add checkmark if item is currently selected */ if (current_thumbnail_mode == thumbnail_mode) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)list->list[i].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = i; } } } return count; } static unsigned menu_displaylist_parse_manual_content_scan_list( file_list_t *info_list) { unsigned count = 0; /* Content directory */ if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_DIR), msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DIR), MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DIR, MENU_SETTING_MANUAL_CONTENT_SCAN_DIR, 0, 0, NULL)) count++; /* System name */ if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_SYSTEM_NAME), msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME), MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME, MENU_SETTING_MANUAL_CONTENT_SCAN_SYSTEM_NAME, 0, 0, NULL)) count++; /* Custom system name */ if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info_list, MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SYSTEM_NAME_CUSTOM, PARSE_ONLY_STRING, false) == 0) count++; /* Core name */ if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_CORE_NAME), msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME), MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_CORE_NAME, MENU_SETTING_MANUAL_CONTENT_SCAN_CORE_NAME, 0, 0, NULL)) count++; /* File extensions */ if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info_list, MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_FILE_EXTS, PARSE_ONLY_STRING, false) == 0) count++; /* Search recursively */ if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info_list, MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SEARCH_RECURSIVELY, PARSE_ONLY_BOOL, false) == 0) count++; /* Search inside archive files */ if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info_list, MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_SEARCH_ARCHIVES, PARSE_ONLY_BOOL, false) == 0) count++; /* Arcade DAT file */ if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info_list, MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DAT_FILE, PARSE_ONLY_PATH, false) == 0) count++; /* Arcade DAT filter */ if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info_list, MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_DAT_FILE_FILTER, PARSE_ONLY_BOOL, false) == 0) count++; /* Overwrite playlist */ if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info_list, MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_OVERWRITE, PARSE_ONLY_BOOL, false) == 0) count++; /* Validate existing entries */ if (!(*manual_content_scan_get_overwrite_playlist_ptr()) && MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info_list, MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_VALIDATE_ENTRIES, PARSE_ONLY_BOOL, false) == 0) count++; /* Start scan */ if (menu_entries_append(info_list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_START), msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_START), MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_START, MENU_SETTING_ACTION_MANUAL_CONTENT_SCAN_START, 0, 0, NULL)) count++; return count; } #ifdef HAVE_CDROM static int menu_displaylist_parse_disc_info(file_list_t *info_list, unsigned type) { unsigned i; unsigned count = 0; struct string_list *list = cdrom_get_available_drives(); const char *msg_drive_number = msg_hash_to_str(MSG_DRIVE_NUMBER); for (i = 0; list && i < list->size; i++) { char drive[2]; char drive_string[256] = {0}; size_t pos = snprintf(drive_string, sizeof(drive_string), msg_drive_number, i + 1); pos += snprintf(drive_string + pos, sizeof(drive_string) - pos, ": %s", list->elems[i].data); drive[0] = list->elems[i].attr.i; drive[1] = '\0'; if (menu_entries_append(info_list, drive_string, drive, MSG_UNKNOWN, type, 0, i, NULL)) count++; } if (list) string_list_free(list); return count; } #endif static unsigned menu_displaylist_populate_subsystem( const struct retro_subsystem_info* subsystem, settings_t *settings, file_list_t *list) { char star_char[16]; unsigned count = 0; const char *menu_driver = menu_driver_ident(); bool menu_show_sublabels = settings->bools.menu_show_sublabels; /* Note: Create this string here explicitly (rather than * using a #define elsewhere) since we need to be aware of * its length... */ #if defined(__APPLE__) /* UTF-8 support is currently broken on Apple devices... */ static const char utf8_star_char[] = "*"; #else /* * UCN equivalent: "\u2605" */ static const char utf8_star_char[] = "\xE2\x98\x85"; #endif int i = 0; bool is_rgui = string_is_equal(menu_driver, "rgui"); /* Select appropriate 'star' marker for subsystem menu entries * (i.e. RGUI does not support unicode, so use a 'standard' * character fallback) */ if (is_rgui) { star_char[0] = '*'; star_char[1] = '\0'; } else strlcpy(star_char, utf8_star_char, sizeof(star_char)); if (menu_displaylist_has_subsystems()) { runloop_state_t *runloop_st = runloop_state_get_ptr(); for (i = 0; i < (int)runloop_st->subsystem_current_count; i++, subsystem++) { char s[PATH_MAX_LENGTH]; if (content_get_subsystem() == i) { if (content_get_subsystem_rom_id() < subsystem->num_roms) { /* TODO/FIXME - Localize string */ size_t _len = strlcpy(s, "Load", sizeof(s)); s[ _len] = ' '; s[++_len] = '\0'; _len += strlcpy(s + _len, subsystem->desc, sizeof(s) - _len); s[ _len] = ' '; s[++_len] = '\0'; _len += strlcpy(s + _len, star_char, sizeof(s) - _len); #ifdef HAVE_RGUI /* If using RGUI with sublabels disabled, add the * appropriate text to the menu entry itself... */ if (is_rgui && !menu_show_sublabels) { _len += strlcpy(s + _len, " [", sizeof(s) - _len); /* TODO/FIXME - Localize */ _len += strlcpy(s + _len, "Current Content:", sizeof(s) - _len); s[ _len] = ' '; s[++_len] = '\0'; _len += strlcpy(s + _len, subsystem->roms[content_get_subsystem_rom_id()].desc, sizeof(s) - _len); s[ _len] = ']'; s[++_len] = '\0'; } #endif if (menu_entries_append(list, s, msg_hash_to_str(MENU_ENUM_LABEL_SUBSYSTEM_ADD), MENU_ENUM_LABEL_SUBSYSTEM_ADD, MENU_SETTINGS_SUBSYSTEM_ADD + i, 0, 0, NULL)) count++; } else { /* TODO/FIXME - Localize string */ size_t _len = strlcpy(s, "Start", sizeof(s)); s[ _len] = ' '; s[++_len] = '\0'; _len += strlcpy(s + _len, subsystem->desc, sizeof(s) - _len); s[ _len] = ' '; s[++_len] = '\0'; _len += strlcpy(s + _len, star_char, sizeof(s) - _len); /* If using RGUI with sublabels disabled, add the * appropriate text to the menu entry itself... */ if (is_rgui && !menu_show_sublabels) { size_t _len2 = 0; unsigned j = 0; char rom_buff[PATH_MAX_LENGTH]; for (j = 0; j < content_get_subsystem_rom_id(); j++) { _len2 += strlcpy(rom_buff + _len2, path_basename(content_get_subsystem_rom(j)), sizeof(rom_buff) - _len2); if (j != content_get_subsystem_rom_id() - 1) _len2 += strlcpy(rom_buff + _len2, "|", sizeof(rom_buff) - _len2); } if (!string_is_empty(rom_buff)) { _len += strlcpy(s + _len, " [", sizeof(s) - _len); _len += strlcpy(s + _len, rom_buff, sizeof(s) - _len); strlcpy(s + _len, "]", sizeof(s) - _len); } } if (menu_entries_append(list, s, msg_hash_to_str(MENU_ENUM_LABEL_SUBSYSTEM_LOAD), MENU_ENUM_LABEL_SUBSYSTEM_LOAD, MENU_SETTINGS_SUBSYSTEM_LOAD, 0, 0, NULL)) count++; } } else { /* TODO/FIXME - Localize */ size_t _len = strlcpy(s, "Load", sizeof(s)); s[ _len] = ' '; s[++_len] = '\0'; _len += strlcpy(s + _len, subsystem->desc, sizeof(s) - _len); /* If using RGUI with sublabels disabled, add the * appropriate text to the menu entry itself... */ if (is_rgui && !menu_show_sublabels) { /* This check is probably not required (it's not done * in menu_cbs_sublabel.c action_bind_sublabel_subsystem_add(), * anyway), but no harm in being safe... */ if (subsystem->num_roms > 0) { _len += strlcpy(s + _len, " [", sizeof(s) - _len); /* TODO/FIXME - Localize */ _len += strlcpy(s + _len, "Current Content:", sizeof(s) - _len); _len += strlcpy(s + _len, " ", sizeof(s) - _len); _len += strlcpy(s + _len, subsystem->roms[0].desc, sizeof(s) - _len); strlcpy(s + _len, "]", sizeof(s) - _len); } } if (menu_entries_append(list, s, msg_hash_to_str(MENU_ENUM_LABEL_SUBSYSTEM_ADD), MENU_ENUM_LABEL_SUBSYSTEM_ADD, MENU_SETTINGS_SUBSYSTEM_ADD + i, 0, 0, NULL)) count++; } } } return count; } #ifdef HAVE_NETWORKING static unsigned menu_displaylist_netplay_refresh_rooms(file_list_t *list) { int i, j; char buf[256]; char passworded[64]; char country[8]; const char *room_type; const char *cnc_netplay_room = NULL; const char *msg_int_nc = NULL; const char *msg_int_relay = NULL; const char *msg_int = NULL; const char *msg_local = NULL; const char *msg_room_pwd = NULL; unsigned count = 0; core_info_list_t *coreinfos = NULL; settings_t *settings = config_get_ptr(); net_driver_state_t *net_st = networking_state_get_ptr(); bool show_only_connectable = settings->bools.netplay_show_only_connectable; bool show_only_installed_cores = settings->bools.netplay_show_only_installed_cores; bool show_passworded = settings->bools.netplay_show_passworded; menu_entries_clear(list); if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETWORK_HOSTING_SETTINGS), msg_hash_to_str(MENU_ENUM_LABEL_NETWORK_HOSTING_SETTINGS), MENU_ENUM_LABEL_NETWORK_HOSTING_SETTINGS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if ( netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL) && !netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_SERVER, NULL) && netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_CONNECTED, NULL)) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_DISCONNECT), msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_DISCONNECT), MENU_ENUM_LABEL_NETPLAY_DISCONNECT, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_ENABLE_CLIENT), msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_ENABLE_CLIENT), MENU_ENUM_LABEL_NETPLAY_ENABLE_CLIENT, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETWORK_SETTINGS), msg_hash_to_str(MENU_ENUM_LABEL_NETWORK_SETTINGS), MENU_ENUM_LABEL_NETWORK_SETTINGS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_LOBBY_FILTERS), msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_LOBBY_FILTERS), MENU_ENUM_LABEL_NETPLAY_LOBBY_FILTERS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_REFRESH_ROOMS), msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_REFRESH_ROOMS), MENU_ENUM_LABEL_NETPLAY_REFRESH_ROOMS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #ifdef HAVE_NETPLAYDISCOVERY if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_REFRESH_LAN), msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_REFRESH_LAN), MENU_ENUM_LABEL_NETPLAY_REFRESH_LAN, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif core_info_get_list(&coreinfos); msg_int_nc = msg_hash_to_str(MSG_INTERNET_NOT_CONNECTABLE); msg_int_relay = msg_hash_to_str(MSG_INTERNET_RELAY); msg_int = msg_hash_to_str(MSG_INTERNET); msg_local = msg_hash_to_str(MSG_LOCAL); msg_room_pwd = msg_hash_to_str(MSG_ROOM_PASSWORDED); cnc_netplay_room = msg_hash_to_str(MENU_ENUM_LABEL_CONNECT_NETPLAY_ROOM); for (i = 0; i < net_st->room_count; i++) { size_t _len; struct netplay_room *room = &net_st->room_list[i]; /* Get rid of any room that is not running RetroArch. */ if (!room->is_retroarch) continue; /* Get rid of rooms running older (incompatible) versions. */ if (!netplay_compatible_version(room->retroarch_version)) continue; /* Get rid of any room that is not connectable, if the user opt-in. */ if (!room->connectable) { if (show_only_connectable) continue; room_type = msg_int_nc; } else if (room->lan) room_type = msg_local; else if (room->host_method == NETPLAY_HOST_METHOD_MITM) room_type = msg_int_relay; else room_type = msg_int; /* Get rid of any room running a core that we don't have installed, if the user opt-in. */ if (show_only_installed_cores) { for (j = 0; j < (int)coreinfos->count; j++) { if (string_is_equal_case_insensitive(coreinfos->list[j].core_name, room->corename)) break; } if (j >= (int)coreinfos->count) continue; } /* Get rid of any room that is passworded, if the user opt-in. */ if (room->has_password || room->has_spectate_password) { if (!show_passworded) continue; _len = strlcpy(passworded, "[", sizeof(passworded)); _len += strlcpy(passworded + _len, msg_room_pwd, sizeof(passworded) - _len); strlcpy(passworded + _len, "] ", sizeof(passworded) - _len); } else *passworded = '\0'; _len = strlcpy(buf, passworded, sizeof(buf)); _len += strlcpy(buf + _len, room_type, sizeof(buf) - _len); _len += strlcpy(buf + _len, ": ", sizeof(buf) - _len); _len += strlcpy(buf + _len, room->nickname, sizeof(buf) - _len); if (!room->lan && !string_is_empty(room->country)) { size_t _len2 = strlcpy(country, " (", sizeof(country)); _len2 += strlcpy(country + _len2, room->country, sizeof(country) - _len2); strlcpy(country + _len2, ")", sizeof(country) - _len2); strlcpy(buf + _len, country, sizeof(buf) - _len); } else *country = '\0'; if (menu_entries_append(list, buf, cnc_netplay_room, MENU_ENUM_LABEL_CONNECT_NETPLAY_ROOM, (unsigned)MENU_SETTINGS_NETPLAY_ROOMS_START + i, 0, 0, NULL)) count++; } return count; } #endif unsigned menu_displaylist_build_list( file_list_t *list, settings_t *settings, enum menu_displaylist_ctl_state type, bool include_everything) { unsigned i; unsigned count = 0; uint32_t flags = runloop_get_flags(); switch (type) { case DISPLAYLIST_OPTIONS_OVERRIDES: { char config_directory[PATH_MAX_LENGTH]; char content_dir_name[PATH_MAX_LENGTH]; char override_path[PATH_MAX_LENGTH]; runloop_state_t *runloop_st = runloop_state_get_ptr(); rarch_system_info_t *sys_info = &runloop_st->system; const char *rarch_path_basename = path_get(RARCH_PATH_BASENAME); const char *core_name = sys_info ? sys_info->info.library_name : NULL; bool has_content = !string_is_empty(path_get(RARCH_PATH_CONTENT)); bool core_override_remove = false; bool content_dir_override_remove = false; bool game_override_remove = false; config_directory[0] = '\0'; content_dir_name[0] = '\0'; override_path[0] = '\0'; fill_pathname_application_special(config_directory, sizeof(config_directory), APPLICATION_SPECIAL_DIRECTORY_CONFIG); if (has_content) { /* Game-specific path */ fill_pathname_join_special_ext(override_path, config_directory, core_name, path_basename_nocompression(rarch_path_basename), FILE_PATH_CONFIG_EXTENSION, sizeof(override_path)); game_override_remove = path_is_valid(override_path); override_path[0] = '\0'; /* Contentdir-specific path */ fill_pathname_parent_dir_name(content_dir_name, rarch_path_basename, sizeof(content_dir_name)); fill_pathname_join_special_ext(override_path, config_directory, core_name, content_dir_name, FILE_PATH_CONFIG_EXTENSION, sizeof(override_path)); content_dir_override_remove = path_is_valid(override_path); override_path[0] = '\0'; } { /* Core-specific path */ fill_pathname_join_special_ext(override_path, config_directory, core_name, core_name, FILE_PATH_CONFIG_EXTENSION, sizeof(override_path)); core_override_remove = path_is_valid(override_path); override_path[0] = '\0'; } /* Show currently 'active' override file */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OVERRIDE_FILE_INFO), msg_hash_to_str(MENU_ENUM_LABEL_OVERRIDE_FILE_INFO), MENU_ENUM_LABEL_OVERRIDE_FILE_INFO, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; /* Load override file */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OVERRIDE_FILE_LOAD), msg_hash_to_str(MENU_ENUM_LABEL_OVERRIDE_FILE_LOAD), MENU_ENUM_LABEL_OVERRIDE_FILE_LOAD, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (!settings->bools.kiosk_mode_enable) { /* Save as */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OVERRIDE_FILE_SAVE_AS), msg_hash_to_str(MENU_ENUM_LABEL_OVERRIDE_FILE_SAVE_AS), MENU_ENUM_LABEL_OVERRIDE_FILE_SAVE_AS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; /* Save/Remove game/content_dir/core */ if (has_content) { if (settings->bools.quick_menu_show_save_game_overrides) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SAVE_CURRENT_CONFIG_OVERRIDE_GAME), msg_hash_to_str(MENU_ENUM_LABEL_SAVE_CURRENT_CONFIG_OVERRIDE_GAME), MENU_ENUM_LABEL_SAVE_CURRENT_CONFIG_OVERRIDE_GAME, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (game_override_remove) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMOVE_CURRENT_CONFIG_OVERRIDE_GAME), msg_hash_to_str(MENU_ENUM_LABEL_REMOVE_CURRENT_CONFIG_OVERRIDE_GAME), MENU_ENUM_LABEL_REMOVE_CURRENT_CONFIG_OVERRIDE_GAME, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } } if (settings->bools.quick_menu_show_save_content_dir_overrides) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SAVE_CURRENT_CONFIG_OVERRIDE_CONTENT_DIR), msg_hash_to_str(MENU_ENUM_LABEL_SAVE_CURRENT_CONFIG_OVERRIDE_CONTENT_DIR), MENU_ENUM_LABEL_SAVE_CURRENT_CONFIG_OVERRIDE_CONTENT_DIR, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (content_dir_override_remove) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMOVE_CURRENT_CONFIG_OVERRIDE_CONTENT_DIR), msg_hash_to_str(MENU_ENUM_LABEL_REMOVE_CURRENT_CONFIG_OVERRIDE_CONTENT_DIR), MENU_ENUM_LABEL_REMOVE_CURRENT_CONFIG_OVERRIDE_CONTENT_DIR, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } } } if (settings->bools.quick_menu_show_save_core_overrides) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SAVE_CURRENT_CONFIG_OVERRIDE_CORE), msg_hash_to_str(MENU_ENUM_LABEL_SAVE_CURRENT_CONFIG_OVERRIDE_CORE), MENU_ENUM_LABEL_SAVE_CURRENT_CONFIG_OVERRIDE_CORE, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (core_override_remove) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMOVE_CURRENT_CONFIG_OVERRIDE_CORE), msg_hash_to_str(MENU_ENUM_LABEL_REMOVE_CURRENT_CONFIG_OVERRIDE_CORE), MENU_ENUM_LABEL_REMOVE_CURRENT_CONFIG_OVERRIDE_CORE, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } } } /* Unload overrides */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OVERRIDE_UNLOAD), msg_hash_to_str(MENU_ENUM_LABEL_OVERRIDE_UNLOAD), MENU_ENUM_LABEL_OVERRIDE_UNLOAD, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } break; case DISPLAYLIST_SUBSYSTEM_SETTINGS_LIST: { runloop_state_t *runloop_st = runloop_state_get_ptr(); const struct retro_subsystem_info* subsystem = runloop_st->subsystem_data; rarch_system_info_t *sys_info = &runloop_st->system; /* Core not loaded completely, use the data we * peeked on load core */ /* Core fully loaded, use the subsystem data */ if (sys_info && sys_info->subsystem.data) subsystem = sys_info->subsystem.data; count = menu_displaylist_populate_subsystem(subsystem, settings, list); } break; case DISPLAYLIST_PLAYLIST_SETTINGS_LIST: if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_LIST), msg_hash_to_str(MENU_ENUM_LABEL_PLAYLIST_MANAGER_LIST), MENU_ENUM_LABEL_PLAYLIST_MANAGER_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; { bool playlist_show_sublabels = settings->bools.playlist_show_sublabels; bool history_list_enable = settings->bools.history_list_enable; bool truncate_playlist = settings->bools.ozone_truncate_playlist_name; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_HISTORY_LIST_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CONTENT_HISTORY_SIZE, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_CONTENT_FAVORITES_SIZE, PARSE_ONLY_INT, true}, {MENU_ENUM_LABEL_PLAYLIST_ENTRY_RENAME, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_PLAYLIST_ENTRY_REMOVE, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_PLAYLIST_SORT_ALPHABETICAL, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_PLAYLIST_USE_OLD_FORMAT, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_PLAYLIST_COMPRESSION, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_PLAYLIST_SHOW_INLINE_CORE_NAME, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_PLAYLIST_SHOW_HISTORY_ICONS, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_PLAYLIST_SHOW_ENTRY_IDX, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_PLAYLIST_SHOW_SUBLABELS, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_PLAYLIST_SUBLABEL_LAST_PLAYED_STYLE, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_PLAYLIST_FUZZY_ARCHIVE_MATCH, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SCAN_WITHOUT_CORE_MATCH, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SCAN_SERIAL_AND_CRC, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_OZONE_TRUNCATE_PLAYLIST_NAME, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_OZONE_SORT_AFTER_TRUNCATE_PLAYLIST_NAME, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG_AGGREGATE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_PLAYLIST_PORTABLE_PATHS, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_PLAYLIST_USE_FILENAME, PARSE_ONLY_BOOL, true}, #ifdef HAVE_NETWORKING {MENU_ENUM_LABEL_NETWORK_ON_DEMAND_THUMBNAILS, PARSE_ONLY_BOOL, true}, #endif }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE: case MENU_ENUM_LABEL_PLAYLIST_SUBLABEL_LAST_PLAYED_STYLE: if (playlist_show_sublabels) build_list[i].checked = true; break; case MENU_ENUM_LABEL_CONTENT_HISTORY_SIZE: if (history_list_enable) build_list[i].checked = true; break; case MENU_ENUM_LABEL_OZONE_SORT_AFTER_TRUNCATE_PLAYLIST_NAME: if (truncate_playlist) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_INPUT_TURBO_FIRE_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_INPUT_TURBO_PERIOD, PARSE_ONLY_UINT}, {MENU_ENUM_LABEL_INPUT_DUTY_CYCLE, PARSE_ONLY_UINT}, {MENU_ENUM_LABEL_INPUT_TURBO_MODE, PARSE_ONLY_UINT}, {MENU_ENUM_LABEL_INPUT_TURBO_DEFAULT_BUTTON, PARSE_ONLY_UINT}, {MENU_ENUM_LABEL_INPUT_ALLOW_TURBO_DPAD, PARSE_ONLY_BOOL}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_INPUT_HAPTIC_FEEDBACK_SETTINGS_LIST: { input_driver_t *current_input = input_state_get_ptr()->current_driver; const frontend_ctx_driver_t *frontend = frontend_get_ptr(); char os_ver[64] = {0}; int major, minor; if (frontend && frontend->get_os) frontend->get_os(os_ver, sizeof(os_ver), &major, &minor); if (current_input->keypress_vibrate) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIBRATE_ON_KEYPRESS, PARSE_ONLY_BOOL, false) == 0) count++; if ( string_is_equal(current_input->ident, "android") || (string_is_equal(current_input->ident, "cocoa") && string_is_equal(os_ver, "iOS"))) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_ENABLE_DEVICE_VIBRATION, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_RUMBLE_GAIN, PARSE_ONLY_UINT, false) == 0) count++; } break; case DISPLAYLIST_INPUT_RETROPAD_BINDS_LIST: { unsigned user; unsigned max_users = settings->uints.input_max_users; for (user = 0; user < max_users; user++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, (enum msg_hash_enums)(MENU_ENUM_LABEL_INPUT_USER_1_BINDS + user), PARSE_ACTION, false) != -1) count++; } } break; case DISPLAYLIST_INPUT_HOTKEY_BINDS_LIST: { /* "Hotkey Enable" */ if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, (enum msg_hash_enums)( MENU_ENUM_LABEL_INPUT_HOTKEY_BIND_BEGIN + RARCH_FIRST_META_KEY), PARSE_ONLY_BIND, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_HOTKEY_BLOCK_DELAY, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_HOTKEY_DEVICE_MERGE, PARSE_ONLY_BOOL, false) == 0) count++; /* All other binds come last */ for (i = 0; i < RARCH_BIND_LIST_END; i++) { uint8_t key = input_config_bind_map_get_retro_key(i); /* Skip "Hotkey Enable" */ if (i == RARCH_FIRST_META_KEY) continue; /* Hidden items */ else if (key == RARCH_OVERLAY_NEXT) continue; /* Show combo entries before normal binds */ else if (key == RARCH_MENU_TOGGLE) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO, PARSE_ONLY_UINT, false) == 0) count++; } else if (key == RARCH_QUIT_KEY) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_QUIT_GAMEPAD_COMBO, PARSE_ONLY_UINT, false) == 0) count++; } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, (enum msg_hash_enums)( MENU_ENUM_LABEL_INPUT_HOTKEY_BIND_BEGIN + i), PARSE_ONLY_BIND, false) == 0) count++; } } break; case DISPLAYLIST_SHADER_PRESET_REMOVE: { #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) const char *dir_video_shader = settings->paths.directory_video_shader; const char *dir_menu_config = settings->paths.directory_menu_config; if (menu_shader_manager_auto_preset_exists(SHADER_PRESET_GLOBAL, dir_video_shader, dir_menu_config)) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_REMOVE_GLOBAL), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE_GLOBAL), MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE_GLOBAL, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_shader_manager_auto_preset_exists(SHADER_PRESET_CORE, dir_video_shader, dir_menu_config)) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_REMOVE_CORE), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE_CORE), MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE_CORE, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_shader_manager_auto_preset_exists(SHADER_PRESET_PARENT, dir_video_shader, dir_menu_config)) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_REMOVE_PARENT), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE_PARENT), MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE_PARENT, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_shader_manager_auto_preset_exists(SHADER_PRESET_GAME, dir_video_shader, dir_menu_config)) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_REMOVE_GAME), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE_GAME), MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE_GAME, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif } break; case DISPLAYLIST_SHADER_PRESET_SAVE: { #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) bool has_content = !string_is_empty(path_get(RARCH_PATH_CONTENT)); if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_REFERENCE, PARSE_ONLY_BOOL, false) == 0) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_AS), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_AS), MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_AS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_GLOBAL), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_GLOBAL), MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_GLOBAL, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_CORE), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_CORE), MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_CORE, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (has_content) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_PARENT), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_PARENT), MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_PARENT, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE_GAME), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_GAME), MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE_GAME, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } #endif } break; case DISPLAYLIST_NETPLAY_ROOM_LIST: #ifdef HAVE_NETWORKING count = menu_displaylist_netplay_refresh_rooms(list); #endif break; case DISPLAYLIST_CONTENT_SETTINGS: count = menu_displaylist_parse_load_content_settings(list, settings, false); if (count == 0) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ITEMS), msg_hash_to_str(MENU_ENUM_LABEL_NO_ITEMS), MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_NO_ITEM, 0, 0, NULL)) count++; break; case DISPLAYLIST_BROWSE_URL_START: #ifdef HAVE_NETWORKING { char link[1024]; char name[1024]; const char *line = "Test\n"; link[0] = name[0] = '\0'; string_parse_html_anchor(line, link, name, sizeof(link), sizeof(name)); if (menu_entries_append(list, link, name, MSG_UNKNOWN, 0, 0, 0, NULL)) count++; } #endif break; case DISPLAYLIST_AUDIO_MIXER_SETTINGS_LIST: { #ifdef HAVE_AUDIOMIXER char msg_lbl[128]; size_t _len = strlcpy(msg_lbl, "audio_mixer_stream_", sizeof(msg_lbl)); #if 1 /* TODO - for developers - * turn this into #if 0 if you want to be able to see * the system streams as well. */ for (i = 0; i < AUDIO_MIXER_MAX_STREAMS; i++) #else for (i = 0; i < AUDIO_MIXER_MAX_SYSTEM_STREAMS; i++) #endif { char msg[128]; snprintf(msg, sizeof(msg), msg_hash_to_str(MENU_ENUM_LABEL_MIXER_STREAM), i+1, "\n"); snprintf(msg_lbl + _len, sizeof(msg_lbl) - _len, "%d\n", i); if (menu_entries_append(list, msg, msg_lbl, MSG_UNKNOWN, (MENU_SETTINGS_AUDIO_MIXER_STREAM_BEGIN + i), 0, 0, NULL)) count++; } #endif } break; case DISPLAYLIST_BLUETOOTH_SETTINGS_LIST: #ifdef HAVE_BLUETOOTH { if (!string_is_equal(settings->arrays.bluetooth_driver, "null")) { struct string_list *device_list = string_list_new(); driver_bluetooth_get_devices(device_list); if (device_list->size == 0) task_push_bluetooth_scan(bluetooth_scan_callback); else { unsigned i; for (i = 0; i < device_list->size; i++) { const char *device = device_list->elems[i].data; if (menu_entries_append(list, device, msg_hash_to_str(MENU_ENUM_LABEL_CONNECT_BLUETOOTH), MENU_ENUM_LABEL_CONNECT_BLUETOOTH, MENU_BLUETOOTH, 0, 0, NULL)) count++; } } } } #endif break; case DISPLAYLIST_WIFI_SETTINGS_LIST: #if defined(HAVE_NETWORKING) && defined(HAVE_WIFI) { bool wifi_enabled = settings->bools.wifi_enabled; bool connected = driver_wifi_connection_info(NULL); menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_WIFI_ENABLED, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_WIFI_NETWORK_SCAN, PARSE_ACTION, false}, {MENU_ENUM_LABEL_WIFI_DISCONNECT, PARSE_ACTION, false}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_WIFI_NETWORK_SCAN: build_list[i].checked = wifi_enabled; break; case MENU_ENUM_LABEL_WIFI_DISCONNECT: build_list[i].checked = wifi_enabled && connected; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (build_list[i].checked && MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } #endif break; case DISPLAYLIST_WIFI_NETWORKS_LIST: #if defined(HAVE_NETWORKING) && defined(HAVE_WIFI) if (!string_is_equal(settings->arrays.wifi_driver, "null")) { wifi_network_scan_t *scan = driver_wifi_get_ssids(); /* Temporary hack: scan periodically, until we have a submenu */ if (!scan || time(NULL) > scan->scan_time + 30) task_push_wifi_scan(wifi_scan_callback); else { unsigned i; for (i = 0; i < RBUF_LEN(scan->net_list); i++) { const char *ssid = scan->net_list[i].ssid; if (menu_entries_append(list, string_is_empty(ssid) ? msg_hash_to_str(MSG_WIFI_EMPTY_SSID) : ssid, msg_hash_to_str(MENU_ENUM_LABEL_CONNECT_WIFI), MENU_ENUM_LABEL_CONNECT_WIFI, MENU_WIFI, 0, 0, NULL)) count++; } } } #endif break; case DISPLAYLIST_SYSTEM_INFO: count = menu_displaylist_parse_system_info(list); break; case DISPLAYLIST_EXPLORE: menu_entries_clear(list); #if defined(HAVE_LIBRETRODB) count = menu_displaylist_explore(list, settings); #endif break; case DISPLAYLIST_SCAN_DIRECTORY_LIST: #ifdef HAVE_LIBRETRODB if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCAN_DIRECTORY), msg_hash_to_str(MENU_ENUM_LABEL_SCAN_DIRECTORY), MENU_ENUM_LABEL_SCAN_DIRECTORY, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCAN_FILE), msg_hash_to_str(MENU_ENUM_LABEL_SCAN_FILE), MENU_ENUM_LABEL_SCAN_FILE, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_LIST), msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST), MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; break; case DISPLAYLIST_INFORMATION_LIST: count = menu_displaylist_parse_information_list(list); break; case DISPLAYLIST_HELP_SCREEN_LIST: if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_HELP_CONTROLS), msg_hash_to_str(MENU_ENUM_LABEL_HELP_CONTROLS), MENU_ENUM_LABEL_HELP_CONTROLS, 0, 0, 0, NULL)) count++; break; case DISPLAYLIST_AUDIO_OUTPUT_SETTINGS_LIST: { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_AUDIO_ENABLE, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_AUDIO_DRIVER, PARSE_ONLY_STRING_OPTIONS, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_AUDIO_DEVICE, PARSE_ONLY_STRING, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_AUDIO_OUTPUT_RATE, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_AUDIO_LATENCY, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_AUDIO_RESAMPLER_DRIVER, PARSE_ONLY_STRING_OPTIONS, false) == 0) count++; if (string_is_not_equal(settings->arrays.audio_resampler, "null")) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_AUDIO_RESAMPLER_QUALITY, PARSE_ONLY_UINT, false) == 0) count++; } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_AUDIO_BLOCK_FRAMES, PARSE_ONLY_UINT, false) == 0) count++; #ifdef HAVE_WASAPI if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_AUDIO_WASAPI_EXCLUSIVE_MODE, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_AUDIO_WASAPI_FLOAT_FORMAT, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_AUDIO_WASAPI_SH_BUFFER_LENGTH, PARSE_ONLY_UINT, false) == 0) count++; #endif } break; #ifdef HAVE_MICROPHONE case DISPLAYLIST_MICROPHONE_SETTINGS_LIST: if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_MICROPHONE_ENABLE, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_MICROPHONE_DRIVER, PARSE_ONLY_STRING_OPTIONS, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_MICROPHONE_DEVICE, PARSE_ONLY_STRING, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_MICROPHONE_INPUT_RATE, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_MICROPHONE_LATENCY, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_MICROPHONE_RESAMPLER_DRIVER, PARSE_ONLY_STRING_OPTIONS, false) == 0) count++; if (string_is_not_equal(settings->arrays.microphone_resampler, "null")) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_MICROPHONE_RESAMPLER_QUALITY, PARSE_ONLY_UINT, false) == 0) count++; } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_MICROPHONE_BLOCK_FRAMES, PARSE_ONLY_UINT, false) == 0) count++; #ifdef HAVE_WASAPI if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_MICROPHONE_WASAPI_EXCLUSIVE_MODE, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_MICROPHONE_WASAPI_FLOAT_FORMAT, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_MICROPHONE_WASAPI_SH_BUFFER_LENGTH, PARSE_ONLY_UINT, false) == 0) count++; #endif break; #endif case DISPLAYLIST_AUDIO_SYNCHRONIZATION_SETTINGS_LIST: { menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_AUDIO_SYNC, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_AUDIO_MAX_TIMING_SKEW, PARSE_ONLY_FLOAT, true }, {MENU_ENUM_LABEL_AUDIO_RATE_CONTROL_DELTA, PARSE_ONLY_FLOAT, true }, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_AUDIO_SETTINGS_LIST: { bool audio_mute_enable = *audio_get_bool_ptr(AUDIO_ACTION_MUTE_ENABLE); #if defined(HAVE_AUDIOMIXER) bool audio_mixer_mute_enable = *audio_get_bool_ptr(AUDIO_ACTION_MIXER_MUTE_ENABLE); #else bool audio_mixer_mute_enable = true; #endif menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_AUDIO_OUTPUT_SETTINGS, PARSE_ACTION, true }, #ifdef HAVE_MICROPHONE {MENU_ENUM_LABEL_MICROPHONE_SETTINGS, PARSE_ACTION, true }, #endif {MENU_ENUM_LABEL_AUDIO_SYNCHRONIZATION_SETTINGS, PARSE_ACTION, true }, {MENU_ENUM_LABEL_MIDI_SETTINGS, PARSE_ACTION, true }, {MENU_ENUM_LABEL_AUDIO_MIXER_SETTINGS, PARSE_ACTION, false }, {MENU_ENUM_LABEL_MENU_SOUNDS, PARSE_ACTION, true }, {MENU_ENUM_LABEL_AUDIO_MUTE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_AUDIO_MIXER_MUTE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_AUDIO_RESPECT_SILENT_MODE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_AUDIO_FASTFORWARD_MUTE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_AUDIO_FASTFORWARD_SPEEDUP, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_AUDIO_VOLUME, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_AUDIO_MIXER_VOLUME, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_SYSTEM_BGM_ENABLE, PARSE_ONLY_BOOL, true }, #if defined(HAVE_DSP_FILTER) {MENU_ENUM_LABEL_AUDIO_DSP_PLUGIN, PARSE_ONLY_PATH, true }, #endif }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_AUDIO_VOLUME: if (!audio_mute_enable) build_list[i].checked = true; break; case MENU_ENUM_LABEL_AUDIO_MIXER_VOLUME: case MENU_ENUM_LABEL_AUDIO_MIXER_SETTINGS: if (!audio_mixer_mute_enable) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } #if defined(HAVE_DSP_FILTER) if (!string_is_empty(settings->paths.path_audio_dsp_plugin)) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_AUDIO_DSP_PLUGIN_REMOVE), msg_hash_to_str(MENU_ENUM_LABEL_AUDIO_DSP_PLUGIN_REMOVE), MENU_ENUM_LABEL_AUDIO_DSP_PLUGIN_REMOVE, MENU_SETTING_ACTION_AUDIO_DSP_PLUGIN_REMOVE, 0, 0, NULL)) count++; #endif break; case DISPLAYLIST_VIDEO_SETTINGS_LIST: { gfx_ctx_flags_t flags; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_OUTPUT_SETTINGS, PARSE_ACTION, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_SCALING_SETTINGS, PARSE_ACTION, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_SYNCHRONIZATION_SETTINGS, PARSE_ACTION, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_FULLSCREEN_MODE_SETTINGS, PARSE_ACTION, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_WINDOWED_MODE_SETTINGS, PARSE_ACTION, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_HDR_SETTINGS, PARSE_ACTION, false) == 0) count++; if (video_display_server_get_flags(&flags)) { if (BIT32_GET(flags.flags, DISPSERV_CTX_CRT_SWITCHRES)) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_CRT_SWITCHRES_SETTINGS, PARSE_ACTION, false) == 0) count++; } else if (video_context_driver_get_flags(&flags)) { if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_CRT_SWITCHRES)) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_CRT_SWITCHRES_SETTINGS, PARSE_ACTION, false) == 0) count++; } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_SUSPEND_SCREENSAVER_ENABLE, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_BRIGHTNESS_CONTROL, PARSE_ONLY_UINT, false) == 0) count++; #ifdef HAVE_SCREENSHOTS { video_driver_state_t *video_st = video_state_get_ptr(); if ( video_st->current_video->read_viewport && video_st->current_video->viewport_info) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_GPU_SCREENSHOT, PARSE_ONLY_BOOL, false) == 0) count++; } #endif if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_CTX_SCALING, PARSE_ONLY_BOOL, false) == 0) count++; #if defined(DINGUX) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_DINGUX_IPU_FILTER_TYPE, PARSE_ONLY_UINT, false) == 0) count++; #if defined(RS90) || defined(MIYOO) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_DINGUX_RS90_SOFTFILTER_TYPE, PARSE_ONLY_UINT, false) == 0) count++; #endif #endif if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_SHADER_DELAY, PARSE_ONLY_UINT, false) == 0) count++; #ifdef HAVE_VIDEO_FILTER if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_FILTER, PARSE_ONLY_PATH, false) == 0) count++; if (!string_is_empty(settings->paths.path_softfilter_plugin)) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_FILTER_REMOVE), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_FILTER_REMOVE), MENU_ENUM_LABEL_VIDEO_FILTER_REMOVE, MENU_SETTING_ACTION_VIDEO_FILTER_REMOVE, 0, 0, NULL)) count++; #endif if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_NOTCH_WRITE_OVER, PARSE_ONLY_BOOL, false) == 0) count++; } break; case DISPLAYLIST_OPTIONS_REMAPPINGS: { unsigned p; unsigned max_users = settings->uints.input_max_users; #ifdef HAVE_CONFIGFILE if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_REMAP_FILE_MANAGER_LIST), msg_hash_to_str(MENU_ENUM_LABEL_REMAP_FILE_MANAGER_LIST), MENU_ENUM_LABEL_REMAP_FILE_MANAGER_LIST, MENU_SETTING_ACTION_REMAP_FILE_MANAGER_LIST, 0, 0, NULL)) count++; #endif if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_TURBO_FIRE_SETTINGS), msg_hash_to_str(MENU_ENUM_LABEL_INPUT_TURBO_FIRE_SETTINGS), MENU_ENUM_LABEL_INPUT_TURBO_FIRE_SETTINGS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; for (p = 0; p < max_users; p++) { char val_s[256], val_d[16]; snprintf(val_s, sizeof(val_s), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_USER_BINDS), p+1); snprintf(val_d, sizeof(val_d), "%d", p); if (menu_entries_append(list, val_s, val_d, MSG_UNKNOWN, MENU_SETTINGS_REMAPPING_PORT_BEGIN + p, p, 0, NULL)) count++; } } break; case DISPLAYLIST_LOAD_CONTENT_LIST: case DISPLAYLIST_LOAD_CONTENT_SPECIAL: { const char *dir_menu_content = settings->paths.directory_menu_content; bool menu_content_show_favorites = settings->bools.menu_content_show_favorites; if (!string_is_empty(dir_menu_content)) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FAVORITES), msg_hash_to_str(MENU_ENUM_LABEL_FAVORITES), MENU_ENUM_LABEL_FAVORITES, MENU_SETTING_ACTION_FAVORITES_DIR, 0, 0, NULL)) count++; if (menu_content_show_favorites) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_FAVORITES), msg_hash_to_str(MENU_ENUM_LABEL_GOTO_FAVORITES), MENU_ENUM_LABEL_GOTO_FAVORITES, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (settings->bools.menu_content_show_images) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_IMAGES), msg_hash_to_str(MENU_ENUM_LABEL_GOTO_IMAGES), MENU_ENUM_LABEL_GOTO_IMAGES, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (settings->bools.menu_content_show_music) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_MUSIC), msg_hash_to_str(MENU_ENUM_LABEL_GOTO_MUSIC), MENU_ENUM_LABEL_GOTO_MUSIC, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #if defined(HAVE_FFMPEG) || defined(HAVE_MPV) if (settings->bools.menu_content_show_video) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_VIDEO), msg_hash_to_str(MENU_ENUM_LABEL_GOTO_VIDEO), MENU_ENUM_LABEL_GOTO_VIDEO, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif #if defined(HAVE_DYNAMIC) if (settings->uints.menu_content_show_contentless_cores != MENU_CONTENTLESS_CORES_DISPLAY_NONE) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_CONTENTLESS_CORES), msg_hash_to_str(MENU_ENUM_LABEL_GOTO_CONTENTLESS_CORES), MENU_ENUM_LABEL_GOTO_CONTENTLESS_CORES, MENU_CONTENTLESS_CORES_TAB, 0, 0, NULL)) count++; #endif #if defined(HAVE_LIBRETRODB) if (settings->bools.menu_content_show_explore) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_EXPLORE), msg_hash_to_str(MENU_ENUM_LABEL_GOTO_EXPLORE), MENU_ENUM_LABEL_GOTO_EXPLORE, MENU_EXPLORE_TAB, 0, 0, NULL)) count++; #endif } { core_info_list_t *info_list = NULL; core_info_get_list(&info_list); if (info_list && info_list->info_count > 0) { if (menu_entries_append(list, msg_hash_to_str( MENU_ENUM_LABEL_VALUE_DOWNLOADED_FILE_DETECT_CORE_LIST), msg_hash_to_str( MENU_ENUM_LABEL_DOWNLOADED_FILE_DETECT_CORE_LIST), MENU_ENUM_LABEL_DOWNLOADED_FILE_DETECT_CORE_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } } { bool menu_content_show_playlists = settings->bools.menu_content_show_playlists; if (menu_content_show_playlists) if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLISTS_TAB), msg_hash_to_str(MENU_ENUM_LABEL_PLAYLISTS_TAB), MENU_ENUM_LABEL_PLAYLISTS_TAB, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } if (frontend_driver_parse_drive_list(list, true) != 0) if (menu_entries_append(list, "/", msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #if 0 if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_BROWSE_URL_LIST), msg_hash_to_str(MENU_ENUM_LABEL_BROWSE_URL_LIST), MENU_ENUM_LABEL_BROWSE_URL_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif break; case DISPLAYLIST_INPUT_MENU_SETTINGS_LIST: { menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_INPUT_UNIFIED_MENU_CONTROLS, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_INPUT_SWAP_OK_CANCEL, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_INPUT_SWAP_SCROLL, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_ALL_USERS_CONTROL_MENU, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_SCROLL_FAST, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_SCROLL_DELAY, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_INPUT_DISABLE_INFO_BUTTON, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_DISABLE_SEARCH_BUTTON, PARSE_ONLY_BOOL, true }, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_INPUT_SETTINGS_LIST: { menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_INPUT_RETROPAD_BINDS, PARSE_ACTION, true }, {MENU_ENUM_LABEL_INPUT_TURBO_FIRE_SETTINGS, PARSE_ACTION, true }, {MENU_ENUM_LABEL_INPUT_HOTKEY_BINDS, PARSE_ACTION, true }, {MENU_ENUM_LABEL_INPUT_MENU_SETTINGS, PARSE_ACTION, true }, {MENU_ENUM_LABEL_INPUT_HAPTIC_FEEDBACK_SETTINGS, PARSE_ACTION, true }, {MENU_ENUM_LABEL_INPUT_MAX_USERS, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_INPUT_AUTODETECT_ENABLE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_REMAP_BINDS_ENABLE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_INPUT_ICADE_ENABLE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_SMALL_KEYBOARD_ENABLE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_KEYBOARD_GAMEPAD_MAPPING_TYPE, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_INPUT_DESCRIPTOR_LABEL_SHOW, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_DESCRIPTOR_HIDE_UNBOUND, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_BUTTON_AXIS_THRESHOLD, PARSE_ONLY_FLOAT, true }, {MENU_ENUM_LABEL_INPUT_ANALOG_DEADZONE, PARSE_ONLY_FLOAT, true }, {MENU_ENUM_LABEL_INPUT_ANALOG_SENSITIVITY, PARSE_ONLY_FLOAT, true }, #if defined(GEKKO) {MENU_ENUM_LABEL_INPUT_MOUSE_SCALE, PARSE_ONLY_UINT, true }, #endif {MENU_ENUM_LABEL_INPUT_TOUCH_ENABLE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_PREFER_FRONT_TOUCH, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_TOUCH_SCALE, PARSE_ONLY_UINT, true }, #ifdef UDEV_TOUCH_SUPPORT {MENU_ENUM_LABEL_INPUT_TOUCH_VMOUSE_POINTER, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_TOUCH_VMOUSE_MOUSE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_TOUCH_VMOUSE_TOUCHPAD, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_TOUCH_VMOUSE_TRACKBALL, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_TOUCH_VMOUSE_GESTURE, PARSE_ONLY_BOOL, true }, #endif {MENU_ENUM_LABEL_INPUT_BIND_TIMEOUT, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_INPUT_BIND_HOLD, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_QUIT_PRESS_TWICE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_PAUSE_ON_DISCONNECT, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_AUTO_MOUSE_GRAB, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_INPUT_AUTO_GAME_FOCUS, PARSE_ONLY_UINT, true }, #if defined(HAVE_DINPUT) || defined(HAVE_WINRAWINPUT) {MENU_ENUM_LABEL_INPUT_NOWINKEY_ENABLE, PARSE_ONLY_BOOL, true }, #endif #ifdef ANDROID {MENU_ENUM_LABEL_ANDROID_INPUT_DISCONNECT_WORKAROUND, PARSE_ONLY_BOOL, true }, #endif {MENU_ENUM_LABEL_INPUT_SENSORS_ENABLE, PARSE_ONLY_BOOL, true }, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } #ifdef ANDROID if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_SELECT_PHYSICAL_KEYBOARD, PARSE_ACTION, true) == 0) count++; #endif #ifdef HAVE_LIBNX { unsigned user; char key_split_joycon[PATH_MAX_LENGTH]; const char *split_joycon_str = msg_hash_to_str(MENU_ENUM_LABEL_INPUT_SPLIT_JOYCON); size_t _len = strlcpy(key_split_joycon, split_joycon_str, sizeof(key_split_joycon)); for (user = 0; user < 8; user++) { unsigned val = user + 1; snprintf(key_split_joycon + _len, sizeof(key_split_joycon) - _len, "_%u", val); if (MENU_DISPLAYLIST_PARSE_SETTINGS(list, key_split_joycon, PARSE_ONLY_UINT, true, 0) != -1) count++; } } #endif break; case DISPLAYLIST_ACCESSIBILITY_SETTINGS_LIST: { bool accessibility_enable = settings->bools.accessibility_enable; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_ACCESSIBILITY_ENABLED, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_ACCESSIBILITY_NARRATOR_SPEECH_SPEED, PARSE_ONLY_UINT, false }, {MENU_ENUM_LABEL_AI_SERVICE_SETTINGS, PARSE_ACTION, true }, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_ACCESSIBILITY_NARRATOR_SPEECH_SPEED: if (accessibility_enable) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_AI_SERVICE_SETTINGS_LIST: { bool ai_service_enable = settings->bools.ai_service_enable; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_AI_SERVICE_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_AI_SERVICE_MODE, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_AI_SERVICE_URL, PARSE_ONLY_STRING, false}, {MENU_ENUM_LABEL_AI_SERVICE_PAUSE, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_AI_SERVICE_SOURCE_LANG, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_AI_SERVICE_TARGET_LANG, PARSE_ONLY_UINT, false}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_AI_SERVICE_MODE: case MENU_ENUM_LABEL_AI_SERVICE_URL: case MENU_ENUM_LABEL_AI_SERVICE_PAUSE: case MENU_ENUM_LABEL_AI_SERVICE_SOURCE_LANG: case MENU_ENUM_LABEL_AI_SERVICE_TARGET_LANG: if (ai_service_enable) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_ADD_CONTENT_LIST: #ifdef HAVE_LIBRETRODB if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCAN_DIRECTORY), msg_hash_to_str(MENU_ENUM_LABEL_SCAN_DIRECTORY), MENU_ENUM_LABEL_SCAN_DIRECTORY, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCAN_FILE), msg_hash_to_str(MENU_ENUM_LABEL_SCAN_FILE), MENU_ENUM_LABEL_SCAN_FILE, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MANUAL_CONTENT_SCAN_LIST), msg_hash_to_str(MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST), MENU_ENUM_LABEL_MANUAL_CONTENT_SCAN_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; break; case DISPLAYLIST_NETWORK_INFO: #if defined(HAVE_NETWORKING) && defined(HAVE_IFINFO) { net_ifinfo_t interfaces = {0}; network_init(); if (net_ifinfo_new(&interfaces)) { size_t i; char buf[768]; const char *msg_intf = msg_hash_to_str(MSG_INTERFACE); size_t _len = strlcpy(buf, msg_intf, sizeof(buf)); for (i = 0; i < interfaces.size; i++) { struct net_ifinfo_entry *entry = &interfaces.entries[i]; snprintf(buf + _len, sizeof(buf) - _len, " (%s): %s\n", entry->name, entry->host); if (menu_entries_append(list, buf, entry->name, MENU_ENUM_LABEL_NETWORK_INFO_ENTRY, MENU_SETTINGS_CORE_INFO_NONE, 0, 0, NULL)) count++; } net_ifinfo_free(&interfaces); } } #endif break; case DISPLAYLIST_OPTIONS_CHEATS: #ifdef HAVE_CHEATS cheat_manager_alloc_if_empty(); { unsigned i; char cheat_label[128]; char on_string[32]; char off_string[32]; menu_search_terms_t *search_terms= menu_entries_search_get_terms(); bool search_active = search_terms && (search_terms->size > 0); unsigned num_cheats = cheat_manager_get_size(); unsigned num_cheats_shown = 0; size_t _len = 0; on_string[0] = '\0'; off_string[0] = '\0'; /* If a search is active, all options are * omitted apart from 'apply changes' */ if (search_active) { /* On/off key strings may be required, * so populate them... */ on_string [ _len] = '.'; on_string [++_len] = '\0'; strlcpy(on_string + _len, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON), sizeof(on_string) - _len); _len = 0; off_string[ _len] = '.'; off_string[++_len] = '\0'; strlcpy(off_string + _len, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF), sizeof(off_string) - _len); } else { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_START_OR_CONT), msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_START_OR_CONT), MENU_ENUM_LABEL_CHEAT_START_OR_CONT, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_CHEAT_APPLY_AFTER_LOAD, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_CHEAT_APPLY_AFTER_TOGGLE, PARSE_ONLY_BOOL, false) == 0) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_FILE_LOAD), msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_FILE_LOAD), MENU_ENUM_LABEL_CHEAT_FILE_LOAD, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_FILE_LOAD_APPEND), msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_FILE_LOAD_APPEND), MENU_ENUM_LABEL_CHEAT_FILE_LOAD_APPEND, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_RELOAD_CHEATS), msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_RELOAD_CHEATS), MENU_ENUM_LABEL_CHEAT_RELOAD_CHEATS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_FILE_SAVE_AS), msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_FILE_SAVE_AS), MENU_ENUM_LABEL_CHEAT_FILE_SAVE_AS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_ADD_NEW_TOP), msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_ADD_NEW_TOP), MENU_ENUM_LABEL_CHEAT_ADD_NEW_TOP, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_ADD_NEW_BOTTOM), msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_ADD_NEW_BOTTOM), MENU_ENUM_LABEL_CHEAT_ADD_NEW_BOTTOM, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_DELETE_ALL), msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_DELETE_ALL), MENU_ENUM_LABEL_CHEAT_DELETE_ALL, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_APPLY_CHANGES), msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_APPLY_CHANGES), MENU_ENUM_LABEL_CHEAT_APPLY_CHANGES, MENU_SETTING_ACTION, 0, 0, NULL)) count++; _len = strlcpy(cheat_label, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT), sizeof(cheat_label)); for (i = 0; i < num_cheats; i++) { const char *cheat_description = cheat_manager_get_desc(i); snprintf(cheat_label + _len, sizeof(cheat_label) - _len, " #%u: ", i); if (!string_is_empty(cheat_description)) strlcat(cheat_label, cheat_description, sizeof(cheat_label)); /* If a search is active, skip non-matching * entries */ if (search_active) { size_t j; bool entry_valid = true; for (j = 0; j < search_terms->size; j++) { const char *search_term = search_terms->terms[j]; if (!string_is_empty(search_term)) { bool cheat_on = cheat_manager_get_code_state(i); /* Check for 'on' keyword */ if (string_is_equal_noncase(search_term, on_string)) { if (!cheat_on) entry_valid = false; } /* Check for 'off' keyword */ else if (string_is_equal_noncase(search_term, off_string)) { if (cheat_on) entry_valid = false; } /* Normal label comparison */ else if (!strcasestr(cheat_label, search_term)) entry_valid = false; } if (!entry_valid) break; } if (!entry_valid) continue; } if (menu_entries_append(list, cheat_label, "", MSG_UNKNOWN, MENU_SETTINGS_CHEAT_BEGIN + i, 0, 0, NULL)) { num_cheats_shown++; count++; } } /* If a search is active and no results are * found, show a 'no entries available' item */ if ( search_active && (num_cheats_shown < 1) && menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL)) count++; } #endif break; case DISPLAYLIST_DROPDOWN_LIST_RESOLUTION: menu_entries_clear(list); { unsigned i, size = 0; struct video_display_config *video_list = (struct video_display_config*) video_display_server_get_resolution_list(&size); if (video_list) { for (i = 0; i < size; i++) { char val_d[256], str[256]; /* If there is exact refresh rate available, use it */ if (video_list[i].refreshrate_float > 0.0f) snprintf(str, sizeof(str), "%dx%d (%.3f Hz)%s%s", video_list[i].width, video_list[i].height, video_list[i].refreshrate_float, video_list[i].interlaced ? "[i]":"", video_list[i].dblscan ? "[d]":""); else snprintf(str, sizeof(str), "%dx%d (%d Hz)%s", video_list[i].width, video_list[i].height, video_list[i].refreshrate, video_list[i].interlaced ? "[i]":""); snprintf(val_d, sizeof(val_d), "%d", i); if (menu_entries_append(list, str, val_d, MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_DROPDOWN_ITEM_RESOLUTION, video_list[i].idx, 0, NULL)) count++; if (video_list[i].current) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)list->list[i].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = i; } } free(video_list); } } break; case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_DEFAULT_CORE: menu_entries_clear(list); { core_info_list_t *core_info_list = NULL; playlist_t *playlist = playlist_get_cached(); /* Get core list */ core_info_get_list(&core_info_list); if (core_info_list && playlist) { size_t i; struct menu_state *menu_st = menu_state_get_ptr(); const char *current_core_name = playlist_get_default_core_name(playlist); core_info_t *core_info = NULL; /* Sort cores alphabetically */ core_info_qsort(core_info_list, CORE_INFO_LIST_SORT_DISPLAY_NAME); /* Add N/A entry */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE), "", MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_DEFAULT_CORE, 0, 0, NULL)) count++; if ( string_is_empty(current_core_name) || string_is_equal(current_core_name, "DETECT")) { menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)list->list[0].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = 0; } /* Loop through cores */ for (i = 0; i < core_info_list->count; i++) { if ((core_info = core_info_get(core_info_list, i))) { if (menu_entries_append(list, core_info->display_name, "", MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_DEFAULT_CORE, i + 1, 0, NULL)) count++; if (string_is_equal(current_core_name, core_info->display_name)) { menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)list->list[i + 1].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = (i + 1); } } } } } break; case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LABEL_DISPLAY_MODE: menu_entries_clear(list); { playlist_t *playlist = playlist_get_cached(); if (playlist) { size_t i; enum playlist_label_display_mode current_display_mode = playlist_get_label_display_mode(playlist); for (i = 0; i <= (unsigned)LABEL_DISPLAY_MODE_KEEP_REGION_AND_DISC_INDEX; i++) { enum msg_hash_enums label_value; enum playlist_label_display_mode display_mode = (enum playlist_label_display_mode)i; switch (display_mode) { case LABEL_DISPLAY_MODE_REMOVE_PARENTHESES: label_value = MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE_REMOVE_PARENS; break; case LABEL_DISPLAY_MODE_REMOVE_BRACKETS: label_value = MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE_REMOVE_BRACKETS; break; case LABEL_DISPLAY_MODE_REMOVE_PARENTHESES_AND_BRACKETS: label_value = MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE_REMOVE_PARENS_AND_BRACKETS; break; case LABEL_DISPLAY_MODE_KEEP_REGION: label_value = MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE_KEEP_REGION; break; case LABEL_DISPLAY_MODE_KEEP_DISC_INDEX: label_value = MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE_KEEP_DISC_INDEX; break; case LABEL_DISPLAY_MODE_KEEP_REGION_AND_DISC_INDEX: label_value = MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE_KEEP_REGION_AND_DISC_INDEX; break; default: /* LABEL_DISPLAY_MODE_DEFAULT */ label_value = MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE_DEFAULT; break; } if (menu_entries_append(list, msg_hash_to_str(label_value), "", MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_LABEL_DISPLAY_MODE, 0, 0, NULL)) count++; if (current_display_mode == display_mode) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)list->list[i].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = i; } } } } break; case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE: menu_entries_clear(list); count = populate_playlist_thumbnail_mode_dropdown_list(list, PLAYLIST_THUMBNAIL_RIGHT); break; case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE: menu_entries_clear(list); count = populate_playlist_thumbnail_mode_dropdown_list(list, PLAYLIST_THUMBNAIL_LEFT); break; case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_SORT_MODE: menu_entries_clear(list); { playlist_t *playlist = playlist_get_cached(); if (playlist) { size_t i; /* Get current sort mode */ enum playlist_sort_mode current_sort_mode = playlist_get_sort_mode(playlist); /* Loop over all defined sort modes */ for (i = 0; i <= (unsigned)PLAYLIST_SORT_MODE_OFF; i++) { enum msg_hash_enums label_value; enum playlist_sort_mode sort_mode = (enum playlist_sort_mode)i; /* Get appropriate entry label */ switch (sort_mode) { case PLAYLIST_SORT_MODE_ALPHABETICAL: label_value = MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_SORT_MODE_ALPHABETICAL; break; case PLAYLIST_SORT_MODE_OFF: label_value = MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_SORT_MODE_OFF; break; case PLAYLIST_SORT_MODE_DEFAULT: default: label_value = MENU_ENUM_LABEL_VALUE_PLAYLIST_MANAGER_SORT_MODE_DEFAULT; break; } /* Add entry */ if (menu_entries_append(list, msg_hash_to_str(label_value), "", MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_SORT_MODE, 0, 0, NULL)) count++; /* Check whether current entry is checked */ if (current_sort_mode == sort_mode) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)list->list[i].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = i; } } } } break; case DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME: menu_entries_clear(list); /* Get system name list */ { bool show_hidden_files = settings->bools.show_hidden_files; #ifdef HAVE_LIBRETRODB const char *path_content_database = settings->paths.path_content_database; struct string_list *system_name_list = manual_content_scan_get_menu_system_name_list( path_content_database, show_hidden_files); #else struct string_list *system_name_list = manual_content_scan_get_menu_system_name_list(NULL, show_hidden_files); #endif if (system_name_list) { const char *current_system_name = NULL; unsigned i; /* Get currently selected system name */ manual_content_scan_get_menu_system_name(¤t_system_name); /* Loop through names */ for (i = 0; i < system_name_list->size; i++) { /* Note: manual_content_scan_get_system_name_list() * ensures that system_name cannot be empty here */ const char *system_name = system_name_list->elems[i].data; /* Add menu entry */ if (menu_entries_append(list, system_name, "", MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_DROPDOWN_ITEM_MANUAL_CONTENT_SCAN_SYSTEM_NAME, i, 0, NULL)) count++; /* Check whether current entry is checked */ if (string_is_equal(current_system_name, system_name)) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)list->list[i].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = i; } } /* Clean up */ string_list_free(system_name_list); } } break; case DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_CORE_NAME: menu_entries_clear(list); { /* Get core name list */ struct string_list *core_name_list = manual_content_scan_get_menu_core_name_list(); if (core_name_list) { const char *current_core_name = NULL; unsigned i; /* Get currently selected core name */ manual_content_scan_get_menu_core_name(¤t_core_name); /* Loop through names */ for (i = 0; i < core_name_list->size; i++) { /* Note: manual_content_scan_get_core_name_list() * ensures that core_name cannot be empty here */ const char *core_name = core_name_list->elems[i].data; /* Add menu entry */ if (menu_entries_append(list, core_name, "", MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_DROPDOWN_ITEM_MANUAL_CONTENT_SCAN_CORE_NAME, i, 0, NULL)) count++; /* Check whether current entry is checked */ if (string_is_equal(current_core_name, core_name)) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)list->list[i].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = i; } } /* Clean up */ string_list_free(core_name_list); } } break; case DISPLAYLIST_DROPDOWN_LIST_DISK_INDEX: menu_entries_clear(list); { rarch_system_info_t *sys_info = &runloop_state_get_ptr()->system; if (sys_info) { if (disk_control_enabled(&sys_info->disk_control)) { unsigned i; unsigned num_images = disk_control_get_num_images(&sys_info->disk_control); unsigned current_image = disk_control_get_image_index(&sys_info->disk_control); unsigned num_digits = 0; /* If core supports labels, index value string * should be padded to maximum width (otherwise * labels will be misaligned/ugly) */ if (disk_control_image_label_enabled(&sys_info->disk_control)) { unsigned digit_counter = num_images; do { num_digits++; digit_counter = digit_counter / 10; } while (digit_counter > 0); } /* Loop through disk images */ for (i = 0; i < num_images; i++) { size_t _len; char current_image_str[PATH_MAX_LENGTH]; char image_label[128]; current_image_str[0] = '\0'; image_label[0] = '\0'; /* Get image label, if supported by core */ disk_control_get_image_label( &sys_info->disk_control, i, image_label, sizeof(image_label)); _len = snprintf( current_image_str, sizeof(current_image_str), "%0*u", num_digits, i + 1); /* Get string representation of disk index * > Note that displayed index starts at '1', * not '0' */ if (!string_is_empty(image_label)) { /* Note: 2-space gap is intentional * (for clarity) */ _len += strlcpy(current_image_str + _len, ": ", sizeof(current_image_str) - _len); strlcpy(current_image_str + _len, image_label, sizeof(current_image_str) - _len); } /* Add menu entry */ if (menu_entries_append(list, current_image_str, "", MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_DROPDOWN_ITEM_DISK_INDEX, i, 0, NULL)) count++; /* Check whether current disk is selected */ if (i == current_image) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)list->list[i].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = i; } } } } } break; case DISPLAYLIST_PERFCOUNTERS_CORE: case DISPLAYLIST_PERFCOUNTERS_FRONTEND: { unsigned i; struct retro_perf_counter **counters = (type == DISPLAYLIST_PERFCOUNTERS_CORE) ? retro_get_perf_counter_libretro() : retro_get_perf_counter_rarch(); unsigned num = (type == DISPLAYLIST_PERFCOUNTERS_CORE) ? retro_get_perf_count_libretro() : retro_get_perf_count_rarch(); unsigned id = (type == DISPLAYLIST_PERFCOUNTERS_CORE) ? MENU_SETTINGS_LIBRETRO_PERF_COUNTERS_BEGIN : MENU_SETTINGS_PERF_COUNTERS_BEGIN; if (counters && num != 0) { for (i = 0; i < num; i++) if (counters[i] && counters[i]->ident) if (menu_entries_append(list, counters[i]->ident, "", (enum msg_hash_enums)(id + i), id + i , 0, 0, NULL)) count++; } } break; case DISPLAYLIST_NETWORK_SETTINGS_LIST: { unsigned user; bool netplay_allow_slaves = settings->bools.netplay_allow_slaves; bool netplay_use_mitm_server = settings->bools.netplay_use_mitm_server; bool network_cmd_enable = settings->bools.network_cmd_enable; bool network_remote_enable = settings->bools.network_remote_enable; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_NETPLAY_PUBLIC_ANNOUNCE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_USE_MITM_SERVER, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_MITM_SERVER, PARSE_ONLY_STRING, false}, {MENU_ENUM_LABEL_NETPLAY_CUSTOM_MITM_SERVER, PARSE_ONLY_STRING, false}, {MENU_ENUM_LABEL_NETPLAY_IP_ADDRESS, PARSE_ONLY_STRING, true}, {MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_NETPLAY_MAX_CONNECTIONS, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_NETPLAY_MAX_PING, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_NETPLAY_PASSWORD, PARSE_ONLY_STRING, true}, {MENU_ENUM_LABEL_NETPLAY_SPECTATE_PASSWORD, PARSE_ONLY_STRING, true}, {MENU_ENUM_LABEL_NETPLAY_START_AS_SPECTATOR, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_FADE_CHAT, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_CHAT_COLOR_NAME, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_NETPLAY_CHAT_COLOR_MSG, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_NETPLAY_ALLOW_PAUSING, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_ALLOW_SLAVES, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_REQUIRE_SLAVES, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_NETPLAY_CHECK_FRAMES, PARSE_ONLY_INT, true}, {MENU_ENUM_LABEL_NETPLAY_INPUT_LATENCY_FRAMES_MIN, PARSE_ONLY_INT, true}, {MENU_ENUM_LABEL_NETPLAY_INPUT_LATENCY_FRAMES_RANGE, PARSE_ONLY_INT, true}, {MENU_ENUM_LABEL_NETPLAY_NAT_TRAVERSAL, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_SHARE_DIGITAL, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_NETPLAY_SHARE_ANALOG, PARSE_ONLY_UINT, true}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_NETPLAY_REQUIRE_SLAVES: if (netplay_allow_slaves) build_list[i].checked = true; break; case MENU_ENUM_LABEL_NETPLAY_MITM_SERVER: case MENU_ENUM_LABEL_NETPLAY_CUSTOM_MITM_SERVER: if (netplay_use_mitm_server) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } for (user = 0; user < MAX_USERS; user++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, (enum msg_hash_enums) (MENU_ENUM_LABEL_NETPLAY_REQUEST_DEVICE_1 + user), PARSE_ONLY_BOOL, false) == 0) count++; } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_NETWORK_CMD_ENABLE, PARSE_ONLY_BOOL, false) == 0) count++; if (network_cmd_enable) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_NETWORK_CMD_PORT, PARSE_ONLY_UINT, false) == 0) count++; } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_NETWORK_REMOTE_ENABLE, PARSE_ONLY_BOOL, false) == 0) count++; if (network_remote_enable) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_NETWORK_REMOTE_PORT, PARSE_ONLY_UINT, false) == 0) count++; for (user = 0; user < settings->uints.input_max_users; user++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, (enum msg_hash_enums) (MENU_ENUM_LABEL_NETWORK_REMOTE_USER_1_ENABLE + user), PARSE_ONLY_BOOL, false) == 0) count++; } } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_STDIN_CMD_ENABLE, PARSE_ONLY_BOOL, false) == 0) count++; } break; case DISPLAYLIST_NETPLAY_LOBBY_FILTERS_LIST: { menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_NETPLAY_SHOW_ONLY_CONNECTABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_SHOW_ONLY_INSTALLED_CORES, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_SHOW_PASSWORDED, PARSE_ONLY_BOOL, true}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_CHEAT_SEARCH_SETTINGS_LIST: #ifdef HAVE_CHEATS { char cheat_label[64]; menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_CHEAT_START_OR_RESTART, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_BIG_ENDIAN, PARSE_ONLY_BOOL }, {MENU_ENUM_LABEL_CHEAT_SEARCH_EXACT, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_SEARCH_LT, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_SEARCH_LTE, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_SEARCH_GT, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_SEARCH_GTE, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_SEARCH_EQ, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_SEARCH_NEQ, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_SEARCH_EQPLUS, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_SEARCH_EQMINUS, PARSE_ONLY_UINT }, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } cheat_label[0] = '\0'; snprintf(cheat_label, sizeof(cheat_label), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_ADD_MATCHES), cheat_manager_state.num_matches); if (menu_entries_append(list, cheat_label, msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_ADD_MATCHES), MENU_ENUM_LABEL_CHEAT_ADD_MATCHES, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_CHEAT_DELETE_MATCH, PARSE_ONLY_UINT, false) != -1) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_CHEAT_COPY_MATCH, PARSE_ONLY_UINT, false) != -1) count++; { unsigned int address_mask = 0; unsigned int address = 0; unsigned int prev_val = 0; unsigned int curr_val = 0; cheat_label[0] = '\0'; cheat_manager_match_action(CHEAT_MATCH_ACTION_TYPE_VIEW, cheat_manager_state.match_idx, &address, &address_mask, &prev_val, &curr_val) ; snprintf(cheat_label, sizeof(cheat_label), msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_MATCH), address, address_mask); if (menu_entries_append(list, cheat_label, "", MSG_UNKNOWN, MENU_SETTINGS_CHEAT_MATCH, 0, 0, NULL)) count++; } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_CHEAT_BROWSE_MEMORY, PARSE_ONLY_UINT, false) != -1) count++; { rarch_setting_t *setting = menu_setting_find_enum(MENU_ENUM_LABEL_CHEAT_DELETE_MATCH); if (setting) setting->max = cheat_manager_state.num_matches-1; if ((setting = menu_setting_find_enum(MENU_ENUM_LABEL_CHEAT_COPY_MATCH))) setting->max = cheat_manager_state.num_matches-1; if ((setting = menu_setting_find_enum(MENU_ENUM_LABEL_CHEAT_BROWSE_MEMORY))) setting->max = cheat_manager_state.total_memory_size>0?cheat_manager_state.total_memory_size-1:0 ; } } #endif break; case DISPLAYLIST_CHEAT_DETAILS_SETTINGS_LIST: #ifdef HAVE_CHEATS { if (!cheat_manager_state.memory_initialized) cheat_manager_initialize_memory(NULL, 0, true); { rarch_setting_t *setting = menu_setting_find_enum(MENU_ENUM_LABEL_CHEAT_ADDRESS); if (setting ) setting->max = cheat_manager_state.total_memory_size==0?0:cheat_manager_state.total_memory_size-1; setting = menu_setting_find_enum(MENU_ENUM_LABEL_CHEAT_ADDRESS_BIT_POSITION); if (setting ) setting->max = (cheat_manager_state.working_cheat.memory_search_size < 3) ? 255 : 0 ; setting = menu_setting_find_enum(MENU_ENUM_LABEL_CHEAT_BROWSE_MEMORY); if (setting ) setting->max = cheat_manager_state.total_memory_size>0?cheat_manager_state.total_memory_size-1:0 ; } { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_CHEAT_IDX, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_STATE, PARSE_ONLY_BOOL }, {MENU_ENUM_LABEL_CHEAT_DESC, PARSE_ONLY_STRING}, {MENU_ENUM_LABEL_CHEAT_HANDLER, PARSE_ONLY_UINT }, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } if (cheat_manager_state.working_cheat.handler == CHEAT_HANDLER_TYPE_EMU) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_CHEAT_CODE, PARSE_ONLY_STRING, false) == 0) count++; } else { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_CHEAT_MEMORY_SEARCH_SIZE, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_TYPE, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_VALUE, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_ADDRESS, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_BROWSE_MEMORY, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_ADDRESS_BIT_POSITION, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_REPEAT_COUNT, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_REPEAT_ADD_TO_ADDRESS, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_REPEAT_ADD_TO_VALUE, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_RUMBLE_TYPE, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_RUMBLE_VALUE, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_RUMBLE_PORT, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_RUMBLE_PRIMARY_STRENGTH, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_RUMBLE_PRIMARY_DURATION, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_RUMBLE_SECONDARY_STRENGTH, PARSE_ONLY_UINT }, {MENU_ENUM_LABEL_CHEAT_RUMBLE_SECONDARY_DURATION, PARSE_ONLY_UINT }, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } /* Inspect Memory At this Address */ if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_ADD_NEW_AFTER), msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_ADD_NEW_AFTER), MENU_ENUM_LABEL_CHEAT_ADD_NEW_AFTER, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_ADD_NEW_BEFORE), msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_ADD_NEW_BEFORE), MENU_ENUM_LABEL_CHEAT_ADD_NEW_BEFORE, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_COPY_AFTER), msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_COPY_AFTER), MENU_ENUM_LABEL_CHEAT_COPY_AFTER, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_COPY_BEFORE), msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_COPY_BEFORE), MENU_ENUM_LABEL_CHEAT_COPY_BEFORE, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CHEAT_DELETE), msg_hash_to_str(MENU_ENUM_LABEL_CHEAT_DELETE), MENU_ENUM_LABEL_CHEAT_DELETE, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } #endif break; case DISPLAYLIST_RECORDING_SETTINGS_LIST: { unsigned streaming_mode = settings->uints.streaming_mode; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_VIDEO_RECORD_QUALITY, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_RECORD_CONFIG, PARSE_ONLY_PATH, true}, {MENU_ENUM_LABEL_VIDEO_RECORD_THREADS, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_VIDEO_POST_FILTER_RECORD, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_VIDEO_GPU_RECORD, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_STREAMING_MODE, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_VIDEO_STREAM_QUALITY, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_STREAM_CONFIG, PARSE_ONLY_PATH, true}, {MENU_ENUM_LABEL_STREAMING_TITLE, PARSE_ONLY_STRING, true}, {MENU_ENUM_LABEL_STREAMING_URL, PARSE_ONLY_STRING, true}, {MENU_ENUM_LABEL_UDP_STREAM_PORT, PARSE_ONLY_UINT, true}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_UDP_STREAM_PORT: if (streaming_mode == STREAMING_MODE_LOCAL) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (build_list[i].checked && MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_ACCOUNTS_YOUTUBE_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_YOUTUBE_STREAM_KEY, PARSE_ONLY_STRING}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_RETRO_ACHIEVEMENTS_SETTINGS_LIST: { bool cheevos_enable = settings->bools.cheevos_enable; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_CHEEVOS_ENABLE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_CHEEVOS_USERNAME, PARSE_ONLY_STRING, false }, {MENU_ENUM_LABEL_CHEEVOS_PASSWORD, PARSE_ONLY_STRING, false }, {MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_SETTINGS, PARSE_ACTION, false }, {MENU_ENUM_LABEL_CHEEVOS_VISIBILITY_SETTINGS, PARSE_ACTION, false }, {MENU_ENUM_LABEL_CHEEVOS_HARDCORE_MODE_ENABLE, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_CHEEVOS_LEADERBOARDS_ENABLE, PARSE_ONLY_STRING_OPTIONS, false }, {MENU_ENUM_LABEL_CHEEVOS_RICHPRESENCE_ENABLE, PARSE_ONLY_BOOL, false }, #ifndef HAVE_GFX_WIDGETS {MENU_ENUM_LABEL_CHEEVOS_BADGES_ENABLE, PARSE_ONLY_BOOL, false }, #endif {MENU_ENUM_LABEL_CHEEVOS_TEST_UNOFFICIAL, PARSE_ONLY_BOOL, false }, #ifdef HAVE_AUDIOMIXER {MENU_ENUM_LABEL_CHEEVOS_UNLOCK_SOUND_ENABLE, PARSE_ONLY_BOOL, false }, #endif #ifdef HAVE_SCREENSHOTS {MENU_ENUM_LABEL_CHEEVOS_AUTO_SCREENSHOT, PARSE_ONLY_BOOL, false }, #endif {MENU_ENUM_LABEL_CHEEVOS_START_ACTIVE, PARSE_ONLY_BOOL, false }, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (cheevos_enable) build_list[i].checked = true; } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_CHEEVOS_APPEARANCE_SETTINGS_LIST: { #if defined(HAVE_CHEEVOS) && defined(HAVE_GFX_WIDGETS) unsigned cheevos_anchor = settings->uints.cheevos_appearance_anchor; bool cheevos_autopad = settings->bools.cheevos_appearance_padding_auto; bool gfx_widgets = settings->bools.menu_enable_widgets; #endif menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_ANCHOR, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_AUTO, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_H, PARSE_ONLY_FLOAT, false}, {MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_V, PARSE_ONLY_FLOAT, false}, }; #if defined(HAVE_CHEEVOS) && defined(HAVE_GFX_WIDGETS) for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!gfx_widgets) build_list[i].checked = false; else if (!cheevos_autopad) { if (build_list[i].enum_idx == MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_V) build_list[i].checked = true; if (build_list[i].enum_idx == MENU_ENUM_LABEL_CHEEVOS_APPEARANCE_PADDING_H && !(cheevos_anchor == CHEEVOS_APPEARANCE_ANCHOR_TOPCENTER || cheevos_anchor == CHEEVOS_APPEARANCE_ANCHOR_BOTTOMCENTER)) build_list[i].checked = true; } } #endif for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_CHEEVOS_VISIBILITY_SETTINGS_LIST: { menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_CHEEVOS_VISIBILITY_SUMMARY, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_CHEEVOS_VISIBILITY_UNLOCK, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CHEEVOS_VISIBILITY_MASTERY, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CHEEVOS_CHALLENGE_INDICATORS, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CHEEVOS_VISIBILITY_PROGRESS_TRACKER, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CHEEVOS_VISIBILITY_LBOARD_START, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CHEEVOS_VISIBILITY_LBOARD_SUBMIT, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CHEEVOS_VISIBILITY_LBOARD_CANCEL, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CHEEVOS_VISIBILITY_LBOARD_TRACKERS, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CHEEVOS_VISIBILITY_ACCOUNT, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CHEEVOS_VERBOSE_ENABLE, PARSE_ONLY_BOOL, true}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_ACCOUNTS_TWITCH_LIST: if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_TWITCH_STREAM_KEY, PARSE_ONLY_STRING, false) == 0) count++; break; case DISPLAYLIST_ACCOUNTS_FACEBOOK_LIST: if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_FACEBOOK_STREAM_KEY, PARSE_ONLY_STRING, false) == 0) count++; break; case DISPLAYLIST_USER_INTERFACE_SETTINGS_LIST: { bool kiosk_mode_enable = settings->bools.kiosk_mode_enable; #if defined(HAVE_QT) || defined(HAVE_COCOA) bool desktop_menu_enable = settings->bools.desktop_menu_enable; #endif struct menu_state *menu_st = menu_state_get_ptr(); bool menu_screensaver_supported = ((menu_st->flags & MENU_ST_FLAG_SCREENSAVER_SUPPORTED) > 0); #if defined(HAVE_MATERIALUI) || defined(HAVE_XMB) || defined(HAVE_OZONE) enum menu_screensaver_effect menu_screensaver_animation = (enum menu_screensaver_effect) settings->uints.menu_screensaver_animation; #endif uico_driver_state_t *uico_st = uico_state_get_ptr(); menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_APPICON_SETTINGS, PARSE_ONLY_STRING_OPTIONS, false}, {MENU_ENUM_LABEL_MENU_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_MENU_VIEWS_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_ONSCREEN_NOTIFICATIONS_SETTINGS, PARSE_ACTION, true}, #if defined(HAVE_OVERLAY) {MENU_ENUM_LABEL_ONSCREEN_OVERLAY_SETTINGS, PARSE_ACTION, true}, #endif {MENU_ENUM_LABEL_MENU_FILE_BROWSER_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_PAUSE_LIBRETRO, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_PAUSE_NONACTIVE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_PAUSE_ON_DISCONNECT, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_QUIT_ON_CLOSE_CONTENT, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_SAVESTATE_RESUME, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_INSERT_DISK_RESUME, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NAVIGATION_WRAPAROUND, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_REMEMBER_SELECTION, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_SHOW_ADVANCED_SETTINGS, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_ENABLE_KIOSK_MODE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_KIOSK_MODE_PASSWORD, PARSE_ONLY_STRING, false}, {MENU_ENUM_LABEL_MOUSE_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_POINTER_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_THREADED_DATA_RUNLOOP_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_SCREENSAVER_TIMEOUT, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_MENU_SCREENSAVER_ANIMATION, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_MENU_SCREENSAVER_ANIMATION_SPEED, PARSE_ONLY_FLOAT, false}, #if !defined(OSX) {MENU_ENUM_LABEL_VIDEO_DISABLE_COMPOSITION, PARSE_ONLY_BOOL, true}, #endif #if defined(HAVE_QT) || defined(HAVE_COCOA) {MENU_ENUM_LABEL_UI_COMPANION_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_UI_COMPANION_START_ON_BOOT, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_UI_COMPANION_TOGGLE, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_DESKTOP_MENU_ENABLE, PARSE_ONLY_BOOL, true}, #endif #ifdef _3DS {MENU_ENUM_LABEL_VIDEO_3DS_DISPLAY_MODE, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_BOTTOM_SETTINGS, PARSE_ACTION, true}, #endif {MENU_ENUM_LABEL_USER_LANGUAGE, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_DRIVER, PARSE_ONLY_STRING_OPTIONS, true}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_APPICON_SETTINGS: if (uico_st->drv && uico_st->drv->get_app_icons) { struct string_list *icons = uico_st->drv->get_app_icons(); build_list[i].checked = icons && icons->size > 1; } break; case MENU_ENUM_LABEL_ONSCREEN_NOTIFICATIONS_SETTINGS: case MENU_ENUM_LABEL_ONSCREEN_OVERLAY_SETTINGS: build_list[i].checked = settings->bools.settings_show_onscreen_display; break; case MENU_ENUM_LABEL_MENU_FILE_BROWSER_SETTINGS: build_list[i].checked = settings->bools.settings_show_file_browser; break; case MENU_ENUM_LABEL_MENU_KIOSK_MODE_PASSWORD: if (kiosk_mode_enable) build_list[i].checked = true; break; case MENU_ENUM_LABEL_MENU_SCREENSAVER_TIMEOUT: if (menu_screensaver_supported) build_list[i].checked = true; break; #if defined(HAVE_MATERIALUI) || defined(HAVE_XMB) || defined(HAVE_OZONE) case MENU_ENUM_LABEL_MENU_SCREENSAVER_ANIMATION: if (menu_screensaver_supported) build_list[i].checked = true; break; case MENU_ENUM_LABEL_MENU_SCREENSAVER_ANIMATION_SPEED: if ( menu_screensaver_supported && (menu_screensaver_animation != MENU_SCREENSAVER_BLANK)) build_list[i].checked = true; break; #endif #if defined(HAVE_XMB) || defined(HAVE_OZONE) case MENU_ENUM_LABEL_MENU_REMEMBER_SELECTION: build_list[i].checked = true; break; #endif #if defined(HAVE_QT) || defined(HAVE_COCOA) case MENU_ENUM_LABEL_UI_COMPANION_TOGGLE: if (desktop_menu_enable) build_list[i].checked = true; break; #endif default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if ( MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_OPTIONS_DISK: count = menu_displaylist_parse_disk_options(list); break; case DISPLAYLIST_MIDI_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_MIDI_OUTPUT, PARSE_ONLY_STRING}, {MENU_ENUM_LABEL_MIDI_INPUT, PARSE_ONLY_STRING}, {MENU_ENUM_LABEL_MIDI_VOLUME, PARSE_ONLY_UINT }, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_VIDEO_WINDOWED_MODE_SETTINGS_LIST: { #if (defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)) || \ (defined(HAVE_COCOA_METAL) && !defined(HAVE_COCOATOUCH)) bool window_custom_size_enable = settings->bools.video_window_save_positions; #else bool window_custom_size_enable = settings->bools.video_window_custom_size_enable; #endif menu_displaylist_build_info_selective_t build_list[] = { #if (defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)) || \ (defined(HAVE_COCOA_METAL) && !defined(HAVE_COCOATOUCH)) {MENU_ENUM_LABEL_VIDEO_WINDOW_SAVE_POSITION, PARSE_ONLY_BOOL, true }, #else {MENU_ENUM_LABEL_VIDEO_WINDOW_CUSTOM_SIZE_ENABLE, PARSE_ONLY_BOOL, true }, #endif {MENU_ENUM_LABEL_VIDEO_SCALE, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_VIDEO_WINDOW_WIDTH, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_VIDEO_WINDOW_HEIGHT, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_VIDEO_WINDOW_AUTO_WIDTH_MAX, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_VIDEO_WINDOW_AUTO_HEIGHT_MAX, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_VIDEO_WINDOW_OPACITY, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_VIDEO_WINDOW_SHOW_DECORATIONS, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_UI_MENUBAR_ENABLE, PARSE_ONLY_BOOL, true }, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_VIDEO_SCALE: if (!window_custom_size_enable) build_list[i].checked = true; break; case MENU_ENUM_LABEL_VIDEO_WINDOW_WIDTH: case MENU_ENUM_LABEL_VIDEO_WINDOW_HEIGHT: if (window_custom_size_enable) build_list[i].checked = true; break; case MENU_ENUM_LABEL_VIDEO_WINDOW_AUTO_WIDTH_MAX: case MENU_ENUM_LABEL_VIDEO_WINDOW_AUTO_HEIGHT_MAX: if (!window_custom_size_enable) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_VIDEO_FULLSCREEN_MODE_SETTINGS_LIST: { menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_VIDEO_FULLSCREEN, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_VIDEO_WINDOWED_FULLSCREEN, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_VIDEO_FULLSCREEN_X, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_VIDEO_FULLSCREEN_Y, PARSE_ONLY_UINT, true }, #ifdef __WINRT__ {MENU_ENUM_LABEL_VIDEO_FORCE_RESOLUTION, PARSE_ONLY_BOOL, true }, #endif }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_VIDEO_OUTPUT_SETTINGS_LIST: { bool *threaded = video_driver_get_threaded(); if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_DRIVER, PARSE_ONLY_STRING_OPTIONS, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_THREADED, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_GPU_INDEX, PARSE_ONLY_INT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_MONITOR_INDEX, PARSE_ONLY_UINT, false) == 0) count++; #if defined(WIIU) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_WIIU_PREFER_DRC, PARSE_ONLY_BOOL, false) == 0) count++; #endif #if defined(GEKKO) || defined(PS2) || defined(__PS3__) if (true) #else if (video_display_server_has_resolution_list()) #endif { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_SCREEN_RESOLUTION, PARSE_ACTION, false) == 0) count++; } #if defined(HAVE_WINDOW_OFFSET) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_WINDOW_OFFSET_X, PARSE_ONLY_INT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_WINDOW_OFFSET_Y, PARSE_ONLY_INT, false) == 0) count++; #endif if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_PAL60_ENABLE, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_GAMMA, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_SOFT_FILTER, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_FILTER_FLICKER, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_ROTATION, PARSE_ONLY_UINT, false) == 0) count++; if (video_display_server_can_set_screen_orientation()) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_SCREEN_ORIENTATION, PARSE_ONLY_UINT, false) == 0) count++; #if defined(DINGUX) && defined(DINGUX_BETA) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_DINGUX_REFRESH_RATE, PARSE_ONLY_UINT, false) == 0) count++; #endif if (threaded && !*threaded) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_REFRESH_RATE, PARSE_ONLY_FLOAT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_POLLED, PARSE_ONLY_FLOAT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_AUTO, PARSE_ONLY_FLOAT, false) == 0) count++; } if (video_display_server_has_resolution_list()) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_AUTOSWITCH_REFRESH_RATE, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_AUTOSWITCH_PAL_THRESHOLD, PARSE_ONLY_FLOAT, false) == 0) count++; } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_FORCE_SRGB_DISABLE, PARSE_ONLY_BOOL, false) == 0) count++; } break; case DISPLAYLIST_VIDEO_SYNCHRONIZATION_SETTINGS_LIST: { bool video_vsync = settings->bools.video_vsync; bool video_hard_sync = settings->bools.video_hard_sync; bool video_wait_swap = settings->bools.video_waitable_swapchains; unsigned bfi = settings->uints.video_black_frame_insertion; unsigned shader_subframes = settings->uints.video_shader_subframes; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_VSYNC, PARSE_ONLY_BOOL, false) == 0) count++; if (video_vsync) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_SWAP_INTERVAL, PARSE_ONLY_UINT, false) == 0) count++; if (video_driver_test_all_flags(GFX_CTX_FLAGS_SUBFRAME_SHADERS)) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_SHADER_SUBFRAMES, PARSE_ONLY_UINT, false) == 0) count++; if (shader_subframes > 1) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_SCAN_SUBFRAMES, PARSE_ONLY_BOOL, false) == 0) count++; } } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_BLACK_FRAME_INSERTION, PARSE_ONLY_UINT, false) == 0) count++; if (bfi > 0) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_BFI_DARK_FRAMES, PARSE_ONLY_UINT, false) == 0) count++; } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_ADAPTIVE_VSYNC, PARSE_ONLY_BOOL, false) == 0) count++; } if (video_driver_test_all_flags(GFX_CTX_FLAGS_HARD_SYNC)) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_HARD_SYNC, PARSE_ONLY_BOOL, false) == 0) count++; if (video_hard_sync) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_HARD_SYNC_FRAMES, PARSE_ONLY_UINT, false) == 0) count++; } if (video_driver_test_all_flags(GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES)) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES, PARSE_ONLY_UINT, false) == 0) count++; } if (video_driver_test_all_flags(GFX_CTX_FLAGS_CUSTOMIZABLE_FRAME_LATENCY)) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_WAITABLE_SWAPCHAINS, PARSE_ONLY_BOOL, false) == 0) count++; if (video_wait_swap) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_MAX_FRAME_LATENCY, PARSE_ONLY_UINT, false) == 0) count++; } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_FRAME_DELAY, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_FRAME_DELAY_AUTO, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VRR_RUNLOOP_ENABLE, PARSE_ONLY_BOOL, false) == 0) count++; } break; case DISPLAYLIST_VIDEO_HDR_SETTINGS_LIST: { if (video_driver_supports_hdr()) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_HDR_ENABLE, PARSE_ONLY_BOOL, false) == 0) count++; if (settings->bools.video_hdr_enable) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_HDR_MAX_NITS, PARSE_ONLY_FLOAT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_HDR_PAPER_WHITE_NITS, PARSE_ONLY_FLOAT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_HDR_CONTRAST, PARSE_ONLY_FLOAT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_HDR_EXPAND_GAMUT, PARSE_ONLY_BOOL, false) == 0) count++; } } } break; case DISPLAYLIST_VIDEO_SCALING_SETTINGS_LIST: { #if defined(DINGUX) if ( string_is_equal(settings->arrays.video_driver, "sdl_dingux") || string_is_equal(settings->arrays.video_driver, "sdl_rs90")) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_DINGUX_IPU_KEEP_ASPECT, PARSE_ONLY_BOOL, false) == 0) count++; } else #endif { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_SCALE_INTEGER_OVERSCALE, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_VIEWPORT_BIAS_X, PARSE_ONLY_FLOAT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_VIEWPORT_BIAS_Y, PARSE_ONLY_FLOAT, false) == 0) count++; #if defined(RARCH_MOBILE) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_VIEWPORT_BIAS_PORTRAIT_X, PARSE_ONLY_FLOAT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_VIEWPORT_BIAS_PORTRAIT_Y, PARSE_ONLY_FLOAT, false) == 0) count++; #endif if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_ASPECT_RATIO_INDEX, PARSE_ONLY_UINT, false) == 0) count++; switch (settings->uints.video_aspect_ratio_idx) { case ASPECT_RATIO_CONFIG: if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_ASPECT_RATIO, PARSE_ONLY_FLOAT, false) == 0) count++; break; case ASPECT_RATIO_CUSTOM: if (!settings->bools.video_scale_integer) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_X, PARSE_ONLY_INT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_Y, PARSE_ONLY_INT, false) == 0) count++; } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_WIDTH, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_HEIGHT, PARSE_ONLY_UINT, false) == 0) count++; break; default: break; } } if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_VI_WIDTH, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_VFILTER, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_SMOOTH, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_CROP_OVERSCAN, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_OVERSCAN_CORRECTION_TOP, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_OVERSCAN_CORRECTION_BOTTOM, PARSE_ONLY_UINT, false) == 0) count++; } break; case DISPLAYLIST_CRT_SWITCHRES_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_CRT_SWITCH_RESOLUTION, PARSE_ONLY_UINT}, {MENU_ENUM_LABEL_CRT_SWITCH_RESOLUTION_SUPER, PARSE_ONLY_UINT}, {MENU_ENUM_LABEL_CRT_SWITCH_X_AXIS_CENTERING, PARSE_ONLY_INT }, {MENU_ENUM_LABEL_CRT_SWITCH_PORCH_ADJUST, PARSE_ONLY_INT }, {MENU_ENUM_LABEL_CRT_SWITCH_RESOLUTION_USE_CUSTOM_REFRESH_RATE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_CRT_SWITCH_HIRES_MENU, PARSE_ONLY_BOOL}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; #ifdef HAVE_LAKKA case DISPLAYLIST_LAKKA_SERVICES_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_SSH_ENABLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SAMBA_ENABLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_BLUETOOTH_ENABLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_LOCALAP_ENABLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_TIMEZONE, PARSE_ONLY_STRING_OPTIONS}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; #endif #ifdef HAVE_LAKKA_SWITCH case DISPLAYLIST_LAKKA_SWITCH_OPTIONS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_SWITCH_OC_ENABLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SWITCH_CEC_ENABLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_BLUETOOTH_ERTM_DISABLE, PARSE_ONLY_BOOL}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; #endif case DISPLAYLIST_MENU_VIEWS_SETTINGS_LIST: { menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_QUICK_MENU_VIEWS_SETTINGS, PARSE_ACTION, true }, {MENU_ENUM_LABEL_SETTINGS_VIEWS_SETTINGS, PARSE_ACTION, true }, {MENU_ENUM_LABEL_MENU_SHOW_LOAD_CORE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_SHOW_LOAD_CONTENT, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_SHOW_LOAD_DISC, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_SHOW_DUMP_DISC, PARSE_ONLY_BOOL, true }, #ifdef HAVE_LAKKA {MENU_ENUM_LABEL_MENU_SHOW_EJECT_DISC, PARSE_ONLY_BOOL, true }, #endif #ifdef HAVE_ONLINE_UPDATER {MENU_ENUM_LABEL_MENU_SHOW_ONLINE_UPDATER, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_SHOW_CORE_UPDATER, PARSE_ONLY_BOOL, true }, #if 0 /* Thumbnailpack removal */ {MENU_ENUM_LABEL_MENU_SHOW_LEGACY_THUMBNAIL_UPDATER, PARSE_ONLY_BOOL, true }, #endif #endif #ifdef HAVE_MIST {MENU_ENUM_LABEL_MENU_SHOW_CORE_MANAGER_STEAM, PARSE_ONLY_BOOL, true }, #endif {MENU_ENUM_LABEL_MENU_SHOW_INFORMATION, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_SHOW_CONFIGURATIONS, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_SHOW_HELP, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_SHOW_WIMP, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_MENU_SHOW_QUIT_RETROARCH, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_SHOW_RESTART_RETROARCH, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_SHOW_REBOOT, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_SHOW_SHUTDOWN, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_CONTENT_SHOW_SETTINGS, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_CONTENT_SHOW_SETTINGS_PASSWORD, PARSE_ONLY_STRING, true}, {MENU_ENUM_LABEL_CONTENT_SHOW_FAVORITES, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_CONTENT_SHOW_HISTORY, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_CONTENT_SHOW_IMAGES, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_CONTENT_SHOW_MUSIC, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_CONTENT_SHOW_VIDEO, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_CONTENT_SHOW_NETPLAY, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_CONTENT_SHOW_ADD, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_CONTENT_SHOW_ADD_ENTRY, PARSE_ONLY_UINT, true }, #if defined(HAVE_DYNAMIC) {MENU_ENUM_LABEL_CONTENT_SHOW_CONTENTLESS_CORES, PARSE_ONLY_UINT, true }, #endif {MENU_ENUM_LABEL_CONTENT_SHOW_EXPLORE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_CONTENT_SHOW_PLAYLISTS, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_TIMEDATE_ENABLE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_TIMEDATE_STYLE, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_TIMEDATE_DATE_SEPARATOR, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_BATTERY_LEVEL_ENABLE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_CORE_ENABLE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_SHOW_SUBLABELS, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_RGUI_SHOW_START_SCREEN, PARSE_ONLY_BOOL, true }, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_MENU_FILE_BROWSER_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_SHOW_HIDDEN_FILES, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_NAVIGATION_BROWSER_FILTER_SUPPORTED_EXTENSIONS_ENABLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_USE_BUILTIN_PLAYER, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_USE_BUILTIN_IMAGE_VIEWER, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_FILTER_BY_CURRENT_CORE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_USE_LAST_START_DIRECTORY, PARSE_ONLY_BOOL}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_ACCOUNTS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_ACCOUNTS_RETRO_ACHIEVEMENTS, PARSE_ACTION}, {MENU_ENUM_LABEL_ACCOUNTS_YOUTUBE, PARSE_ACTION}, {MENU_ENUM_LABEL_ACCOUNTS_TWITCH, PARSE_ACTION}, {MENU_ENUM_LABEL_ACCOUNTS_FACEBOOK, PARSE_ACTION}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_ACCOUNTS_CHEEVOS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_CHEEVOS_USERNAME, PARSE_ONLY_STRING}, {MENU_ENUM_LABEL_CHEEVOS_PASSWORD, PARSE_ONLY_STRING}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; #if defined(HAVE_OVERLAY) case DISPLAYLIST_ONSCREEN_OVERLAY_SETTINGS_LIST: { struct menu_state *menu_st = menu_state_get_ptr(); bool input_overlay_enable = settings->bools.input_overlay_enable; bool input_overlay_ptr_enable = settings->bools.input_overlay_pointer_enable; bool input_overlay_auto_scale = settings->bools.input_overlay_auto_scale; enum overlay_show_input_type input_overlay_show_inputs = (enum overlay_show_input_type) settings->uints.input_overlay_show_inputs; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_INPUT_OVERLAY_ENABLE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_OVERLAY_PRESET, PARSE_ONLY_PATH, false }, {MENU_ENUM_LABEL_OVERLAY_OPACITY, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_INPUT_OVERLAY_BEHIND_MENU, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_INPUT_OVERLAY_HIDE_IN_MENU, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_INPUT_OVERLAY_HIDE_WHEN_GAMEPAD_CONNECTED, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_INPUT_OVERLAY_SHOW_INPUTS, PARSE_ONLY_UINT, false }, {MENU_ENUM_LABEL_INPUT_OVERLAY_SHOW_INPUTS_PORT, PARSE_ONLY_UINT, false }, {MENU_ENUM_LABEL_INPUT_OVERLAY_SHOW_MOUSE_CURSOR, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_INPUT_OVERLAY_DPAD_DIAGONAL_SENSITIVITY, PARSE_ONLY_UINT, false }, {MENU_ENUM_LABEL_INPUT_OVERLAY_ABXY_DIAGONAL_SENSITIVITY, PARSE_ONLY_UINT, false }, {MENU_ENUM_LABEL_INPUT_OVERLAY_AUTO_ROTATE, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_INPUT_OVERLAY_AUTO_SCALE, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_OVERLAY_SCALE_LANDSCAPE, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_OVERLAY_ASPECT_ADJUST_LANDSCAPE, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_OVERLAY_X_SEPARATION_LANDSCAPE, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_OVERLAY_Y_SEPARATION_LANDSCAPE, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_OVERLAY_X_OFFSET_LANDSCAPE, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_OVERLAY_Y_OFFSET_LANDSCAPE, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_OVERLAY_SCALE_PORTRAIT, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_OVERLAY_ASPECT_ADJUST_PORTRAIT, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_OVERLAY_X_SEPARATION_PORTRAIT, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_OVERLAY_Y_SEPARATION_PORTRAIT, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_OVERLAY_X_OFFSET_PORTRAIT, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_OVERLAY_Y_OFFSET_PORTRAIT, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_INPUT_OVERLAY_POINTER_ENABLE, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_OVERLAY_LIGHTGUN_SETTINGS, PARSE_ACTION, false }, {MENU_ENUM_LABEL_OVERLAY_MOUSE_SETTINGS, PARSE_ACTION, false }, {MENU_ENUM_LABEL_OSK_OVERLAY_SETTINGS, PARSE_ACTION, false }, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_INPUT_OVERLAY_BEHIND_MENU: case MENU_ENUM_LABEL_INPUT_OVERLAY_HIDE_IN_MENU: case MENU_ENUM_LABEL_INPUT_OVERLAY_HIDE_WHEN_GAMEPAD_CONNECTED: case MENU_ENUM_LABEL_INPUT_OVERLAY_SHOW_INPUTS: case MENU_ENUM_LABEL_INPUT_OVERLAY_SHOW_MOUSE_CURSOR: case MENU_ENUM_LABEL_INPUT_OVERLAY_AUTO_ROTATE: case MENU_ENUM_LABEL_INPUT_OVERLAY_AUTO_SCALE: case MENU_ENUM_LABEL_OVERLAY_PRESET: case MENU_ENUM_LABEL_OVERLAY_OPACITY: case MENU_ENUM_LABEL_INPUT_OVERLAY_POINTER_ENABLE: if (input_overlay_enable) build_list[i].checked = true; break; case MENU_ENUM_LABEL_INPUT_OVERLAY_SHOW_INPUTS_PORT: if (input_overlay_enable && (input_overlay_show_inputs == OVERLAY_SHOW_INPUT_PHYSICAL)) build_list[i].checked = true; break; case MENU_ENUM_LABEL_OVERLAY_SCALE_LANDSCAPE: case MENU_ENUM_LABEL_OVERLAY_ASPECT_ADJUST_LANDSCAPE: case MENU_ENUM_LABEL_OVERLAY_X_SEPARATION_LANDSCAPE: case MENU_ENUM_LABEL_OVERLAY_Y_SEPARATION_LANDSCAPE: case MENU_ENUM_LABEL_OVERLAY_X_OFFSET_LANDSCAPE: case MENU_ENUM_LABEL_OVERLAY_Y_OFFSET_LANDSCAPE: case MENU_ENUM_LABEL_OVERLAY_SCALE_PORTRAIT: case MENU_ENUM_LABEL_OVERLAY_ASPECT_ADJUST_PORTRAIT: case MENU_ENUM_LABEL_OVERLAY_X_SEPARATION_PORTRAIT: case MENU_ENUM_LABEL_OVERLAY_Y_SEPARATION_PORTRAIT: case MENU_ENUM_LABEL_OVERLAY_X_OFFSET_PORTRAIT: case MENU_ENUM_LABEL_OVERLAY_Y_OFFSET_PORTRAIT: if (input_overlay_enable && !input_overlay_auto_scale) build_list[i].checked = true; break; case MENU_ENUM_LABEL_INPUT_OVERLAY_DPAD_DIAGONAL_SENSITIVITY: if (input_overlay_enable && BIT16_GET(menu_st->overlay_types, OVERLAY_TYPE_DPAD_AREA)) build_list[i].checked = true; break; case MENU_ENUM_LABEL_INPUT_OVERLAY_ABXY_DIAGONAL_SENSITIVITY: if (input_overlay_enable && BIT16_GET(menu_st->overlay_types, OVERLAY_TYPE_ABXY_AREA)) build_list[i].checked = true; break; case MENU_ENUM_LABEL_OVERLAY_LIGHTGUN_SETTINGS: case MENU_ENUM_LABEL_OVERLAY_MOUSE_SETTINGS: if (input_overlay_enable && input_overlay_ptr_enable) build_list[i].checked = true; break; case MENU_ENUM_LABEL_OSK_OVERLAY_SETTINGS: /* Show keyboard menu if the main overlay has * an osk_toggle or if the OSK hotkey is set */ if (input_overlay_enable && (BIT16_GET(menu_st->overlay_types, OVERLAY_TYPE_OSK_TOGGLE) || input_config_binds[0][RARCH_OSK].joykey != NO_BTN || input_config_binds[0][RARCH_OSK].joyaxis != AXIS_NONE || input_config_binds[0][RARCH_OSK].key != RETROK_UNKNOWN || input_config_binds[0][RARCH_OSK].mbutton != NO_BTN)) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_OSK_OVERLAY_SETTINGS_LIST: if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_OSK_OVERLAY_PRESET, PARSE_ONLY_PATH, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_OSK_OVERLAY_AUTO_SCALE, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_OSK_OVERLAY_OPACITY, PARSE_ONLY_FLOAT, false) == 0) count++; break; case DISPLAYLIST_OVERLAY_LIGHTGUN_SETTINGS_LIST: if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_OVERLAY_LIGHTGUN_PORT, PARSE_ONLY_INT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_OVERLAY_LIGHTGUN_TRIGGER_ON_TOUCH, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_OVERLAY_LIGHTGUN_TRIGGER_DELAY, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_OVERLAY_LIGHTGUN_TWO_TOUCH_INPUT, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_OVERLAY_LIGHTGUN_THREE_TOUCH_INPUT, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_OVERLAY_LIGHTGUN_FOUR_TOUCH_INPUT, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_OVERLAY_LIGHTGUN_ALLOW_OFFSCREEN, PARSE_ONLY_BOOL, false) == 0) count++; break; case DISPLAYLIST_OVERLAY_MOUSE_SETTINGS_LIST: if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_OVERLAY_MOUSE_SPEED, PARSE_ONLY_FLOAT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_OVERLAY_MOUSE_HOLD_TO_DRAG, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_OVERLAY_MOUSE_HOLD_MSEC, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_OVERLAY_MOUSE_DTAP_TO_DRAG, PARSE_ONLY_BOOL, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_OVERLAY_MOUSE_DTAP_MSEC, PARSE_ONLY_UINT, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_OVERLAY_MOUSE_SWIPE_THRESHOLD, PARSE_ONLY_FLOAT, false) == 0) count++; break; #endif case DISPLAYLIST_LATENCY_SETTINGS_LIST: { bool video_hard_sync = settings->bools.video_hard_sync; bool video_wait_swap = settings->bools.video_waitable_swapchains; #ifdef HAVE_RUNAHEAD bool runahead_supported = true; bool runahead_enabled = settings->bools.run_ahead_enabled; bool preempt_enabled = settings->bools.preemptive_frames_enable; #endif menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_AUDIO_LATENCY, PARSE_ONLY_UINT, true }, #ifdef HAVE_MICROPHONE {MENU_ENUM_LABEL_MICROPHONE_LATENCY, PARSE_ONLY_UINT, true }, #endif {MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_INPUT_BLOCK_TIMEOUT, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_VIDEO_FRAME_DELAY, PARSE_ONLY_UINT, true }, {MENU_ENUM_LABEL_VIDEO_FRAME_DELAY_AUTO, PARSE_ONLY_BOOL, true }, #ifdef HAVE_RUNAHEAD {MENU_ENUM_LABEL_RUN_AHEAD_ENABLED, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_RUN_AHEAD_FRAMES, PARSE_ONLY_UINT, false }, {MENU_ENUM_LABEL_RUN_AHEAD_SECONDARY_INSTANCE, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_RUN_AHEAD_HIDE_WARNINGS, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_PREEMPT_ENABLE, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_PREEMPT_FRAMES, PARSE_ONLY_UINT, false }, {MENU_ENUM_LABEL_PREEMPT_HIDE_WARNINGS, PARSE_ONLY_BOOL, false }, #endif }; if (video_driver_test_all_flags(GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES)) { MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES, PARSE_ONLY_UINT, false); count++; } if (video_driver_test_all_flags(GFX_CTX_FLAGS_CUSTOMIZABLE_FRAME_LATENCY)) { MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_WAITABLE_SWAPCHAINS, PARSE_ONLY_BOOL, false); count++; if (video_wait_swap) { MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_MAX_FRAME_LATENCY, PARSE_ONLY_UINT, false); count++; } } if (video_driver_test_all_flags(GFX_CTX_FLAGS_HARD_SYNC)) { MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_HARD_SYNC, PARSE_ONLY_BOOL, false); count++; if (video_hard_sync) { MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_VIDEO_HARD_SYNC_FRAMES, PARSE_ONLY_UINT, false); count++; } } #ifdef HAVE_RUNAHEAD if ( (flags & RUNLOOP_FLAG_CORE_RUNNING) && !retroarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) runahead_supported = core_info_current_supports_runahead(); if (runahead_supported) { for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_RUN_AHEAD_ENABLED: case MENU_ENUM_LABEL_PREEMPT_ENABLE: build_list[i].checked = true; break; case MENU_ENUM_LABEL_RUN_AHEAD_FRAMES: case MENU_ENUM_LABEL_RUN_AHEAD_SECONDARY_INSTANCE: case MENU_ENUM_LABEL_RUN_AHEAD_HIDE_WARNINGS: if (runahead_enabled) build_list[i].checked = true; break; case MENU_ENUM_LABEL_PREEMPT_FRAMES: case MENU_ENUM_LABEL_PREEMPT_HIDE_WARNINGS: if (preempt_enabled) build_list[i].checked = true; break; default: break; } } } #endif for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } #ifdef HAVE_RUNAHEAD if (!runahead_supported) { if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RUN_AHEAD_UNSUPPORTED), msg_hash_to_str(MENU_ENUM_LABEL_RUN_AHEAD_UNSUPPORTED), MENU_ENUM_LABEL_RUN_AHEAD_UNSUPPORTED, FILE_TYPE_NONE, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PREEMPT_UNSUPPORTED), msg_hash_to_str(MENU_ENUM_LABEL_PREEMPT_UNSUPPORTED), MENU_ENUM_LABEL_PREEMPT_UNSUPPORTED, FILE_TYPE_NONE, 0, 0, NULL)) count++; } #endif #ifndef HAVE_LAKKA if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_GAMEMODE_ENABLE, PARSE_ONLY_BOOL, false) == 0) count++; #endif /*HAVE_LAKKA?*/ } break; case DISPLAYLIST_ONSCREEN_NOTIFICATIONS_SETTINGS_LIST: { bool video_font_enable = settings->bools.video_font_enable; bool video_msg_bgcolor_enable = settings->bools.video_msg_bgcolor_enable; #ifdef HAVE_GFX_WIDGETS video_driver_state_t *video_st= video_state_get_ptr(); bool widgets_supported = video_st->current_video && video_st->current_video->gfx_widgets_enabled && video_st->current_video->gfx_widgets_enabled(video_st->data); bool widgets_active = gfx_widgets_ready(); bool menu_widget_scale_auto = settings->bools.menu_widget_scale_auto; #else bool widgets_active = false; #endif menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_ONSCREEN_NOTIFICATIONS_VIEWS_SETTINGS, PARSE_ACTION, false }, {MENU_ENUM_LABEL_VIDEO_FONT_ENABLE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_MENU_WIDGETS_ENABLE, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_MENU_WIDGET_SCALE_AUTO, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_MENU_WIDGET_SCALE_FACTOR, PARSE_ONLY_FLOAT, false }, #if !(defined(RARCH_CONSOLE) || defined(RARCH_MOBILE)) {MENU_ENUM_LABEL_MENU_WIDGET_SCALE_FACTOR_WINDOWED, PARSE_ONLY_FLOAT, false }, #endif {MENU_ENUM_LABEL_VIDEO_FONT_PATH, PARSE_ONLY_PATH, false }, {MENU_ENUM_LABEL_VIDEO_FONT_SIZE, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_VIDEO_MESSAGE_POS_X, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_VIDEO_MESSAGE_POS_Y, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_VIDEO_MESSAGE_COLOR_RED, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_VIDEO_MESSAGE_COLOR_GREEN, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_VIDEO_MESSAGE_COLOR_BLUE, PARSE_ONLY_FLOAT, false }, {MENU_ENUM_LABEL_VIDEO_MESSAGE_BGCOLOR_ENABLE, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_VIDEO_MESSAGE_BGCOLOR_RED, PARSE_ONLY_UINT, false }, {MENU_ENUM_LABEL_VIDEO_MESSAGE_BGCOLOR_GREEN, PARSE_ONLY_UINT, false }, {MENU_ENUM_LABEL_VIDEO_MESSAGE_BGCOLOR_BLUE, PARSE_ONLY_UINT, false }, {MENU_ENUM_LABEL_VIDEO_MESSAGE_BGCOLOR_OPACITY, PARSE_ONLY_FLOAT, false }, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { #ifdef HAVE_GFX_WIDGETS case MENU_ENUM_LABEL_MENU_WIDGETS_ENABLE: if (video_font_enable && widgets_supported) build_list[i].checked = true; break; case MENU_ENUM_LABEL_MENU_WIDGET_SCALE_AUTO: if (widgets_active) build_list[i].checked = true; break; case MENU_ENUM_LABEL_MENU_WIDGET_SCALE_FACTOR: if (widgets_active && !menu_widget_scale_auto) build_list[i].checked = true; break; #if !(defined(RARCH_CONSOLE) || defined(RARCH_MOBILE)) case MENU_ENUM_LABEL_MENU_WIDGET_SCALE_FACTOR_WINDOWED: if (widgets_active && !menu_widget_scale_auto) build_list[i].checked = true; break; #endif #endif case MENU_ENUM_LABEL_ONSCREEN_NOTIFICATIONS_VIEWS_SETTINGS: case MENU_ENUM_LABEL_VIDEO_FONT_PATH: case MENU_ENUM_LABEL_VIDEO_FONT_SIZE: if (video_font_enable || widgets_active) build_list[i].checked = true; break; case MENU_ENUM_LABEL_VIDEO_MESSAGE_POS_X: case MENU_ENUM_LABEL_VIDEO_MESSAGE_POS_Y: case MENU_ENUM_LABEL_VIDEO_MESSAGE_COLOR_RED: case MENU_ENUM_LABEL_VIDEO_MESSAGE_COLOR_GREEN: case MENU_ENUM_LABEL_VIDEO_MESSAGE_COLOR_BLUE: case MENU_ENUM_LABEL_VIDEO_MESSAGE_BGCOLOR_ENABLE: if (!widgets_active && video_font_enable) build_list[i].checked = true; break; case MENU_ENUM_LABEL_VIDEO_MESSAGE_BGCOLOR_RED: case MENU_ENUM_LABEL_VIDEO_MESSAGE_BGCOLOR_GREEN: case MENU_ENUM_LABEL_VIDEO_MESSAGE_BGCOLOR_BLUE: case MENU_ENUM_LABEL_VIDEO_MESSAGE_BGCOLOR_OPACITY: if (!widgets_active && video_font_enable && video_msg_bgcolor_enable) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_ONSCREEN_NOTIFICATIONS_VIEWS_SETTINGS_LIST: { bool video_font_enable = settings->bools.video_font_enable; bool video_fps_show = settings->bools.video_fps_show; bool video_memory_show = settings->bools.video_memory_show; #ifdef HAVE_GFX_WIDGETS bool widgets_active = gfx_widgets_ready(); bool notifications_active = video_font_enable || widgets_active; #ifdef HAVE_SCREENSHOTS bool notification_show_screenshot = settings->bools.notification_show_screenshot; #endif #else bool notifications_active = video_font_enable; #endif menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_FPS_SHOW, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_FPS_UPDATE_INTERVAL, PARSE_ONLY_UINT, false }, {MENU_ENUM_LABEL_FRAMECOUNT_SHOW, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_STATISTICS_SHOW, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_MEMORY_SHOW, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_MEMORY_UPDATE_INTERVAL, PARSE_ONLY_UINT, false }, {MENU_ENUM_LABEL_MENU_SHOW_LOAD_CONTENT_ANIMATION, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_NOTIFICATION_SHOW_WHEN_MENU_IS_ALIVE, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_NOTIFICATION_SHOW_AUTOCONFIG, PARSE_ONLY_BOOL, false }, #ifdef HAVE_CHEATS {MENU_ENUM_LABEL_NOTIFICATION_SHOW_CHEATS_APPLIED, PARSE_ONLY_BOOL, false }, #endif #ifdef HAVE_PATCH {MENU_ENUM_LABEL_NOTIFICATION_SHOW_PATCH_APPLIED, PARSE_ONLY_BOOL, false }, #endif {MENU_ENUM_LABEL_NOTIFICATION_SHOW_REMAP_LOAD, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_NOTIFICATION_SHOW_CONFIG_OVERRIDE_LOAD, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_NOTIFICATION_SHOW_SET_INITIAL_DISK, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_NOTIFICATION_SHOW_DISK_CONTROL, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_NOTIFICATION_SHOW_SAVE_STATE, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_NOTIFICATION_SHOW_FAST_FORWARD, PARSE_ONLY_BOOL, false }, {MENU_ENUM_LABEL_NOTIFICATION_SHOW_REFRESH_RATE, PARSE_ONLY_BOOL, false }, #ifdef HAVE_SCREENSHOTS {MENU_ENUM_LABEL_NOTIFICATION_SHOW_SCREENSHOT, PARSE_ONLY_BOOL, false }, #ifdef HAVE_GFX_WIDGETS {MENU_ENUM_LABEL_NOTIFICATION_SHOW_SCREENSHOT_DURATION, PARSE_ONLY_UINT, false }, {MENU_ENUM_LABEL_NOTIFICATION_SHOW_SCREENSHOT_FLASH, PARSE_ONLY_UINT, false }, #endif #endif #if defined(HAVE_NETWORKING) && defined(HAVE_GFX_WIDGETS) {MENU_ENUM_LABEL_NETPLAY_PING_SHOW, PARSE_ONLY_BOOL, false }, #endif #ifdef HAVE_NETWORKING {MENU_ENUM_LABEL_NOTIFICATION_SHOW_NETPLAY_EXTRA, PARSE_ONLY_BOOL, false }, #endif }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_FPS_UPDATE_INTERVAL: if (notifications_active && video_fps_show) build_list[i].checked = true; break; case MENU_ENUM_LABEL_MEMORY_UPDATE_INTERVAL: if (notifications_active && video_memory_show) build_list[i].checked = true; break; case MENU_ENUM_LABEL_STATISTICS_SHOW: if (notifications_active && video_font_enable) build_list[i].checked = true; break; #ifdef HAVE_GFX_WIDGETS #ifdef HAVE_NETWORKING case MENU_ENUM_LABEL_NETPLAY_PING_SHOW: if (widgets_active) build_list[i].checked = true; break; #endif case MENU_ENUM_LABEL_MENU_SHOW_LOAD_CONTENT_ANIMATION: if (widgets_active) build_list[i].checked = true; break; #ifdef HAVE_SCREENSHOTS case MENU_ENUM_LABEL_NOTIFICATION_SHOW_SCREENSHOT_DURATION: if (widgets_active && notification_show_screenshot) build_list[i].checked = true; break; case MENU_ENUM_LABEL_NOTIFICATION_SHOW_SCREENSHOT_FLASH: if (widgets_active) build_list[i].checked = true; break; #endif #endif default: if (notifications_active) build_list[i].checked = true; break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_CONFIGURATIONS_LIST: if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CONFIGURATIONS), msg_hash_to_str(MENU_ENUM_LABEL_CONFIGURATIONS), MENU_ENUM_LABEL_CONFIGURATIONS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SAVE_CURRENT_CONFIG), msg_hash_to_str(MENU_ENUM_LABEL_SAVE_CURRENT_CONFIG), MENU_ENUM_LABEL_SAVE_CURRENT_CONFIG, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SAVE_NEW_CONFIG), msg_hash_to_str(MENU_ENUM_LABEL_SAVE_NEW_CONFIG), MENU_ENUM_LABEL_SAVE_NEW_CONFIG, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RESET_TO_DEFAULT_CONFIG), msg_hash_to_str(MENU_ENUM_LABEL_RESET_TO_DEFAULT_CONFIG), MENU_ENUM_LABEL_RESET_TO_DEFAULT_CONFIG, MENU_SETTING_ACTION, 0, 0, NULL)) count++; break; case DISPLAYLIST_PRIVACY_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_CAMERA_ALLOW, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_DISCORD_ALLOW, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_LOCATION_ALLOW, PARSE_ONLY_BOOL}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_SAVING_SETTINGS_LIST: { bool savestate_auto_index = settings->bools.savestate_auto_index; bool replay_auto_index = settings->bools.replay_auto_index; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_SORT_SAVEFILES_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SORT_SAVESTATES_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SORT_SAVEFILES_BY_CONTENT_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SORT_SAVESTATES_BY_CONTENT_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SORT_SCREENSHOTS_BY_CONTENT_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SAVEFILES_IN_CONTENT_DIR_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SAVESTATES_IN_CONTENT_DIR_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SCREENSHOTS_IN_CONTENT_DIR_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_AUTOSAVE_INTERVAL, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_BLOCK_SRAM_OVERWRITE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SAVE_FILE_COMPRESSION, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SAVESTATE_FILE_COMPRESSION, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SAVESTATE_THUMBNAIL_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SAVESTATE_AUTO_SAVE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SAVESTATE_AUTO_LOAD, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SAVESTATE_AUTO_INDEX, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SAVESTATE_MAX_KEEP, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_REPLAY_AUTO_INDEX, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_REPLAY_MAX_KEEP, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_REPLAY_CHECKPOINT_INTERVAL, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_CONTENT_RUNTIME_LOG_AGGREGATE, PARSE_ONLY_BOOL, true}, #if HAVE_CLOUDSYNC {MENU_ENUM_LABEL_CLOUD_SYNC_SETTINGS, PARSE_ACTION, true}, #endif }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_SAVESTATE_MAX_KEEP: build_list[i].checked = savestate_auto_index; break; case MENU_ENUM_LABEL_REPLAY_MAX_KEEP: build_list[i].checked = replay_auto_index; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (build_list[i].checked && MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_CLOUD_SYNC_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_CLOUD_SYNC_ENABLE, PARSE_ONLY_BOOL }, {MENU_ENUM_LABEL_CLOUD_SYNC_DESTRUCTIVE, PARSE_ONLY_BOOL }, {MENU_ENUM_LABEL_CLOUD_SYNC_SYNC_SAVES, PARSE_ONLY_BOOL }, {MENU_ENUM_LABEL_CLOUD_SYNC_SYNC_CONFIGS, PARSE_ONLY_BOOL }, {MENU_ENUM_LABEL_CLOUD_SYNC_DRIVER, PARSE_ONLY_STRING_OPTIONS }, {MENU_ENUM_LABEL_CLOUD_SYNC_URL, PARSE_ONLY_STRING }, {MENU_ENUM_LABEL_CLOUD_SYNC_USERNAME, PARSE_ONLY_STRING }, {MENU_ENUM_LABEL_CLOUD_SYNC_PASSWORD, PARSE_ONLY_STRING }, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; #ifdef HAVE_MIST case DISPLAYLIST_STEAM_SETTINGS_LIST: { menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_STEAM_RICH_PRESENCE_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_STEAM_RICH_PRESENCE_FORMAT, PARSE_ONLY_UINT, false}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_STEAM_RICH_PRESENCE_FORMAT: if (settings->bools.steam_rich_presence_enable) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; #endif case DISPLAYLIST_SETTINGS_ALL: { #ifdef HAVE_TRANSLATE bool settings_show_ai_service = settings->bools.settings_show_ai_service; #endif menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_USER_INTERFACE_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_VIDEO_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_AUDIO_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_INPUT_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_LATENCY_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_FRAME_THROTTLE_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_DRIVER_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_PLAYLIST_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_CORE_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_SAVING_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_RECORDING_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_CONFIGURATION_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_ACCESSIBILITY_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_POWER_MANAGEMENT_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_BLUETOOTH_SETTINGS, PARSE_ACTION, true}, #ifdef HAVE_NETWORKING {MENU_ENUM_LABEL_WIFI_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_NETWORK_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_NETPLAY_LAN_SCAN_SETTINGS, PARSE_ACTION, true}, #endif #ifdef HAVE_CHEEVOS {MENU_ENUM_LABEL_RETRO_ACHIEVEMENTS_SETTINGS, PARSE_ACTION}, #endif {MENU_ENUM_LABEL_USER_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_DIRECTORY_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_LAKKA_SERVICES, PARSE_ACTION, true}, #ifdef HAVE_LAKKA_SWITCH {MENU_ENUM_LABEL_LAKKA_SWITCH_OPTIONS, PARSE_ACTION, true}, #endif #ifdef HAVE_MIST {MENU_ENUM_LABEL_STEAM_SETTINGS, PARSE_ACTION, true}, #endif {MENU_ENUM_LABEL_LOGGING_SETTINGS, PARSE_ACTION, true}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_AI_SERVICE_SETTINGS: #ifdef HAVE_TRANSLATE build_list[i].checked = settings_show_ai_service; #else build_list[i].checked = false; #endif break; case MENU_ENUM_LABEL_DRIVER_SETTINGS: build_list[i].checked = settings->bools.settings_show_drivers; break; case MENU_ENUM_LABEL_VIDEO_SETTINGS: build_list[i].checked = settings->bools.settings_show_video; break; case MENU_ENUM_LABEL_AUDIO_SETTINGS: build_list[i].checked = settings->bools.settings_show_audio; break; case MENU_ENUM_LABEL_INPUT_SETTINGS: build_list[i].checked = settings->bools.settings_show_input; break; case MENU_ENUM_LABEL_LATENCY_SETTINGS: build_list[i].checked = settings->bools.settings_show_latency; break; case MENU_ENUM_LABEL_CORE_SETTINGS: build_list[i].checked = settings->bools.settings_show_core; break; case MENU_ENUM_LABEL_CONFIGURATION_SETTINGS: build_list[i].checked = settings->bools.settings_show_configuration; break; case MENU_ENUM_LABEL_SAVING_SETTINGS: build_list[i].checked = settings->bools.settings_show_saving; break; case MENU_ENUM_LABEL_LOGGING_SETTINGS: build_list[i].checked = settings->bools.settings_show_logging; break; case MENU_ENUM_LABEL_FRAME_THROTTLE_SETTINGS: build_list[i].checked = settings->bools.settings_show_frame_throttle; break; case MENU_ENUM_LABEL_RECORDING_SETTINGS: build_list[i].checked = settings->bools.settings_show_recording; break; case MENU_ENUM_LABEL_USER_INTERFACE_SETTINGS: build_list[i].checked = settings->bools.settings_show_user_interface; break; case MENU_ENUM_LABEL_ACCESSIBILITY_SETTINGS: build_list[i].checked = settings->bools.settings_show_accessibility; break; case MENU_ENUM_LABEL_POWER_MANAGEMENT_SETTINGS: build_list[i].checked = settings->bools.settings_show_power_management; break; case MENU_ENUM_LABEL_RETRO_ACHIEVEMENTS_SETTINGS: build_list[i].checked = settings->bools.settings_show_achievements; break; case MENU_ENUM_LABEL_NETWORK_SETTINGS: build_list[i].checked = settings->bools.settings_show_network; break; case MENU_ENUM_LABEL_PLAYLIST_SETTINGS: build_list[i].checked = settings->bools.settings_show_playlists; break; case MENU_ENUM_LABEL_USER_SETTINGS: build_list[i].checked = settings->bools.settings_show_user; break; case MENU_ENUM_LABEL_DIRECTORY_SETTINGS: build_list[i].checked = settings->bools.settings_show_directory; break; #ifdef HAVE_MIST case MENU_ENUM_LABEL_STEAM_SETTINGS: build_list[i].checked = settings->bools.settings_show_steam; break; #endif /* MISSING: * MENU_ENUM_LABEL_BLUETOOTH_SETTINGS * MENU_ENUM_LABEL_WIFI_SETTINGS * MENU_ENUM_LABEL_NETPLAY_LAN_SCAN_SETTINGS * MENU_ENUM_LABEL_LAKKA_SERVICES */ default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (build_list[i].checked && MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_POWER_MANAGEMENT_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_FASTFORWARD_FRAMESKIP, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_VIDEO_FRAME_REST, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SUSTAINED_PERFORMANCE_MODE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_CPU_PERFPOWER, PARSE_ACTION}, #ifdef HAVE_LAKKA {MENU_ENUM_LABEL_GAMEMODE_ENABLE, PARSE_ONLY_BOOL}, #endif /*HAVE_LAKKA*/ }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } #ifdef _3DS u8 device_model = 0xFF; CFGU_GetSystemModel(&device_model); if ( (device_model == 2) || (device_model == 4) || (device_model == 5)) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_NEW3DS_SPEEDUP_ENABLE, PARSE_ONLY_BOOL, false) == 0) count++; } #endif } break; case DISPLAYLIST_ONSCREEN_DISPLAY_SETTINGS_LIST: { /* Not used */ menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_ONSCREEN_NOTIFICATIONS_SETTINGS, PARSE_ACTION}, #if defined(HAVE_OVERLAY) {MENU_ENUM_LABEL_ONSCREEN_OVERLAY_SETTINGS, PARSE_ACTION}, #endif }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_USER_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_PRIVACY_SETTINGS, PARSE_ACTION}, {MENU_ENUM_LABEL_ACCOUNTS_LIST, PARSE_ACTION}, {MENU_ENUM_LABEL_NETPLAY_NICKNAME, PARSE_ONLY_STRING}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_UPDATER_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_CORE_UPDATER_BUILDBOT_URL, PARSE_ONLY_STRING}, {MENU_ENUM_LABEL_BUILDBOT_ASSETS_URL, PARSE_ONLY_STRING}, {MENU_ENUM_LABEL_CORE_UPDATER_AUTO_EXTRACT_ARCHIVE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_CORE_UPDATER_SHOW_EXPERIMENTAL_CORES, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_CORE_UPDATER_AUTO_BACKUP, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE, PARSE_ONLY_UINT}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_MENU_SOUNDS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_AUDIO_ENABLE_MENU, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_MENU_SOUND_OK, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_MENU_SOUND_CANCEL, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_MENU_SOUND_NOTICE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_MENU_SOUND_BGM, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_MENU_SOUND_SCROLL, PARSE_ONLY_BOOL}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_SETTINGS_VIEWS_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_SETTINGS_SHOW_USER_INTERFACE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_ONSCREEN_DISPLAY, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_FILE_BROWSER, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_VIDEO, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_AUDIO, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_INPUT, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_LATENCY, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_FRAME_THROTTLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_DRIVERS, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_PLAYLISTS, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_CORE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_SAVING, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_RECORDING, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_CONFIGURATION, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_ACCESSIBILITY, PARSE_ONLY_BOOL}, #ifdef HAVE_TRANSLATE {MENU_ENUM_LABEL_SETTINGS_SHOW_AI_SERVICE, PARSE_ONLY_BOOL}, #endif {MENU_ENUM_LABEL_SETTINGS_SHOW_POWER_MANAGEMENT, PARSE_ONLY_BOOL}, #ifdef HAVE_NETWORKING {MENU_ENUM_LABEL_SETTINGS_SHOW_NETWORK, PARSE_ONLY_BOOL}, #endif #ifdef HAVE_CHEEVOS {MENU_ENUM_LABEL_SETTINGS_SHOW_ACHIEVEMENTS, PARSE_ONLY_BOOL}, #endif {MENU_ENUM_LABEL_SETTINGS_SHOW_USER, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SETTINGS_SHOW_DIRECTORY, PARSE_ONLY_BOOL}, #ifdef HAVE_MIST {MENU_ENUM_LABEL_SETTINGS_SHOW_STEAM, PARSE_ONLY_BOOL}, #endif {MENU_ENUM_LABEL_SETTINGS_SHOW_LOGGING, PARSE_ONLY_BOOL}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_QUICK_MENU_VIEWS_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_QUICK_MENU_SHOW_RESUME_CONTENT, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_RESTART_CONTENT, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_CLOSE_CONTENT, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_SAVESTATE_SUBMENU, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_SAVE_LOAD_STATE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_UNDO_SAVE_LOAD_STATE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_REPLAY, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_OPTIONS, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_CORE_OPTIONS_FLUSH, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_CONTROLS, PARSE_ONLY_BOOL}, #ifdef HAVE_SCREENSHOTS {MENU_ENUM_LABEL_QUICK_MENU_SHOW_TAKE_SCREENSHOT, PARSE_ONLY_BOOL}, #endif {MENU_ENUM_LABEL_QUICK_MENU_SHOW_START_RECORDING, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_START_STREAMING, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_ADD_TO_FAVORITES, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_ADD_TO_PLAYLIST, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_CONTENT_SHOW_OVERLAYS, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_CONTENT_SHOW_LATENCY, PARSE_ONLY_BOOL}, #ifdef HAVE_REWIND {MENU_ENUM_LABEL_CONTENT_SHOW_REWIND, PARSE_ONLY_BOOL}, #endif {MENU_ENUM_LABEL_QUICK_MENU_SHOW_SAVE_CORE_OVERRIDES, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_SAVE_CONTENT_DIR_OVERRIDES, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_SAVE_GAME_OVERRIDES, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_CHEATS, PARSE_ONLY_BOOL}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) if (video_shader_any_supported()) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_QUICK_MENU_SHOW_SHADERS, PARSE_ONLY_BOOL, false) == 0) count++; } #endif { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_QUICK_MENU_SHOW_SET_CORE_ASSOCIATION, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_QUICK_MENU_SHOW_RESET_CORE_ASSOCIATION, PARSE_ONLY_BOOL}, #ifdef HAVE_NETWORKING {MENU_ENUM_LABEL_QUICK_MENU_SHOW_DOWNLOAD_THUMBNAILS, PARSE_ONLY_BOOL}, #endif {MENU_ENUM_LABEL_QUICK_MENU_SHOW_INFORMATION, PARSE_ONLY_BOOL}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_CORE_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_CORE_INFO_CACHE_ENABLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_CORE_INFO_SAVESTATE_BYPASS, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_CHECK_FOR_MISSING_FIRMWARE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_SYSTEMFILES_IN_CONTENT_DIR_ENABLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_CORE_OPTION_CATEGORY_ENABLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_DRIVER_SWITCH_ENABLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_VIDEO_ALLOW_ROTATE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_VIDEO_SHARED_CONTEXT, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_DUMMY_ON_CORE_SHUTDOWN, PARSE_ONLY_BOOL}, #ifndef HAVE_DYNAMIC {MENU_ENUM_LABEL_ALWAYS_RELOAD_CORE_ON_RUN_CONTENT, PARSE_ONLY_BOOL}, #endif }; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_MANAGER_LIST), msg_hash_to_str(MENU_ENUM_LABEL_CORE_MANAGER_LIST), MENU_ENUM_LABEL_CORE_MANAGER_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #ifdef HAVE_ONLINE_UPDATER if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATER_SETTINGS), msg_hash_to_str(MENU_ENUM_LABEL_UPDATER_SETTINGS), MENU_ENUM_LABEL_UPDATER_SETTINGS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_CONFIGURATION_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_CONFIG_SAVE_ON_EXIT, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_REMAP_SAVE_ON_EXIT, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_GAME_SPECIFIC_OPTIONS, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_AUTO_OVERRIDES_ENABLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_AUTO_REMAPS_ENABLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_INITIAL_DISK_CHANGE_ENABLE, PARSE_ONLY_BOOL}, {MENU_ENUM_LABEL_GLOBAL_CORE_OPTIONS, PARSE_ONLY_BOOL}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_DIRECTORY_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_SYSTEM_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_CORE_ASSETS_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_ASSETS_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_DYNAMIC_WALLPAPERS_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_THUMBNAILS_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_RGUI_BROWSER_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_RGUI_CONFIG_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_LIBRETRO_DIR_PATH, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_LIBRETRO_INFO_PATH, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_CONTENT_DATABASE_DIRECTORY, PARSE_ONLY_DIR}, #ifdef HAVE_CHEATS {MENU_ENUM_LABEL_CHEAT_DATABASE_PATH, PARSE_ONLY_DIR}, #endif #ifdef HAVE_VIDEO_FILTER {MENU_ENUM_LABEL_VIDEO_FILTER_DIR, PARSE_ONLY_DIR}, #endif #ifdef HAVE_DSP_FILTER {MENU_ENUM_LABEL_AUDIO_FILTER_DIR, PARSE_ONLY_DIR}, #endif {MENU_ENUM_LABEL_VIDEO_SHADER_DIR, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_RECORDING_OUTPUT_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_RECORDING_CONFIG_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_OVERLAY_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_OSK_OVERLAY_DIRECTORY, PARSE_ONLY_DIR}, #ifdef HAVE_SCREENSHOTS {MENU_ENUM_LABEL_SCREENSHOT_DIRECTORY, PARSE_ONLY_DIR}, #endif {MENU_ENUM_LABEL_JOYPAD_AUTOCONFIG_DIR, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_INPUT_REMAPPING_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_PLAYLIST_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_CONTENT_FAVORITES_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_CONTENT_HISTORY_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_CONTENT_IMAGE_HISTORY_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_CONTENT_MUSIC_HISTORY_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_CONTENT_VIDEO_HISTORY_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_RUNTIME_LOG_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_SAVEFILE_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_SAVESTATE_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_CACHE_DIRECTORY, PARSE_ONLY_DIR}, {MENU_ENUM_LABEL_LOG_DIR, PARSE_ONLY_DIR}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_DRIVER_SETTINGS_LIST: { menu_displaylist_build_info_t build_list[] = { {MENU_ENUM_LABEL_MENU_DRIVER, PARSE_ONLY_STRING_OPTIONS}, {MENU_ENUM_LABEL_VIDEO_DRIVER, PARSE_ONLY_STRING_OPTIONS}, {MENU_ENUM_LABEL_AUDIO_DRIVER, PARSE_ONLY_STRING_OPTIONS}, #ifdef HAVE_MICROPHONE {MENU_ENUM_LABEL_MICROPHONE_DRIVER, PARSE_ONLY_STRING_OPTIONS}, #endif #if 0 /* This is better suited under audio options only */ {MENU_ENUM_LABEL_AUDIO_RESAMPLER_DRIVER,PARSE_ONLY_STRING_OPTIONS}, #endif {MENU_ENUM_LABEL_INPUT_DRIVER, PARSE_ONLY_STRING_OPTIONS}, {MENU_ENUM_LABEL_JOYPAD_DRIVER, PARSE_ONLY_STRING_OPTIONS}, {MENU_ENUM_LABEL_RECORD_DRIVER, PARSE_ONLY_STRING_OPTIONS}, {MENU_ENUM_LABEL_MIDI_DRIVER, PARSE_ONLY_STRING_OPTIONS}, #ifdef HAVE_BLUETOOTH {MENU_ENUM_LABEL_BLUETOOTH_DRIVER, PARSE_ONLY_STRING_OPTIONS}, #endif #if defined(HAVE_LAKKA) || defined(HAVE_WIFI) {MENU_ENUM_LABEL_WIFI_DRIVER, PARSE_ONLY_STRING_OPTIONS}, #endif {MENU_ENUM_LABEL_CAMERA_DRIVER, PARSE_ONLY_STRING_OPTIONS}, {MENU_ENUM_LABEL_LOCATION_DRIVER, PARSE_ONLY_STRING_OPTIONS}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_LOGGING_SETTINGS_LIST: { bool log_to_file = settings->bools.log_to_file; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_LOG_VERBOSITY, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_FRONTEND_LOG_LEVEL, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_LIBRETRO_LOG_LEVEL, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_LOG_TO_FILE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_LOG_TO_FILE_TIMESTAMP, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_PERFCNT_ENABLE, PARSE_ONLY_BOOL, true}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_FRONTEND_LOG_LEVEL: case MENU_ENUM_LABEL_LIBRETRO_LOG_LEVEL: if (verbosity_is_enabled()) build_list[i].checked = true; break; case MENU_ENUM_LABEL_LOG_TO_FILE_TIMESTAMP: if (log_to_file) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_FRAME_TIME_COUNTER_SETTINGS_LIST: { menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_VIDEO_REFRESH_RATE_AUTO, PARSE_ONLY_FLOAT, true}, {MENU_ENUM_LABEL_FRAME_TIME_COUNTER_RESET_AFTER_FASTFORWARDING, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_FRAME_TIME_COUNTER_RESET_AFTER_LOAD_STATE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_FRAME_TIME_COUNTER_RESET_AFTER_SAVE_STATE, PARSE_ONLY_BOOL, true}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_REWIND_SETTINGS_LIST: { bool rewind_enable = settings->bools.rewind_enable; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_REWIND_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_REWIND_GRANULARITY, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_REWIND_BUFFER_SIZE, PARSE_ONLY_SIZE, false}, {MENU_ENUM_LABEL_REWIND_BUFFER_SIZE_STEP, PARSE_ONLY_UINT, false}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_REWIND_GRANULARITY: case MENU_ENUM_LABEL_REWIND_BUFFER_SIZE: case MENU_ENUM_LABEL_REWIND_BUFFER_SIZE_STEP: if (rewind_enable) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_FRAME_THROTTLE_SETTINGS_LIST: { #ifdef HAVE_REWIND bool rewind_supported = true; #endif menu_displaylist_build_info_selective_t build_list[] = { #ifdef HAVE_REWIND {MENU_ENUM_LABEL_REWIND_SETTINGS, PARSE_ACTION, false}, #endif {MENU_ENUM_LABEL_FRAME_TIME_COUNTER_SETTINGS, PARSE_ACTION, true}, {MENU_ENUM_LABEL_FASTFORWARD_RATIO, PARSE_ONLY_FLOAT, true}, {MENU_ENUM_LABEL_FASTFORWARD_FRAMESKIP, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_SLOWMOTION_RATIO, PARSE_ONLY_FLOAT, true}, {MENU_ENUM_LABEL_VRR_RUNLOOP_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_THROTTLE_FRAMERATE, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_VIDEO_FRAME_REST, PARSE_ONLY_BOOL, true}, }; #ifdef HAVE_REWIND if ( (flags & RUNLOOP_FLAG_CORE_RUNNING) && !retroarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) rewind_supported = core_info_current_supports_rewind(); if (rewind_supported) for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_REWIND_SETTINGS: build_list[i].checked = true; break; default: break; } } #endif for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_MENU_THROTTLE_FRAMERATE: if (settings->bools.vrr_runloop_enable) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; case DISPLAYLIST_MENU_SETTINGS_LIST: { bool menu_horizontal_animation = settings->bools.menu_horizontal_animation; bool menu_materialui_icons_enable = settings->bools.menu_materialui_icons_enable; bool menu_materialui_show_nav_bar = settings->bools.menu_materialui_show_nav_bar; bool menu_use_preferred_system_color_theme = settings->bools.menu_use_preferred_system_color_theme; bool truncate_playlist = settings->bools.ozone_truncate_playlist_name; unsigned menu_rgui_color_theme = settings->uints.menu_rgui_color_theme; unsigned menu_rgui_particle_effect = settings->uints.menu_rgui_particle_effect; unsigned menu_screensaver_timeout = settings->uints.menu_screensaver_timeout; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_MENU_SCALE_FACTOR, PARSE_ONLY_FLOAT, true}, {MENU_ENUM_LABEL_MENU_FRAMEBUFFER_OPACITY, PARSE_ONLY_FLOAT, true}, {MENU_ENUM_LABEL_XMB_RIBBON_ENABLE, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_XMB_MENU_COLOR_THEME, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_XMB_ALPHA_FACTOR, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_WALLPAPER_OPACITY, PARSE_ONLY_FLOAT, true}, {MENU_ENUM_LABEL_MENU_WALLPAPER, PARSE_ONLY_PATH , true}, {MENU_ENUM_LABEL_DYNAMIC_WALLPAPER, PARSE_ONLY_BOOL , true}, {MENU_ENUM_LABEL_MENU_USE_PREFERRED_SYSTEM_COLOR_THEME, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_OZONE_MENU_COLOR_THEME, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_MATERIALUI_MENU_COLOR_THEME, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_RGUI_MENU_COLOR_THEME, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_RGUI_MENU_THEME_PRESET, PARSE_ONLY_PATH, false}, {MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT_SPEED, PARSE_ONLY_FLOAT, false}, {MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT_SCREENSAVER, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_RGUI_BORDER_FILLER_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_RGUI_FULL_WIDTH_LAYOUT, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_RGUI_TRANSPARENCY, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_MENU_LINEAR_FILTER, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_RGUI_INTERNAL_UPSCALE_LEVEL, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_RGUI_ASPECT_RATIO, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_RGUI_ASPECT_RATIO_LOCK, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_XMB_VERTICAL_FADE_FACTOR, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_XMB_LAYOUT, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_RGUI_SHADOWS, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_XMB_SHADOWS_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MATERIALUI_ICONS_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MATERIALUI_PLAYLIST_ICONS_ENABLE, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_XMB_SWITCH_ICONS, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_RGUI_SWITCH_ICONS, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MATERIALUI_SWITCH_ICONS, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_XMB_THEME, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_OZONE_COLLAPSE_SIDEBAR, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MATERIALUI_LANDSCAPE_LAYOUT_OPTIMIZATION, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MATERIALUI_SHOW_NAV_BAR, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MATERIALUI_AUTO_ROTATE_NAV_BAR, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_MATERIALUI_MENU_HEADER_OPACITY, PARSE_ONLY_FLOAT, true}, {MENU_ENUM_LABEL_MATERIALUI_MENU_FOOTER_OPACITY, PARSE_ONLY_FLOAT, true}, {MENU_ENUM_LABEL_MATERIALUI_MENU_THUMBNAIL_VIEW_PORTRAIT, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MATERIALUI_MENU_THUMBNAIL_VIEW_LANDSCAPE, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MATERIALUI_DUAL_THUMBNAIL_LIST_VIEW_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MATERIALUI_THUMBNAIL_BACKGROUND_ENABLE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_RGUI_INLINE_THUMBNAILS, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_THUMBNAILS, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_LEFT_THUMBNAILS, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_XMB_VERTICAL_THUMBNAILS, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_XMB_THUMBNAIL_SCALE_FACTOR, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_OZONE_THUMBNAIL_SCALE_FACTOR, PARSE_ONLY_FLOAT, true}, {MENU_ENUM_LABEL_MENU_THUMBNAIL_UPSCALE_THRESHOLD, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_RGUI_SWAP_THUMBNAILS, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_RGUI_THUMBNAIL_DELAY, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_XMB_FONT, PARSE_ONLY_PATH, true}, {MENU_ENUM_LABEL_MENU_FONT_COLOR_RED, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_FONT_COLOR_GREEN, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_FONT_COLOR_BLUE, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_XMB_SHOW_TITLE_HEADER, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_XMB_TITLE_MARGIN, PARSE_ONLY_INT, true}, {MENU_ENUM_LABEL_MENU_XMB_TITLE_MARGIN_HORIZONTAL_OFFSET, PARSE_ONLY_INT, true}, {MENU_ENUM_LABEL_OZONE_TRUNCATE_PLAYLIST_NAME, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_OZONE_SORT_AFTER_TRUNCATE_PLAYLIST_NAME, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_MENU_TICKER_TYPE, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_TICKER_SPEED, PARSE_ONLY_FLOAT, true}, {MENU_ENUM_LABEL_MENU_TICKER_SMOOTH, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_OZONE_SCROLL_CONTENT_METADATA, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_RGUI_EXTENDED_ASCII, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MATERIALUI_MENU_TRANSITION_ANIMATION, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_MENU_HORIZONTAL_ANIMATION, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_MENU_XMB_ANIMATION_HORIZONTAL_HIGHLIGHT, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_MENU_XMB_ANIMATION_OPENING_MAIN_MENU, PARSE_ONLY_UINT, false}, {MENU_ENUM_LABEL_MENU_XMB_ANIMATION_MOVE_UP_DOWN, PARSE_ONLY_UINT, true}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_MENU_XMB_ANIMATION_HORIZONTAL_HIGHLIGHT: case MENU_ENUM_LABEL_MENU_XMB_ANIMATION_OPENING_MAIN_MENU: if (menu_horizontal_animation) build_list[i].checked = true; break; case MENU_ENUM_LABEL_RGUI_MENU_THEME_PRESET: if (menu_rgui_color_theme == RGUI_THEME_CUSTOM) build_list[i].checked = true; break; case MENU_ENUM_LABEL_MENU_RGUI_TRANSPARENCY: if ((menu_rgui_color_theme != RGUI_THEME_CUSTOM) && (menu_rgui_color_theme != RGUI_THEME_DYNAMIC)) build_list[i].checked = true; break; case MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT_SPEED: if (menu_rgui_particle_effect != RGUI_PARTICLE_EFFECT_NONE) build_list[i].checked = true; break; case MENU_ENUM_LABEL_MENU_RGUI_PARTICLE_EFFECT_SCREENSAVER: if ((menu_screensaver_timeout != 0) && (menu_rgui_particle_effect != RGUI_PARTICLE_EFFECT_NONE)) build_list[i].checked = true; break; case MENU_ENUM_LABEL_MATERIALUI_PLAYLIST_ICONS_ENABLE: if (menu_materialui_icons_enable) build_list[i].checked = true; break; case MENU_ENUM_LABEL_MATERIALUI_AUTO_ROTATE_NAV_BAR: if (menu_materialui_show_nav_bar) build_list[i].checked = true; break; case MENU_ENUM_LABEL_OZONE_MENU_COLOR_THEME: if (!menu_use_preferred_system_color_theme) build_list[i].checked = true; break; case MENU_ENUM_LABEL_OZONE_SORT_AFTER_TRUNCATE_PLAYLIST_NAME: if (truncate_playlist) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; #ifdef _3DS case DISPLAYLIST_MENU_BOTTOM_SETTINGS_LIST: { bool video_3ds_lcd_bottom = settings->bools.video_3ds_lcd_bottom; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_VIDEO_3DS_LCD_BOTTOM, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_BOTTOM_ASSETS_DIRECTORY, PARSE_ONLY_DIR, false}, {MENU_ENUM_LABEL_BOTTOM_FONT_ENABLE, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_BOTTOM_FONT_COLOR_RED, PARSE_ONLY_INT, false}, {MENU_ENUM_LABEL_BOTTOM_FONT_COLOR_GREEN, PARSE_ONLY_INT, false}, {MENU_ENUM_LABEL_BOTTOM_FONT_COLOR_BLUE, PARSE_ONLY_INT, false}, {MENU_ENUM_LABEL_BOTTOM_FONT_COLOR_OPACITY, PARSE_ONLY_INT, false}, {MENU_ENUM_LABEL_BOTTOM_FONT_SCALE, PARSE_ONLY_FLOAT, false}, }; for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_BOTTOM_ASSETS_DIRECTORY: case MENU_ENUM_LABEL_BOTTOM_FONT_ENABLE: case MENU_ENUM_LABEL_BOTTOM_FONT_COLOR_RED: case MENU_ENUM_LABEL_BOTTOM_FONT_COLOR_GREEN: case MENU_ENUM_LABEL_BOTTOM_FONT_COLOR_BLUE: case MENU_ENUM_LABEL_BOTTOM_FONT_COLOR_OPACITY: case MENU_ENUM_LABEL_BOTTOM_FONT_SCALE: if (video_3ds_lcd_bottom) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked && !include_everything) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } break; #endif case DISPLAYLIST_BROWSE_URL_LIST: if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_BROWSE_URL), msg_hash_to_str(MENU_ENUM_LABEL_BROWSE_URL), MENU_ENUM_LABEL_BROWSE_URL, 0, 0, 0, NULL)) count++; if (menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_BROWSE_START), msg_hash_to_str(MENU_ENUM_LABEL_BROWSE_START), MENU_ENUM_LABEL_BROWSE_START, 0, 0, 0, NULL)) count++; break; case DISPLAYLIST_DISC_INFO: #ifdef HAVE_CDROM count = menu_displaylist_parse_disc_info(list, MENU_SET_CDROM_INFO); #endif break; case DISPLAYLIST_DUMP_DISC: #ifdef HAVE_CDROM count = menu_displaylist_parse_disc_info(list, MENU_SET_CDROM_LIST); #endif break; #ifdef HAVE_LAKKA case DISPLAYLIST_EJECT_DISC: #ifdef HAVE_CDROM count = menu_displaylist_parse_disc_info(list, MENU_SET_EJECT_DISC); #endif /* HAVE_CDROM */ break; #endif /* HAVE_LAKKA */ default: break; } return count; } /* Returns true if selection pointer should be reset * to zero when viewing specified history playlist */ static bool history_needs_navigation_clear( menu_handle_t *menu, playlist_t *playlist) { if (menu) { /* If content is running, compare last selected path * with current content path */ if (!retroarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) return string_is_equal(menu->deferred_path, path_get(RARCH_PATH_CONTENT)); /* If content is not running, have to examine the * playlist... */ if (playlist) { if (menu->rpl_entry_selection_ptr < playlist_size(playlist)) { const struct playlist_entry *entry = NULL; playlist_get_index(playlist, menu->rpl_entry_selection_ptr, &entry); return !string_is_equal(menu->deferred_path, entry->path); } } } return false; } static unsigned menu_displaylist_build_shader_parameter( file_list_t *list, unsigned entry_type, unsigned _offset, unsigned setting_type) { video_shader_ctx_t shader_info; float current_value = 0.0f; float original_value = 0.0f; unsigned count = 0; float min = 0.0f; float max = 0.0f; float half_step = 0.0f; unsigned i = 0; unsigned checked = 0; bool checked_found = false; struct video_shader_parameter *param = NULL; unsigned offset = entry_type - _offset; video_shader_driver_get_current_shader(&shader_info); param = &shader_info.data->parameters[offset]; if (!param) return 0; min = param->minimum; max = param->maximum; half_step = param->step * 0.5f; current_value = min; original_value = param->current; for (i = 0; current_value < (max + 0.0001f); i++) { char val_s[16], val_d[16]; snprintf(val_s, sizeof(val_s), "%.2f", current_value); snprintf(val_d, sizeof(val_d), "%d", i); if (menu_entries_append(list, val_s, val_d, MENU_ENUM_LABEL_NO_ITEMS, setting_type, i, entry_type, NULL)) { if (!checked_found && (fabs(current_value - original_value) < half_step)) { checked = count; checked_found = true; } count++; } current_value += param->step; } if (checked_found) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)list->list[checked].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = checked; } return count; } #ifdef HAVE_NETWORKING static unsigned print_buf_lines(file_list_t *list, char *buf, const char *label, int buf_size, enum msg_file_type type, bool append, bool extended) { char c; unsigned count = 0; int i = 0; char *line_start = buf; if (!buf || !buf_size) return 0; if (extended) { for (i = 0; i < buf_size; i++) { size_t ln; /* The end of the buffer, print the last bit */ if (*(buf + i) == '\0') break; if (*(buf + i) != '\n') continue; /* Found a line ending, print the line and compute new line_start */ c = *(buf + i + 1); /* Save the next character */ *(buf + i + 1) = '\0'; /* Replace with \0 */ /* We need to strip the newline. */ ln = strlen(line_start) - 1; if (line_start[ln] == '\n') line_start[ln] = '\0'; { char *save = NULL; char *line_start_cpy = strdup(line_start); const char *con = strtok_r(line_start_cpy, " ", &save); if (con) { if ((con = strtok_r(NULL, " ", &save))) { if ((con = strtok_r(NULL, " ", &save))) { /* Get third parameter */ if (append) { if (menu_entries_append(list, con, "", MENU_ENUM_LABEL_URL_ENTRY, type, 0, 0, NULL)) count++; } else { menu_entries_prepend(list, con, "", MENU_ENUM_LABEL_URL_ENTRY, type, 0, 0); count++; } } } } free(line_start_cpy); } /* Restore the saved character */ *(buf + i + 1) = c; line_start = buf + i + 1; } } else { for (i = 0; i < buf_size; i++) { size_t ln; /* The end of the buffer, print the last bit */ if (*(buf + i) == '\0') break; if (*(buf + i) != '\n') continue; /* Found a line ending, print the line and compute new line_start */ c = *(buf + i + 1); /* Save the next character */ *(buf + i + 1) = '\0'; /* Replace with \0 */ /* We need to strip the newline. */ ln = strlen(line_start) - 1; if (line_start[ln] == '\n') line_start[ln] = '\0'; if (append) { if (menu_entries_append(list, line_start, label, MENU_ENUM_LABEL_URL_ENTRY, type, 0, 0, NULL)) count++; } else { menu_entries_prepend(list, line_start, label, MENU_ENUM_LABEL_URL_ENTRY, type, 0, 0); count++; } /* Restore the saved character */ *(buf + i + 1) = c; line_start = buf + i + 1; } } if (append && type != FILE_TYPE_DOWNLOAD_LAKKA) file_list_sort_on_alt(list); /* If the buffer was completely full, and didn't end * with a newline, just ignore the partial last line. */ return count; } static unsigned menu_displaylist_netplay_kick(file_list_t *list) { unsigned count = 0; if (netplay_driver_ctl(RARCH_NETPLAY_CTL_REFRESH_CLIENT_INFO, NULL)) { size_t i; char client_id[4]; net_driver_state_t *net_st = networking_state_get_ptr(); for (i = 0; i < net_st->client_info_count; i++) { netplay_client_info_t *client = &net_st->client_info[i]; snprintf(client_id, sizeof(client_id), "%d", client->id); if (menu_entries_append(list, client->name, client_id, MENU_ENUM_LABEL_NETPLAY_KICK_CLIENT, MENU_NETPLAY_KICK, 0, i, NULL)) count++; } } return count; } static unsigned menu_displaylist_netplay_ban(file_list_t *list) { unsigned count = 0; if (netplay_driver_ctl(RARCH_NETPLAY_CTL_REFRESH_CLIENT_INFO, NULL)) { size_t i; char client_id[4]; net_driver_state_t *net_st = networking_state_get_ptr(); for (i = 0; i < net_st->client_info_count; i++) { netplay_client_info_t *client = &net_st->client_info[i]; snprintf(client_id, sizeof(client_id), "%d", client->id); if (menu_entries_append(list, client->name, client_id, MENU_ENUM_LABEL_NETPLAY_BAN_CLIENT, MENU_NETPLAY_BAN, 0, i, NULL)) count++; } } return count; } #endif bool menu_displaylist_has_subsystems(void) { runloop_state_t *runloop_st = runloop_state_get_ptr(); const struct retro_subsystem_info* subsystem = runloop_st->subsystem_data; rarch_system_info_t *sys_info = &runloop_st->system; /* Core not loaded completely, use the data we * peeked on load core */ /* Core fully loaded, use the subsystem data */ if (sys_info && sys_info->subsystem.data) subsystem = sys_info->subsystem.data; return (subsystem && runloop_st->subsystem_current_count > 0); } bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist_info_t *info, settings_t *settings) { struct menu_state *menu_st = menu_state_get_ptr(); menu_dialog_t *p_dialog = &menu_st->dialog_st; bool push_list = (menu_st->driver_ctx->list_push && menu_st->driver_ctx->list_push(menu_st->driver_data, menu_st->userdata, info, type) == 0); if (!push_list) { menu_handle_t *menu = menu_st->driver_data; bool load_content = true; bool use_filebrowser = false; unsigned count = 0; int ret = 0; switch (type) { case DISPLAYLIST_NETWORK_HOSTING_SETTINGS_LIST: #ifdef HAVE_NETWORKING { size_t i; file_list_t *list = info->list; bool netplay_allow_slaves = settings->bools.netplay_allow_slaves; bool netplay_use_mitm_server = settings->bools.netplay_use_mitm_server; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_NETPLAY_MAX_CONNECTIONS, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_NETPLAY_MAX_PING, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_NETPLAY_PUBLIC_ANNOUNCE, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_USE_MITM_SERVER, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_MITM_SERVER, PARSE_ONLY_STRING, false}, {MENU_ENUM_LABEL_NETPLAY_CUSTOM_MITM_SERVER, PARSE_ONLY_STRING, false}, {MENU_ENUM_LABEL_NETPLAY_PASSWORD, PARSE_ONLY_STRING, true}, {MENU_ENUM_LABEL_NETPLAY_SPECTATE_PASSWORD, PARSE_ONLY_STRING, true}, {MENU_ENUM_LABEL_NETPLAY_ALLOW_PAUSING, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_ALLOW_SLAVES, PARSE_ONLY_BOOL, true}, {MENU_ENUM_LABEL_NETPLAY_REQUIRE_SLAVES, PARSE_ONLY_BOOL, false}, {MENU_ENUM_LABEL_NETPLAY_NAT_TRAVERSAL, PARSE_ONLY_BOOL, true}, }; menu_entries_clear(list); if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL)) { if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_SERVER, NULL)) { menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_DISABLE_HOST), msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_DISCONNECT), MENU_ENUM_LABEL_NETPLAY_DISCONNECT, MENU_SETTING_ACTION, 0, 0, NULL); if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL)) { menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_KICK), msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_KICK), MENU_ENUM_LABEL_NETPLAY_KICK, MENU_SETTING_ACTION, 0, 0, NULL); menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_BAN), msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_BAN), MENU_ENUM_LABEL_NETPLAY_BAN, MENU_SETTING_ACTION, 0, 0, NULL); } } } else { menu_entries_append(list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_ENABLE_HOST), msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_ENABLE_HOST), MENU_ENUM_LABEL_NETPLAY_ENABLE_HOST, MENU_SETTING_ACTION, 0, 0, NULL); } for (i = 0; i < ARRAY_SIZE(build_list); i++) { switch (build_list[i].enum_idx) { case MENU_ENUM_LABEL_NETPLAY_REQUIRE_SLAVES: if (netplay_allow_slaves) build_list[i].checked = true; break; case MENU_ENUM_LABEL_NETPLAY_MITM_SERVER: case MENU_ENUM_LABEL_NETPLAY_CUSTOM_MITM_SERVER: if (netplay_use_mitm_server) build_list[i].checked = true; break; default: break; } } for (i = 0; i < ARRAY_SIZE(build_list); i++) { if (!build_list[i].checked) continue; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, build_list[i].enum_idx, build_list[i].parse_type, false) == 0) count++; } } #endif info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_NETPLAY_KICK_LIST: #ifdef HAVE_NETWORKING menu_entries_clear(info->list); count = menu_displaylist_netplay_kick(info->list); if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_NETPLAY_CLIENTS_FOUND), msg_hash_to_str(MENU_ENUM_LABEL_NO_NETPLAY_CLIENTS_FOUND), MENU_ENUM_LABEL_NO_NETPLAY_CLIENTS_FOUND, 0, 0, 0, NULL)) count++; #endif info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_NETPLAY_BAN_LIST: #ifdef HAVE_NETWORKING menu_entries_clear(info->list); count = menu_displaylist_netplay_ban(info->list); if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_NETPLAY_CLIENTS_FOUND), msg_hash_to_str(MENU_ENUM_LABEL_NO_NETPLAY_CLIENTS_FOUND), MENU_ENUM_LABEL_NO_NETPLAY_CLIENTS_FOUND, 0, 0, 0, NULL)) count++; #endif info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_OPTIONS_REMAPPINGS_PORT: { unsigned max_users = settings->uints.input_max_users; struct menu_state *menu_st = menu_state_get_ptr(); const char *menu_driver = menu_driver_ident(); bool is_rgui = string_is_equal(menu_driver, "rgui"); file_list_t *list = info->list; unsigned port = string_to_unsigned(info->path); unsigned mapped_port = settings->uints.input_remap_ports[port]; size_t selection = menu_st->selection_ptr; menu_entries_clear(info->list); { char key[64]; key[0] = '\0'; snprintf(key, sizeof(key), msg_hash_to_str(MENU_ENUM_LABEL_INPUT_LIBRETRO_DEVICE), mapped_port + 1); if (MENU_DISPLAYLIST_PARSE_SETTINGS(list, key, PARSE_ONLY_UINT, true, MENU_SETTINGS_INPUT_LIBRETRO_DEVICE) == 0) count++; snprintf(key, sizeof(key), msg_hash_to_str(MENU_ENUM_LABEL_INPUT_PLAYER_ANALOG_DPAD_MODE), port + 1); if (MENU_DISPLAYLIST_PARSE_SETTINGS(list, key, PARSE_ONLY_UINT, true, MENU_SETTINGS_INPUT_ANALOG_DPAD_MODE) == 0) count++; snprintf(key, sizeof(key), msg_hash_to_str(MENU_ENUM_LABEL_INPUT_REMAP_PORT), port + 1); if (MENU_DISPLAYLIST_PARSE_SETTINGS(list, key, PARSE_ONLY_UINT, true, MENU_SETTINGS_INPUT_INPUT_REMAP_PORT) == 0) count++; } { unsigned j; unsigned device = settings->uints.input_libretro_device[mapped_port]; device &= RETRO_DEVICE_MASK; if (device == RETRO_DEVICE_JOYPAD || device == RETRO_DEVICE_ANALOG) { const char *msg_val_port = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PORT); for (j = 0; j < RARCH_ANALOG_BIND_LIST_END; j++) { char descriptor[300]; unsigned retro_id = (j < RARCH_ANALOG_BIND_LIST_END) ? input_config_bind_order[j] : j; const struct retro_keybind *keybind = &input_config_binds[port][retro_id]; const struct retro_keybind *auto_bind = (const struct retro_keybind*) input_config_get_bind_auto(port, retro_id); size_t desc_len = input_config_get_bind_string( settings, descriptor, keybind, auto_bind, sizeof(descriptor)); if (!strstr(descriptor, "Auto")) { char desc_label[400]; const struct retro_keybind *keyptr = &input_config_binds[port][retro_id]; size_t _len = strlcpy(desc_label, msg_hash_to_str(keyptr->enum_idx), sizeof(desc_label)); desc_label[ _len] = ','; desc_label[++_len] = ' '; desc_label[++_len] = '\0'; strlcpy(desc_label + _len, descriptor, sizeof(desc_label) - _len); desc_len = strlcpy(descriptor, desc_label, sizeof(descriptor)); } /* Add user index when display driver == rgui and sublabels * are disabled, but only if there is more than one user */ if ( (is_rgui) && (max_users > 1) && !settings->bools.menu_show_sublabels) { desc_len += strlcpy(descriptor + desc_len, " [", sizeof(descriptor) - desc_len); snprintf(descriptor + desc_len, sizeof(descriptor) - desc_len, "%s %u]", msg_val_port, port + 1); } /* Note: 'physical' port is passed as label */ if (menu_entries_append(list, descriptor, info->path, MSG_UNKNOWN, MENU_SETTINGS_INPUT_DESC_BEGIN + (port * (RARCH_FIRST_CUSTOM_BIND + 8)) + retro_id, 0, 0, NULL)) count++; } } else if (device == RETRO_DEVICE_KEYBOARD) { const char *val_port = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PORT); for (j = 0; j < RARCH_ANALOG_BIND_LIST_END; j++) { char descriptor[300]; unsigned retro_id = (j < RARCH_ANALOG_BIND_LIST_END) ? input_config_bind_order[j] : j; const struct retro_keybind *keybind = &input_config_binds[port][retro_id]; const struct retro_keybind *auto_bind = (const struct retro_keybind*) input_config_get_bind_auto(port, retro_id); size_t desc_len = input_config_get_bind_string( settings, descriptor, keybind, auto_bind, sizeof(descriptor)); if (!strstr(descriptor, "Auto")) { char desc_label[400]; const struct retro_keybind *keyptr = &input_config_binds[port][retro_id]; size_t _len = strlcpy(desc_label, msg_hash_to_str(keyptr->enum_idx), sizeof(desc_label)); desc_label[ _len] = ','; desc_label[++_len] = ' '; desc_label[++_len] = '\0'; strlcpy(desc_label + _len, descriptor, sizeof(desc_label) - _len); desc_len = strlcpy(descriptor, desc_label, sizeof(descriptor)); } /* Add user index when display driver == rgui and sublabels * are disabled, but only if there is more than one user */ if ( (is_rgui) && (max_users > 1) && !settings->bools.menu_show_sublabels) { desc_len += strlcpy(descriptor + desc_len, " [", sizeof(descriptor) - desc_len); snprintf(descriptor + desc_len, sizeof(descriptor) - desc_len, "%s %u]", val_port, port + 1); } /* Note: 'physical' port is passed as label */ if (menu_entries_append(list, descriptor, info->path, MSG_UNKNOWN, MENU_SETTINGS_INPUT_DESC_KBD_BEGIN + (port * RARCH_ANALOG_BIND_LIST_END) + retro_id, 0, 0, NULL)) count++; } } } info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; if (selection >= count) info->flags |= MD_FLAG_NEED_CLEAR; } break; #ifdef HAVE_CDROM case DISPLAYLIST_CDROM_DETAIL_INFO: { RFILE *file; media_detect_cd_info_t cd_info = {{0}}; char file_path[PATH_MAX_LENGTH] = {0}; char drive = info->path[0]; bool atip = false; menu_entries_clear(info->list); count = 0; if (cdrom_drive_has_media(drive)) { cdrom_device_fillpath(file_path, sizeof(file_path), drive, 0, true); /* opening the cue triggers storing of TOC info internally */ if ((file = filestream_open(file_path, RETRO_VFS_FILE_ACCESS_READ, 0))) { unsigned i; const cdrom_toc_t *toc = retro_vfs_file_get_cdrom_toc(); unsigned first_data_track = 1; atip = cdrom_has_atip( filestream_get_vfs_handle(file)); filestream_close(file); for (i = 0; i < toc->num_tracks; i++) { if (!toc->track[i].audio) { first_data_track = i + 1; break; } } /* open first data track */ memset(file_path, 0, sizeof(file_path)); cdrom_device_fillpath(file_path, sizeof(file_path), drive, first_data_track, false); if (media_detect_cd_info(file_path, 0, &cd_info)) { if (!string_is_empty(cd_info.title)) { /* TODO/FIXME - localize */ char title[sizeof("Title: ") + sizeof(cd_info.title)]; /* TODO/FIXME - C89 compliance */ size_t _len = strlcpy(title, "Title: ", sizeof(title)); strlcpy(title + _len, cd_info.title, sizeof(title) - _len); if (menu_entries_append(info->list, title, "", MSG_UNKNOWN, FILE_TYPE_NONE, 0, 0, NULL)) count++; } if (!string_is_empty(cd_info.system)) { char system[256]; /* TODO/FIXME - Localize */ size_t _len = strlcpy(system, "System: ", sizeof(system)); strlcpy(system + _len, cd_info.system, sizeof(system) - _len); if (menu_entries_append(info->list, system, "", MSG_UNKNOWN, FILE_TYPE_NONE, 0, 0, NULL)) count++; } if (!string_is_empty(cd_info.serial)) { char serial[256]; size_t _len = strlcpy(serial, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RDB_ENTRY_SERIAL), sizeof(serial)); _len += strlcpy(serial + _len, "#: ", sizeof(serial) - _len); strlcpy(serial + _len, cd_info.serial, sizeof(serial) - _len); if (menu_entries_append(info->list, serial, "", MSG_UNKNOWN, FILE_TYPE_NONE, 0, 0, NULL)) count++; } if (!string_is_empty(cd_info.version)) { char version[256]; /* TODO/FIXME - localize */ size_t _len = strlcpy(version, "Version: ", sizeof(version)); strlcpy(version + _len, cd_info.version, sizeof(version) - _len); if (menu_entries_append(info->list, version, "", MSG_UNKNOWN, FILE_TYPE_NONE, 0, 0, NULL)) count++; } if (!string_is_empty(cd_info.release_date)) { char release_date[256]; /* TODO/FIXME - Localize */ size_t _len = strlcpy(release_date, "Release Date: ", sizeof(release_date)); strlcpy(release_date + _len, cd_info.release_date, sizeof(release_date) - _len); if (menu_entries_append(info->list, release_date, "", MSG_UNKNOWN, FILE_TYPE_NONE, 0, 0, NULL)) count++; } if (atip) { /* TODO/FIXME - Localize */ const char *atip_string = "Genuine Disc: No"; if (menu_entries_append(info->list, atip_string, "", MSG_UNKNOWN, FILE_TYPE_NONE, 0, 0, NULL)) count++; } else { /* TODO/FIXME - Localize */ const char *atip_string = "Genuine Disc: Yes"; if (menu_entries_append(info->list, atip_string, "", MSG_UNKNOWN, FILE_TYPE_NONE, 0, 0, NULL)) count++; } { /* TODO/FIXME - Localize */ char tracks_str[32] = {"Number of tracks: "}; size_t strlen_tracks_str = STRLEN_CONST("Number of tracks: "); snprintf(tracks_str + strlen_tracks_str, sizeof(tracks_str) - strlen_tracks_str, "%d", toc->num_tracks); if (menu_entries_append(info->list, tracks_str, "", MSG_UNKNOWN, FILE_TYPE_NONE, 0, 0, NULL)) count++; } { unsigned i; for (i = 0; i < toc->num_tracks; i++) { char track_str[16] = {"Track "}; char mode_str[16] = {" - Mode: "}; char size_str[32] = {" - Size: "}; char length_str[32] = {" - Length: "}; size_t strlen_track_str = STRLEN_CONST("Track "); size_t strlen_mode_str = STRLEN_CONST(" - Mode: "); size_t strlen_size_str = STRLEN_CONST(" - Size: "); snprintf(track_str + strlen_track_str, sizeof(track_str) - strlen_track_str, "%d:", i + 1); if (menu_entries_append(info->list, track_str, "", MSG_UNKNOWN, FILE_TYPE_NONE, 0, 0, NULL)) count++; /* TODO/FIXME - localize */ if (toc->track[i].audio) snprintf(mode_str + strlen_mode_str, sizeof(mode_str) - strlen_mode_str, "Audio"); else snprintf(mode_str + strlen_mode_str, sizeof(mode_str) - strlen_mode_str, "Mode %d", toc->track[i].mode%10); if (menu_entries_append(info->list, mode_str, "", MSG_UNKNOWN, FILE_TYPE_NONE, 0, 0, NULL)) count++; snprintf(size_str + strlen_size_str, sizeof(size_str) - strlen_size_str, "%.1f MB", toc->track[i].track_bytes / 1000.0 / 1000.0); if (menu_entries_append(info->list, size_str, "", MSG_UNKNOWN, FILE_TYPE_NONE, 0, 0, NULL)) count++; { unsigned char min = 0; unsigned char sec = 0; unsigned char frame = 0; size_t strlen_length_str = strlen(length_str); cdrom_lba_to_msf(toc->track[i].track_size, &min, &sec, &frame); snprintf(length_str + strlen_length_str, sizeof(length_str) - strlen_length_str, "%02d:%02d.%02d", min, sec, frame); if (menu_entries_append(info->list, length_str, "", MSG_UNKNOWN, FILE_TYPE_NONE, 0, 0, NULL)) count++; } } } } else RARCH_ERR("[CDROM]: Could not detect any disc info.\n"); } else RARCH_ERR("[CDROM]: Error opening file for reading: %s\n", file_path); } else { /* TODO/FIXME - localize */ RARCH_LOG("[CDROM]: No media is inserted or drive is not ready.\n"); runloop_msg_queue_push( msg_hash_to_str(MSG_NO_DISC_INSERTED), 1, 100, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); } if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_CLEAR; break; } case DISPLAYLIST_LOAD_DISC: menu_entries_clear(info->list); count = menu_displaylist_parse_disc_info(info->list, MENU_SET_LOAD_CDROM_LIST); if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_CLEAR; break; #else case DISPLAYLIST_CDROM_DETAIL_INFO: case DISPLAYLIST_LOAD_DISC: /* No-op */ break; #endif #ifdef HAVE_LAKKA case DISPLAYLIST_CPU_POLICY_LIST: menu_entries_clear(info->list); menu_entries_append(info->list, info->path, info->path, MENU_ENUM_LABEL_CPU_POLICY_MIN_FREQ, MENU_SETTINGS_CPU_POLICY_SET_MINFREQ, 0, 0, NULL); menu_entries_append(info->list, info->path, info->path, MENU_ENUM_LABEL_CPU_POLICY_MAX_FREQ, MENU_SETTINGS_CPU_POLICY_SET_MAXFREQ, 0, 0, NULL); menu_entries_append(info->list, info->path, info->path, MENU_ENUM_LABEL_CPU_POLICY_GOVERNOR, MENU_SETTINGS_CPU_POLICY_SET_GOVERNOR, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_CLEAR; break; case DISPLAYLIST_CPU_PERFPOWER_LIST: { cpu_scaling_driver_t **drivers = get_cpu_scaling_drivers(true); menu_entries_clear(info->list); if (drivers) { int count = 0; menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CPU_PERF_MODE), msg_hash_to_str(MENU_ENUM_LABEL_CPU_PERF_MODE), MENU_ENUM_LABEL_CPU_PERF_MODE, 0, 0, 0, NULL); switch (get_cpu_scaling_mode(NULL)) { case CPUSCALING_MANUAL: while (*drivers) { char policyid[16]; snprintf(policyid, sizeof(policyid), "%u", count++); menu_entries_append(info->list, policyid, policyid, MENU_ENUM_LABEL_CPU_POLICY_ENTRY, 0, 0, 0, NULL); drivers++; } break; case CPUSCALING_MANAGED_PER_CONTEXT: /* Allows user to pick two governors */ menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CPU_POLICY_CORE_GOVERNOR), "0", MENU_ENUM_LABEL_CPU_POLICY_CORE_GOVERNOR, 0, 0, 0, NULL); menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CPU_POLICY_MENU_GOVERNOR), "1", MENU_ENUM_LABEL_CPU_POLICY_MENU_GOVERNOR, 0, 0, 0, NULL); /* fallthrough */ case CPUSCALING_MANAGED_PERFORMANCE: /* Allow users to choose max/min frequencies */ menu_entries_append(info->list, "0", "0", MENU_ENUM_LABEL_CPU_MANAGED_MIN_FREQ, MENU_SETTINGS_CPU_MANAGED_SET_MINFREQ, 0, 0, NULL); menu_entries_append(info->list, "1", "1", MENU_ENUM_LABEL_CPU_MANAGED_MAX_FREQ, MENU_SETTINGS_CPU_MANAGED_SET_MAXFREQ, 0, 0, NULL); break; case CPUSCALING_MAX_PERFORMANCE: case CPUSCALING_MIN_POWER: case CPUSCALING_BALANCED: /* No settings for these modes */ break; }; } info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_CLEAR; break; } #endif #if defined(HAVE_LIBNX) case DISPLAYLIST_SWITCH_CPU_PROFILE: { size_t _len; unsigned i; char text[PATH_MAX_LENGTH]; const size_t profiles_count = sizeof(SWITCH_CPU_PROFILES)/sizeof(SWITCH_CPU_PROFILES[1]); /* TODO/FIXME - localize */ runloop_msg_queue_push("Warning : extended overclocking can damage the Switch", 1, 90, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); menu_entries_clear(info->list); { u32 currentClock = 0; if (hosversionBefore(8, 0, 0)) pcvGetClockRate(PcvModule_CpuBus, ¤tClock); else { ClkrstSession session = {0}; clkrstOpenSession(&session, PcvModuleId_CpuBus, 3); clkrstGetClockRate(&session, ¤tClock); clkrstCloseSession(&session); } /* TODO/FIXME - localize */ _len = strlcpy(text, "Current clock: ", sizeof(text)); snprintf(text + _len, sizeof(text) - _len, "%i", currentClock); } if (menu_entries_append(info->list, text, "", 0, MENU_INFO_MESSAGE, 0, 0, NULL)) count++; for (i = 0; i < profiles_count; i++) { char title[PATH_MAX_LENGTH]; char* profile = SWITCH_CPU_PROFILES[i]; char* speed = SWITCH_CPU_SPEEDS[i]; size_t _len = strlcpy(title, profile, sizeof(title)); snprintf(title + _len, sizeof(title) - _len, " (%s)", speed); if (menu_entries_append(info->list, title, "", 0, MENU_SET_SWITCH_CPU_PROFILE, 0, i, NULL)) count++; } info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_CLEAR; break; } #endif /* HAVE_LIBNX */ case DISPLAYLIST_MUSIC_LIST: { #if defined(HAVE_AUDIOMIXER) || defined(HAVE_FFMPEG) || defined(HAVE_MPV) bool multimedia_builtin_mediaplayer_enable = settings->bools.multimedia_builtin_mediaplayer_enable; char combined_path[PATH_MAX_LENGTH]; const char *ext = NULL; fill_pathname_join_special(combined_path, menu->scratch2_buf, menu->scratch_buf, sizeof(combined_path)); ext = path_get_extension(combined_path); #endif menu_entries_clear(info->list); #if defined(HAVE_AUDIOMIXER) || defined(HAVE_FFMPEG) || defined(HAVE_MPV) if (multimedia_builtin_mediaplayer_enable) { #if defined(HAVE_FFMPEG) || defined(HAVE_MPV) struct retro_system_info sysinfo = {0}; #endif #ifdef HAVE_AUDIOMIXER if (audio_driver_mixer_extension_supported(ext)) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER_AND_COLLECTION), msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_MIXER_AND_COLLECTION), MENU_ENUM_LABEL_ADD_TO_MIXER_AND_COLLECTION, FILE_TYPE_PLAYLIST_ENTRY, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER_AND_COLLECTION_AND_PLAY), msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_MIXER_AND_COLLECTION_AND_PLAY), MENU_ENUM_LABEL_ADD_TO_MIXER_AND_COLLECTION_AND_PLAY, FILE_TYPE_PLAYLIST_ENTRY, 0, 0, NULL)) count++; } #endif #if defined(HAVE_FFMPEG) || defined(HAVE_MPV) #if defined(HAVE_FFMPEG) libretro_ffmpeg_retro_get_system_info(&sysinfo); #elif defined(HAVE_MPV) libretro_mpv_retro_get_system_info(&sysinfo); #endif if (strstr(sysinfo.valid_extensions,ext)) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RUN_MUSIC), msg_hash_to_str(MENU_ENUM_LABEL_RUN_MUSIC), MENU_ENUM_LABEL_RUN_MUSIC, FILE_TYPE_PLAYLIST_ENTRY, 0, 0, NULL)) count++; } #endif } #endif } if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ITEMS), msg_hash_to_str(MENU_ENUM_LABEL_NO_ITEMS), MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_NO_ITEM, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_CLEAR; break; case DISPLAYLIST_MIXER_STREAM_SETTINGS_LIST: menu_entries_clear(info->list); #ifdef HAVE_AUDIOMIXER { char lbl[128]; char mixer_stream_str[128]; unsigned id = info->type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_BEGIN; size_t _len = strlcpy(mixer_stream_str, "mixer_stream_", sizeof(mixer_stream_str)); lbl[0] = '\0'; snprintf(mixer_stream_str + _len, sizeof(mixer_stream_str) - _len, "%d", id); _len = strlcpy(lbl, mixer_stream_str, sizeof(lbl)); strlcpy(lbl + _len, "_action_play", sizeof(lbl) - _len); if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_PLAY), lbl, MSG_UNKNOWN, (MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_BEGIN + id), 0, 0, NULL)) count++; strlcpy(lbl + _len, "_action_play_looped", sizeof(lbl) - _len); if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_PLAY_LOOPED), lbl, MSG_UNKNOWN, (MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_BEGIN + id), 0, 0, NULL)) count++; strlcpy(lbl + _len, "_action_play_sequential",sizeof(lbl) - _len); if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_PLAY_SEQUENTIAL), lbl, MSG_UNKNOWN, (MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_SEQUENTIAL_BEGIN + id), 0, 0, NULL)) count++; strlcpy(lbl + _len, "_action_stop", sizeof(lbl) - _len); if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_STOP), lbl, MSG_UNKNOWN, (MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_STOP_BEGIN + id), 0, 0, NULL)) count++; strlcpy(lbl + _len, "_action_remove", sizeof(lbl) - _len); if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_REMOVE), lbl, MSG_UNKNOWN, (MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_REMOVE_BEGIN + id), 0, 0, NULL)) count++; strlcpy(lbl + _len, "_action_volume", sizeof(lbl) - _len); if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_VOLUME), lbl, MSG_UNKNOWN, (MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN + id), 0, 0, NULL)) count++; } #endif if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_CLEAR; break; case DISPLAYLIST_NETPLAY_LAN_SCAN_SETTINGS_LIST: case DISPLAYLIST_OPTIONS_MANAGEMENT: /* TODO/FIXME ? */ break; case DISPLAYLIST_NETPLAY: menu_entries_clear(info->list); info->flags |= MD_FLAG_NEED_PUSH; /* TODO/FIXME ? */ break; case DISPLAYLIST_INFORMATION: menu_entries_clear(info->list); if (settings) count = menu_displaylist_parse_content_information(menu, settings, info->list); if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_DATABASE_ENTRY: menu_entries_clear(info->list); { char *elem0 = NULL; char *elem1 = NULL; #ifdef HAVE_LIBRETRODB bool parse_database = false; #endif if (!string_is_empty(info->label)) { char *tok, *save; char *info_label_cpy = strdup(info->label); if ((tok = strtok_r(info_label_cpy, "|", &save))) elem0 = strdup(tok); if ((tok = strtok_r(NULL, "|", &save))) elem1 = strdup(tok); free(info_label_cpy); free(info->label); info->label = NULL; } if (!string_is_empty(info->path_b)) { free(info->path_b); info->path_b = NULL; } if ( !string_is_empty(elem0) && !string_is_empty(elem1)) { info->path_b = elem1; info->label = elem0; #ifdef HAVE_LIBRETRODB parse_database = true; #endif } #ifdef HAVE_LIBRETRODB if (parse_database) ret = menu_displaylist_parse_database_entry(menu, settings, info); else info->flags |= MD_FLAG_NEED_PUSH_NO_PLAYLIST_ENTRIES; #else ret = 0; info->flags |= MD_FLAG_NEED_PUSH_NO_PLAYLIST_ENTRIES; #endif } info->flags |= MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_DATABASE_QUERY: menu_entries_clear(info->list); #ifdef HAVE_LIBRETRODB { unsigned i; const char *query = string_is_empty(info->path_c) ? NULL : info->path_c; database_info_list_t *db_list = database_info_list_new(info->path, query); if (db_list) { for (i = 0; i < db_list->count; i++) { if (!string_is_empty(db_list->list[i].name)) if (menu_entries_append(info->list, db_list->list[i].name, info->path, MENU_ENUM_LABEL_RDB_ENTRY, FILE_TYPE_RDB_ENTRY, 0, 0, NULL)) count++; } } database_info_list_free(db_list); free(db_list); } #endif if (!string_is_empty(info->path)) free(info->path); info->path = strdup(info->path_b); if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_SORT | MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_OPTIONS_SHADERS: menu_entries_clear(info->list); #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) { unsigned i; struct video_shader *shader = menu_shader_get(); unsigned pass_count = shader ? shader->passes : 0; bool video_shader_enable = settings->bools.video_shader_enable; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_VIDEO_SHADERS_ENABLE, PARSE_ONLY_BOOL, false) == 0) count++; if (video_shader_enable) { char buf_tmp[64]; size_t _len; const char *val_shdr = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER); const char *shdr_pass = msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PASS); const char *shdr_filter_pass = msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_FILTER_PASS); const char *shdr_scale_pass = msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_SCALE_PASS); const char *val_filter = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FILTER); const char *val_scale = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCALE); if (frontend_driver_can_watch_for_changes()) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER_WATCH_FOR_CHANGES), msg_hash_to_str(MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES), MENU_ENUM_LABEL_SHADER_WATCH_FOR_CHANGES, 0, 0, 0, NULL)) count++; } if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_REMEMBER_LAST_DIR), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_REMEMBER_LAST_DIR), MENU_ENUM_LABEL_VIDEO_SHADER_REMEMBER_LAST_DIR, 0, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET), MENU_ENUM_LABEL_VIDEO_SHADER_PRESET, FILE_TYPE_PATH, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_PREPEND), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_PREPEND), MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_PREPEND, FILE_TYPE_PATH, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_APPEND), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_APPEND), MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_APPEND, FILE_TYPE_PATH, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_SAVE), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE), MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_SAVE, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PRESET_REMOVE), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE), MENU_ENUM_LABEL_VIDEO_SHADER_PRESET_REMOVE, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER_APPLY_CHANGES), msg_hash_to_str(MENU_ENUM_LABEL_SHADER_APPLY_CHANGES), MENU_ENUM_LABEL_SHADER_APPLY_CHANGES, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PARAMETERS), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_PARAMETERS), MENU_ENUM_LABEL_VIDEO_SHADER_PARAMETERS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_NUM_PASSES), msg_hash_to_str(MENU_ENUM_LABEL_VIDEO_SHADER_NUM_PASSES), MENU_ENUM_LABEL_VIDEO_SHADER_NUM_PASSES, 0, 0, 0, NULL)) count++; _len = strlcpy(buf_tmp, val_shdr, sizeof(buf_tmp)); for (i = 0; i < pass_count; i++) { size_t _len2; char buf[128]; snprintf(buf_tmp + _len, sizeof(buf_tmp) - _len, " #%u", i); if (menu_entries_append(info->list, buf_tmp, shdr_pass, MENU_ENUM_LABEL_VIDEO_SHADER_PASS, MENU_SETTINGS_SHADER_PASS_0 + i, 0, 0, NULL)) count++; _len2 = strlcpy(buf, buf_tmp, sizeof(buf)); buf[ _len2] = ' '; buf[++_len2] = '\0'; strlcpy(buf + _len2, val_filter, sizeof(buf) - _len2); if (menu_entries_append(info->list, buf, shdr_filter_pass, MENU_ENUM_LABEL_VIDEO_SHADER_FILTER_PASS, MENU_SETTINGS_SHADER_PASS_FILTER_0 + i, 0, 0, NULL)) count++; _len2 = strlcpy(buf, buf_tmp, sizeof(buf)); buf[ _len2] = ' '; buf[++_len2] = '\0'; strlcpy(buf + _len2, val_scale, sizeof(buf) - _len2); if (menu_entries_append(info->list, buf, shdr_scale_pass, MENU_ENUM_LABEL_VIDEO_SHADER_SCALE_PASS, MENU_SETTINGS_SHADER_PASS_SCALE_0 + i, 0, 0, NULL)) count++; } } } #endif if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_CORE_CONTENT: menu_entries_clear(info->list); #ifdef HAVE_NETWORKING count = print_buf_lines(info->list, menu->core_buf, "", (int)menu->core_len, FILE_TYPE_DOWNLOAD_CORE_CONTENT, true, false); if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_CLEAR; #endif break; case DISPLAYLIST_CORE_CONTENT_DIRS_SUBDIR: { #ifdef HAVE_NETWORKING char new_label[PATH_MAX_LENGTH]; char *save = NULL; char *info_path_cpy = strdup(info->path); const char *con = strtok_r(info_path_cpy, ";", &save); if (con) strlcpy(new_label, con, sizeof(new_label)); else new_label[0] = '\0'; if ((con = strtok_r(NULL, ";", &save))) /* Get second parameter */ strlcpy(menu->core_buf, con, menu->core_len); free(info_path_cpy); if ((count = print_buf_lines( info->list, menu->core_buf, new_label, (int)menu->core_len, FILE_TYPE_DOWNLOAD_URL, false, false)) == 0) menu_entries_append(info->list, msg_hash_to_str( MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str( MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_CLEAR; #endif } break; case DISPLAYLIST_CORE_CONTENT_DIRS: menu_entries_clear(info->list); { #ifdef HAVE_NETWORKING char new_label[PATH_MAX_LENGTH]; const char * network_buildbot_assets_url = settings->paths.network_buildbot_assets_url; fill_pathname_join_special(new_label, network_buildbot_assets_url, "cores", sizeof(new_label)); if ((count = print_buf_lines(info->list, menu->core_buf, new_label, (int)menu->core_len, FILE_TYPE_DOWNLOAD_URL, true, false)) == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_CLEAR; #endif } break; case DISPLAYLIST_CORE_SYSTEM_FILES: menu_entries_clear(info->list); #ifdef HAVE_NETWORKING count = print_buf_lines(info->list, menu->core_buf, "", (int)menu->core_len, FILE_TYPE_DOWNLOAD_CORE_SYSTEM_FILES, true, false); if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_CLEAR; #endif break; case DISPLAYLIST_CORES_UPDATER: menu_entries_clear(info->list); #ifdef HAVE_NETWORKING { core_updater_list_t *core_list = core_updater_list_get_cached(); menu_search_terms_t *search_terms= menu_entries_search_get_terms(); struct menu_state *menu_st = menu_state_get_ptr(); bool show_experimental_cores = settings->bools.network_buildbot_show_experimental_cores; size_t selection = menu_st->selection_ptr; if (core_list) { size_t menu_index = 0; size_t i; for (i = 0; i < core_updater_list_size(core_list); i++) { const core_updater_list_entry_t *entry = NULL; if (core_updater_list_get_index(core_list, i, &entry)) { /* Skip 'experimental' cores, if required * > Note: We always show cores that are already * installed, regardless of status (a user should * always have the option to update existing cores) */ if ( !show_experimental_cores && (entry->is_experimental && !path_is_valid(entry->local_core_path))) continue; /* If a search is active, skip non-matching * entries */ if (search_terms) { bool entry_valid = true; size_t j; for (j = 0; j < search_terms->size; j++) { const char *search_term = search_terms->terms[j]; if ( !string_is_empty(search_term) && !string_is_empty(entry->display_name) && !strcasestr(entry->display_name, search_term)) { entry_valid = false; break; } } if (!entry_valid) continue; } if (menu_entries_append(info->list, entry->remote_filename, "", MENU_ENUM_LABEL_CORE_UPDATER_ENTRY, FILE_TYPE_DOWNLOAD_CORE, 0, 0, NULL)) { file_list_set_alt_at_offset( info->list, menu_index, entry->display_name); menu_index++; count++; } } } } if (selection >= count) info->flags |= MD_FLAG_NEED_CLEAR; } #endif if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; #if 0 /* Thumbnailpack removal */ case DISPLAYLIST_THUMBNAILS_UPDATER: menu_entries_clear(info->list); #ifdef HAVE_NETWORKING count = print_buf_lines(info->list, menu->core_buf, "", (int)menu->core_len, FILE_TYPE_DOWNLOAD_THUMBNAIL_CONTENT, true, false); if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_CLEAR; #endif break; #endif case DISPLAYLIST_PL_THUMBNAILS_UPDATER: menu_entries_clear(info->list); #ifdef HAVE_NETWORKING count = menu_displaylist_parse_pl_thumbnail_download_list(info->list, settings); if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_CLEAR; #endif break; case DISPLAYLIST_LAKKA: menu_entries_clear(info->list); #ifdef HAVE_NETWORKING count = print_buf_lines(info->list, menu->core_buf, "", (int)menu->core_len, FILE_TYPE_DOWNLOAD_LAKKA, true, false); if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_CLEAR; #endif break; case DISPLAYLIST_PLAYLIST_COLLECTION: /* Note: This would appear to be legacy code. Cannot find * a single instance where this case is met... */ menu_entries_clear(info->list); if ( string_starts_with_size(info->path, "content_", STRLEN_CONST("content_")) && string_ends_with_size (info->path, ".lpl", strlen(info->path), STRLEN_CONST(".lpl"))) { if (string_is_equal(info->path, FILE_PATH_CONTENT_HISTORY)) { if (menu_displaylist_ctl(DISPLAYLIST_HISTORY, info, settings)) return menu_displaylist_process(info); return false; } if (string_is_equal(info->path, FILE_PATH_CONTENT_FAVORITES)) { if (menu_displaylist_ctl(DISPLAYLIST_FAVORITES, info, settings)) return menu_displaylist_process(info); return false; } } { size_t _len; char path_playlist[PATH_MAX_LENGTH]; playlist_t *playlist = NULL; const char *dir_playlist = settings->paths.directory_playlist; fill_pathname_join_special(path_playlist, dir_playlist, info->path, sizeof(path_playlist)); menu_displaylist_set_new_playlist(menu, settings, path_playlist, true); _len = strlcpy(path_playlist, msg_hash_to_str(MENU_ENUM_LABEL_COLLECTION), sizeof(path_playlist)); playlist = playlist_get_cached(); if (playlist) { if (menu_displaylist_parse_playlist(info->list, info->path, playlist, settings, path_playlist, _len, true) == 0) info->flags |= MD_FLAG_NEED_PUSH_NO_PLAYLIST_ENTRIES; ret = 0; } if (ret == 0) { /* Playlists themselves are sorted * > Display lists generated from playlists * must never be sorted */ info->flags &= ~MD_FLAG_NEED_SORT; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; } } break; case DISPLAYLIST_HISTORY: { bool history_list_enable = settings->bools.history_list_enable; const char *path_content_history = settings->paths.path_content_history; menu_entries_clear(info->list); if (history_list_enable) count = menu_displaylist_parse_playlist_generic( menu, info, settings, "history", STRLEN_CONST("history"), path_content_history, false, /* Not a collection */ false, /* Do not sort */ &ret); if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_HISTORY_AVAILABLE), msg_hash_to_str(MENU_ENUM_LABEL_NO_HISTORY_AVAILABLE), MENU_ENUM_LABEL_NO_HISTORY_AVAILABLE, MENU_INFO_MESSAGE, 0, 0, NULL)) count++; } ret = 0; /* Playlists themselves are sorted * > Display lists generated from playlists * must never be sorted */ info->flags &= ~MD_FLAG_NEED_SORT; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; if (history_needs_navigation_clear(menu, g_defaults.content_history)) info->flags |= MD_FLAG_NEED_NAVIGATION_CLEAR; break; case DISPLAYLIST_FAVORITES: { const char *path_content_favorites = settings->paths.path_content_favorites; menu_entries_clear(info->list); count = menu_displaylist_parse_playlist_generic(menu, info, settings, "favorites", STRLEN_CONST("favorites"), path_content_favorites, false, /* Not a conventional collection */ true, /* Enable sorting (if allowed by user config) */ &ret); if (count == 0) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_FAVORITES_AVAILABLE), msg_hash_to_str(MENU_ENUM_LABEL_NO_FAVORITES_AVAILABLE), MENU_ENUM_LABEL_NO_FAVORITES_AVAILABLE, MENU_INFO_MESSAGE, 0, 0, NULL)) count++; info->flags &= ~MD_FLAG_NEED_PUSH_NO_PLAYLIST_ENTRIES; ret = 0; } ret = 0; /* Playlists themselves are sorted * > Display lists generated from playlists * must never be sorted */ info->flags &= ~MD_FLAG_NEED_SORT; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; } break; case DISPLAYLIST_MUSIC_HISTORY: menu_entries_clear(info->list); { const char * path_content_music_history = settings->paths.path_content_music_history; if (settings->bools.history_list_enable) count = menu_displaylist_parse_playlist_generic(menu, info, settings, "music_history", STRLEN_CONST("music_history"), path_content_music_history, false, /* Not a collection */ false, /* Do not sort */ &ret); if (count == 0) { if (menu_entries_append(info->list, msg_hash_to_str( MENU_ENUM_LABEL_VALUE_NO_MUSIC_AVAILABLE), msg_hash_to_str(MENU_ENUM_LABEL_NO_MUSIC_AVAILABLE), MENU_ENUM_LABEL_NO_MUSIC_AVAILABLE, MENU_INFO_MESSAGE, 0, 0, NULL)) count++; info->flags &= ~MD_FLAG_NEED_PUSH_NO_PLAYLIST_ENTRIES; ret = 0; } } if (ret == 0) { /* Playlists themselves are sorted * > Display lists generated from playlists * must never be sorted */ info->flags &= ~MD_FLAG_NEED_SORT; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; if (history_needs_navigation_clear(menu, g_defaults.music_history)) info->flags |= MD_FLAG_NEED_NAVIGATION_CLEAR; } break; case DISPLAYLIST_VIDEO_HISTORY: menu_entries_clear(info->list); #if defined(HAVE_FFMPEG) || defined(HAVE_MPV) { bool history_list_enable = settings->bools.history_list_enable; const char * path_content_video_history = settings->paths.path_content_video_history; if (history_list_enable) count = menu_displaylist_parse_playlist_generic(menu, info, settings, "video_history", STRLEN_CONST("video_history"), path_content_video_history, false, /* Not a collection */ false, /* Do not sort */ &ret); else ret = 0; } #endif if (count == 0) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_VIDEOS_AVAILABLE), msg_hash_to_str(MENU_ENUM_LABEL_NO_VIDEOS_AVAILABLE), MENU_ENUM_LABEL_NO_VIDEOS_AVAILABLE, MENU_INFO_MESSAGE, 0, 0, NULL)) count++; info->flags &= ~MD_FLAG_NEED_PUSH_NO_PLAYLIST_ENTRIES; ret = 0; } if (ret == 0) { /* Playlists themselves are sorted * > Display lists generated from playlists * must never be sorted */ info->flags &= ~MD_FLAG_NEED_SORT; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; #if (defined(HAVE_FFMPEG) || defined(HAVE_MPV)) if (history_needs_navigation_clear(menu, g_defaults.video_history)) info->flags |= MD_FLAG_NEED_NAVIGATION_CLEAR; #endif } break; case DISPLAYLIST_ACHIEVEMENT_PAUSE_MENU: #ifdef HAVE_CHEEVOS menu_entries_clear(info->list); rcheevos_menu_populate_hardcore_pause_submenu(info); #endif info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_ACHIEVEMENT_LIST: #ifdef HAVE_CHEEVOS menu_entries_clear(info->list); rcheevos_menu_populate(info); #endif info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_CORES_SUPPORTED: menu_entries_clear(info->list); count = menu_displaylist_parse_supported_cores(info, settings, menu->deferred_path, MENU_ENUM_LABEL_DETECT_CORE_LIST_OK, MENU_ENUM_LABEL_DETECT_CORE_LIST_OK_CURRENT_CORE); info->flags &= ~MD_FLAG_NEED_SORT; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_CORES_COLLECTION_SUPPORTED: menu_entries_clear(info->list); count = menu_displaylist_parse_supported_cores(info, settings, menu->deferred_path, MENU_ENUM_LABEL_FILE_BROWSER_CORE_SELECT_FROM_COLLECTION, MENU_ENUM_LABEL_FILE_BROWSER_CORE_SELECT_FROM_COLLECTION_CURRENT_CORE); info->flags &= ~MD_FLAG_NEED_SORT; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; /* Pre-select current associated core */ if (menu) { size_t idx = menu->rpl_entry_selection_ptr; playlist_t *cached_playlist = playlist_get_cached(); const struct playlist_entry *entry = NULL; const core_info_t* core_info = NULL; if (cached_playlist) playlist_get_index(cached_playlist, idx, &entry); if (!entry) break; core_info = playlist_entry_get_core_info(entry); if ( core_info && !string_is_empty(core_info->display_name)) { size_t selection_idx = 0; if (menu_entries_list_search(core_info->display_name, &selection_idx)) { menu_st->selection_ptr = selection_idx; if (menu_st->driver_ctx->navigation_set) menu_st->driver_ctx->navigation_set(menu_st->userdata, false); } } } break; case DISPLAYLIST_CORE_INFO: { /* The number of items in the core info menu: * - *May* (possibly) change after performing a * core restore operation (i.e. the core info * files are reloaded, and if an unknown error * occurs then info entries may not be available * upon popping the stack) * - *Will* change when toggling the core lock * status * To prevent the menu selection from going out * of bounds, we therefore have to check that the * current selection index is less than the current * number of menu entries - if not, we reset the * navigation pointer */ struct menu_state *menu_st = menu_state_get_ptr(); size_t selection = menu_st->selection_ptr; menu_entries_clear(info->list); count = menu_displaylist_parse_core_info(info->list, info->type, info->path, settings); if (selection >= count) info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_NAVIGATION_CLEAR; info->flags |= MD_FLAG_NEED_PUSH; } break; case DISPLAYLIST_CORE_RESTORE_BACKUP_LIST: menu_entries_clear(info->list); count = menu_displaylist_parse_core_backup_list( info->list, info->path, settings, true); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_CORE_DELETE_BACKUP_LIST: menu_entries_clear(info->list); count = menu_displaylist_parse_core_backup_list( info->list, info->path, settings, false); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH | MD_FLAG_NEED_NAVIGATION_CLEAR; break; case DISPLAYLIST_CORE_MANAGER_LIST: { /* When a core is deleted, the number of items in * the core manager list will change. We therefore * have to cache the last set menu size, and reset * the navigation pointer if the current size is * different */ static size_t prev_count = 0; struct menu_state *menu_st = menu_state_get_ptr(); size_t selection = menu_st->selection_ptr; menu_entries_clear(info->list); count = menu_displaylist_parse_core_manager_list (info->list, settings); if (count == 0) menu_entries_append(info->list, msg_hash_to_str( MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); if ( (count != prev_count) || (selection >= count)) { info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_NAVIGATION_CLEAR; prev_count = count; } info->flags |= MD_FLAG_NEED_PUSH; } break; #ifdef HAVE_MIST case DISPLAYLIST_CORE_MANAGER_STEAM_LIST: menu_entries_clear(info->list); count = menu_displaylist_parse_core_manager_steam_list(info->list, settings); info->flags &= ~MD_FLAG_NEED_REFRESH; info->flags |= MD_FLAG_NEED_PUSH | MD_FLAG_NEED_NAVIGATION_CLEAR; /* No core dlcs were found */ if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL)) count++; break; case DISPLAYLIST_CORE_INFORMATION_STEAM_LIST: menu_entries_clear(info->list); info->flags &= ~MD_FLAG_NEED_REFRESH; info->flags |= MD_FLAG_NEED_PUSH | MD_FLAG_NEED_NAVIGATION_CLEAR; count = menu_displaylist_parse_core_information_steam(info->list, info->path, settings); if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL)) count++; break; #endif case DISPLAYLIST_CONTENTLESS_CORES: { struct menu_state *menu_st = menu_state_get_ptr(); size_t contentless_core_ptr = menu_st->contentless_core_ptr; menu_entries_clear(info->list); count = menu_displaylist_contentless_cores(info->list, settings); /* TODO/FIXME: Selecting an entry in the * contentless cores list will cause the * quick menu to be pushed on the subsequent * frame via the RARCH_MENU_CTL_SET_PENDING_QUICK_MENU * command. The way this is implemented 'breaks' the * menu stack record, so when leaving the quick * menu via a 'cancel' operation, the last selected * menu index is lost. We therefore have to apply * a cached index value after rebuilding the list... */ if (contentless_core_ptr < count) menu_st->selection_ptr = contentless_core_ptr; info->flags &= ~MD_FLAG_NEED_SORT; info->flags |= MD_FLAG_NEED_PUSH; } break; case DISPLAYLIST_SAVESTATE_LIST: { bool savestates_enabled = core_info_current_supports_savestate(); menu_entries_clear(info->list); if ( savestates_enabled && settings->bools.quick_menu_show_save_load_state) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_STATE_SLOT, PARSE_ONLY_INT, true) == 0) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SAVE_STATE), msg_hash_to_str(MENU_ENUM_LABEL_SAVE_STATE), MENU_ENUM_LABEL_SAVE_STATE, MENU_SETTING_ACTION_SAVESTATE, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_LOAD_STATE), msg_hash_to_str(MENU_ENUM_LABEL_LOAD_STATE), MENU_ENUM_LABEL_LOAD_STATE, MENU_SETTING_ACTION_LOADSTATE, 0, 0, NULL)) count++; } if ( savestates_enabled && settings->bools.quick_menu_show_save_load_state && settings->bools.quick_menu_show_undo_save_load_state) { #ifdef HAVE_CHEEVOS if (!rcheevos_hardcore_active()) #endif { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UNDO_LOAD_STATE), msg_hash_to_str(MENU_ENUM_LABEL_UNDO_LOAD_STATE), MENU_ENUM_LABEL_UNDO_LOAD_STATE, MENU_SETTING_ACTION_LOADSTATE, 0, 0, NULL)) count++; } if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UNDO_SAVE_STATE), msg_hash_to_str(MENU_ENUM_LABEL_UNDO_SAVE_STATE), MENU_ENUM_LABEL_UNDO_SAVE_STATE, MENU_SETTING_ACTION_LOADSTATE, 0, 0, NULL)) count++; } #ifdef HAVE_BSV_MOVIE if ( savestates_enabled && settings->bools.quick_menu_show_replay) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_REPLAY_SLOT, PARSE_ONLY_INT, true) == 0) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_RECORD_REPLAY), msg_hash_to_str(MENU_ENUM_LABEL_RECORD_REPLAY), MENU_ENUM_LABEL_RECORD_REPLAY, MENU_SETTING_ACTION_RECORDREPLAY, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAY_REPLAY), msg_hash_to_str(MENU_ENUM_LABEL_PLAY_REPLAY), MENU_ENUM_LABEL_PLAY_REPLAY, MENU_SETTING_ACTION_PLAYREPLAY, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_HALT_REPLAY), msg_hash_to_str(MENU_ENUM_LABEL_HALT_REPLAY), MENU_ENUM_LABEL_HALT_REPLAY, MENU_SETTING_ACTION_HALTREPLAY, 0, 0, NULL)) count++; } #endif if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_PUSH; } break; case DISPLAYLIST_CORE_OPTIONS: { /* Number of displayed options is dynamic. If user opens * 'Quick Menu > Core Options', toggles something * that changes the number of displayed items, then * toggles the Quick Menu off and on again (returning * to the Core Options menu) the menu must be refreshed * (or undefined behaviour occurs). * To prevent the menu selection from going out of bounds, * we therefore have to check that the current selection * index is less than the current number of menu entries * - if not, we reset the navigation pointer */ struct menu_state *menu_st = menu_state_get_ptr(); size_t selection = menu_st->selection_ptr; runloop_state_t *runloop_st = runloop_state_get_ptr(); menu_entries_clear(info->list); if (runloop_st->core_options) { bool game_specific_options = settings->bools.game_specific_options; const char *category = info->path; bool is_category = !string_is_empty(category); core_option_manager_t *coreopts = NULL; if (game_specific_options && !is_category) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_OPTION_OVERRIDE_LIST), msg_hash_to_str(MENU_ENUM_LABEL_CORE_OPTION_OVERRIDE_LIST), MENU_ENUM_LABEL_CORE_OPTION_OVERRIDE_LIST, MENU_SETTING_ACTION_CORE_OPTION_OVERRIDE_LIST, 0, 0, NULL)) count++; if (retroarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts)) { size_t i; nested_list_t *option_list = NULL; /* Empty 'category' string signifies top * level core options menu */ if (!is_category) option_list = coreopts->option_map; else { nested_list_item_t *category_item = nested_list_get_item(coreopts->option_map, category, NULL); if (category_item) option_list = nested_list_item_get_children(category_item); } if (option_list) { /* Loop over child options */ for (i = 0; i < nested_list_get_size(option_list); i++) { nested_list_item_t *option_item = nested_list_get_item_idx(option_list, i); const struct core_option *option = (const struct core_option *) nested_list_item_get_value(option_item); /* Check whether this is an option or a * subcategory */ if (option) { /* This is a regular option */ size_t opt_idx = option->opt_idx; if (core_option_manager_get_visible(coreopts, opt_idx)) if (menu_entries_append(info->list, core_option_manager_get_desc(coreopts, opt_idx, true), "", MENU_ENUM_LABEL_CORE_OPTION_ENTRY, (unsigned)(MENU_SETTINGS_CORE_OPTION_START + opt_idx), 0, 0, NULL)) count++; } else if (option_item) { /* This is a subcategory */ const char *category_id = nested_list_item_get_id(option_item); bool category_visible = core_option_manager_get_category_visible( coreopts, category_id); /* Note: We use nested_list_item_get_id() because we * guarantee that the list can only be two levels * deep. If we supported arbitrary nesting, would * have to use nested_list_item_get_address() here */ if ( category_visible && !string_is_empty(category_id)) { if (menu_entries_append(info->list, category_id, msg_hash_to_str(MENU_ENUM_LABEL_CORE_OPTIONS), MENU_ENUM_LABEL_CORE_OPTIONS, MENU_SETTING_ACTION_CORE_OPTIONS, 0, 0, NULL)) count++; } } } } } } if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_CORE_OPTIONS_AVAILABLE), msg_hash_to_str(MENU_ENUM_LABEL_NO_CORE_OPTIONS_AVAILABLE), MENU_ENUM_LABEL_NO_CORE_OPTIONS_AVAILABLE, MENU_SETTINGS_CORE_OPTION_NONE, 0, 0, NULL); if (selection >= count) info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_NAVIGATION_CLEAR; info->flags |= MD_FLAG_NEED_PUSH; } break; case DISPLAYLIST_CORE_OPTION_OVERRIDE_LIST: { /* The number of items in the core option override * list will vary depending upon whether game or * content directory overrides are currently active. * To prevent the menu selection from going out * of bounds, we therefore have to check that the * current selection index is less than the current * number of menu entries - if not, we reset the * navigation pointer */ struct menu_state *menu_st = menu_state_get_ptr(); size_t selection = menu_st->selection_ptr; menu_entries_clear(info->list); count = menu_displaylist_parse_core_option_override_list(info->list, settings); /* Fallback, in case we open this menu while running * a core without options */ if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND), msg_hash_to_str(MENU_ENUM_LABEL_NO_SETTINGS_FOUND), MENU_ENUM_LABEL_NO_SETTINGS_FOUND, 0, 0, 0, NULL)) count++; if (selection >= count) info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_NAVIGATION_CLEAR; info->flags |= MD_FLAG_NEED_PUSH; } break; case DISPLAYLIST_REMAP_FILE_MANAGER: { /* The number of items in the remap file manager * list will vary depending upon which remap type * is currently active (if any). * To prevent the menu selection from going out * of bounds, we therefore have to check that the * current selection index is less than the current * number of menu entries - if not, we reset the * navigation pointer */ struct menu_state *menu_st = menu_state_get_ptr(); size_t selection = menu_st->selection_ptr; menu_entries_clear(info->list); count = menu_displaylist_parse_remap_file_manager_list(info->list, settings); /* Fallback */ if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL)) count++; if (selection >= count) info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_NAVIGATION_CLEAR; info->flags |= MD_FLAG_NEED_PUSH; } break; case DISPLAYLIST_ARCHIVE_ACTION: menu_entries_clear(info->list); #ifdef HAVE_COMPRESSION if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OPEN_ARCHIVE), msg_hash_to_str(MENU_ENUM_LABEL_OPEN_ARCHIVE), MENU_ENUM_LABEL_OPEN_ARCHIVE, 0, 0, 0, NULL)) count++; #endif if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_LOAD_ARCHIVE), msg_hash_to_str(MENU_ENUM_LABEL_LOAD_ARCHIVE), MENU_ENUM_LABEL_LOAD_ARCHIVE, 0, 0, 0, NULL)) count++; info->flags |= MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_ARCHIVE_ACTION_DETECT_CORE: menu_entries_clear(info->list); #ifdef HAVE_COMPRESSION if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OPEN_ARCHIVE), msg_hash_to_str(MENU_ENUM_LABEL_OPEN_ARCHIVE_DETECT_CORE), MENU_ENUM_LABEL_OPEN_ARCHIVE_DETECT_CORE, 0, 0, 0, NULL)) count++; #endif if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_LOAD_ARCHIVE), msg_hash_to_str(MENU_ENUM_LABEL_LOAD_ARCHIVE_DETECT_CORE), MENU_ENUM_LABEL_LOAD_ARCHIVE_DETECT_CORE, 0, 0, 0, NULL)) count++; info->flags |= MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_PLAYLIST_MANAGER_LIST: menu_entries_clear(info->list); count = menu_displaylist_parse_playlist_manager_list(info->list, settings); if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_ADD_TO_PLAYLIST_LIST: menu_entries_clear(info->list); /* add new list button here */ menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CREATE_NEW_PLAYLIST), msg_hash_to_str(MENU_ENUM_LABEL_CREATE_NEW_PLAYLIST), MENU_ENUM_LABEL_CREATE_NEW_PLAYLIST, MENU_SETTING_ACTION, 0, 0, NULL); count = menu_displaylist_parse_add_to_playlist_list(info->list, settings); if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_PLAYLIST_MANAGER_SETTINGS: menu_entries_clear(info->list); if (!menu_displaylist_parse_playlist_manager_settings(menu, settings, info->list, info->path)) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_DROPDOWN_LIST_VIDEO_SHADER_PARAMETER: menu_entries_clear(info->list); count = menu_displaylist_build_shader_parameter( info->list, info->type, MENU_SETTINGS_SHADER_PARAMETER_0, MENU_SETTING_DROPDOWN_ITEM_VIDEO_SHADER_PARAM); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_DROPDOWN_LIST_VIDEO_SHADER_PRESET_PARAMETER: menu_entries_clear(info->list); count = menu_displaylist_build_shader_parameter( info->list, info->type, MENU_SETTINGS_SHADER_PRESET_PARAMETER_0, MENU_SETTING_DROPDOWN_ITEM_VIDEO_SHADER_PRESET_PARAM); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_DROPDOWN_LIST_INPUT_DEVICE_TYPE: menu_entries_clear(info->list); count = menu_displaylist_parse_input_device_type_list(info->list, info->path, settings); if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL)) count++; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_DROPDOWN_LIST_INPUT_SELECT_RESERVED_DEVICE: menu_entries_clear(info->list); count = menu_displaylist_parse_input_select_reserved_device_list(info->list, info->path, settings); if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL)) count++; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; #ifdef ANDROID case DISPLAYLIST_DROPDOWN_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD: menu_entries_clear(info->list); count = menu_displaylist_parse_input_select_physical_keyboard_list(info->list, info->path, settings); if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL)) count++; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; #endif case DISPLAYLIST_DROPDOWN_LIST_INPUT_DESCRIPTION: menu_entries_clear(info->list); count = menu_displaylist_parse_input_description_list(info, settings); if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL)) count++; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_DROPDOWN_LIST_INPUT_DESCRIPTION_KBD: menu_entries_clear(info->list); count = menu_displaylist_parse_input_description_kbd_list( info->list, info->type, settings); if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL)) count++; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_DROPDOWN_LIST_AUDIO_DEVICE: menu_entries_clear(info->list); count = menu_displaylist_parse_audio_device_list(info->list, info->path, settings); if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL)) count++; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; #ifdef HAVE_MICROPHONE case DISPLAYLIST_DROPDOWN_LIST_MICROPHONE_DEVICE: menu_entries_clear(info->list); count = menu_displaylist_parse_microphone_device_list(info->list, info->path, settings); if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL)) count++; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; #endif #ifdef HAVE_NETWORKING case DISPLAYLIST_DROPDOWN_LIST_NETPLAY_MITM_SERVER: menu_entries_clear(info->list); count = menu_displaylist_parse_netplay_mitm_server_list(info->list, settings); if (count == 0) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, 0, 0, 0, NULL)) count++; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; #endif case DISPLAYLIST_SAVING_SETTINGS_LIST: case DISPLAYLIST_CLOUD_SYNC_SETTINGS_LIST: case DISPLAYLIST_DRIVER_SETTINGS_LIST: case DISPLAYLIST_LOGGING_SETTINGS_LIST: case DISPLAYLIST_FRAME_THROTTLE_SETTINGS_LIST: case DISPLAYLIST_REWIND_SETTINGS_LIST: case DISPLAYLIST_DIRECTORY_SETTINGS_LIST: case DISPLAYLIST_CONFIGURATION_SETTINGS_LIST: case DISPLAYLIST_CORE_SETTINGS_LIST: case DISPLAYLIST_SETTINGS_VIEWS_SETTINGS_LIST: case DISPLAYLIST_QUICK_MENU_VIEWS_SETTINGS_LIST: case DISPLAYLIST_MENU_SOUNDS_LIST: case DISPLAYLIST_UPDATER_SETTINGS_LIST: case DISPLAYLIST_USER_SETTINGS_LIST: case DISPLAYLIST_ONSCREEN_DISPLAY_SETTINGS_LIST: case DISPLAYLIST_POWER_MANAGEMENT_SETTINGS_LIST: case DISPLAYLIST_SETTINGS_ALL: case DISPLAYLIST_PRIVACY_SETTINGS_LIST: case DISPLAYLIST_CONFIGURATIONS_LIST: case DISPLAYLIST_ONSCREEN_NOTIFICATIONS_SETTINGS_LIST: case DISPLAYLIST_ONSCREEN_NOTIFICATIONS_VIEWS_SETTINGS_LIST: case DISPLAYLIST_LATENCY_SETTINGS_LIST: #if defined(HAVE_OVERLAY) case DISPLAYLIST_ONSCREEN_OVERLAY_SETTINGS_LIST: case DISPLAYLIST_OSK_OVERLAY_SETTINGS_LIST: case DISPLAYLIST_OVERLAY_LIGHTGUN_SETTINGS_LIST: case DISPLAYLIST_OVERLAY_MOUSE_SETTINGS_LIST: #endif case DISPLAYLIST_ACCOUNTS_CHEEVOS_LIST: case DISPLAYLIST_ACCOUNTS_LIST: case DISPLAYLIST_MENU_FILE_BROWSER_SETTINGS_LIST: case DISPLAYLIST_MENU_VIEWS_SETTINGS_LIST: case DISPLAYLIST_LAKKA_SERVICES_LIST: #ifdef HAVE_LAKKA_SWITCH case DISPLAYLIST_LAKKA_SWITCH_OPTIONS_LIST: #endif case DISPLAYLIST_MIDI_SETTINGS_LIST: case DISPLAYLIST_CRT_SWITCHRES_SETTINGS_LIST: case DISPLAYLIST_VIDEO_FULLSCREEN_MODE_SETTINGS_LIST: case DISPLAYLIST_VIDEO_WINDOWED_MODE_SETTINGS_LIST: case DISPLAYLIST_VIDEO_OUTPUT_SETTINGS_LIST: case DISPLAYLIST_VIDEO_HDR_SETTINGS_LIST: case DISPLAYLIST_VIDEO_SYNCHRONIZATION_SETTINGS_LIST: case DISPLAYLIST_VIDEO_SCALING_SETTINGS_LIST: case DISPLAYLIST_OPTIONS_DISK: case DISPLAYLIST_AI_SERVICE_SETTINGS_LIST: case DISPLAYLIST_ACCESSIBILITY_SETTINGS_LIST: case DISPLAYLIST_USER_INTERFACE_SETTINGS_LIST: case DISPLAYLIST_ACCOUNTS_TWITCH_LIST: case DISPLAYLIST_RETRO_ACHIEVEMENTS_SETTINGS_LIST: case DISPLAYLIST_CHEEVOS_APPEARANCE_SETTINGS_LIST: case DISPLAYLIST_CHEEVOS_VISIBILITY_SETTINGS_LIST: case DISPLAYLIST_ACCOUNTS_YOUTUBE_LIST: case DISPLAYLIST_ACCOUNTS_FACEBOOK_LIST: case DISPLAYLIST_RECORDING_SETTINGS_LIST: case DISPLAYLIST_CHEAT_DETAILS_SETTINGS_LIST: case DISPLAYLIST_CHEAT_SEARCH_SETTINGS_LIST: case DISPLAYLIST_NETWORK_SETTINGS_LIST: case DISPLAYLIST_NETPLAY_LOBBY_FILTERS_LIST: case DISPLAYLIST_OPTIONS_CHEATS: case DISPLAYLIST_NETWORK_INFO: case DISPLAYLIST_DROPDOWN_LIST_RESOLUTION: case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_DEFAULT_CORE: case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LABEL_DISPLAY_MODE: case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE: case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE: case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_SORT_MODE: case DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME: case DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_CORE_NAME: case DISPLAYLIST_DROPDOWN_LIST_DISK_INDEX: case DISPLAYLIST_PERFCOUNTERS_CORE: case DISPLAYLIST_PERFCOUNTERS_FRONTEND: case DISPLAYLIST_MENU_SETTINGS_LIST: #ifdef _3DS case DISPLAYLIST_MENU_BOTTOM_SETTINGS_LIST: #endif case DISPLAYLIST_ADD_CONTENT_LIST: case DISPLAYLIST_INPUT_SETTINGS_LIST: case DISPLAYLIST_INPUT_MENU_SETTINGS_LIST: case DISPLAYLIST_FRAME_TIME_COUNTER_SETTINGS_LIST: case DISPLAYLIST_BROWSE_URL_LIST: case DISPLAYLIST_DISC_INFO: case DISPLAYLIST_DUMP_DISC: #ifdef HAVE_LAKKA case DISPLAYLIST_EJECT_DISC: #endif case DISPLAYLIST_LOAD_CONTENT_LIST: case DISPLAYLIST_LOAD_CONTENT_SPECIAL: case DISPLAYLIST_OPTIONS_REMAPPINGS: case DISPLAYLIST_VIDEO_SETTINGS_LIST: case DISPLAYLIST_AUDIO_SETTINGS_LIST: case DISPLAYLIST_AUDIO_OUTPUT_SETTINGS_LIST: #ifdef HAVE_MICROPHONE case DISPLAYLIST_MICROPHONE_SETTINGS_LIST: #endif case DISPLAYLIST_AUDIO_SYNCHRONIZATION_SETTINGS_LIST: case DISPLAYLIST_HELP_SCREEN_LIST: case DISPLAYLIST_INFORMATION_LIST: case DISPLAYLIST_EXPLORE: case DISPLAYLIST_SCAN_DIRECTORY_LIST: case DISPLAYLIST_SYSTEM_INFO: case DISPLAYLIST_BLUETOOTH_SETTINGS_LIST: case DISPLAYLIST_WIFI_SETTINGS_LIST: case DISPLAYLIST_WIFI_NETWORKS_LIST: case DISPLAYLIST_AUDIO_MIXER_SETTINGS_LIST: case DISPLAYLIST_BROWSE_URL_START: case DISPLAYLIST_CONTENT_SETTINGS: case DISPLAYLIST_NETPLAY_ROOM_LIST: case DISPLAYLIST_SHADER_PRESET_SAVE: case DISPLAYLIST_SHADER_PRESET_REMOVE: case DISPLAYLIST_INPUT_RETROPAD_BINDS_LIST: case DISPLAYLIST_INPUT_HOTKEY_BINDS_LIST: case DISPLAYLIST_INPUT_TURBO_FIRE_SETTINGS_LIST: case DISPLAYLIST_INPUT_HAPTIC_FEEDBACK_SETTINGS_LIST: case DISPLAYLIST_PLAYLIST_SETTINGS_LIST: case DISPLAYLIST_SUBSYSTEM_SETTINGS_LIST: #ifdef HAVE_MIST case DISPLAYLIST_STEAM_SETTINGS_LIST: #endif case DISPLAYLIST_OPTIONS_OVERRIDES: menu_entries_clear(info->list); count = menu_displaylist_build_list(info->list, settings, type, false); if (count == 0) { switch (type) { case DISPLAYLIST_SHADER_PRESET_REMOVE: menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_PRESETS_FOUND), msg_hash_to_str(MENU_ENUM_LABEL_NO_PRESETS_FOUND), MENU_ENUM_LABEL_NO_PRESETS_FOUND, 0, 0, 0, NULL); break; case DISPLAYLIST_DISC_INFO: case DISPLAYLIST_DUMP_DISC: #ifdef HAVE_LAKKA case DISPLAYLIST_EJECT_DISC: #endif case DISPLAYLIST_MENU_SETTINGS_LIST: #ifdef _3DS case DISPLAYLIST_MENU_BOTTOM_SETTINGS_LIST: #endif case DISPLAYLIST_ADD_CONTENT_LIST: case DISPLAYLIST_DROPDOWN_LIST_RESOLUTION: case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_DEFAULT_CORE: case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LABEL_DISPLAY_MODE: case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE: case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE: case DISPLAYLIST_DROPDOWN_LIST_PLAYLIST_SORT_MODE: case DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME: case DISPLAYLIST_DROPDOWN_LIST_MANUAL_CONTENT_SCAN_CORE_NAME: case DISPLAYLIST_DROPDOWN_LIST_DISK_INDEX: case DISPLAYLIST_INFORMATION_LIST: case DISPLAYLIST_SCAN_DIRECTORY_LIST: menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); break; case DISPLAYLIST_PERFCOUNTERS_CORE: case DISPLAYLIST_PERFCOUNTERS_FRONTEND: menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_PERFORMANCE_COUNTERS), msg_hash_to_str(MENU_ENUM_LABEL_NO_PERFORMANCE_COUNTERS), MENU_ENUM_LABEL_NO_PERFORMANCE_COUNTERS, 0, 0, 0, NULL); break; case DISPLAYLIST_BLUETOOTH_SETTINGS_LIST: menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_BT_DEVICES_FOUND), msg_hash_to_str(MENU_ENUM_LABEL_NO_BT_DEVICES_FOUND), MENU_ENUM_LABEL_NO_BT_DEVICES_FOUND, 0, 0, 0, NULL); break; case DISPLAYLIST_WIFI_NETWORKS_LIST: menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_NETWORKS_FOUND), msg_hash_to_str(MENU_ENUM_LABEL_NO_NETWORKS_FOUND), MENU_ENUM_LABEL_NO_NETWORKS_FOUND, 0, 0, 0, NULL); break; case DISPLAYLIST_NETPLAY_ROOM_LIST: break; default: menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND), msg_hash_to_str(MENU_ENUM_LABEL_NO_SETTINGS_FOUND), MENU_ENUM_LABEL_NO_SETTINGS_FOUND, 0, 0, 0, NULL); break; } } info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; /* Special pass */ switch (type) { case DISPLAYLIST_DISC_INFO: case DISPLAYLIST_DUMP_DISC: #ifdef HAVE_LAKKA case DISPLAYLIST_EJECT_DISC: #endif info->flags |= MD_FLAG_NEED_CLEAR; break; default: break; } break; case DISPLAYLIST_HORIZONTAL: menu_entries_clear(info->list); ret = menu_displaylist_parse_horizontal_list(menu, menu_st, settings, info); /* Playlists themselves are sorted * > Display lists generated from playlists * must never be sorted */ info->flags &= ~MD_FLAG_NEED_SORT; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_HORIZONTAL_CONTENT_ACTIONS: menu_entries_clear(info->list); ret = menu_displaylist_parse_horizontal_content_actions(menu, settings, info->list); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_OPTIONS: menu_entries_clear(info->list); { #ifdef HAVE_LAKKA if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_LAKKA), msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_LAKKA), MENU_ENUM_LABEL_UPDATE_LAKKA, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE_CONTENT), msg_hash_to_str(MENU_ENUM_LABEL_DOWNLOAD_CORE_CONTENT_DIRS), MENU_ENUM_LABEL_DOWNLOAD_CORE_CONTENT_DIRS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PL_THUMBNAILS_UPDATER_LIST), msg_hash_to_str(MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST), MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #if 0 /* Thumbnailpack removal */ if (settings->bools.menu_show_legacy_thumbnail_updater) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_THUMBNAILS_UPDATER_LIST), msg_hash_to_str(MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST), MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } #endif #elif defined(HAVE_NETWORKING) #ifdef HAVE_UPDATE_CORES if (settings->bools.menu_show_core_updater) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_UPDATER_LIST), msg_hash_to_str(MENU_ENUM_LABEL_CORE_UPDATER_LIST), MENU_ENUM_LABEL_CORE_UPDATER_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; /* Only show 'update installed cores' if * one or more cores are installed */ if (core_info_count() > 0) { #if defined(ANDROID) /* When using Play Store builds, cores are * updated automatically - the 'update * installed cores' option is therefore * irrelevant/useless, so we instead present * an option for switching any existing buildbot * or sideloaded cores to the latest Play Store * version */ if (play_feature_delivery_enabled()) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SWITCH_INSTALLED_CORES_PFD), msg_hash_to_str(MENU_ENUM_LABEL_SWITCH_INSTALLED_CORES_PFD), MENU_ENUM_LABEL_SWITCH_INSTALLED_CORES_PFD, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } else #endif if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_INSTALLED_CORES), msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_INSTALLED_CORES), MENU_ENUM_LABEL_UPDATE_INSTALLED_CORES, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } } #endif /* HAVE_UPDATE_CORES */ #if defined(HAVE_COMPRESSION) && !defined(HAVE_MIST) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE_SYSTEM_FILES), msg_hash_to_str(MENU_ENUM_LABEL_DOWNLOAD_CORE_SYSTEM_FILES), MENU_ENUM_LABEL_DOWNLOAD_CORE_SYSTEM_FILES, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE_CONTENT), msg_hash_to_str(MENU_ENUM_LABEL_DOWNLOAD_CORE_CONTENT_DIRS), MENU_ENUM_LABEL_DOWNLOAD_CORE_CONTENT_DIRS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #ifdef HAVE_ONLINE_UPDATER if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_UPDATER_SETTINGS, PARSE_ACTION, false) == 0) count++; #endif if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PL_THUMBNAILS_UPDATER_LIST), msg_hash_to_str(MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST), MENU_ENUM_LABEL_PL_THUMBNAILS_UPDATER_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #if 0 /* Thumbnailpack removal */ if (settings->bools.menu_show_legacy_thumbnail_updater) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_THUMBNAILS_UPDATER_LIST), msg_hash_to_str(MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST), MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } #endif #ifdef HAVE_NETWORKING if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_NETWORK_ON_DEMAND_THUMBNAILS, PARSE_ONLY_BOOL, false) != -1) count++; #endif #ifdef HAVE_COMPRESSION #ifdef HAVE_UPDATE_CORE_INFO if (settings->bools.menu_show_core_updater) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_CORE_INFO_FILES), msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_CORE_INFO_FILES), MENU_ENUM_LABEL_UPDATE_CORE_INFO_FILES, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } #endif #ifdef HAVE_UPDATE_ASSETS if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_ASSETS), msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_ASSETS), MENU_ENUM_LABEL_UPDATE_ASSETS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif #if !defined(_3DS) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_AUTOCONFIG_PROFILES), msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_AUTOCONFIG_PROFILES), MENU_ENUM_LABEL_UPDATE_AUTOCONFIG_PROFILES, MENU_SETTING_ACTION, 0, 0, NULL)) count++; if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_CHEATS), msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_CHEATS), MENU_ENUM_LABEL_UPDATE_CHEATS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif #ifdef HAVE_LIBRETRODB #if !defined(VITA) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_DATABASES), msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_DATABASES), MENU_ENUM_LABEL_UPDATE_DATABASES, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif #endif /* HAVE_LIBRETRODB */ #if !defined(_3DS) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_OVERLAYS), msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_OVERLAYS), MENU_ENUM_LABEL_UPDATE_OVERLAYS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) if (video_shader_is_supported(RARCH_SHADER_CG)) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_CG_SHADERS), msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_CG_SHADERS), MENU_ENUM_LABEL_UPDATE_CG_SHADERS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } if (video_shader_is_supported(RARCH_SHADER_GLSL)) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_GLSL_SHADERS), msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_GLSL_SHADERS), MENU_ENUM_LABEL_UPDATE_GLSL_SHADERS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } if (video_shader_is_supported(RARCH_SHADER_SLANG)) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UPDATE_SLANG_SHADERS), msg_hash_to_str(MENU_ENUM_LABEL_UPDATE_SLANG_SHADERS), MENU_ENUM_LABEL_UPDATE_SLANG_SHADERS, MENU_SETTING_ACTION, 0, 0, NULL)) count++; } #endif #endif /* !defined(_3DS) */ #endif /* HAVE_COMPRESSION */ #endif } if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ITEMS), msg_hash_to_str(MENU_ENUM_LABEL_NO_ITEMS), MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_NO_ITEM, 0, 0, NULL); ret = 0; info->flags |= MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_SHADER_PARAMETERS: case DISPLAYLIST_SHADER_PARAMETERS_PRESET: menu_entries_clear(info->list); #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) { video_shader_ctx_t shader_info; if (video_shader_driver_get_current_shader(&shader_info)) { unsigned i; struct video_shader *shader = shader_info.data; size_t list_size = shader ? shader->num_parameters : 0; unsigned base_parameter = (type == DISPLAYLIST_SHADER_PARAMETERS) ? MENU_SETTINGS_SHADER_PARAMETER_0 : MENU_SETTINGS_SHADER_PRESET_PARAMETER_0; for (i = 0; i < list_size; i++) if (menu_entries_append(info->list, shader->parameters[i].desc, info->label, MENU_ENUM_LABEL_SHADER_PARAMETERS_ENTRY, base_parameter + i, 0, 0, NULL)) count++; } } #endif if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SHADER_PARAMETERS), msg_hash_to_str(MENU_ENUM_LABEL_NO_SHADER_PARAMETERS), MENU_ENUM_LABEL_NO_SHADER_PARAMETERS, 0, 0, 0, NULL); ret = 0; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_MAIN_MENU: menu_entries_clear(info->list); { rarch_system_info_t *sys_info = &runloop_state_get_ptr()->system; bool show_add_content = false; #if defined(HAVE_RGUI) || defined(HAVE_MATERIALUI) || defined(HAVE_OZONE) || defined(HAVE_XMB) const char *menu_ident = menu_driver_ident(); #endif uint32_t flags = runloop_get_flags(); if (flags & RUNLOOP_FLAG_CORE_RUNNING) { if (!retroarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_CONTENT_SETTINGS, PARSE_ACTION, false) == 0) count++; } else { if (sys_info && sys_info->load_no_content) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_START_CORE, PARSE_ACTION, false) == 0) count++; #ifndef HAVE_DYNAMIC if (frontend_driver_has_fork()) #endif { if (settings->bools.menu_show_load_core) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_CORE_LIST, PARSE_ACTION, false) == 0) count++; } } } if (settings->bools.menu_show_load_content) { /* Core not loaded completely, use the data we * peeked on load core */ if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_LOAD_CONTENT_LIST, PARSE_ACTION, false) == 0) count++; if (menu_displaylist_has_subsystems()) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_SUBSYSTEM_SETTINGS, PARSE_ACTION, false) == 0) count++; } } if (settings->bools.menu_content_show_history) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_LOAD_CONTENT_HISTORY, PARSE_ACTION, false) == 0) count++; #ifdef HAVE_CDROM if (settings->bools.menu_show_load_disc) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_LOAD_DISC, PARSE_ACTION, false) == 0) count++; } if (settings->bools.menu_show_dump_disc) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_DUMP_DISC, PARSE_ACTION, false) == 0) count++; } #ifdef HAVE_LAKKA if (settings->bools.menu_show_eject_disc) { if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_EJECT_DISC, PARSE_ACTION, false) == 0) count++; } #endif /* HAVE_LAKKA */ #endif #if defined(HAVE_RGUI) || defined(HAVE_MATERIALUI) if (( string_is_equal(menu_ident, "rgui") || string_is_equal(menu_ident, "glui")) && settings->bools.menu_content_show_playlists) if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLISTS_TAB), msg_hash_to_str(MENU_ENUM_LABEL_PLAYLISTS_TAB), MENU_ENUM_LABEL_PLAYLISTS_TAB, MENU_SETTING_ACTION, 0, 0, NULL)) count++; #endif #if defined(HAVE_XMB) || defined(HAVE_OZONE) if ( string_is_equal(menu_ident, "xmb") || string_is_equal(menu_ident, "ozone")) show_add_content = settings->bools.menu_content_show_add; else #endif show_add_content = (settings->uints.menu_content_show_add_entry == MENU_ADD_CONTENT_ENTRY_DISPLAY_MAIN_TAB); if (show_add_content) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_ADD_CONTENT_LIST, PARSE_ACTION, false) == 0) count++; #ifdef HAVE_NETWORKING if (settings->bools.menu_content_show_netplay) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_NETPLAY, PARSE_ACTION, false) == 0) count++; #endif #ifdef HAVE_ONLINE_UPDATER if (settings->bools.menu_show_online_updater) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_ONLINE_UPDATER, PARSE_ACTION, false) == 0) count++; #endif #ifdef HAVE_MIST if (settings->bools.menu_show_core_manager_steam) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_CORE_MANAGER_STEAM_LIST, PARSE_ACTION, false) == 0) count++; #endif if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_SETTINGS, PARSE_ACTION, false) == 0) count++; if (settings->bools.menu_show_information) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_INFORMATION_LIST, PARSE_ACTION, false) == 0) count++; #ifdef HAVE_CONFIGFILE if (settings->bools.menu_show_configurations) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_CONFIGURATIONS_LIST, PARSE_ACTION, false) == 0) count++; #endif if (settings->bools.menu_show_restart_retroarch) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_RESTART_RETROARCH, PARSE_ACTION, false) == 0) count++; if (settings->bools.menu_show_quit_retroarch) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_QUIT_RETROARCH, PARSE_ACTION, false) == 0) count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_SWITCH_GPU_PROFILE, PARSE_ACTION, false) == 0) count++; if (settings->bools.menu_show_reboot) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_REBOOT, PARSE_ACTION, false) == 0) count++; if (settings->bools.menu_show_shutdown) if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, MENU_ENUM_LABEL_SHUTDOWN, PARSE_ACTION, false) == 0) count++; info->flags |= MD_FLAG_NEED_PUSH; } break; case DISPLAYLIST_HELP: if (menu_entries_append(info->list, info->path, info->label, MSG_UNKNOWN, info->type, info->directory_ptr, 0, NULL)) count++; p_dialog->pending_push = false; break; case DISPLAYLIST_INFO: if (menu_entries_append(info->list, info->path, info->label, MSG_UNKNOWN, info->type, info->directory_ptr, 0, NULL)) count++; break; case DISPLAYLIST_FILE_BROWSER_SCAN_DIR: case DISPLAYLIST_FILE_BROWSER_SELECT_DIR: case DISPLAYLIST_FILE_BROWSER_SELECT_FILE: case DISPLAYLIST_FILE_BROWSER_SELECT_CORE: case DISPLAYLIST_FILE_BROWSER_SELECT_COLLECTION: case DISPLAYLIST_GENERIC: info->flags |= MD_FLAG_NEED_NAVIGATION_CLEAR; /* fall-through */ case DISPLAYLIST_PENDING_CLEAR: if (menu_st->driver_ctx && menu_st->driver_ctx->list_cache) menu_st->driver_ctx->list_cache(menu_st->userdata, MENU_LIST_PLAIN, MENU_ACTION_NOOP); if (menu_entries_append(info->list, info->path, info->label, MSG_UNKNOWN, info->type, info->directory_ptr, 0, NULL)) count++; info->flags |= MD_FLAG_NEED_ENTRIES_REFRESH; break; case DISPLAYLIST_USER_BINDS_LIST: menu_entries_clear(info->list); { char lbl[PATH_MAX_LENGTH]; unsigned val = atoi(info->path); const char *temp_val = msg_hash_to_str( (enum msg_hash_enums)(MENU_ENUM_LABEL_INPUT_USER_1_BINDS + (val-1))); strlcpy(lbl, temp_val, sizeof(lbl)); ret = MENU_DISPLAYLIST_PARSE_SETTINGS(info->list, lbl, PARSE_NONE, true, MENU_SETTINGS_INPUT_BEGIN); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; } break; case DISPLAYLIST_DATABASES: menu_entries_clear(info->list); filebrowser_clear_type(); if (!string_is_empty(info->exts)) free(info->exts); if (info->path) free(info->path); info->type_default = FILE_TYPE_RDB; info->exts = strldup(".rdb", sizeof(".rdb")); info->enum_idx = MENU_ENUM_LABEL_PLAYLISTS_TAB; info->path = strdup(settings->paths.path_content_database); load_content = false; use_filebrowser = true; break; case DISPLAYLIST_SHADER_PASS: case DISPLAYLIST_SHADER_PRESET: menu_entries_clear(info->list); #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) { char new_exts[PATH_MAX_LENGTH]; size_t _len = 0; new_exts[0] = '\0'; filebrowser_clear_type(); switch (type) { case DISPLAYLIST_SHADER_PRESET: info->type_default = FILE_TYPE_SHADER_PRESET; if (video_shader_is_supported(RARCH_SHADER_CG)) _len += strlcpy(new_exts + _len, "cgp", sizeof(new_exts) - _len); if (video_shader_is_supported(RARCH_SHADER_GLSL)) { if (new_exts[_len-1] != '\0') _len += strlcpy(new_exts + _len, "|", sizeof(new_exts) - _len); _len += strlcpy(new_exts + _len, "glslp", sizeof(new_exts) - _len); } if (video_shader_is_supported(RARCH_SHADER_SLANG)) { if (new_exts[_len-1] != '\0') _len += strlcpy(new_exts + _len, "|", sizeof(new_exts) - _len); _len += strlcpy(new_exts + _len, "slangp", sizeof(new_exts) - _len); } break; case DISPLAYLIST_SHADER_PASS: info->type_default = FILE_TYPE_SHADER; if (video_shader_is_supported(RARCH_SHADER_CG)) _len += strlcpy(new_exts + _len, "cg", sizeof(new_exts) - _len); if (video_shader_is_supported(RARCH_SHADER_GLSL)) { if (new_exts[_len-1] != '\0') _len += strlcpy(new_exts + _len, "|", sizeof(new_exts) - _len); _len += strlcpy(new_exts + _len, "glsl", sizeof(new_exts) - _len); } if (video_shader_is_supported(RARCH_SHADER_SLANG)) { if (new_exts[_len-1] != '\0') _len += strlcpy(new_exts + _len, "|", sizeof(new_exts) - _len); _len += strlcpy(new_exts + _len, "slang", sizeof(new_exts) - _len); } break; default: break; } if (!string_is_empty(info->exts)) free(info->exts); info->exts = strdup(new_exts); use_filebrowser = true; } #endif break; case DISPLAYLIST_SHADER_PRESET_PREPEND: case DISPLAYLIST_SHADER_PRESET_APPEND: menu_entries_clear(info->list); #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) { char new_exts[PATH_MAX_LENGTH]; size_t _len = 0; new_exts[0] = '\0'; filebrowser_clear_type(); info->type_default = FILE_TYPE_SHADER_PRESET; if (video_shader_is_supported(RARCH_SHADER_CG)) _len += strlcpy(new_exts + _len, "cgp", sizeof(new_exts) - _len); if (video_shader_is_supported(RARCH_SHADER_GLSL)) { if (new_exts[_len-1] != '\0') _len += strlcpy(new_exts + _len, "|", sizeof(new_exts) - _len); _len += strlcpy(new_exts + _len, "glslp", sizeof(new_exts) - _len); } if (video_shader_is_supported(RARCH_SHADER_SLANG)) { if (new_exts[_len-1] != '\0') _len += strlcpy(new_exts + _len, "|", sizeof(new_exts) - _len); _len += strlcpy(new_exts + _len, "slangp", sizeof(new_exts) - _len); } if (!string_is_empty(info->exts)) free(info->exts); info->exts = strdup(new_exts); use_filebrowser = true; } #endif break; case DISPLAYLIST_IMAGES: menu_entries_clear(info->list); if ( (filebrowser_get_type() != FILEBROWSER_SELECT_FILE) && (filebrowser_get_type() != FILEBROWSER_SELECT_IMAGE)) filebrowser_clear_type(); info->type_default = FILE_TYPE_IMAGE; { size_t _len = 0; char new_exts[PATH_MAX_LENGTH]; new_exts[0] = '\0'; #ifdef HAVE_RBMP _len += strlcpy(new_exts + _len, "bmp", sizeof(new_exts) - _len); #endif #ifdef HAVE_RPNG if (new_exts[_len-1] != '\0') _len += strlcpy(new_exts + _len, "|", sizeof(new_exts) - _len); _len += strlcpy(new_exts + _len, "png", sizeof(new_exts) - _len); #endif #ifdef HAVE_RJPEG if (new_exts[_len-1] != '\0') _len += strlcpy(new_exts + _len, "|", sizeof(new_exts) - _len); _len += strlcpy(new_exts + _len, "jpeg", sizeof(new_exts) - _len); if (new_exts[_len-1] != '\0') _len += strlcpy(new_exts + _len, "|", sizeof(new_exts) - _len); _len += strlcpy(new_exts + _len, "jpg", sizeof(new_exts) - _len); #endif #ifdef HAVE_RTGA if (new_exts[_len-1] != '\0') _len += strlcpy(new_exts + _len, "|", sizeof(new_exts) - _len); _len += strlcpy(new_exts + _len, "tga", sizeof(new_exts) - _len); #endif if (!string_is_empty(info->exts)) free(info->exts); info->exts = strdup(new_exts); } use_filebrowser = true; break; case DISPLAYLIST_PLAYLIST: { const char *_msg = path_basename_nocompression(info->path); menu_entries_clear(info->list); count = menu_displaylist_parse_playlist_generic( menu, info, settings, _msg, strlen(_msg), info->path, true, /* Is a collection */ true, /* Enable sorting (if allowed by user config) */ &ret); ret = 0; /* Why do we do this...? */ /* Playlists themselves are sorted * > Display lists generated from playlists * must never be sorted */ info->flags &= ~MD_FLAG_NEED_SORT; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; } break; case DISPLAYLIST_IMAGES_HISTORY: menu_entries_clear(info->list); #ifdef HAVE_IMAGEVIEWER { bool history_list_enable = settings->bools.history_list_enable; const char *path_content_image_history = settings->paths.path_content_image_history; if (history_list_enable) count = menu_displaylist_parse_playlist_generic(menu, info, settings, "images_history", STRLEN_CONST("images_history"), path_content_image_history, false, /* Not a collection */ false, /* Do not sort */ &ret); } #endif if (count == 0) { if (menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_IMAGES_AVAILABLE), msg_hash_to_str(MENU_ENUM_LABEL_NO_IMAGES_AVAILABLE), MENU_ENUM_LABEL_NO_IMAGES_AVAILABLE, MENU_INFO_MESSAGE, 0, 0, NULL)) count++; info->flags &= ~MD_FLAG_NEED_PUSH_NO_PLAYLIST_ENTRIES; } ret = 0; /* Playlists themselves are sorted * > Display lists generated from playlists * must never be sorted */ info->flags &= ~MD_FLAG_NEED_SORT; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; #if defined(HAVE_IMAGEVIEWER) if (history_needs_navigation_clear(menu, g_defaults.image_history)) info->flags |= MD_FLAG_NEED_NAVIGATION_CLEAR; #endif break; case DISPLAYLIST_VIDEO_FILTERS: case DISPLAYLIST_CONFIG_FILES: case DISPLAYLIST_REMAP_FILES: case DISPLAYLIST_RGUI_THEME_PRESETS: case DISPLAYLIST_STREAM_CONFIG_FILES: case DISPLAYLIST_RECORD_CONFIG_FILES: case DISPLAYLIST_OVERLAYS: case DISPLAYLIST_OSK_OVERLAYS: case DISPLAYLIST_FONTS: case DISPLAYLIST_VIDEO_FONTS: case DISPLAYLIST_AUDIO_FILTERS: case DISPLAYLIST_CHEAT_FILES: case DISPLAYLIST_MANUAL_CONTENT_SCAN_DAT_FILES: case DISPLAYLIST_FILE_BROWSER_SELECT_SIDELOAD_CORE: menu_entries_clear(info->list); filebrowser_clear_type(); if (!string_is_empty(info->exts)) free(info->exts); switch (type) { case DISPLAYLIST_VIDEO_FILTERS: info->type_default = FILE_TYPE_VIDEOFILTER; info->exts = strldup("filt", sizeof("filt")); break; case DISPLAYLIST_CONFIG_FILES: info->type_default = FILE_TYPE_CONFIG; info->exts = strldup("cfg", sizeof("cfg")); break; case DISPLAYLIST_REMAP_FILES: info->type_default = FILE_TYPE_REMAP; info->exts = strldup("rmp", sizeof("rmp")); break; case DISPLAYLIST_RGUI_THEME_PRESETS: info->type_default = FILE_TYPE_RGUI_THEME_PRESET; info->exts = strldup("cfg", sizeof("cfg")); break; case DISPLAYLIST_STREAM_CONFIG_FILES: info->type_default = FILE_TYPE_STREAM_CONFIG; info->exts = strldup("cfg", sizeof("cfg")); break; case DISPLAYLIST_RECORD_CONFIG_FILES: info->type_default = FILE_TYPE_RECORD_CONFIG; info->exts = strldup("cfg", sizeof("cfg")); break; case DISPLAYLIST_OVERLAYS: info->type_default = FILE_TYPE_OVERLAY; info->exts = strldup("cfg", sizeof("cfg")); break; case DISPLAYLIST_OSK_OVERLAYS: info->type_default = FILE_TYPE_OSK_OVERLAY; info->exts = strldup("cfg", sizeof("cfg")); break; case DISPLAYLIST_FONTS: info->type_default = FILE_TYPE_FONT; info->exts = strldup("ttf", sizeof("ttf")); break; case DISPLAYLIST_VIDEO_FONTS: info->type_default = FILE_TYPE_VIDEO_FONT; info->exts = strldup("ttf", sizeof("ttf")); break; case DISPLAYLIST_AUDIO_FILTERS: info->type_default = FILE_TYPE_AUDIOFILTER; info->exts = strldup("dsp", sizeof("dsp")); break; case DISPLAYLIST_CHEAT_FILES: info->type_default = FILE_TYPE_CHEAT; info->exts = strldup("cht", sizeof("cht")); break; case DISPLAYLIST_MANUAL_CONTENT_SCAN_DAT_FILES: info->type_default = FILE_TYPE_MANUAL_SCAN_DAT; info->exts = strldup("dat|xml", sizeof("dat|xml")); break; case DISPLAYLIST_FILE_BROWSER_SELECT_SIDELOAD_CORE: { size_t _len; char ext_names[32]; info->type_default = FILE_TYPE_SIDELOAD_CORE; _len = frontend_driver_get_core_extension(ext_names, sizeof(ext_names)); if (_len > 0) { _len += strlcpy(ext_names + _len, "|", sizeof(ext_names) - _len); _len += strlcpy(ext_names + _len, FILE_PATH_CORE_BACKUP_EXTENSION_NO_DOT, sizeof(ext_names) - _len); } else strlcpy(ext_names, FILE_PATH_CORE_BACKUP_EXTENSION_NO_DOT, sizeof(ext_names)); info->exts = strdup(ext_names); } break; default: break; } load_content = false; use_filebrowser = true; break; case DISPLAYLIST_CONTENT_HISTORY: menu_entries_clear(info->list); filebrowser_clear_type(); info->type_default = FILE_TYPE_PLAIN; use_filebrowser = true; if (!string_is_empty(info->exts)) free(info->exts); info->exts = strldup("lpl", sizeof("lpl")); break; case DISPLAYLIST_DATABASE_PLAYLISTS: case DISPLAYLIST_DATABASE_PLAYLISTS_HORIZONTAL: { bool is_horizontal = (type == DISPLAYLIST_DATABASE_PLAYLISTS_HORIZONTAL); menu_entries_clear(info->list); count = menu_displaylist_parse_playlists(info->list, info->type_default, info->path, settings, is_horizontal); if (count == 0 && !is_horizontal) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_PLAYLISTS), msg_hash_to_str(MENU_ENUM_LABEL_NO_PLAYLISTS), MENU_ENUM_LABEL_NO_PLAYLISTS, MENU_SETTING_NO_ITEM, 0, 0, NULL); info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; } break; case DISPLAYLIST_CORES: menu_entries_clear(info->list); { char ext_name[16]; filebrowser_clear_type(); info->type_default = FILE_TYPE_PLAIN; if (frontend_driver_get_core_extension( ext_name, sizeof(ext_name))) { if (!string_is_empty(info->exts)) free(info->exts); info->exts = strdup(ext_name); } } count = menu_displaylist_parse_cores(menu, settings, info); if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ITEMS), msg_hash_to_str(MENU_ENUM_LABEL_NO_ITEMS), MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_NO_ITEM, 0, 0, NULL); if (string_is_equal(info->label, msg_hash_to_str(MENU_ENUM_LABEL_CORE_LIST))) info->flags |= MD_FLAG_PUSH_BUILTIN_CORES; info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_DEFAULT: menu_entries_clear(info->list); load_content = false; use_filebrowser = true; break; case DISPLAYLIST_CORES_DETECTED: menu_entries_clear(info->list); use_filebrowser = true; break; case DISPLAYLIST_MANUAL_CONTENT_SCAN_LIST: menu_entries_clear(info->list); count = menu_displaylist_parse_manual_content_scan_list(info->list); if (count == 0) menu_entries_append(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY), msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY), MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY, FILE_TYPE_NONE, 0, 0, NULL); info->flags |= MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_DROPDOWN_LIST: menu_entries_clear(info->list); { if (string_starts_with_size(info->path, "core_option_", STRLEN_CONST("core_option_"))) count = menu_displaylist_parse_core_option_dropdown_list(info->list, info->path); else { enum msg_hash_enums enum_idx = (enum msg_hash_enums)atoi(info->path); rarch_setting_t *setting = menu_setting_find_enum(enum_idx); if (setting) { switch (setting->type) { case ST_STRING_OPTIONS: { char val_d[16]; char *tok, *save; unsigned i = 0; bool checked_found = false; unsigned checked = 0; char* orig_val = setting->get_string_representation ? strdup(setting->value.target.string) : setting->value.target.string; char *setting_values_cpy = strdup(setting->values); snprintf(val_d, sizeof(val_d), "%d", setting->enum_idx); for (tok = strtok_r(setting_values_cpy, "|", &save); tok; tok = strtok_r(NULL, "|", &save), i++) { if (setting->get_string_representation) { char val_s[256]; strlcpy(setting->value.target.string, tok, setting->size); setting->get_string_representation(setting, val_s, sizeof(val_s)); if (menu_entries_append(info->list, val_s, val_d, MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_DROPDOWN_SETTING_STRING_OPTIONS_ITEM, i, 0, NULL)) count++; } else { if (menu_entries_append(info->list, tok, val_d, MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_DROPDOWN_SETTING_STRING_OPTIONS_ITEM, i, 0, NULL)) count++; } if (!checked_found && string_is_equal(tok, orig_val)) { checked = i; checked_found = true; } } free(setting_values_cpy); if (setting->get_string_representation) { strlcpy(setting->value.target.string, orig_val, setting->size); free(orig_val); } if (checked_found) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[checked].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = checked; } } break; case ST_INT: { float i; char val_d[16]; int32_t orig_value = *setting->value.target.integer; unsigned setting_type = MENU_SETTING_DROPDOWN_SETTING_INT_ITEM; float step = setting->step; float min = (setting->flags & SD_FLAG_ENFORCE_MINRANGE) ? setting->min : 0.00f; float max = (setting->flags & SD_FLAG_ENFORCE_MAXRANGE) ? setting->max : 99999.00f; bool checked_found = false; unsigned checked = 0; unsigned entry_index = 0; snprintf(val_d, sizeof(val_d), "%d", setting->enum_idx); if (setting->get_string_representation) { for (i = min; i <= max; i += step) { char val_s[256]; int val = (int)i; *setting->value.target.integer = val; setting->get_string_representation(setting, val_s, sizeof(val_s)); if (menu_entries_append(info->list, val_s, val_d, MENU_ENUM_LABEL_NO_ITEMS, setting_type, val, 0, NULL)) count++; if (!checked_found && val == orig_value) { checked = entry_index; checked_found = true; } entry_index++; } *setting->value.target.integer = orig_value; } else { for (i = min; i <= max; i += step) { char val_s[16]; int val = (int)i; snprintf(val_s, sizeof(val_s), "%d", val); if (menu_entries_append(info->list, val_s, val_d, MENU_ENUM_LABEL_NO_ITEMS, setting_type, val, 0, NULL)) count++; if (!checked_found && val == orig_value) { checked = entry_index; checked_found = true; } entry_index++; } } if (checked_found) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[checked].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = checked; } } break; case ST_FLOAT: { float i; char val_d[16]; float orig_value = *setting->value.target.fraction; unsigned setting_type = MENU_SETTING_DROPDOWN_SETTING_FLOAT_ITEM; float step = setting->step; float half_step = step * 0.5f; float min = (setting->flags & SD_FLAG_ENFORCE_MINRANGE) ? setting->min : 0.00f; float max = (setting->flags & SD_FLAG_ENFORCE_MAXRANGE) ? setting->max : 9999.00f; bool checked_found = false; unsigned checked = 0; unsigned entry_index = 0; snprintf(val_d, sizeof(val_d), "%d", setting->enum_idx); if (setting->get_string_representation) { for (i = min; i <= max + half_step; i += step) { char val_s[256]; *setting->value.target.fraction = i; setting->get_string_representation(setting, val_s, sizeof(val_s)); if (menu_entries_append(info->list, val_s, val_d, MENU_ENUM_LABEL_NO_ITEMS, setting_type, 0, 0, NULL)) count++; if (!checked_found && (fabs(i - orig_value) < half_step)) { checked = entry_index; checked_found = true; } entry_index++; } *setting->value.target.fraction = orig_value; } else { for (i = min; i <= max + half_step; i += step) { char val_s[16]; snprintf(val_s, sizeof(val_s), "%.2f", i); if (menu_entries_append(info->list, val_s, val_d, MENU_ENUM_LABEL_NO_ITEMS, setting_type, 0, 0, NULL)) count++; if (!checked_found && (fabs(i - orig_value) < half_step)) { checked = entry_index; checked_found = true; } entry_index++; } } if (checked_found) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[checked].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = checked; } } break; case ST_UINT: { float i; char val_d[16]; unsigned orig_value = *setting->value.target.unsigned_integer; unsigned setting_type = MENU_SETTING_DROPDOWN_SETTING_UINT_ITEM; float step = setting->step; float min = (setting->flags & SD_FLAG_ENFORCE_MINRANGE) ? setting->min : 0.00f; float max = (setting->flags & SD_FLAG_ENFORCE_MAXRANGE) ? setting->max : 9999.00f; bool checked_found = false; unsigned checked = 0; unsigned entry_index = 0; snprintf(val_d, sizeof(val_d), "%d", setting->enum_idx); if (setting->get_string_representation) { for (i = min; i <= max; i += step) { char val_s[256]; int val = (int)i; *setting->value.target.unsigned_integer = val; setting->get_string_representation(setting, val_s, sizeof(val_s)); if (menu_entries_append(info->list, val_s, val_d, MENU_ENUM_LABEL_NO_ITEMS, setting_type, val, 0, NULL)) count++; if (!checked_found && val == (int)orig_value) { checked = entry_index; checked_found = true; } entry_index++; } *setting->value.target.unsigned_integer = orig_value; } else { for (i = min; i <= max; i += step) { char val_s[16]; int val = (int)i; snprintf(val_s, sizeof(val_s), "%d", val); if (menu_entries_append(info->list, val_s, val_d, MENU_ENUM_LABEL_NO_ITEMS, setting_type, val, 0, NULL)) count++; if (!checked_found && val == (int)orig_value) { checked = entry_index; checked_found = true; } entry_index++; } } if (checked_found) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[checked].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = checked; } } break; default: break; } } } info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; } break; case DISPLAYLIST_DROPDOWN_LIST_VIDEO_SHADER_NUM_PASSES: menu_entries_clear(info->list); #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL) { unsigned i; struct video_shader *shader = menu_shader_get(); unsigned pass_count = shader ? shader->passes : 0; menu_entries_clear(info->list); for (i = 0; i < GFX_MAX_SHADERS+1; i++) { char val_d[16]; snprintf(val_d, sizeof(val_d), "%d", i); if (menu_entries_append(info->list, val_d, val_d, MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_DROPDOWN_ITEM_VIDEO_SHADER_NUM_PASS, i, 0, NULL)) count++; if (i == pass_count) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[i].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = i; } } info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; } #endif break; case DISPLAYLIST_DROPDOWN_LIST_SPECIAL: menu_entries_clear(info->list); if (string_starts_with_size(info->path, "core_option_", STRLEN_CONST("core_option_"))) count = menu_displaylist_parse_core_option_dropdown_list(info->list, info->path); else { enum msg_hash_enums enum_idx = (enum msg_hash_enums)atoi(info->path); rarch_setting_t *setting = menu_setting_find_enum(enum_idx); if (setting) { switch (setting->type) { case ST_STRING_OPTIONS: { char val_d[16]; char *tok, *save; unsigned i = 0; bool checked_found = false; unsigned checked = 0; char *setting_values_cpy = strdup(setting->values); snprintf(val_d, sizeof(val_d), "%d", setting->enum_idx); for (tok = strtok_r(setting_values_cpy, "|", &save); tok; tok = strtok_r(NULL, "|", &save), i++) { if (menu_entries_append(info->list, tok, val_d, MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_DROPDOWN_SETTING_STRING_OPTIONS_ITEM_SPECIAL, i, 0, NULL)) count++; if ( !checked_found && string_is_equal(tok, setting->value.target.string)) { checked = i; checked_found = true; } } free(setting_values_cpy); if (checked_found) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[checked].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = checked; } } break; case ST_INT: { float i; char val_d[16]; int32_t orig_value = *setting->value.target.integer; unsigned setting_type = MENU_SETTING_DROPDOWN_SETTING_INT_ITEM_SPECIAL; float step = setting->step; float min = (setting->flags & SD_FLAG_ENFORCE_MINRANGE) ? setting->min : 0.00f; float max = (setting->flags & SD_FLAG_ENFORCE_MAXRANGE) ? setting->max : 9999.00f; bool checked_found = false; unsigned checked = 0; unsigned entry_index = 0; snprintf(val_d, sizeof(val_d), "%d", setting->enum_idx); if (setting->get_string_representation) { for (i = min; i <= max; i += step) { char val_s[256]; int val = (int)i; *setting->value.target.integer = val; setting->get_string_representation(setting, val_s, sizeof(val_s)); if (menu_entries_append(info->list, val_s, val_d, MENU_ENUM_LABEL_NO_ITEMS, setting_type, val, 0, NULL)) count++; if (!checked_found && val == orig_value) { checked = entry_index; checked_found = true; } entry_index++; } *setting->value.target.integer = orig_value; } else { for (i = min; i <= max; i += step) { char val_s[16]; int val = (int)i; snprintf(val_s, sizeof(val_s), "%d", val); if (menu_entries_append(info->list, val_s, val_d, MENU_ENUM_LABEL_NO_ITEMS, setting_type, val, 0, NULL)) count++; if (!checked_found && val == orig_value) { checked = entry_index; checked_found = true; } entry_index++; } } if (checked_found) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[checked].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = checked; } } break; case ST_FLOAT: { float i; char val_d[16]; float orig_value = *setting->value.target.fraction; unsigned setting_type = MENU_SETTING_DROPDOWN_SETTING_FLOAT_ITEM_SPECIAL; float step = setting->step; float half_step = step * 0.5f; float min = (setting->flags & SD_FLAG_ENFORCE_MINRANGE) ? setting->min : 0.00f; float max = (setting->flags & SD_FLAG_ENFORCE_MAXRANGE) ? setting->max : 9999.00f; bool checked_found = false; unsigned checked = 0; unsigned entry_index = 0; snprintf(val_d, sizeof(val_d), "%d", setting->enum_idx); if (setting->get_string_representation) { for (i = min; i <= max; i += step) { char val_s[256]; *setting->value.target.fraction = i; setting->get_string_representation(setting, val_s, sizeof(val_s)); if (menu_entries_append(info->list, val_s, val_d, MENU_ENUM_LABEL_NO_ITEMS, setting_type, 0, 0, NULL)) count++; if (!checked_found && (fabs(i - orig_value) < half_step)) { checked = entry_index; checked_found = true; } entry_index++; } *setting->value.target.fraction = orig_value; } else { for (i = min; i <= max; i += step) { char val_s[16]; snprintf(val_s, sizeof(val_s), "%.2f", i); if (menu_entries_append(info->list, val_s, val_d, MENU_ENUM_LABEL_NO_ITEMS, setting_type, 0, 0, NULL)) count++; if (!checked_found && (fabs(i - orig_value) < half_step)) { checked = entry_index; checked_found = true; } entry_index++; } } if (checked_found) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[checked].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = checked; } } break; case ST_UINT: { float i; char val_d[16]; unsigned orig_value = *setting->value.target.unsigned_integer; unsigned setting_type = MENU_SETTING_DROPDOWN_SETTING_UINT_ITEM_SPECIAL; float step = setting->step; float min = (setting->flags & SD_FLAG_ENFORCE_MINRANGE) ? setting->min : 0.00f; float max = (setting->flags & SD_FLAG_ENFORCE_MAXRANGE) ? setting->max : 9999.00f; bool checked_found = false; unsigned checked = 0; unsigned entry_index = 0; snprintf(val_d, sizeof(val_d), "%d", setting->enum_idx); if (setting->get_string_representation) { for (i = min; i <= max; i += step) { char val_s[256]; int val = (int)i; *setting->value.target.unsigned_integer = val; setting->get_string_representation(setting, val_s, sizeof(val_s)); if (menu_entries_append(info->list, val_s, val_d, MENU_ENUM_LABEL_NO_ITEMS, setting_type, val, 0, NULL)) count++; if (!checked_found && val == (int)orig_value) { checked = entry_index; checked_found = true; } entry_index++; } *setting->value.target.unsigned_integer = orig_value; } else { for (i = min; i <= max; i += step) { char val_s[16]; int val = (int)i; snprintf(val_s, sizeof(val_s), "%d", val); if (menu_entries_append(info->list, val_s, val_d, MENU_ENUM_LABEL_NO_ITEMS, setting_type, val, 0, NULL)) count++; if (!checked_found && val == (int)orig_value) { checked = entry_index; checked_found = true; } entry_index++; } } if (checked_found) { struct menu_state *menu_st = menu_state_get_ptr(); menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[checked].actiondata; if (cbs) cbs->checked = true; menu_st->selection_ptr = checked; } } break; default: break; } } } info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; break; case DISPLAYLIST_NONE: break; } if (use_filebrowser) { if (string_is_empty(info->path)) { if (frontend_driver_parse_drive_list(info->list, load_content) != 0) if (menu_entries_append(info->list, "/", "", load_content ? MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR : MENU_ENUM_LABEL_FILE_BROWSER_DIRECTORY, FILE_TYPE_DIRECTORY, 0, 0, NULL)) count++; } else { const char *pending_selection = menu_state_get_ptr()->pending_selection; bool show_hidden_files = settings->bools.show_hidden_files; bool multimedia_builtin_mediaplayer_enable = settings->bools.multimedia_builtin_mediaplayer_enable; bool multimedia_builtin_imageviewer_enable = settings->bools.multimedia_builtin_imageviewer_enable; bool filter_supported_extensions_enable = settings->bools.menu_navigation_browser_filter_supported_extensions_enable; filebrowser_parse(info->list, info->path, info->exts, info->label, info->type_default, type, show_hidden_files, multimedia_builtin_mediaplayer_enable, multimedia_builtin_imageviewer_enable, filter_supported_extensions_enable ); /* Apply pending selection */ if (!string_is_empty(pending_selection)) { size_t selection_idx = 0; if (menu_entries_list_search(pending_selection, &selection_idx)) { struct menu_state *menu_st = menu_state_get_ptr(); menu_st->selection_ptr = selection_idx; if (menu_st->driver_ctx->navigation_set) menu_st->driver_ctx->navigation_set(menu_st->userdata, true); } menu_driver_set_pending_selection(NULL); } } info->flags |= MD_FLAG_NEED_REFRESH | MD_FLAG_NEED_PUSH; } if (ret != 0) return false; } return true; }