Add directory support for libretro_path/-L.

This commit is contained in:
Themaister 2012-10-11 22:31:47 +02:00
parent 174d17b1a2
commit 8a1327cefd
5 changed files with 99 additions and 5 deletions

View File

@ -21,7 +21,7 @@ libretro provides emulation of a game system, and can be implemented by any fron
.TP
\fB[rom file]\fR
If no rom file path is defined on the command line, \fBretroarch\fR will try to load a rom from \fBstdin\fR.
\fBretroarch\fR only supports loading of \fBuncompressed\fR roms, such as *.sfc or *.smc.
\fBretroarch\fR does not uncompress roms. ROM types supported depends on the libretro implementation used.
.TP
\fB--help, -h\fR
@ -37,6 +37,10 @@ Path to a libretro implementation which is to be used.
This option will override any setting in a config file.
This option is only available if RetroArch is compiled with dynamic libretro loading.
If PATH is a directory, RetroArch will try to find the first implementation that claims to support
the extension of the ROM used, and use that libretro implementation.
If two or more different implementations claim to support a certain ROM extension, there might be collisions.
.TP
\fB--save PATH, -s PATH\fR
Overrides the path used for save ram (*.srm).

View File

@ -17,6 +17,7 @@
#include "general.h"
#include "compat/strl.h"
#include "compat/posix_string.h"
#include "file.h"
#include <string.h>
#ifdef RARCH_CONSOLE
@ -90,14 +91,98 @@ size_t (*pretro_get_memory_size)(unsigned);
static void set_environment(void);
static void set_environment_defaults(void);
#if defined(__APPLE__)
#define DYNAMIC_EXT "dylib"
#elif defined(_WIN32)
#define DYNAMIC_EXT "dll"
#else
#define DYNAMIC_EXT "so"
#endif
static bool find_first_libretro(char *path, size_t size,
const char *dir, const char *rom_path)
{
bool ret = false;
const char *ext = path_get_extension(rom_path);
if (!ext || !*ext)
{
RARCH_ERR("Path has no extension. Cannot infer libretro implementation.\n");
return false;
}
RARCH_LOG("Searching for valid libretro implementation in: \"%s\".\n", dir);
struct string_list *list = dir_list_new(dir, DYNAMIC_EXT, false);
if (!list)
{
RARCH_ERR("Couldn't open directory: \"%s\".\n", dir);
return false;
}
for (size_t i = 0; i < list->size && !ret; i++)
{
RARCH_LOG("Checking library: \"%s\".\n", list->elems[i].data);
dylib_t lib = dylib_load(list->elems[i].data);
if (!lib)
continue;
void (*proc)(struct retro_system_info*) =
(void (*)(struct retro_system_info*))dylib_proc(lib, "retro_get_system_info");
if (!proc)
{
dylib_close(lib);
continue;
}
struct retro_system_info info = {0};
proc(&info);
if (!info.valid_extensions)
{
dylib_close(lib);
continue;
}
struct string_list *supported_ext = string_split(info.valid_extensions, "|");
if (string_list_find_elem(supported_ext, ext))
{
strlcpy(path, list->elems[i].data, size);
ret = true;
}
string_list_free(supported_ext);
dylib_close(lib);
}
dir_list_free(list);
return ret;
}
static void load_symbols(void)
{
const char *libretro_path = g_settings.libretro;
char libretro_core_buffer[PATH_MAX];
if (path_is_directory(g_settings.libretro))
{
if (!find_first_libretro(libretro_core_buffer, sizeof(libretro_core_buffer),
g_settings.libretro, g_extern.fullpath))
{
RARCH_ERR("libretro_path is a directory, but no valid libretro implementation was found.\n");
rarch_fail(1, "load_dynamic()");
}
libretro_path = libretro_core_buffer;
}
#ifdef HAVE_DYNAMIC
RARCH_LOG("Loading dynamic libretro from: \"%s\"\n", g_settings.libretro);
lib_handle = dylib_load(g_settings.libretro);
RARCH_LOG("Loading dynamic libretro from: \"%s\"\n", libretro_path);
lib_handle = dylib_load(libretro_path);
if (!lib_handle)
{
RARCH_ERR("Failed to open dynamic library: \"%s\"\n", g_settings.libretro);
RARCH_ERR("Failed to open dynamic library: \"%s\"\n", libretro_path);
rarch_fail(1, "load_dynamic()");
}
#endif

1
file.h
View File

@ -63,6 +63,7 @@ void dir_list_free(struct string_list *list);
bool string_list_find_elem(const struct string_list *list, const char *elem);
bool string_list_find_elem_prefix(const struct string_list *list, const char *prefix, const char *elem);
struct string_list *string_split(const char *str, const char *delim);
void string_list_free(struct string_list *list);
bool path_is_directory(const char *path);
bool path_file_exists(const char *path);

View File

@ -47,7 +47,7 @@
#include <dirent.h>
#endif
static void string_list_free(struct string_list *list)
void string_list_free(struct string_list *list)
{
if (!list)
return;

View File

@ -15,6 +15,10 @@
# Load libretro from a dynamic location for dynamically built RetroArch.
# This option is mandatory.
# If a directory, RetroArch will look through the directory until it finds an implementation
# that appears to support the extension of the ROM loaded.
# This could fail if ROM extensions overlap.
# libretro_path = "/path/to/libretro.so"
# Environment variables internally in RetroArch.