mirror of
https://github.com/libretro/RetroArch
synced 2024-12-27 15:29:23 +00:00
Add directory support for libretro_path/-L.
This commit is contained in:
parent
174d17b1a2
commit
8a1327cefd
@ -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).
|
||||
|
91
dynamic.c
91
dynamic.c
@ -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
1
file.h
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user