Add 'Standalone Cores' menu (#13655)

This commit is contained in:
jdgleaver 2022-02-22 18:23:48 +00:00 committed by GitHub
parent 6dec52fda7
commit 9b0cb0fc92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 929 additions and 69 deletions

View File

@ -1088,7 +1088,8 @@ ifeq ($(HAVE_MENU_COMMON), 1)
menu/cbs/menu_cbs_label.o \
menu/cbs/menu_cbs_sublabel.o \
menu/cbs/menu_cbs_title.o \
menu/menu_displaylist.o
menu/menu_displaylist.o \
menu/menu_contentless_cores.o
endif
ifeq ($(HAVE_GFX_WIDGETS), 1)

View File

@ -730,6 +730,7 @@ static const bool content_show_playlists = true;
#if defined(HAVE_LIBRETRODB)
#define DEFAULT_MENU_CONTENT_SHOW_EXPLORE true
#endif
#define DEFAULT_MENU_CONTENT_SHOW_CONTENTLESS_CORES MENU_CONTENTLESS_CORES_DISPLAY_SINGLE_PURPOSE
#ifdef HAVE_XMB
#define DEFAULT_XMB_ANIMATION 0

View File

@ -2162,6 +2162,7 @@ static struct config_uint_setting *populate_settings_uint(
SETTING_UINT("menu_ticker_type", &settings->uints.menu_ticker_type, true, DEFAULT_MENU_TICKER_TYPE, false);
SETTING_UINT("menu_scroll_delay", &settings->uints.menu_scroll_delay, true, DEFAULT_MENU_SCROLL_DELAY, false);
SETTING_UINT("content_show_add_entry", &settings->uints.menu_content_show_add_entry, true, DEFAULT_MENU_CONTENT_SHOW_ADD_ENTRY, false);
SETTING_UINT("content_show_contentless_cores", &settings->uints.menu_content_show_contentless_cores, true, DEFAULT_MENU_CONTENT_SHOW_CONTENTLESS_CORES, false);
SETTING_UINT("menu_screensaver_timeout", &settings->uints.menu_screensaver_timeout, true, DEFAULT_MENU_SCREENSAVER_TIMEOUT, false);
#if defined(HAVE_MATERIALUI) || defined(HAVE_XMB) || defined(HAVE_OZONE)
SETTING_UINT("menu_screensaver_animation", &settings->uints.menu_screensaver_animation, true, DEFAULT_MENU_SCREENSAVER_ANIMATION, false);

View File

@ -295,6 +295,7 @@ typedef struct settings
unsigned menu_ticker_type;
unsigned menu_scroll_delay;
unsigned menu_content_show_add_entry;
unsigned menu_content_show_contentless_cores;
unsigned menu_screensaver_timeout;
unsigned menu_screensaver_animation;

View File

@ -48,7 +48,7 @@
/* Core Info Cache START */
/*************************/
#define CORE_INFO_CACHE_VERSION "1.1"
#define CORE_INFO_CACHE_VERSION "1.2"
#define CORE_INFO_CACHE_DEFAULT_CAPACITY 8
/* TODO/FIXME: Apparently rzip compression is an issue on UWP */
@ -203,6 +203,8 @@ static bool CCJSONObjectMemberHandler(void *context,
}
else if (string_is_equal(pValue, "supports_no_game"))
pCtx->current_entry_bool_val = &pCtx->core_info->supports_no_game;
else if (string_is_equal(pValue, "single_purpose"))
pCtx->current_entry_bool_val = &pCtx->core_info->single_purpose;
else if (string_is_equal(pValue, "savestate_support_level"))
pCtx->current_entry_uint_val = &pCtx->core_info->savestate_support_level;
break;
@ -472,6 +474,7 @@ static void core_info_copy(core_info_t *src, core_info_t *dst)
dst->savestate_support_level = src->savestate_support_level;
dst->has_info = src->has_info;
dst->supports_no_game = src->supports_no_game;
dst->single_purpose = src->single_purpose;
dst->database_match_archive_member = src->database_match_archive_member;
dst->is_experimental = src->is_experimental;
dst->is_locked = src->is_locked;
@ -567,6 +570,7 @@ static void core_info_transfer(core_info_t *src, core_info_t *dst)
dst->savestate_support_level = src->savestate_support_level;
dst->has_info = src->has_info;
dst->supports_no_game = src->supports_no_game;
dst->single_purpose = src->single_purpose;
dst->database_match_archive_member = src->database_match_archive_member;
dst->is_experimental = src->is_experimental;
dst->is_locked = src->is_locked;
@ -1118,6 +1122,14 @@ static bool core_info_cache_write(core_info_cache_list_t *list, const char *info
rjsonwriter_add_comma(writer);
rjsonwriter_add_newline(writer);
rjsonwriter_add_spaces(writer, 6);
rjsonwriter_add_string(writer, "single_purpose");
rjsonwriter_add_colon(writer);
rjsonwriter_add_space(writer);
rjsonwriter_add_bool(writer, info->single_purpose);
rjsonwriter_add_comma(writer);
rjsonwriter_add_newline(writer);
rjsonwriter_add_spaces(writer, 6);
rjsonwriter_add_string(writer, "database_match_archive_member");
rjsonwriter_add_colon(writer);
@ -1746,6 +1758,10 @@ static void core_info_parse_config_file(
&tmp_bool))
info->supports_no_game = tmp_bool;
if (config_get_bool(conf, "single_purpose",
&tmp_bool))
info->single_purpose = tmp_bool;
if (config_get_bool(conf, "database_match_archive_member",
&tmp_bool))
info->database_match_archive_member = tmp_bool;
@ -2178,6 +2194,7 @@ bool core_info_init_current_core(void)
return false;
current->has_info = false;
current->supports_no_game = false;
current->single_purpose = false;
current->database_match_archive_member = false;
current->is_experimental = false;
current->is_locked = false;

View File

@ -104,6 +104,7 @@ typedef struct
uint32_t savestate_support_level;
bool has_info;
bool supports_no_game;
bool single_purpose;
bool database_match_archive_member;
bool is_experimental;
bool is_locked;

View File

@ -627,6 +627,7 @@ void drivers_init(
#ifdef HAVE_LIBRETRODB
menu_explore_context_init();
#endif
menu_contentless_cores_context_init();
}
}
@ -694,6 +695,7 @@ void driver_uninit(int flags)
#ifdef HAVE_LIBRETRODB
menu_explore_context_deinit();
#endif
menu_contentless_cores_context_deinit();
menu_driver_ctl(RARCH_MENU_CTL_DEINIT, NULL);
}

View File

@ -1416,6 +1416,7 @@ MENU
#include "../menu/cbs/menu_cbs_label.c"
#include "../menu/cbs/menu_cbs_sublabel.c"
#include "../menu/menu_displaylist.c"
#include "../menu/menu_contentless_cores.c"
#ifdef HAVE_LIBRETRODB
#include "../menu/menu_explore.c"
#include "../tasks/task_menu_explore.c"

View File

@ -82,6 +82,14 @@ MSG_HASH(
MENU_ENUM_LABEL_EXPLORE_INITIALISING_LIST,
"explore_initialising_list"
)
MSG_HASH(
MENU_ENUM_LABEL_CONTENTLESS_CORES_TAB,
"contentless_cores_tab"
)
MSG_HASH(
MENU_ENUM_LABEL_CONTENTLESS_CORE,
"contentless_core"
)
MSG_HASH(
MENU_ENUM_LABEL_ADD_TAB,
"add_tab"
@ -768,6 +776,10 @@ MSG_HASH(
MENU_ENUM_LABEL_DEFERRED_EXPLORE_LIST,
"deferred_explore_list"
)
MSG_HASH(
MENU_ENUM_LABEL_DEFERRED_CONTENTLESS_CORES_LIST,
"deferred_contentless_cores_list"
)
MSG_HASH(
MENU_ENUM_LABEL_DEFERRED_NETPLAY,
"deferred_netplay"
@ -3752,6 +3764,10 @@ MSG_HASH(
MENU_ENUM_LABEL_CONTENT_SHOW_EXPLORE,
"content_show_explore"
)
MSG_HASH(
MENU_ENUM_LABEL_CONTENT_SHOW_CONTENTLESS_CORES,
"content_show_contentless_cores"
)
MSG_HASH(
MENU_ENUM_LABEL_CONTENT_SHOW_FAVORITES,
"content_show_favorites"
@ -4070,6 +4086,10 @@ MSG_HASH(
MENU_ENUM_LABEL_GOTO_EXPLORE,
"goto_explore"
)
MSG_HASH(
MENU_ENUM_LABEL_GOTO_CONTENTLESS_CORES,
"goto_contentless_cores"
)
MSG_HASH(
MENU_ENUM_LABEL_MATERIALUI_ICONS_ENABLE,
"materialui_icons_enable"

View File

@ -44,6 +44,10 @@ MSG_HASH(
MENU_ENUM_LABEL_VALUE_EXPLORE_TAB,
"Explore"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_CONTENTLESS_CORES_TAB,
"Standalone Cores"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_ADD_TAB,
"Import Content"
@ -286,6 +290,14 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_GOTO_EXPLORE,
"Browse all content matching the database via a categorized search interface."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_GOTO_CONTENTLESS_CORES,
"Standalone Cores"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_GOTO_CONTENTLESS_CORES,
"Installed cores which can operate without loading content will appear here."
)
/* Main Menu > Online Updater */
@ -4620,6 +4632,22 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_CONTENT_SHOW_EXPLORE,
"Show the content explorer option. (Restart Required on Ozone/XMB)"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_CONTENTLESS_CORES,
"Show 'Standalone Cores'"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_CONTENT_SHOW_CONTENTLESS_CORES,
"Specify the type of core (if any) to show in the 'Standalone Cores' menu. (Restart Required on Ozone/XMB)"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_SHOW_CONTENTLESS_CORES_ALL,
"All"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_SHOW_CONTENTLESS_CORES_SINGLE_PURPOSE,
"Single-Use"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_TIMEDATE_ENABLE,
"Show Date and Time"

View File

@ -92,6 +92,13 @@ int action_cancel_pop_default(const char *path,
return 0;
}
static int action_cancel_contentless_core(const char *path,
const char *label, unsigned type, size_t idx)
{
menu_state_get_ptr()->contentless_core_ptr = 0;
return action_cancel_pop_default(path, label, type, idx) ;
}
#ifdef HAVE_CHEATS
static int action_cancel_cheat_details(const char *path,
const char *label, unsigned type, size_t idx)
@ -164,6 +171,11 @@ static int menu_cbs_init_bind_cancel_compare_type(
case FILE_TYPE_DOWNLOAD_CORE:
BIND_ACTION_CANCEL(cbs, action_cancel_core_content);
return 0;
case MENU_SETTING_ACTION_CONTENTLESS_CORE_RUN:
BIND_ACTION_CANCEL(cbs, action_cancel_contentless_core);
return 0;
default:
break;
}
#ifdef HAVE_CHEATS

View File

@ -648,6 +648,7 @@ GENERIC_DEFERRED_PUSH_GENERAL(deferred_music_history_list, PUSH_DEFAULT, DISPLAY
GENERIC_DEFERRED_PUSH_GENERAL(deferred_image_history_list, PUSH_DEFAULT, DISPLAYLIST_IMAGES_HISTORY)
GENERIC_DEFERRED_PUSH_GENERAL(deferred_video_history_list, PUSH_DEFAULT, DISPLAYLIST_VIDEO_HISTORY)
GENERIC_DEFERRED_PUSH_GENERAL(deferred_explore_list, PUSH_DEFAULT, DISPLAYLIST_EXPLORE)
GENERIC_DEFERRED_PUSH_GENERAL(deferred_contentless_cores_list, PUSH_DEFAULT, DISPLAYLIST_CONTENTLESS_CORES)
GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST)
GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_special, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_SPECIAL)
GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_resolution, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_RESOLUTION)
@ -759,6 +760,7 @@ static int menu_cbs_init_bind_deferred_push_compare_label(
{MENU_ENUM_LABEL_DEFERRED_IMAGES_LIST, deferred_image_history_list},
{MENU_ENUM_LABEL_DEFERRED_VIDEO_LIST, deferred_video_history_list},
{MENU_ENUM_LABEL_DEFERRED_EXPLORE_LIST, deferred_explore_list},
{MENU_ENUM_LABEL_DEFERRED_CONTENTLESS_CORES_LIST, deferred_contentless_cores_list},
{MENU_ENUM_LABEL_DEFERRED_INPUT_SETTINGS_LIST, deferred_push_input_settings_list},
{MENU_ENUM_LABEL_DEFERRED_INPUT_MENU_SETTINGS_LIST, deferred_push_input_menu_settings_list},
{MENU_ENUM_LABEL_DEFERRED_INPUT_TURBO_FIRE_SETTINGS_LIST, deferred_push_input_turbo_fire_settings_list},

View File

@ -519,6 +519,25 @@ static void menu_action_setting_disp_set_label_core_manager_entry(
}
}
static void menu_action_setting_disp_set_label_contentless_core(
file_list_t* list,
unsigned *w, unsigned type, unsigned i,
const char *label,
char *s, size_t len,
const char *path,
char *s2, size_t len2)
{
const char *alt = list->list[i].alt
? list->list[i].alt
: list->list[i].path;
*s = '\0';
*w = 0;
if (alt)
strlcpy(s2, alt, len2);
}
#ifndef HAVE_LAKKA_SWITCH
#ifdef HAVE_LAKKA
static void menu_action_setting_disp_cpu_gov_mode(
@ -1912,6 +1931,10 @@ static int menu_cbs_init_bind_get_string_representation_compare_label(
BIND_ACTION_GET_VALUE(cbs,
menu_action_setting_disp_set_label_core_manager_entry);
break;
case MENU_ENUM_LABEL_CONTENTLESS_CORE:
BIND_ACTION_GET_VALUE(cbs,
menu_action_setting_disp_set_label_contentless_core);
break;
case MENU_ENUM_LABEL_CORE_OPTION_OVERRIDE_INFO:
BIND_ACTION_GET_VALUE(cbs,
menu_action_setting_disp_set_label_core_option_override_info);
@ -2120,6 +2143,7 @@ static int menu_cbs_init_bind_get_string_representation_compare_type(
case MENU_SETTING_ACTION_DELETE_ENTRY:
case MENU_SETTING_ACTION_CORE_DISK_OPTIONS:
case MENU_EXPLORE_TAB:
case MENU_CONTENTLESS_CORES_TAB:
BIND_ACTION_GET_VALUE(cbs,
menu_action_setting_disp_set_label_menu_more);
break;

View File

@ -1006,6 +1006,7 @@ static int menu_cbs_init_bind_left_compare_label(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_SUBSYSTEM_LOAD:
case MENU_ENUM_LABEL_CONNECT_NETPLAY_ROOM:
case MENU_ENUM_LABEL_EXPLORE_ITEM:
case MENU_ENUM_LABEL_CONTENTLESS_CORE:
case MENU_ENUM_LABEL_NO_SETTINGS_FOUND:
BIND_ACTION_LEFT(cbs, action_left_mainmenu);
break;
@ -1043,6 +1044,7 @@ static int menu_cbs_init_bind_left_compare_label(menu_file_list_cbs_t *cbs,
break;
case MENU_ENUM_LABEL_NO_ITEMS:
case MENU_ENUM_LABEL_NO_PLAYLIST_ENTRIES_AVAILABLE:
case MENU_ENUM_LABEL_NO_CORES_AVAILABLE:
case MENU_ENUM_LABEL_EXPLORE_INITIALISING_LIST:
if (
string_ends_with_size(menu_label, "_tab",

View File

@ -612,6 +612,15 @@ int generic_action_ok_displaylist_push(const char *path,
info.enum_idx = MENU_ENUM_LABEL_DEFERRED_EXPLORE_LIST;
dl_type = DISPLAYLIST_GENERIC;
break;
case ACTION_OK_DL_CONTENTLESS_CORES_LIST:
info.type = type;
info.directory_ptr = idx;
info_path = label;
info_label = msg_hash_to_str(
MENU_ENUM_LABEL_DEFERRED_CONTENTLESS_CORES_LIST);
info.enum_idx = MENU_ENUM_LABEL_DEFERRED_CONTENTLESS_CORES_LIST;
dl_type = DISPLAYLIST_GENERIC;
break;
case ACTION_OK_DL_REMAPPINGS_PORT_LIST:
info.type = type;
info.directory_ptr = idx;
@ -5172,14 +5181,30 @@ int action_ok_close_content(const char *path, const char *label, unsigned type,
/* Unload core */
ret = generic_action_ok_command(CMD_EVENT_UNLOAD_CORE);
/* If close content was selected via 'Main Menu > Quick Menu',
* have to flush the menu stack back to 'Main Menu'
/* If close content was selected via any means other than
* 'Playlist > Quick Menu', have to flush the menu stack
* (otherwise users will be presented with an empty
* 'No items' quick menu, requiring needless backwards
* navigation) */
if (type == MENU_SETTING_ACTION_CLOSE)
{
menu_entries_flush_stack(msg_hash_to_str(MENU_ENUM_LABEL_MAIN_MENU), 0);
const char *flush_target = msg_hash_to_str(MENU_ENUM_LABEL_MAIN_MENU);
const char *parent_label = NULL;
struct menu_state *menu_st = menu_state_get_ptr();
file_list_t *list = NULL;
if (menu_st->entries.list)
list = MENU_LIST_GET(menu_st->entries.list, 0);
if (list && (list->size > 1))
{
file_list_get_at_offset(list, list->size - 2, NULL, &parent_label, NULL, NULL);
if (string_is_equal(parent_label, msg_hash_to_str(MENU_ENUM_LABEL_CONTENTLESS_CORES_TAB)) ||
string_is_equal(parent_label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_CONTENTLESS_CORES_LIST)))
flush_target = parent_label;
}
menu_entries_flush_stack(flush_target, 0);
/* An annoyance - some menu drivers (Ozone...) call
* RARCH_MENU_CTL_SET_PREVENT_POPULATE in awkward
* places, which can cause breakage here when flushing
@ -5611,6 +5636,7 @@ DEFAULT_ACTION_OK_FUNC(action_ok_cdrom_info_list, ACTION_OK_DL_CDROM_INFO_DETAIL
DEFAULT_ACTION_OK_FUNC(action_ok_goto_video, ACTION_OK_DL_VIDEO_LIST)
DEFAULT_ACTION_OK_FUNC(action_ok_goto_music, ACTION_OK_DL_MUSIC_LIST)
DEFAULT_ACTION_OK_FUNC(action_ok_goto_explore, ACTION_OK_DL_EXPLORE_LIST)
DEFAULT_ACTION_OK_FUNC(action_ok_goto_contentless_cores, ACTION_OK_DL_CONTENTLESS_CORES_LIST)
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
DEFAULT_ACTION_OK_FUNC(action_ok_shader_preset_save, ACTION_OK_DL_SHADER_PRESET_SAVE)
DEFAULT_ACTION_OK_FUNC(action_ok_shader_preset_remove, ACTION_OK_DL_SHADER_PRESET_REMOVE)
@ -6670,12 +6696,20 @@ static int action_ok_start_core(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
{
content_ctx_info_t content_info;
menu_ctx_list_t list_info;
content_info.argc = 0;
content_info.argv = NULL;
content_info.args = NULL;
content_info.environ_get = NULL;
/* We are going to push a new menu; ensure
* that the current one is cached for animation
* purposes */
list_info.type = MENU_LIST_PLAIN;
list_info.action = 0;
menu_driver_list_cache(&list_info);
path_clear(RARCH_PATH_BASENAME);
if (!task_push_start_current_core(&content_info))
return -1;
@ -6683,6 +6717,54 @@ static int action_ok_start_core(const char *path,
return 0;
}
static int action_ok_contentless_core_run(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
{
const char *core_path = path;
/* TODO/FIXME: If this function succeeds, the
* quick menu will 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 cache
* the current selection here, and reapply it manually
* when building the contentless cores list... */
size_t selection = menu_navigation_get_selection();
if (string_is_empty(core_path))
return menu_cbs_exit();
/* If core is already running, open quick menu */
if (retroarch_ctl(RARCH_CTL_IS_CORE_LOADED, (void*)core_path) &&
retroarch_ctl(RARCH_CTL_CORE_IS_RUNNING, NULL))
{
bool flush_menu = false;
menu_driver_ctl(RARCH_MENU_CTL_SET_PENDING_QUICK_MENU, &flush_menu);
menu_state_get_ptr()->contentless_core_ptr = selection;
menu_navigation_set_selection(0);
return 0;
}
/* Cache current menu selection *before* attempting
* to start the core, to ensure consistent menu
* navigation (i.e. running a core will in general
* cause a redraw of the menu, so must record current
* position even if the operation fails) */
menu_state_get_ptr()->contentless_core_ptr = selection;
/* Load and start core */
path_clear(RARCH_PATH_BASENAME);
if (!task_push_load_contentless_core_from_menu(core_path))
{
if (retroarch_ctl(RARCH_CTL_IS_CORE_LOADED, (void*)core_path))
generic_action_ok_command(CMD_EVENT_UNLOAD_CORE);
return -1;
}
return 0;
}
static int action_ok_load_archive(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
{
@ -7384,6 +7466,9 @@ static int action_ok_core_delete(const char *path,
/* Reload core info files */
command_event(CMD_EVENT_CORE_INFO_INIT, NULL);
/* Force reload of contentless cores icons */
menu_contentless_cores_free();
/* Return to higher level menu */
return action_cancel_pop_default(NULL, NULL, 0, 0);
}
@ -7787,6 +7872,7 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs,
{MENU_ENUM_LABEL_GOTO_IMAGES, action_ok_goto_images},
{MENU_ENUM_LABEL_GOTO_VIDEO, action_ok_goto_video},
{MENU_ENUM_LABEL_GOTO_EXPLORE, action_ok_goto_explore},
{MENU_ENUM_LABEL_GOTO_CONTENTLESS_CORES, action_ok_goto_contentless_cores},
{MENU_ENUM_LABEL_BROWSE_START, action_ok_browse_url_start},
{MENU_ENUM_LABEL_FILE_BROWSER_CORE, action_ok_load_core},
{MENU_ENUM_LABEL_FILE_BROWSER_CORE_SELECT_FROM_COLLECTION, action_ok_core_deferred_set},
@ -8020,6 +8106,7 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs,
{MENU_ENUM_LABEL_PLAYLIST_MANAGER_DEFAULT_CORE, action_ok_playlist_default_core},
{MENU_ENUM_LABEL_CORE_MANAGER_LIST, action_ok_push_core_manager_list},
{MENU_ENUM_LABEL_EXPLORE_TAB, action_ok_push_default},
{MENU_ENUM_LABEL_CONTENTLESS_CORES_TAB, action_ok_push_default},
};
for (i = 0; i < ARRAY_SIZE(ok_list); i++)
@ -8652,6 +8739,9 @@ static int menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t *cbs,
case MENU_SETTING_ACTION_AUDIO_DSP_PLUGIN_REMOVE:
BIND_ACTION_OK(cbs, action_ok_audio_dsp_plugin_remove);
break;
case MENU_SETTING_ACTION_CONTENTLESS_CORE_RUN:
BIND_ACTION_OK(cbs, action_ok_contentless_core_run);
break;
default:
return -1;
}

View File

@ -1126,6 +1126,7 @@ static int menu_cbs_init_bind_right_compare_label(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_SUBSYSTEM_LOAD:
case MENU_ENUM_LABEL_CONNECT_NETPLAY_ROOM:
case MENU_ENUM_LABEL_EXPLORE_ITEM:
case MENU_ENUM_LABEL_CONTENTLESS_CORE:
case MENU_ENUM_LABEL_NO_SETTINGS_FOUND:
BIND_ACTION_RIGHT(cbs, action_right_mainmenu);
break;
@ -1163,6 +1164,7 @@ static int menu_cbs_init_bind_right_compare_label(menu_file_list_cbs_t *cbs,
break;
case MENU_ENUM_LABEL_NO_ITEMS:
case MENU_ENUM_LABEL_NO_PLAYLIST_ENTRIES_AVAILABLE:
case MENU_ENUM_LABEL_NO_CORES_AVAILABLE:
case MENU_ENUM_LABEL_EXPLORE_INITIALISING_LIST:
if (
string_ends_with_size(menu_label, "_tab",

View File

@ -693,6 +693,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_goto_images,
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_goto_music, MENU_ENUM_SUBLABEL_GOTO_MUSIC)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_goto_video, MENU_ENUM_SUBLABEL_GOTO_VIDEO)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_goto_explore, MENU_ENUM_SUBLABEL_GOTO_EXPLORE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_goto_contentless_cores, MENU_ENUM_SUBLABEL_GOTO_CONTENTLESS_CORES)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_filebrowser_settings, MENU_ENUM_SUBLABEL_MENU_FILE_BROWSER_SETTINGS)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_filebrowser_open_uwp_permissions, MENU_ENUM_SUBLABEL_FILE_BROWSER_OPEN_UWP_PERMISSIONS)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_filebrowser_open_picker, MENU_ENUM_SUBLABEL_FILE_BROWSER_OPEN_PICKER)
@ -855,6 +856,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_import_content_tab,
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_import_content_entry, MENU_ENUM_SUBLABEL_CONTENT_SHOW_ADD_ENTRY)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_playlist_tabs, MENU_ENUM_SUBLABEL_CONTENT_SHOW_PLAYLISTS)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_explore_tab, MENU_ENUM_SUBLABEL_CONTENT_SHOW_EXPLORE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_contentless_cores_tab, MENU_ENUM_SUBLABEL_CONTENT_SHOW_CONTENTLESS_CORES)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_main_menu_enable_settings, MENU_ENUM_SUBLABEL_XMB_MAIN_MENU_ENABLE_SETTINGS)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_rgui_show_start_screen, MENU_ENUM_SUBLABEL_RGUI_SHOW_START_SCREEN)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_header_opacity, MENU_ENUM_SUBLABEL_MATERIALUI_MENU_HEADER_OPACITY)
@ -1968,6 +1970,7 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
{
case MENU_ENUM_LABEL_FILE_BROWSER_CORE:
case MENU_ENUM_LABEL_CORE_MANAGER_ENTRY:
case MENU_ENUM_LABEL_CONTENTLESS_CORE:
BIND_ACTION_SUBLABEL(cbs, menu_action_sublabel_file_browser_core);
break;
#ifdef HAVE_NETWORKING
@ -2297,6 +2300,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_CONTENT_SHOW_EXPLORE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_explore_tab);
break;
case MENU_ENUM_LABEL_CONTENT_SHOW_CONTENTLESS_CORES:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_contentless_cores_tab);
break;
case MENU_ENUM_LABEL_XMB_MAIN_MENU_ENABLE_SETTINGS:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_main_menu_enable_settings);
break;
@ -2321,6 +2327,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_GOTO_EXPLORE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_goto_explore);
break;
case MENU_ENUM_LABEL_GOTO_CONTENTLESS_CORES:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_goto_contentless_cores);
break;
case MENU_ENUM_LABEL_GOTO_FAVORITES:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_goto_favorites);
break;

View File

@ -754,6 +754,8 @@ DEFAULT_TITLE_SEARCH_FILTER_MACRO(action_get_title_deferred_favorites_list, MENU
DEFAULT_TITLE_SEARCH_FILTER_MACRO(action_get_title_deferred_images_list, MENU_ENUM_LABEL_VALUE_GOTO_IMAGES)
DEFAULT_TITLE_SEARCH_FILTER_MACRO(action_get_title_deferred_music_list, MENU_ENUM_LABEL_VALUE_GOTO_MUSIC)
DEFAULT_TITLE_SEARCH_FILTER_MACRO(action_get_title_deferred_video_list, MENU_ENUM_LABEL_VALUE_GOTO_VIDEO)
DEFAULT_TITLE_SEARCH_FILTER_MACRO(action_get_title_deferred_contentless_cores_list, MENU_ENUM_LABEL_VALUE_GOTO_CONTENTLESS_CORES)
DEFAULT_TITLE_SEARCH_FILTER_MACRO(action_get_core_updater_list, MENU_ENUM_LABEL_VALUE_CORE_UPDATER_LIST)
DEFAULT_TITLE_SEARCH_FILTER_MACRO(action_get_core_manager_list, MENU_ENUM_LABEL_VALUE_CORE_MANAGER_LIST)
DEFAULT_TITLE_SEARCH_FILTER_MACRO(action_get_core_cheat_options_list, MENU_ENUM_LABEL_VALUE_CORE_CHEAT_OPTIONS)
@ -853,18 +855,19 @@ static int action_get_title_group_settings(const char *path, const char *label,
* tab, but its actual title is set elsewhere - so treat
* it as a generic top-level item */
title_info_list_t info_list[] = {
{MENU_ENUM_LABEL_MAIN_MENU, MENU_ENUM_LABEL_VALUE_MAIN_MENU, false },
{MENU_ENUM_LABEL_HISTORY_TAB, MENU_ENUM_LABEL_VALUE_HISTORY_TAB, true },
{MENU_ENUM_LABEL_FAVORITES_TAB, MENU_ENUM_LABEL_VALUE_FAVORITES_TAB, true },
{MENU_ENUM_LABEL_IMAGES_TAB, MENU_ENUM_LABEL_VALUE_IMAGES_TAB, true },
{MENU_ENUM_LABEL_MUSIC_TAB, MENU_ENUM_LABEL_VALUE_MUSIC_TAB, true },
{MENU_ENUM_LABEL_VIDEO_TAB, MENU_ENUM_LABEL_VALUE_VIDEO_TAB, true },
{MENU_ENUM_LABEL_SETTINGS_TAB, MENU_ENUM_LABEL_VALUE_SETTINGS_TAB, false },
{MENU_ENUM_LABEL_PLAYLISTS_TAB, MENU_ENUM_LABEL_VALUE_PLAYLISTS_TAB, false },
{MENU_ENUM_LABEL_ADD_TAB, MENU_ENUM_LABEL_VALUE_ADD_TAB, false },
{MENU_ENUM_LABEL_EXPLORE_TAB, MENU_ENUM_LABEL_VALUE_EXPLORE_TAB, false },
{MENU_ENUM_LABEL_NETPLAY_TAB, MENU_ENUM_LABEL_VALUE_NETPLAY_TAB, false },
{MENU_ENUM_LABEL_HORIZONTAL_MENU, MENU_ENUM_LABEL_VALUE_HORIZONTAL_MENU, false },
{MENU_ENUM_LABEL_MAIN_MENU, MENU_ENUM_LABEL_VALUE_MAIN_MENU, false },
{MENU_ENUM_LABEL_HISTORY_TAB, MENU_ENUM_LABEL_VALUE_HISTORY_TAB, true },
{MENU_ENUM_LABEL_FAVORITES_TAB, MENU_ENUM_LABEL_VALUE_FAVORITES_TAB, true },
{MENU_ENUM_LABEL_IMAGES_TAB, MENU_ENUM_LABEL_VALUE_IMAGES_TAB, true },
{MENU_ENUM_LABEL_MUSIC_TAB, MENU_ENUM_LABEL_VALUE_MUSIC_TAB, true },
{MENU_ENUM_LABEL_VIDEO_TAB, MENU_ENUM_LABEL_VALUE_VIDEO_TAB, true },
{MENU_ENUM_LABEL_SETTINGS_TAB, MENU_ENUM_LABEL_VALUE_SETTINGS_TAB, false },
{MENU_ENUM_LABEL_PLAYLISTS_TAB, MENU_ENUM_LABEL_VALUE_PLAYLISTS_TAB, false },
{MENU_ENUM_LABEL_ADD_TAB, MENU_ENUM_LABEL_VALUE_ADD_TAB, false },
{MENU_ENUM_LABEL_EXPLORE_TAB, MENU_ENUM_LABEL_VALUE_EXPLORE_TAB, false },
{MENU_ENUM_LABEL_CONTENTLESS_CORES_TAB, MENU_ENUM_LABEL_VALUE_CONTENTLESS_CORES_TAB, false },
{MENU_ENUM_LABEL_NETPLAY_TAB, MENU_ENUM_LABEL_VALUE_NETPLAY_TAB, false },
{MENU_ENUM_LABEL_HORIZONTAL_MENU, MENU_ENUM_LABEL_VALUE_HORIZONTAL_MENU, false },
};
for (i = 0; i < ARRAY_SIZE(info_list); i++)
@ -989,6 +992,7 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs,
{MENU_ENUM_LABEL_DEFERRED_IMAGES_LIST, action_get_title_deferred_images_list},
{MENU_ENUM_LABEL_DEFERRED_MUSIC_LIST, action_get_title_deferred_music_list},
{MENU_ENUM_LABEL_DEFERRED_VIDEO_LIST, action_get_title_deferred_video_list},
{MENU_ENUM_LABEL_DEFERRED_CONTENTLESS_CORES_LIST, action_get_title_deferred_contentless_cores_list},
{MENU_ENUM_LABEL_DEFERRED_DRIVER_SETTINGS_LIST, action_get_driver_settings_list},
{MENU_ENUM_LABEL_DEFERRED_AUDIO_SETTINGS_LIST, action_get_audio_settings_list},
{MENU_ENUM_LABEL_DEFERRED_AUDIO_RESAMPLER_SETTINGS_LIST, action_get_audio_resampler_settings_list},

View File

@ -1303,7 +1303,8 @@ enum materialui_node_icon_type
MUI_ICON_TYPE_NONE = 0,
MUI_ICON_TYPE_INTERNAL,
MUI_ICON_TYPE_MENU_EXPLORE,
MUI_ICON_TYPE_PLAYLIST
MUI_ICON_TYPE_PLAYLIST,
MUI_ICON_TYPE_MENU_CONTENTLESS_CORE
};
/* This structure holds auxiliary information for
@ -2797,6 +2798,7 @@ static void materialui_compute_entries_box_default(
has_icon = mui->textures.list[node->icon_texture_index] != 0;
break;
case MUI_ICON_TYPE_MENU_EXPLORE:
case MUI_ICON_TYPE_MENU_CONTENTLESS_CORE:
has_icon = true;
break;
case MUI_ICON_TYPE_PLAYLIST:
@ -3996,6 +3998,9 @@ static void materialui_render_menu_entry_default(
case MUI_ICON_TYPE_MENU_EXPLORE:
icon_texture = menu_explore_get_entry_icon(entry_type);
break;
case MUI_ICON_TYPE_MENU_CONTENTLESS_CORE:
icon_texture = menu_contentless_cores_get_entry_icon(entry->label);
break;
case MUI_ICON_TYPE_PLAYLIST:
icon_texture = materialui_get_playlist_icon(
mui, node->icon_texture_index);
@ -10105,6 +10110,7 @@ static void materialui_list_insert(
case MENU_SETTING_ACTION_CORE_MANAGER_OPTIONS:
case MENU_SETTING_ACTION_CORE_LOCK:
case MENU_EXPLORE_TAB:
case MENU_CONTENTLESS_CORES_TAB:
node->icon_texture_index = MUI_TEXTURE_CORES;
node->icon_type = MUI_ICON_TYPE_INTERNAL;
break;
@ -10189,6 +10195,9 @@ static void materialui_list_insert(
node->icon_texture_index = MUI_TEXTURE_FILE;
node->icon_type = MUI_ICON_TYPE_INTERNAL;
break;
case MENU_SETTING_ACTION_CONTENTLESS_CORE_RUN:
node->icon_type = MUI_ICON_TYPE_MENU_CONTENTLESS_CORE;
break;
case FILE_TYPE_RPL_ENTRY:
case MENU_SETTING_DROPDOWN_ITEM:
case MENU_SETTING_DROPDOWN_ITEM_RESOLUTION:

View File

@ -144,6 +144,7 @@ enum
#if defined(HAVE_LIBRETRODB)
OZONE_SYSTEM_TAB_EXPLORE,
#endif
OZONE_SYSTEM_TAB_CONTENTLESS_CORES,
/* End of this enum - use the last one to determine num of possible tabs */
OZONE_SYSTEM_TAB_LAST
@ -181,6 +182,8 @@ enum OZONE_TAB_TEXTURES
OZONE_TAB_TEXTURE_IMAGE,
OZONE_TAB_TEXTURE_NETWORK,
OZONE_TAB_TEXTURE_SCAN_CONTENT,
OZONE_TAB_TEXTURE_EXPLORE,
OZONE_TAB_TEXTURE_CONTENTLESS_CORES,
OZONE_TAB_TEXTURE_LAST
};
@ -570,6 +573,7 @@ struct ozone_handle
bool is_db_manager_list;
bool is_file_list;
bool is_quick_menu;
bool is_contentless_cores;
bool first_frame;
struct
@ -604,15 +608,17 @@ static const char *OZONE_TEXTURES_FILES[OZONE_TEXTURE_LAST] = {
};
static const char *OZONE_TAB_TEXTURES_FILES[OZONE_TAB_TEXTURE_LAST] = {
"retroarch",
"settings",
"history",
"favorites",
"music",
"video",
"image",
"netplay",
"add"
"retroarch", /* MAIN_MENU */
"settings", /* SETTINGS_TAB */
"history", /* HISTORY_TAB */
"favorites", /* FAVORITES_TAB */
"music", /* MUSIC_TAB */
"video", /* VIDEO_TAB */
"image", /* IMAGES_TAB */
"netplay", /* NETPLAY_TAB */
"add", /* ADD_TAB */
"retroarch", /* EXPLORE_TAB */
"retroarch" /* CONTENTLESS_CORES_TAB */
};
static const enum msg_hash_enums ozone_system_tabs_value[OZONE_SYSTEM_TAB_LAST] = {
@ -630,12 +636,11 @@ static const enum msg_hash_enums ozone_system_tabs_value[OZONE_SYSTEM_TAB_LAST]
#ifdef HAVE_NETWORKING
MENU_ENUM_LABEL_VALUE_NETPLAY_TAB,
#endif
#ifdef HAVE_LIBRETRODB
MENU_ENUM_LABEL_VALUE_ADD_TAB,
MENU_ENUM_LABEL_VALUE_EXPLORE_TAB
#else
MENU_ENUM_LABEL_VALUE_ADD_TAB
#ifdef HAVE_LIBRETRODB
MENU_ENUM_LABEL_VALUE_EXPLORE_TAB,
#endif
MENU_ENUM_LABEL_VALUE_CONTENTLESS_CORES_TAB
};
static const enum menu_settings_type ozone_system_tabs_type[OZONE_SYSTEM_TAB_LAST] = {
@ -653,12 +658,11 @@ static const enum menu_settings_type ozone_system_tabs_type[OZONE_SYSTEM_TAB_LAS
#ifdef HAVE_NETWORKING
MENU_NETPLAY_TAB,
#endif
#ifdef HAVE_LIBRETRODB
MENU_ADD_TAB,
MENU_EXPLORE_TAB
#else
MENU_ADD_TAB
#ifdef HAVE_LIBRETRODB
MENU_EXPLORE_TAB,
#endif
MENU_CONTENTLESS_CORES_TAB
};
static const enum msg_hash_enums ozone_system_tabs_idx[OZONE_SYSTEM_TAB_LAST] = {
@ -676,12 +680,11 @@ static const enum msg_hash_enums ozone_system_tabs_idx[OZONE_SYSTEM_TAB_LAST] =
#ifdef HAVE_NETWORKING
MENU_ENUM_LABEL_NETPLAY_TAB,
#endif
#ifdef HAVE_LIBRETRODB
MENU_ENUM_LABEL_ADD_TAB,
MENU_ENUM_LABEL_EXPLORE_TAB
#else
MENU_ENUM_LABEL_ADD_TAB
#ifdef HAVE_LIBRETRODB
MENU_ENUM_LABEL_EXPLORE_TAB,
#endif
MENU_ENUM_LABEL_CONTENTLESS_CORES_TAB
};
static const unsigned ozone_system_tabs_icons[OZONE_SYSTEM_TAB_LAST] = {
@ -699,7 +702,11 @@ static const unsigned ozone_system_tabs_icons[OZONE_SYSTEM_TAB_LAST] = {
#ifdef HAVE_NETWORKING
OZONE_TAB_TEXTURE_NETWORK,
#endif
OZONE_TAB_TEXTURE_SCAN_CONTENT
OZONE_TAB_TEXTURE_SCAN_CONTENT,
#ifdef HAVE_LIBRETRODB
OZONE_TAB_TEXTURE_EXPLORE,
#endif
OZONE_TAB_TEXTURE_CONTENTLESS_CORES
};
static const char *OZONE_THEME_TEXTURES_FILES[OZONE_THEME_TEXTURE_LAST] = {
@ -1597,7 +1604,7 @@ static void ozone_set_background_running_opacity(
static uintptr_t ozone_entries_icon_get_texture(ozone_handle_t *ozone,
enum msg_hash_enums enum_idx, const char *enum_path,
unsigned type, bool active)
const char *enum_label, unsigned type, bool active)
{
switch (enum_idx)
{
@ -1675,6 +1682,8 @@ static uintptr_t ozone_entries_icon_get_texture(ozone_handle_t *ozone,
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_MUSIC];
case MENU_ENUM_LABEL_GOTO_EXPLORE:
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_RDB];
case MENU_ENUM_LABEL_GOTO_CONTENTLESS_CORES:
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_CORE];
/* Menu icons */
case MENU_ENUM_LABEL_CONTENT_SETTINGS:
@ -1735,6 +1744,8 @@ static uintptr_t ozone_entries_icon_get_texture(ozone_handle_t *ozone,
case MENU_ENUM_LABEL_UPDATE_DATABASES:
case MENU_ENUM_LABEL_DATABASE_MANAGER_LIST:
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_RDB];
case MENU_ENUM_LABEL_CONTENTLESS_CORES_TAB:
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_CORE];
case MENU_ENUM_LABEL_CURSOR_MANAGER_LIST:
return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_CURSOR];
case MENU_ENUM_LABEL_HELP_LIST:
@ -1930,6 +1941,12 @@ static uintptr_t ozone_entries_icon_get_texture(ozone_handle_t *ozone,
break;
}
#endif
case MENU_ENUM_LABEL_CONTENTLESS_CORE:
{
uintptr_t icon = menu_contentless_cores_get_entry_icon(enum_label);
if (icon) return icon;
break;
}
default:
break;
}
@ -3288,6 +3305,7 @@ static bool ozone_is_playlist(ozone_handle_t *ozone, bool depth)
#ifdef HAVE_LIBRETRODB
case OZONE_SYSTEM_TAB_EXPLORE:
#endif
case OZONE_SYSTEM_TAB_CONTENTLESS_CORES:
is_playlist = false;
break;
case OZONE_SYSTEM_TAB_HISTORY:
@ -4490,7 +4508,7 @@ static void ozone_compute_entries_position(
if (ozone->is_playlist && entries_end == 1)
{
uintptr_t tex = ozone_entries_icon_get_texture(ozone,
entry.enum_idx, entry.path, entry.type, false);
entry.enum_idx, entry.path, entry.label, entry.type, false);
ozone->empty_playlist = tex == ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_CORE_INFO];
}
else
@ -4783,7 +4801,7 @@ border_iterate:
MENU_ENTRY_INIT(entry);
entry.path_enabled = false;
entry.label_enabled = false;
entry.label_enabled = ozone->is_contentless_cores;
menu_entry_get(&entry, 0, (unsigned)i, selection_buf, true);
if (entry.enum_idx == MENU_ENUM_LABEL_CHEEVOS_PASSWORD)
@ -4856,7 +4874,7 @@ border_iterate:
/* Icon */
tex = ozone_entries_icon_get_texture(ozone,
entry.enum_idx, entry.path, entry.type, entry_selected);
entry.enum_idx, entry.path, entry.label, entry.type, entry_selected);
if (tex != ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_SUBSETTING])
{
uintptr_t texture = tex;
@ -7150,6 +7168,12 @@ static void *ozone_init(void **userdata, bool video_is_threaded)
ozone->tabs[++ozone->system_tab_end] = OZONE_SYSTEM_TAB_EXPLORE;
#endif
#if defined(HAVE_DYNAMIC)
if (settings->uints.menu_content_show_contentless_cores !=
MENU_CONTENTLESS_CORES_DISPLAY_NONE)
ozone->tabs[++ozone->system_tab_end] = OZONE_SYSTEM_TAB_CONTENTLESS_CORES;
#endif
menu_driver_ctl(RARCH_MENU_CTL_UNSET_PREVENT_POPULATE, NULL);
gfx_display_set_width(width);
@ -9844,14 +9868,16 @@ static void ozone_populate_entries(void *data,
new_depth = (int)ozone_list_get_size(ozone, MENU_LIST_PLAIN);
animate = new_depth != ozone->depth;
ozone->fade_direction = new_depth <= ozone->depth;
ozone->depth = new_depth;
ozone->is_playlist = ozone_is_playlist(ozone, true);
ozone->is_db_manager_list = string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_DATABASE_MANAGER_LIST));
ozone->is_file_list = string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_FAVORITES));
ozone->is_quick_menu = string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RPL_ENTRY_ACTIONS)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_SETTINGS));
animate = new_depth != ozone->depth;
ozone->fade_direction = new_depth <= ozone->depth;
ozone->depth = new_depth;
ozone->is_playlist = ozone_is_playlist(ozone, true);
ozone->is_db_manager_list = string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_DATABASE_MANAGER_LIST));
ozone->is_file_list = string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_FAVORITES));
ozone->is_quick_menu = string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RPL_ENTRY_ACTIONS)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_SETTINGS));
ozone->is_contentless_cores = string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CONTENTLESS_CORES_TAB)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_CONTENTLESS_CORES_LIST));
if (animate)
if (ozone->categories_selection_ptr == ozone->categories_active_idx_old)

View File

@ -248,6 +248,7 @@ enum
#if defined(HAVE_LIBRETRODB)
XMB_SYSTEM_TAB_EXPLORE,
#endif
XMB_SYSTEM_TAB_CONTENTLESS_CORES,
/* End of this enum - use the last one to determine num of possible tabs */
XMB_SYSTEM_TAB_MAX_LENGTH
@ -294,6 +295,7 @@ typedef struct xmb_handle
#if defined(HAVE_LIBRETRODB)
xmb_node_t explore_tab_node;
#endif
xmb_node_t contentless_cores_tab_node;
xmb_node_t netplay_tab_node;
menu_input_pointer_t pointer;
@ -399,6 +401,7 @@ typedef struct xmb_handle
/* Favorites, History, Images, Music, Videos, user generated */
bool is_playlist;
bool is_db_manager_list;
bool is_contentless_cores;
/* Load Content file browser */
bool is_file_list;
@ -1978,6 +1981,8 @@ static xmb_node_t* xmb_get_node(xmb_handle_t *xmb, unsigned i)
case XMB_SYSTEM_TAB_EXPLORE:
return &xmb->explore_tab_node;
#endif
case XMB_SYSTEM_TAB_CONTENTLESS_CORES:
return &xmb->contentless_cores_tab_node;
default:
if (i > xmb->system_tab_end)
return xmb_get_userdata_from_horizontal_list(
@ -2472,6 +2477,10 @@ static void xmb_populate_entries(void *data,
/* Determine whether this is a database manager list */
xmb->is_db_manager_list = string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_DATABASE_MANAGER_LIST));
/* Determine whether this is the contentless cores menu */
xmb->is_contentless_cores = string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CONTENTLESS_CORES_TAB)) ||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_CONTENTLESS_CORES_LIST));
/* Determine whether this is a 'file list'
* (needed for handling thumbnails when viewing images
* via 'load content')
@ -2539,7 +2548,8 @@ static void xmb_populate_entries(void *data,
static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb,
xmb_node_t *core_node, xmb_node_t *node,
enum msg_hash_enums enum_idx, const char *enum_path,
unsigned type, bool active, bool checked)
const char *enum_label, unsigned type, bool active,
bool checked)
{
switch (enum_idx)
{
@ -2635,7 +2645,8 @@ static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb,
return xmb->textures.list[XMB_TEXTURE_MUSIC];
case MENU_ENUM_LABEL_GOTO_EXPLORE:
return xmb->textures.list[XMB_TEXTURE_MAIN_MENU];
case MENU_ENUM_LABEL_GOTO_CONTENTLESS_CORES:
return xmb->textures.list[XMB_TEXTURE_MAIN_MENU];
case MENU_ENUM_LABEL_LOAD_DISC:
case MENU_ENUM_LABEL_DUMP_DISC:
#ifdef HAVE_LAKKA
@ -2865,6 +2876,13 @@ static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb,
break;
}
#endif
case MENU_ENUM_LABEL_CONTENTLESS_CORE:
{
uintptr_t icon = menu_contentless_cores_get_entry_icon(enum_label);
if (icon)
return icon;
break;
}
default:
break;
}
@ -3224,7 +3242,7 @@ static int xmb_draw_item(
return 0;
MENU_ENTRY_INIT(entry);
entry.label_enabled = false;
entry.label_enabled = xmb->is_contentless_cores;
entry.sublabel_enabled = (i == current);
menu_entry_get(&entry, 0, i, list, true);
entry_type = entry.type;
@ -3582,7 +3600,8 @@ static int xmb_draw_item(
math_matrix_4x4 mymat_tmp;
gfx_display_ctx_rotate_draw_t rotate_draw;
uintptr_t texture = xmb_icon_get_id(xmb, core_node, node,
entry.enum_idx, entry.path, entry_type, (i == current), entry.checked);
entry.enum_idx, entry.path, entry.label,
entry_type, (i == current), entry.checked);
float x = icon_x;
float y = icon_y;
float scale_factor = node->zoom;
@ -5933,6 +5952,12 @@ static void *xmb_init(void **userdata, bool video_is_threaded)
xmb->tabs[++xmb->system_tab_end] = XMB_SYSTEM_TAB_EXPLORE;
#endif
#if defined(HAVE_DYNAMIC)
if (settings->uints.menu_content_show_contentless_cores !=
MENU_CONTENTLESS_CORES_DISPLAY_NONE)
xmb->tabs[++xmb->system_tab_end] = XMB_SYSTEM_TAB_CONTENTLESS_CORES;
#endif
menu_driver_ctl(RARCH_MENU_CTL_UNSET_PREVENT_POPULATE, NULL);
/* TODO/FIXME - we don't use framebuffer at all
@ -6410,6 +6435,10 @@ static void xmb_context_reset_textures(
xmb->explore_tab_node.zoom = xmb->categories_active_zoom;
#endif
xmb->contentless_cores_tab_node.icon = xmb->textures.list[XMB_TEXTURE_MAIN_MENU];
xmb->contentless_cores_tab_node.alpha = xmb->categories_active_alpha;
xmb->contentless_cores_tab_node.zoom = xmb->categories_active_zoom;
#ifdef HAVE_NETWORKING
xmb->netplay_tab_node.icon = xmb->textures.list[XMB_TEXTURE_NETPLAY];
xmb->netplay_tab_node.alpha = xmb->categories_active_alpha;
@ -6871,6 +6900,12 @@ static void xmb_list_cache(void *data, enum menu_list_type type, unsigned action
MENU_EXPLORE_TAB;
break;
#endif
case XMB_SYSTEM_TAB_CONTENTLESS_CORES:
menu_stack->list[stack_size - 1].label =
strdup(msg_hash_to_str(MENU_ENUM_LABEL_CONTENTLESS_CORES_TAB));
menu_stack->list[stack_size - 1].type =
MENU_CONTENTLESS_CORES_TAB;
break;
default:
menu_stack->list[stack_size - 1].label =
strdup(msg_hash_to_str(MENU_ENUM_LABEL_HORIZONTAL_MENU));

View File

@ -77,6 +77,7 @@ enum
ACTION_OK_DL_IMAGES_LIST,
ACTION_OK_DL_VIDEO_LIST,
ACTION_OK_DL_EXPLORE_LIST,
ACTION_OK_DL_CONTENTLESS_CORES_LIST,
ACTION_OK_DL_MUSIC_LIST,
ACTION_OK_DL_SHADER_PARAMETERS,
ACTION_OK_DL_SHADER_PRESET,

View File

@ -0,0 +1,302 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2011-2020 - Daniel De Matteis
* Copyright (C) 2019-2022 - James Leaver
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stddef.h>
#include <compat/strcasestr.h>
#include <compat/strl.h>
#include <array/rhmap.h>
#include <file/file_path.h>
#include <string/stdstring.h>
#include "menu_driver.h"
#include "menu_displaylist.h"
#include "../retroarch.h"
#include "../core_info.h"
#include "../configuration.h"
#define CONTENTLESS_CORE_ICON_DEFAULT "default.png"
typedef struct
{
uintptr_t **system;
uintptr_t fallback;
} contentless_core_icons_t;
typedef struct
{
contentless_core_icons_t *icons;
bool icons_enabled;
} contentless_cores_state_t;
static contentless_cores_state_t *contentless_cores_state = NULL;
static void contentless_cores_unload_icons(contentless_cores_state_t *state)
{
size_t i, cap;
if (!state || !state->icons)
return;
if (state->icons->fallback)
video_driver_texture_unload(&state->icons->fallback);
for (i = 0, cap = RHMAP_CAP(state->icons->system); i != cap; i++)
{
if (RHMAP_KEY(state->icons->system, i))
{
uintptr_t *icon = state->icons->system[i];
if (!icon)
continue;
video_driver_texture_unload(icon);
free(icon);
}
}
RHMAP_FREE(state->icons->system);
free(state->icons);
state->icons = NULL;
}
static void contentless_cores_load_icons(contentless_cores_state_t *state)
{
bool rgba_supported = video_driver_supports_rgba();
core_info_list_t *core_info_list = NULL;
char icon_directory[PATH_MAX_LENGTH];
char icon_path[PATH_MAX_LENGTH];
size_t i;
icon_directory[0] = '\0';
icon_path[0] = '\0';
if (!state)
return;
/* Unload any existing icons */
contentless_cores_unload_icons(state);
if (!state->icons_enabled)
return;
/* Create new icon container */
state->icons = (contentless_core_icons_t*)calloc(
1, sizeof(*state->icons));
/* Get icon directory */
fill_pathname_application_special(icon_directory,
sizeof(icon_directory),
APPLICATION_SPECIAL_DIRECTORY_ASSETS_SYSICONS);
if (string_is_empty(icon_directory))
return;
/* Load fallback icon */
fill_pathname_join(icon_path, icon_directory,
CONTENTLESS_CORE_ICON_DEFAULT, sizeof(icon_path));
if (path_is_valid(icon_path))
{
struct texture_image ti = {0};
ti.supports_rgba = rgba_supported;
if (image_texture_load(&ti, icon_path))
{
if (ti.pixels)
video_driver_texture_load(&ti,
TEXTURE_FILTER_MIPMAP_LINEAR,
&state->icons->fallback);
image_texture_free(&ti);
}
}
/* Get icons for all contentless cores */
core_info_get_list(&core_info_list);
if (!core_info_list)
return;
for (i = 0; i < core_info_list->count; i++)
{
core_info_t *core_info = core_info_get(core_info_list, i);
/* Icon name is the first entry in the core
* info database list */
if (core_info &&
core_info->supports_no_game &&
core_info->databases_list &&
(core_info->databases_list->size > 0))
{
const char *icon_name =
core_info->databases_list->elems[0].data;
struct texture_image ti = {0};
ti.supports_rgba = rgba_supported;
fill_pathname_join(icon_path, icon_directory,
icon_name, sizeof(icon_path));
strlcat(icon_path, ".png", sizeof(icon_path));
if (!path_is_valid(icon_path))
continue;
if (image_texture_load(&ti, icon_path))
{
if (ti.pixels)
{
uintptr_t *icon = (uintptr_t*)calloc(1, sizeof(*icon));
video_driver_texture_load(&ti,
TEXTURE_FILTER_MIPMAP_LINEAR,
icon);
/* Add icon to hash map */
RHMAP_SET_STR(state->icons->system, core_info->core_file_id.str, icon);
}
image_texture_free(&ti);
}
}
}
}
uintptr_t menu_contentless_cores_get_entry_icon(const char *core_id)
{
contentless_cores_state_t *state = contentless_cores_state;
uintptr_t *icon = NULL;
if (!state ||
!state->icons_enabled ||
!state->icons ||
string_is_empty(core_id))
return 0;
icon = RHMAP_GET_STR(state->icons->system, core_id);
if (icon)
return *icon;
return state->icons->fallback;
}
void menu_contentless_cores_context_init(void)
{
if (!contentless_cores_state)
return;
contentless_cores_load_icons(contentless_cores_state);
}
void menu_contentless_cores_context_deinit(void)
{
if (!contentless_cores_state)
return;
contentless_cores_unload_icons(contentless_cores_state);
}
void menu_contentless_cores_free(void)
{
if (!contentless_cores_state)
return;
contentless_cores_unload_icons(contentless_cores_state);
free(contentless_cores_state);
contentless_cores_state = NULL;
}
unsigned menu_displaylist_contentless_cores(file_list_t *list, settings_t *settings)
{
unsigned count = 0;
enum menu_contentless_cores_display_type
core_display_type = (enum menu_contentless_cores_display_type)
settings->uints.menu_content_show_contentless_cores;
core_info_list_t *core_info_list = NULL;
/* Get core list */
core_info_get_list(&core_info_list);
if (core_info_list)
{
size_t menu_index = 0;
size_t i;
/* 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);
bool core_valid = false;
if (core_info)
{
switch (core_display_type)
{
case MENU_CONTENTLESS_CORES_DISPLAY_ALL:
core_valid = core_info->supports_no_game;
break;
case MENU_CONTENTLESS_CORES_DISPLAY_SINGLE_PURPOSE:
core_valid = core_info->supports_no_game &&
core_info->single_purpose;
break;
default:
break;
}
if (core_valid &&
menu_entries_append_enum(list,
core_info->path,
core_info->core_file_id.str,
MENU_ENUM_LABEL_CONTENTLESS_CORE,
MENU_SETTING_ACTION_CONTENTLESS_CORE_RUN,
0, 0))
{
file_list_set_alt_at_offset(
list, menu_index, core_info->display_name);
menu_index++;
count++;
}
}
}
}
/* Initialise icons, if required */
if (!contentless_cores_state && (count > 0))
{
contentless_cores_state = (contentless_cores_state_t*)calloc(1,
sizeof(*contentless_cores_state));
/* Disable icons when using menu drivers without
* icon support */
contentless_cores_state->icons_enabled =
!string_is_equal(menu_driver_ident(), "rgui");
contentless_cores_load_icons(contentless_cores_state);
}
if ((count == 0) &&
menu_entries_append_enum(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))
count++;
return count;
}

View File

@ -130,6 +130,16 @@ enum menu_add_content_entry_display_type
MENU_ADD_CONTENT_ENTRY_DISPLAY_LAST
};
/* Specifies which type of core will be displayed
* in the 'contentless cores' menu */
enum menu_contentless_cores_display_type
{
MENU_CONTENTLESS_CORES_DISPLAY_NONE = 0,
MENU_CONTENTLESS_CORES_DISPLAY_ALL,
MENU_CONTENTLESS_CORES_DISPLAY_SINGLE_PURPOSE,
MENU_CONTENTLESS_CORES_DISPLAY_LAST
};
enum rgui_color_theme
{
RGUI_THEME_CUSTOM = 0,

View File

@ -3586,6 +3586,17 @@ static unsigned menu_displaylist_parse_playlists(
MENU_EXPLORE_TAB, 0, 0))
count++;
#endif
#if defined(HAVE_DYNAMIC)
if (settings->uints.menu_content_show_contentless_cores !=
MENU_CONTENTLESS_CORES_DISPLAY_NONE)
if (menu_entries_append_enum(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))
count++;
#endif
if (settings->bools.menu_content_show_favorites)
if (menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_FAVORITES),
@ -6321,6 +6332,17 @@ unsigned menu_displaylist_build_list(
MENU_EXPLORE_TAB, 0, 0))
count++;
#endif
#if defined(HAVE_DYNAMIC)
if (settings->uints.menu_content_show_contentless_cores !=
MENU_CONTENTLESS_CORES_DISPLAY_NONE)
if (menu_entries_append_enum(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))
count++;
#endif
if (menu_content_show_favorites)
if (menu_entries_append_enum(list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_GOTO_FAVORITES),
@ -8268,6 +8290,9 @@ unsigned menu_displaylist_build_list(
{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_EXPLORE, PARSE_ONLY_BOOL, true },
#if defined(HAVE_DYNAMIC)
{MENU_ENUM_LABEL_CONTENT_SHOW_CONTENTLESS_CORES, PARSE_ONLY_UINT, true },
#endif
{MENU_ENUM_LABEL_CONTENT_SHOW_FAVORITES, PARSE_ONLY_BOOL, true },
{MENU_ENUM_LABEL_CONTENT_SHOW_IMAGES, PARSE_ONLY_BOOL, true },
{MENU_ENUM_LABEL_CONTENT_SHOW_MUSIC, PARSE_ONLY_BOOL, true },
@ -8288,6 +8313,9 @@ unsigned menu_displaylist_build_list(
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)
@ -11687,6 +11715,30 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
info->need_push = true;
}
break;
case DISPLAYLIST_CONTENTLESS_CORES:
{
size_t contentless_core_ptr =
menu_state_get_ptr()->contentless_core_ptr;
menu_entries_ctl(MENU_ENTRIES_CTL_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_navigation_set_selection(contentless_core_ptr);
info->need_sort = false;
info->need_push = true;
}
break;
case DISPLAYLIST_CORE_OPTIONS:
{
/* Number of displayed options is dynamic. If user opens

View File

@ -83,6 +83,7 @@ enum menu_displaylist_ctl_state
DISPLAYLIST_HORIZONTAL_CONTENT_ACTIONS,
DISPLAYLIST_HISTORY,
DISPLAYLIST_EXPLORE,
DISPLAYLIST_CONTENTLESS_CORES,
DISPLAYLIST_FAVORITES,
DISPLAYLIST_PLAYLIST,
DISPLAYLIST_VIDEO_HISTORY,
@ -344,6 +345,7 @@ bool menu_displaylist_has_subsystems(void);
#if defined(HAVE_LIBRETRODB)
unsigned menu_displaylist_explore(file_list_t *list, settings_t *settings);
#endif
unsigned menu_displaylist_contentless_cores(file_list_t *list, settings_t *settings);
enum filebrowser_enums filebrowser_get_type(void);

View File

@ -2334,6 +2334,11 @@ static bool menu_driver_displaylist_push_internal(
return true;
}
#endif
else if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CONTENTLESS_CORES_TAB)))
{
if (menu_displaylist_ctl(DISPLAYLIST_CONTENTLESS_CORES, info, settings))
return true;
}
else if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_TAB)))
{
if (menu_displaylist_ctl(DISPLAYLIST_NETPLAY_ROOM_LIST, info, settings))
@ -4155,6 +4160,7 @@ int menu_driver_deferred_push_content_list(file_list_t *list)
file_list_t *selection_buf = MENU_LIST_GET_SELECTION(menu_list, (unsigned)0);
menu_st->selection_ptr = 0;
menu_st->contentless_core_ptr = 0;
if (!menu_driver_displaylist_push(
menu_st,
@ -4518,6 +4524,7 @@ bool menu_entries_append_enum(
if ( enum_idx != MENU_ENUM_LABEL_PLAYLIST_ENTRY
&& enum_idx != MENU_ENUM_LABEL_PLAYLIST_COLLECTION_ENTRY
&& enum_idx != MENU_ENUM_LABEL_EXPLORE_ITEM
&& enum_idx != MENU_ENUM_LABEL_CONTENTLESS_CORE
&& enum_idx != MENU_ENUM_LABEL_RDB_ENTRY)
cbs->setting = menu_setting_find_enum(enum_idx);
@ -6974,8 +6981,12 @@ bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data)
switch (state)
{
case RARCH_MENU_CTL_SET_PENDING_QUICK_MENU:
menu_entries_flush_stack(NULL, MENU_SETTINGS);
menu_st->pending_quick_menu = true;
{
bool flush_stack = !data ? true : *((bool *)data);
if (flush_stack)
menu_entries_flush_stack(NULL, MENU_SETTINGS);
menu_st->pending_quick_menu = true;
}
break;
case RARCH_MENU_CTL_SET_PREVENT_POPULATE:
menu_st->prevent_populate = true;
@ -7000,21 +7011,25 @@ bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data)
#ifdef HAVE_NETWORKING
core_updater_list_free_cached();
#endif
#if defined(HAVE_MENU) && defined(HAVE_LIBRETRODB)
#if defined(HAVE_MENU)
#if defined(HAVE_LIBRETRODB)
/* Before freeing the explore menu, we
* must wait for any explore menu initialisation
* tasks to complete */
menu_explore_wait_for_init_task();
menu_explore_free();
#endif
menu_contentless_cores_free();
#endif
if (menu_st->driver_data)
{
unsigned i;
menu_st->scroll.acceleration = 0;
menu_st->selection_ptr = 0;
menu_st->scroll.index_size = 0;
menu_st->scroll.acceleration = 0;
menu_st->selection_ptr = 0;
menu_st->contentless_core_ptr = 0;
menu_st->scroll.index_size = 0;
for (i = 0; i < SCROLL_INDEX_SIZE; i++)
menu_st->scroll.index_list[i] = 0;
@ -7517,6 +7532,7 @@ static int generic_menu_iterate(
break;
#endif
case MENU_ENUM_LABEL_CORE_MANAGER_ENTRY:
case MENU_ENUM_LABEL_CONTENTLESS_CORE:
{
core_info_t *core_info = NULL;
const char *path = selection_buf->list[selection].path;

View File

@ -90,6 +90,7 @@ enum menu_settings_type
MENU_IMAGES_TAB,
MENU_NETPLAY_TAB,
MENU_EXPLORE_TAB,
MENU_CONTENTLESS_CORES_TAB,
MENU_ADD_TAB,
MENU_PLAYLISTS_TAB,
MENU_SETTING_DROPDOWN_ITEM,
@ -268,6 +269,8 @@ enum menu_settings_type
MENU_SETTING_ACTION_CORE_OPTIONS_RESET,
MENU_SETTING_ACTION_CORE_OPTIONS_FLUSH,
MENU_SETTING_ACTION_CONTENTLESS_CORE_RUN,
MENU_SETTINGS_LAST
};
@ -454,6 +457,7 @@ struct menu_state
size_t begin;
} entries;
size_t selection_ptr;
size_t contentless_core_ptr;
/* Quick jumping indices with L/R.
* Rebuilt when parsing directory. */
@ -635,6 +639,11 @@ void menu_explore_free(void);
void menu_explore_set_state(explore_state_t *state);
#endif
uintptr_t menu_contentless_cores_get_entry_icon(const char *core_id);
void menu_contentless_cores_context_init(void);
void menu_contentless_cores_context_deinit(void);
void menu_contentless_cores_free(void);
/* Returns true if search filter is enabled
* for the specified menu list */
bool menu_driver_search_filter_enabled(const char *label, unsigned type);

View File

@ -3674,6 +3674,36 @@ static void setting_get_string_representation_uint_menu_add_content_entry_displa
}
}
static void setting_get_string_representation_uint_menu_contentless_cores_display_type(
rarch_setting_t *setting,
char *s, size_t len)
{
if (!setting)
return;
switch (*setting->value.target.unsigned_integer)
{
case MENU_CONTENTLESS_CORES_DISPLAY_NONE:
strlcpy(s,
msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_OFF),
len);
break;
case MENU_CONTENTLESS_CORES_DISPLAY_ALL:
strlcpy(s,
msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_SHOW_CONTENTLESS_CORES_ALL),
len);
break;
case MENU_CONTENTLESS_CORES_DISPLAY_SINGLE_PURPOSE:
strlcpy(s,
msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_SHOW_CONTENTLESS_CORES_SINGLE_PURPOSE),
len);
break;
}
}
static void setting_get_string_representation_uint_rgui_menu_color_theme(
rarch_setting_t *setting,
char *s, size_t len)
@ -16711,6 +16741,23 @@ static bool setting_append_list(
general_read_handler,
SD_FLAG_NONE);
#endif
CONFIG_UINT(
list, list_info,
&settings->uints.menu_content_show_contentless_cores,
MENU_ENUM_LABEL_CONTENT_SHOW_CONTENTLESS_CORES,
MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_CONTENTLESS_CORES,
DEFAULT_MENU_CONTENT_SHOW_CONTENTLESS_CORES,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_uint_menu_contentless_cores_display_type;
menu_settings_list_current_add_range(list, list_info, 0, MENU_CONTENTLESS_CORES_DISPLAY_LAST-1, 1, true, true);
(*list)[list_info->index - 1].ui_type = ST_UI_TYPE_UINT_COMBOBOX;
SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_LAKKA_ADVANCED);
#ifdef HAVE_MATERIALUI
if (string_is_equal(settings->arrays.menu_driver, "glui"))

View File

@ -1224,6 +1224,9 @@ enum msg_hash_enums
MENU_LABEL(CONTENT_SHOW_ADD_ENTRY),
MENU_LABEL(CONTENT_SHOW_PLAYLISTS),
MENU_LABEL(CONTENT_SHOW_EXPLORE),
MENU_LABEL(CONTENT_SHOW_CONTENTLESS_CORES),
MENU_ENUM_LABEL_VALUE_SHOW_CONTENTLESS_CORES_ALL,
MENU_ENUM_LABEL_VALUE_SHOW_CONTENTLESS_CORES_SINGLE_PURPOSE,
MENU_LABEL(XMB_RIBBON_ENABLE),
MENU_LABEL(THUMBNAILS),
MENU_LABEL(THUMBNAILS_RGUI),
@ -1368,6 +1371,7 @@ enum msg_hash_enums
MENU_LABEL(GOTO_IMAGES),
MENU_LABEL(GOTO_VIDEO),
MENU_LABEL(GOTO_EXPLORE),
MENU_LABEL(GOTO_CONTENTLESS_CORES),
MENU_LABEL(ADD_TO_FAVORITES),
MENU_LABEL(ADD_TO_FAVORITES_PLAYLIST),
MENU_LABEL(SET_CORE_ASSOCIATION),
@ -1524,6 +1528,7 @@ enum msg_hash_enums
MENU_ENUM_LABEL_DEFERRED_MUSIC_LIST,
MENU_ENUM_LABEL_DEFERRED_VIDEO_LIST,
MENU_ENUM_LABEL_DEFERRED_EXPLORE_LIST,
MENU_ENUM_LABEL_DEFERRED_CONTENTLESS_CORES_LIST,
MENU_ENUM_LABEL_DEFERRED_NETPLAY,
MENU_ENUM_LABEL_DEFERRED_MUSIC,
MENU_ENUM_LABEL_DEFERRED_BROWSE_URL_START,
@ -2159,6 +2164,8 @@ enum msg_hash_enums
MENU_ENUM_LABEL_EXPLORE_TAB,
MENU_ENUM_LABEL_EXPLORE_ITEM,
MENU_ENUM_LABEL_VALUE_EXPLORE_TAB,
MENU_LABEL(CONTENTLESS_CORES_TAB),
MENU_LABEL(CONTENTLESS_CORE),
MENU_LABEL(ADD_TAB),
MENU_LABEL(NETPLAY_TAB),
MENU_LABEL(PLAYLISTS_TAB),

View File

@ -6678,13 +6678,20 @@ static enum runloop_state_enum runloop_check_state(
/* Iterate the menu driver for one frame. */
/* If the user had requested that the Quick Menu
* be spawned during the previous frame, do this now
* and exit the function to go to the next frame. */
if (menu_st->pending_quick_menu)
{
/* If the user had requested that the Quick Menu
* be spawned during the previous frame, do this now
* and exit the function to go to the next frame.
*/
menu_entries_flush_stack(NULL, MENU_SETTINGS);
menu_ctx_list_t list_info;
/* We are going to push a new menu; ensure
* that the current one is cached for animation
* purposes */
list_info.type = MENU_LIST_PLAIN;
list_info.action = 0;
menu_driver_list_cache(&list_info);
p_disp->msg_force = true;
generic_action_ok_displaylist_push("", NULL,

View File

@ -2096,8 +2096,14 @@ bool task_push_start_current_core(content_ctx_info_t *content_info)
if (firmware_update_status(&content_ctx))
goto end;
/* Loads content into currently selected core. */
if (!(ret = content_load(content_info, p_content)))
/* Loads content into currently selected core.
* Note that 'content_load()' can fail and yet still
* return 'true'... In this case, the dummy core
* will be loaded; the 'start core' operation can
* therefore only be considered successful if the
* dummy core is not running following 'content_load()' */
if (!(ret = content_load(content_info, p_content)) ||
!(ret = (runloop_st->current_core_type != CORE_TYPE_DUMMY)))
{
if (error_string)
{
@ -2159,6 +2165,101 @@ bool task_push_load_new_core(
}
#ifdef HAVE_MENU
bool task_push_load_contentless_core_from_menu(
const char *core_path)
{
content_ctx_info_t content_info = {0};
content_information_ctx_t content_ctx = {0};
content_state_t *p_content = content_state_get_ptr();
bool ret = true;
char *error_string = NULL;
runloop_state_t *runloop_st = runloop_state_get_ptr();
settings_t *settings = config_get_ptr();
const char *path_dir_system = settings->paths.directory_system;
bool check_firmware_before_loading = settings->bools.check_firmware_before_loading;
bool flush_menu = true;
const char *menu_label = NULL;
if (string_is_empty(core_path))
return false;
content_info.environ_get = menu_content_environment_get;
content_ctx.check_firmware_before_loading = check_firmware_before_loading;
content_ctx.bios_is_missing = retroarch_ctl(RARCH_CTL_IS_MISSING_BIOS, NULL);
if (!string_is_empty(path_dir_system))
content_ctx.directory_system = strdup(path_dir_system);
/* Set core path */
path_set(RARCH_PATH_CORE, core_path);
/* Clear content path */
path_clear(RARCH_PATH_CONTENT);
#if defined(HAVE_DYNAMIC)
/* Load core */
command_event(CMD_EVENT_LOAD_CORE, NULL);
runloop_set_current_core_type(CORE_TYPE_PLAIN, true);
if (firmware_update_status(&content_ctx))
goto end;
/* Loads content into currently selected core.
* Note that 'content_load()' can fail and yet still
* return 'true'... In this case, the dummy core
* will be loaded; the 'start core' operation can
* therefore only be considered successful if the
* dummy core is not running following 'content_load()' */
if (!(ret = content_load(&content_info, p_content)) ||
!(ret = (runloop_st->current_core_type != CORE_TYPE_DUMMY)))
{
if (error_string)
{
runloop_msg_queue_push(error_string, 2, 90,
true, NULL, MESSAGE_QUEUE_ICON_DEFAULT,
MESSAGE_QUEUE_CATEGORY_INFO);
RARCH_ERR("[Content]: %s\n", error_string);
free(error_string);
}
retroarch_menu_running();
goto end;
}
#else
/* TODO/FIXME: Static builds do not support running
* a core directly from the 'command line' without
* supplying a content path, so this *will not work*.
* In order to support this functionality, the '-L'
* command line argument must be enabled for static
* builds to inform the frontend that the core should
* run automatically on launch. We will leave this
* non-functional code here as a place-marker for
* future devs who may wish to implement this... */
command_event_cmd_exec(p_content,
path_get(RARCH_PATH_CONTENT), &content_ctx,
false, &error_string);
command_event(CMD_EVENT_QUIT, NULL);
#endif
/* Push quick menu onto menu stack */
menu_entries_get_last_stack(NULL, &menu_label, NULL, NULL, NULL);
if (string_is_equal(menu_label, msg_hash_to_str(MENU_ENUM_LABEL_CONTENTLESS_CORES_TAB)) ||
string_is_equal(menu_label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_CONTENTLESS_CORES_LIST)))
flush_menu = false;
menu_driver_ctl(RARCH_MENU_CTL_SET_PENDING_QUICK_MENU, &flush_menu);
#ifdef HAVE_DYNAMIC
end:
#endif
if (content_ctx.directory_system)
free(content_ctx.directory_system);
return ret;
}
bool task_push_load_content_with_new_core_from_menu(
const char *core_path,
const char *fullpath,

View File

@ -99,6 +99,9 @@ bool task_push_load_content_from_playlist_from_menu(
content_ctx_info_t *content_info,
retro_task_callback_t cb,
void *user_data);
bool task_push_load_contentless_core_from_menu(
const char *core_path);
#endif
bool task_push_load_content_with_core(

View File

@ -36,6 +36,10 @@
#include "../core_info.h"
#include "../core_backup.h"
#if defined(RARCH_INTERNAL) && defined(HAVE_MENU)
#include "../menu/menu_driver.h"
#endif
#if defined(ANDROID)
#include "../play_feature_delivery/play_feature_delivery.h"
#endif
@ -649,6 +653,11 @@ static void cb_task_core_restore(
/* Reload core info files
* > This must be done on the main thread */
command_event(CMD_EVENT_CORE_INFO_INIT, NULL);
#if defined(RARCH_INTERNAL) && defined(HAVE_MENU)
/* Force reload of contentless cores icons */
menu_contentless_cores_free();
#endif
}
static void task_core_restore_handler(retro_task_t *task)

View File

@ -45,6 +45,7 @@
#if defined(RARCH_INTERNAL) && defined(HAVE_MENU)
#include "../menu/menu_entries.h"
#include "../menu/menu_driver.h"
#endif
/* Get core updater list */
@ -521,6 +522,11 @@ static void cb_task_core_updater_download(
/* Reload core info files
* > This must be done on the main thread */
command_event(CMD_EVENT_CORE_INFO_INIT, NULL);
#if defined(RARCH_INTERNAL) && defined(HAVE_MENU)
/* Force reload of contentless cores icons */
menu_contentless_cores_free();
#endif
}
static void cb_decompress_task_core_updater_download(