Begin implementing core autoselect.

This commit is contained in:
Themaister 2013-10-05 17:07:56 +02:00
parent a470ae0d04
commit 050e2375e3
7 changed files with 188 additions and 17 deletions

View File

@ -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;
}

View File

@ -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
}

View File

@ -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);
}

View File

@ -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];

View File

@ -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:

View File

@ -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.

View File

@ -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: