Begin implementing core autoselect.
This commit is contained in:
parent
a470ae0d04
commit
050e2375e3
65
core_info.c
65
core_info.c
|
@ -42,6 +42,7 @@ core_info_list_t *core_info_list_new(const char *modules_path)
|
|||
|
||||
for (size_t i = 0; i < contents->size; i++)
|
||||
{
|
||||
#if 0
|
||||
char buffer[PATH_MAX];
|
||||
char info_path[PATH_MAX];
|
||||
|
||||
|
@ -63,6 +64,11 @@ core_info_list_t *core_info_list_new(const char *modules_path)
|
|||
snprintf(info_path, PATH_MAX, "%s.info", buffer);
|
||||
else
|
||||
fill_pathname(info_path, buffer, ".info", sizeof(info_path));
|
||||
#else
|
||||
core_info[i].path = strdup(contents->elems[i].data);
|
||||
char info_path[PATH_MAX];
|
||||
fill_pathname(info_path, core_info[i].path, ".info", sizeof(info_path));
|
||||
#endif
|
||||
|
||||
core_info[i].data = config_file_new(info_path);
|
||||
|
||||
|
@ -78,6 +84,27 @@ core_info_list_t *core_info_list_new(const char *modules_path)
|
|||
core_info[i].display_name = strdup(path_basename(core_info[i].path));
|
||||
}
|
||||
|
||||
size_t all_ext_len = 0;
|
||||
for (size_t i = 0; i < core_info_list->count; i++)
|
||||
{
|
||||
all_ext_len += core_info_list->list[i].supported_extensions ?
|
||||
(strlen(core_info_list->list[i].supported_extensions) + 2) : 0;
|
||||
}
|
||||
|
||||
if (all_ext_len)
|
||||
core_info_list->all_ext = (char*)calloc(1, all_ext_len);
|
||||
if (core_info_list->all_ext)
|
||||
{
|
||||
for (size_t i = 0; i < core_info_list->count; i++)
|
||||
{
|
||||
if (core_info_list->list[i].supported_extensions)
|
||||
{
|
||||
strlcat(core_info_list->all_ext, core_info_list->list[i].supported_extensions, all_ext_len);
|
||||
strlcat(core_info_list->all_ext, "|", all_ext_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dir_list_free(contents);
|
||||
return core_info_list;
|
||||
|
||||
|
@ -102,11 +129,12 @@ void core_info_list_free(core_info_list_t *core_info_list)
|
|||
config_file_free(core_info_list->list[i].data);
|
||||
}
|
||||
|
||||
free(core_info_list->all_ext);
|
||||
free(core_info_list->list);
|
||||
free(core_info_list);
|
||||
}
|
||||
|
||||
bool core_info_list_does_support_file(core_info_t *core, const char *path)
|
||||
bool core_info_does_support_file(const core_info_t *core, const char *path)
|
||||
{
|
||||
if (!path || !core || !core->supported_extensions_list)
|
||||
return false;
|
||||
|
@ -114,3 +142,38 @@ bool core_info_list_does_support_file(core_info_t *core, const char *path)
|
|||
return string_list_find_elem_prefix(core->supported_extensions_list, ".", path_get_extension(path));
|
||||
}
|
||||
|
||||
const char *core_info_list_get_all_extensions(core_info_list_t *core_info_list)
|
||||
{
|
||||
return core_info_list->all_ext;
|
||||
}
|
||||
|
||||
static const char *core_info_tmp_path; // qsort_r() is not in standard C, sadly.
|
||||
static int core_info_qsort_cmp(const void *a_, const void *b_)
|
||||
{
|
||||
const core_info_t *a = (const core_info_t*)a_;
|
||||
const core_info_t *b = (const core_info_t*)b_;
|
||||
int support_a = core_info_does_support_file(a, core_info_tmp_path);
|
||||
int support_b = core_info_does_support_file(b, core_info_tmp_path);
|
||||
if (support_a != support_b)
|
||||
return support_b - support_a;
|
||||
else
|
||||
return strcasecmp(a->display_name, b->display_name);
|
||||
}
|
||||
|
||||
void core_info_list_get_supported_cores(core_info_list_t *core_info_list, const char *path,
|
||||
const core_info_t **infos, size_t *num_infos)
|
||||
{
|
||||
core_info_tmp_path = path;
|
||||
qsort(core_info_list->list, core_info_list->count, sizeof(core_info_t), core_info_qsort_cmp);
|
||||
|
||||
size_t supported = 0;
|
||||
for (size_t i = 0; i < core_info_list->count; i++, supported++)
|
||||
{
|
||||
if (!core_info_does_support_file(&core_info_list->list[i], path))
|
||||
break;
|
||||
}
|
||||
|
||||
*infos = core_info_list->list;
|
||||
*num_infos = supported;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,12 +35,19 @@ typedef struct {
|
|||
typedef struct {
|
||||
core_info_t *list;
|
||||
size_t count;
|
||||
char *all_ext;
|
||||
} core_info_list_t;
|
||||
|
||||
core_info_list_t *core_info_list_new(const char *modules_path);
|
||||
void core_info_list_free(core_info_list_t *core_info_list);
|
||||
|
||||
bool core_info_list_does_support_file(core_info_t *core, const char *path);
|
||||
bool core_info_does_support_file(const core_info_t *core, const char *path);
|
||||
|
||||
// Non-reentrant, does not allocate. Returns pointer to internal state.
|
||||
void core_info_list_get_supported_cores(core_info_list_t *core_info_list, const char *path,
|
||||
const core_info_t **infos, size_t *num_infos);
|
||||
|
||||
const char *core_info_list_get_all_extensions(core_info_list_t *core_info_list);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -408,6 +408,11 @@ static void menu_update_libretro_info(void)
|
|||
#else
|
||||
retro_get_system_info(&rgui->info);
|
||||
#endif
|
||||
|
||||
core_info_list_free(rgui->core_info);
|
||||
rgui->core_info = NULL;
|
||||
if (*rgui->libretro_dir)
|
||||
rgui->core_info = core_info_list_new(rgui->libretro_dir);
|
||||
}
|
||||
|
||||
bool load_menu_game(void)
|
||||
|
@ -513,6 +518,7 @@ void menu_free(void)
|
|||
#endif
|
||||
|
||||
rom_history_free(rgui->history);
|
||||
core_info_list_free(rgui->core_info);
|
||||
|
||||
free(rgui);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#endif
|
||||
|
||||
#include "../../performance.h"
|
||||
#include "../../core_info.h"
|
||||
|
||||
#ifdef HAVE_RGUI
|
||||
#define MENU_TEXTURE_FULLSCREEN false
|
||||
|
@ -98,8 +99,10 @@ typedef enum
|
|||
|
||||
// settings options are done here too
|
||||
RGUI_SETTINGS_OPEN_FILEBROWSER,
|
||||
RGUI_SETTINGS_OPEN_FILEBROWSER_DEFERRED_CORE,
|
||||
RGUI_SETTINGS_OPEN_HISTORY,
|
||||
RGUI_SETTINGS_CORE,
|
||||
RGUI_SETTINGS_DEFERRED_CORE,
|
||||
RGUI_SETTINGS_CONFIG,
|
||||
RGUI_SETTINGS_SAVE_CONFIG,
|
||||
RGUI_SETTINGS_CORE_OPTIONS,
|
||||
|
@ -288,6 +291,10 @@ typedef struct
|
|||
bool need_refresh;
|
||||
bool msg_force;
|
||||
|
||||
core_info_list_t *core_info;
|
||||
bool defer_core;
|
||||
char deferred_path[PATH_MAX];
|
||||
|
||||
// Quick jumping indices with L/R.
|
||||
// Rebuilt when parsing directory.
|
||||
size_t scroll_indices[2 * (26 + 2) + 1];
|
||||
|
|
|
@ -610,7 +610,11 @@ int menu_set_settings(unsigned setting, unsigned action)
|
|||
#ifdef HAVE_DYNAMIC
|
||||
case RGUI_LIBRETRO_DIR_PATH:
|
||||
if (action == RGUI_ACTION_START)
|
||||
{
|
||||
*rgui->libretro_dir = '\0';
|
||||
core_info_list_free(rgui->core_info);
|
||||
rgui->core_info = NULL;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case RGUI_CONFIG_DIR_PATH:
|
||||
|
|
|
@ -227,6 +227,18 @@ static void rgui_resolve_libretro_names(rgui_list_t *list, const char *dir)
|
|||
}
|
||||
}
|
||||
|
||||
static void rgui_resolve_supported_cores(rgui_handle_t *rgui)
|
||||
{
|
||||
const core_info_t *info = NULL;
|
||||
size_t cores = 0;
|
||||
core_info_list_get_supported_cores(rgui->core_info, rgui->deferred_path, &info, &cores);
|
||||
for (size_t i = 0; i < cores; i++)
|
||||
{
|
||||
rgui_list_push(rgui->selection_buf, info[i].path, RGUI_FILE_PLAIN, 0);
|
||||
rgui_list_set_alt_at_offset(rgui->selection_buf, i, info[i].display_name);
|
||||
}
|
||||
}
|
||||
|
||||
static int rgui_settings_toggle_setting(rgui_handle_t *rgui, unsigned setting, rgui_action_t action, unsigned menu_type)
|
||||
{
|
||||
#ifdef HAVE_SHADER_MANAGER
|
||||
|
@ -277,7 +289,18 @@ static void rgui_settings_populate_entries(rgui_handle_t *rgui)
|
|||
#endif
|
||||
if (rgui->history)
|
||||
rgui_list_push(rgui->selection_buf, "Load Game (History)", RGUI_SETTINGS_OPEN_HISTORY, 0);
|
||||
rgui_list_push(rgui->selection_buf, "Load Game", RGUI_SETTINGS_OPEN_FILEBROWSER, 0);
|
||||
|
||||
if (rgui->core_info)
|
||||
rgui_list_push(rgui->selection_buf, "Load Game (Autodetect Core)", RGUI_SETTINGS_OPEN_FILEBROWSER_DEFERRED_CORE, 0);
|
||||
|
||||
if (rgui->info.library_name || g_extern.system.info.library_name)
|
||||
{
|
||||
char load_game_core_msg[64];
|
||||
snprintf(load_game_core_msg, sizeof(load_game_core_msg), "Load Game (%s)",
|
||||
rgui->info.library_name ? rgui->info.library_name : g_extern.system.info.library_name);
|
||||
rgui_list_push(rgui->selection_buf, load_game_core_msg, RGUI_SETTINGS_OPEN_FILEBROWSER, 0);
|
||||
}
|
||||
|
||||
rgui_list_push(rgui->selection_buf, "Core Options", RGUI_SETTINGS_CORE_OPTIONS, 0);
|
||||
rgui_list_push(rgui->selection_buf, "Video Options", RGUI_SETTINGS_VIDEO_OPTIONS, 0);
|
||||
rgui_list_push(rgui->selection_buf, "Audio Options", RGUI_SETTINGS_AUDIO_OPTIONS, 0);
|
||||
|
@ -799,8 +822,10 @@ static int rgui_settings_iterate(rgui_handle_t *rgui, rgui_action_t action)
|
|||
case RGUI_ACTION_RIGHT:
|
||||
case RGUI_ACTION_OK:
|
||||
case RGUI_ACTION_START:
|
||||
if (type == RGUI_SETTINGS_OPEN_FILEBROWSER && action == RGUI_ACTION_OK)
|
||||
if ((type == RGUI_SETTINGS_OPEN_FILEBROWSER || type == RGUI_SETTINGS_OPEN_FILEBROWSER_DEFERRED_CORE)
|
||||
&& action == RGUI_ACTION_OK)
|
||||
{
|
||||
rgui->defer_core = type == RGUI_SETTINGS_OPEN_FILEBROWSER_DEFERRED_CORE;
|
||||
rgui_list_push(rgui->menu_stack, rgui->base_path, RGUI_FILE_DIRECTORY, rgui->selection_ptr);
|
||||
rgui->selection_ptr = 0;
|
||||
rgui->need_refresh = true;
|
||||
|
@ -1066,6 +1091,8 @@ static bool rgui_directory_parse(rgui_handle_t *rgui, const char *directory, uns
|
|||
#endif
|
||||
else if (menu_type_is_directory_browser(menu_type))
|
||||
exts = ""; // we ignore files anyway
|
||||
else if (rgui->defer_core)
|
||||
exts = rgui->core_info ? core_info_list_get_all_extensions(rgui->core_info) : "";
|
||||
else if (rgui->info.valid_extensions)
|
||||
{
|
||||
exts = ext_buf;
|
||||
|
@ -1238,7 +1265,23 @@ static int rgui_iterate(void *data, unsigned action)
|
|||
}
|
||||
else
|
||||
#endif
|
||||
if (menu_type == RGUI_SETTINGS_CORE)
|
||||
if (menu_type == RGUI_SETTINGS_DEFERRED_CORE)
|
||||
{
|
||||
// FIXME: Add for consoles.
|
||||
#ifdef HAVE_DYNAMIC
|
||||
strlcpy(g_settings.libretro, path, sizeof(g_settings.libretro));
|
||||
libretro_free_system_info(&rgui->info);
|
||||
libretro_get_system_info(g_settings.libretro, &rgui->info,
|
||||
&rgui->load_no_rom);
|
||||
|
||||
strlcpy(g_extern.fullpath, rgui->deferred_path, sizeof(g_extern.fullpath));
|
||||
g_extern.lifecycle_mode_state |= (1ULL << MODE_LOAD_GAME);
|
||||
rgui->msg_force = true;
|
||||
ret = -1;
|
||||
#endif
|
||||
rgui_flush_menu_stack_type(rgui, RGUI_SETTINGS);
|
||||
}
|
||||
else if (menu_type == RGUI_SETTINGS_CORE)
|
||||
{
|
||||
#if defined(HAVE_DYNAMIC)
|
||||
fill_pathname_join(g_settings.libretro, dir, path, sizeof(g_settings.libretro));
|
||||
|
@ -1346,6 +1389,10 @@ static int rgui_iterate(void *data, unsigned action)
|
|||
else if (menu_type == RGUI_LIBRETRO_DIR_PATH)
|
||||
{
|
||||
strlcpy(rgui->libretro_dir, dir, sizeof(rgui->libretro_dir));
|
||||
core_info_list_free(rgui->core_info);
|
||||
rgui->core_info = NULL;
|
||||
if (*rgui->libretro_dir)
|
||||
rgui->core_info = core_info_list_new(rgui->libretro_dir);
|
||||
rgui_flush_menu_stack_type(rgui, RGUI_SETTINGS_PATH_OPTIONS);
|
||||
}
|
||||
else if (menu_type == RGUI_CONFIG_DIR_PATH)
|
||||
|
@ -1366,12 +1413,47 @@ static int rgui_iterate(void *data, unsigned action)
|
|||
}
|
||||
else
|
||||
{
|
||||
fill_pathname_join(g_extern.fullpath, dir, path, sizeof(g_extern.fullpath));
|
||||
g_extern.lifecycle_mode_state |= (1ULL << MODE_LOAD_GAME);
|
||||
if (rgui->defer_core)
|
||||
{
|
||||
fill_pathname_join(rgui->deferred_path, dir, path, sizeof(rgui->deferred_path));
|
||||
|
||||
rgui_flush_menu_stack_type(rgui, RGUI_SETTINGS);
|
||||
rgui->msg_force = true;
|
||||
ret = -1;
|
||||
const core_info_t *info = NULL;
|
||||
size_t supported = 0;
|
||||
if (rgui->core_info)
|
||||
core_info_list_get_supported_cores(rgui->core_info, rgui->deferred_path, &info, &supported);
|
||||
|
||||
if (supported == 1) // Can make a decision right now.
|
||||
{
|
||||
strlcpy(g_extern.fullpath, rgui->deferred_path, sizeof(g_extern.fullpath));
|
||||
|
||||
strlcpy(g_settings.libretro, info->path, sizeof(g_settings.libretro));
|
||||
|
||||
#ifdef HAVE_DYNAMIC
|
||||
libretro_free_system_info(&rgui->info);
|
||||
libretro_get_system_info(g_settings.libretro, &rgui->info,
|
||||
&rgui->load_no_rom);
|
||||
#endif
|
||||
|
||||
g_extern.lifecycle_mode_state |= (1ULL << MODE_LOAD_GAME);
|
||||
rgui_flush_menu_stack_type(rgui, RGUI_SETTINGS);
|
||||
rgui->msg_force = true;
|
||||
ret = -1;
|
||||
}
|
||||
else // Present a selection.
|
||||
{
|
||||
rgui_list_push(rgui->menu_stack, rgui->libretro_dir, RGUI_SETTINGS_DEFERRED_CORE, 0);
|
||||
rgui->need_refresh = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fill_pathname_join(g_extern.fullpath, dir, path, sizeof(g_extern.fullpath));
|
||||
g_extern.lifecycle_mode_state |= (1ULL << MODE_LOAD_GAME);
|
||||
|
||||
rgui_flush_menu_stack_type(rgui, RGUI_SETTINGS);
|
||||
rgui->msg_force = true;
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1401,6 +1483,7 @@ static int rgui_iterate(void *data, unsigned action)
|
|||
#ifdef HAVE_OVERLAY
|
||||
menu_type == RGUI_SETTINGS_OVERLAY_PRESET ||
|
||||
#endif
|
||||
menu_type == RGUI_SETTINGS_DEFERRED_CORE ||
|
||||
menu_type == RGUI_SETTINGS_CORE ||
|
||||
menu_type == RGUI_SETTINGS_CONFIG ||
|
||||
menu_type == RGUI_SETTINGS_OPEN_HISTORY ||
|
||||
|
@ -1412,11 +1495,13 @@ static int rgui_iterate(void *data, unsigned action)
|
|||
rgui->scroll_indices_size = 0;
|
||||
if (menu_type == RGUI_SETTINGS_OPEN_HISTORY)
|
||||
history_parse(rgui);
|
||||
else
|
||||
else if (menu_type != RGUI_SETTINGS_DEFERRED_CORE)
|
||||
rgui_directory_parse(rgui, dir, menu_type, rgui->selection_buf);
|
||||
|
||||
if (menu_type == RGUI_SETTINGS_CORE)
|
||||
rgui_resolve_libretro_names(rgui->selection_buf, dir);
|
||||
else if (menu_type == RGUI_SETTINGS_DEFERRED_CORE)
|
||||
rgui_resolve_supported_cores(rgui);
|
||||
|
||||
// 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.
|
||||
|
|
|
@ -232,6 +232,8 @@ static void render_text(rgui_handle_t *rgui)
|
|||
|
||||
if (menu_type == RGUI_SETTINGS_CORE)
|
||||
snprintf(title, sizeof(title), "CORE SELECTION %s", dir);
|
||||
else if (menu_type == RGUI_SETTINGS_DEFERRED_CORE)
|
||||
snprintf(title, sizeof(title), "DETECTED CORES %s", dir);
|
||||
else if (menu_type == RGUI_SETTINGS_CONFIG)
|
||||
snprintf(title, sizeof(title), "CONFIG %s", dir);
|
||||
else if (menu_type == RGUI_SETTINGS_DISK_APPEND)
|
||||
|
@ -360,9 +362,8 @@ static void render_text(rgui_handle_t *rgui)
|
|||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_DYNAMIC
|
||||
// Pretty-print libretro cores from menu.
|
||||
if (menu_type == RGUI_SETTINGS_CORE)
|
||||
if (menu_type == RGUI_SETTINGS_CORE || menu_type == RGUI_SETTINGS_DEFERRED_CORE)
|
||||
{
|
||||
if (type == RGUI_FILE_PLAIN)
|
||||
{
|
||||
|
@ -377,10 +378,7 @@ static void render_text(rgui_handle_t *rgui)
|
|||
w = 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (menu_type == RGUI_SETTINGS_CORE ||
|
||||
menu_type == RGUI_SETTINGS_CONFIG ||
|
||||
else if (menu_type == RGUI_SETTINGS_CONFIG ||
|
||||
#ifdef HAVE_OVERLAY
|
||||
menu_type == RGUI_SETTINGS_OVERLAY_PRESET ||
|
||||
#endif
|
||||
|
@ -568,6 +566,7 @@ static void render_text(rgui_handle_t *rgui)
|
|||
strlcpy(type_str, "<default>", sizeof(type_str));
|
||||
break;
|
||||
case RGUI_SETTINGS_OPEN_FILEBROWSER:
|
||||
case RGUI_SETTINGS_OPEN_FILEBROWSER_DEFERRED_CORE:
|
||||
case RGUI_SETTINGS_OPEN_HISTORY:
|
||||
case RGUI_SETTINGS_CORE_OPTIONS:
|
||||
case RGUI_SETTINGS_CUSTOM_VIEWPORT:
|
||||
|
|
Loading…
Reference in New Issue