mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-23 16:09:47 +00:00
Cleanups - 80-char limit
This commit is contained in:
parent
4a2d3cbd4b
commit
0856091296
232
dynamic.c
232
dynamic.c
@ -82,7 +82,8 @@ void (*pretro_cheat_reset)(void);
|
|||||||
void (*pretro_cheat_set)(unsigned, bool, const char*);
|
void (*pretro_cheat_set)(unsigned, bool, const char*);
|
||||||
|
|
||||||
bool (*pretro_load_game)(const struct retro_game_info*);
|
bool (*pretro_load_game)(const struct retro_game_info*);
|
||||||
bool (*pretro_load_game_special)(unsigned, const struct retro_game_info*, size_t);
|
bool (*pretro_load_game_special)(unsigned,
|
||||||
|
const struct retro_game_info*, size_t);
|
||||||
|
|
||||||
void (*pretro_unload_game)(void);
|
void (*pretro_unload_game)(void);
|
||||||
|
|
||||||
@ -101,6 +102,7 @@ size_t (*pretro_get_memory_size)(unsigned);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool *load_no_content_hook;
|
static bool *load_no_content_hook;
|
||||||
|
|
||||||
static bool environ_cb_get_system_info(unsigned cmd, void *data)
|
static bool environ_cb_get_system_info(unsigned cmd, void *data)
|
||||||
{
|
{
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
@ -116,7 +118,8 @@ static bool environ_cb_get_system_info(unsigned cmd, void *data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void libretro_get_environment_info(void (*func)(retro_environment_t), bool *load_no_content)
|
void libretro_get_environment_info(void (*func)(retro_environment_t),
|
||||||
|
bool *load_no_content)
|
||||||
{
|
{
|
||||||
load_no_content_hook = load_no_content;
|
load_no_content_hook = load_no_content;
|
||||||
|
|
||||||
@ -124,14 +127,16 @@ void libretro_get_environment_info(void (*func)(retro_environment_t), bool *load
|
|||||||
func(environ_cb_get_system_info);
|
func(environ_cb_get_system_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static dylib_t libretro_get_system_info_lib(const char *path, struct retro_system_info *info, bool *load_no_content)
|
static dylib_t libretro_get_system_info_lib(const char *path,
|
||||||
|
struct retro_system_info *info, bool *load_no_content)
|
||||||
{
|
{
|
||||||
dylib_t lib = dylib_load(path);
|
dylib_t lib = dylib_load(path);
|
||||||
if (!lib)
|
if (!lib)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
void (*proc)(struct retro_system_info*) =
|
void (*proc)(struct retro_system_info*) =
|
||||||
(void (*)(struct retro_system_info*))dylib_proc(lib, "retro_get_system_info");
|
(void (*)(struct retro_system_info*))dylib_proc(lib,
|
||||||
|
"retro_get_system_info");
|
||||||
|
|
||||||
if (!proc)
|
if (!proc)
|
||||||
{
|
{
|
||||||
@ -145,7 +150,8 @@ static dylib_t libretro_get_system_info_lib(const char *path, struct retro_syste
|
|||||||
{
|
{
|
||||||
*load_no_content = false;
|
*load_no_content = false;
|
||||||
void (*set_environ)(retro_environment_t) =
|
void (*set_environ)(retro_environment_t) =
|
||||||
(void (*)(retro_environment_t))dylib_proc(lib, "retro_set_environment");
|
(void (*)(retro_environment_t))dylib_proc(lib,
|
||||||
|
"retro_set_environment");
|
||||||
|
|
||||||
if (!set_environ)
|
if (!set_environ)
|
||||||
return lib;
|
return lib;
|
||||||
@ -156,11 +162,12 @@ static dylib_t libretro_get_system_info_lib(const char *path, struct retro_syste
|
|||||||
return lib;
|
return lib;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool libretro_get_system_info(const char *path, struct retro_system_info *info,
|
bool libretro_get_system_info(const char *path,
|
||||||
bool *load_no_content)
|
struct retro_system_info *info, bool *load_no_content)
|
||||||
{
|
{
|
||||||
struct retro_system_info dummy_info = {0};
|
struct retro_system_info dummy_info = {0};
|
||||||
dylib_t lib = libretro_get_system_info_lib(path, &dummy_info, load_no_content);
|
dylib_t lib = libretro_get_system_info_lib(path,
|
||||||
|
&dummy_info, load_no_content);
|
||||||
if (!lib)
|
if (!lib)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -183,7 +190,8 @@ void libretro_free_system_info(struct retro_system_info *info)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const struct retro_subsystem_info *libretro_find_subsystem_info(const struct retro_subsystem_info *info, unsigned num_info,
|
const struct retro_subsystem_info *libretro_find_subsystem_info(
|
||||||
|
const struct retro_subsystem_info *info, unsigned num_info,
|
||||||
const char *ident)
|
const char *ident)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
@ -191,14 +199,16 @@ const struct retro_subsystem_info *libretro_find_subsystem_info(const struct ret
|
|||||||
{
|
{
|
||||||
if (!strcmp(info[i].ident, ident))
|
if (!strcmp(info[i].ident, ident))
|
||||||
return &info[i];
|
return &info[i];
|
||||||
else if (!strcmp(info[i].desc, ident)) // Doesn't hurt
|
else if (!strcmp(info[i].desc, ident))
|
||||||
return &info[i];
|
return &info[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct retro_controller_description *libretro_find_controller_description(const struct retro_controller_info *info, unsigned id)
|
const struct retro_controller_description *
|
||||||
|
libretro_find_controller_description(
|
||||||
|
const struct retro_controller_info *info, unsigned id)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i < info->num_types; i++)
|
for (i = 0; i < info->num_types; i++)
|
||||||
@ -251,15 +261,19 @@ static void load_symbols(bool is_dummy)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DYNAMIC
|
#ifdef HAVE_DYNAMIC
|
||||||
// Need to use absolute path for this setting. It can be saved to content history,
|
/* Need to use absolute path for this setting. It can be
|
||||||
// and a relative path would break in that scenario.
|
* saved to content history, and a relative path would
|
||||||
path_resolve_realpath(g_settings.libretro, sizeof(g_settings.libretro));
|
* break in that scenario. */
|
||||||
|
path_resolve_realpath(g_settings.libretro,
|
||||||
|
sizeof(g_settings.libretro));
|
||||||
|
|
||||||
RARCH_LOG("Loading dynamic libretro from: \"%s\"\n", g_settings.libretro);
|
RARCH_LOG("Loading dynamic libretro from: \"%s\"\n",
|
||||||
|
g_settings.libretro);
|
||||||
lib_handle = dylib_load(g_settings.libretro);
|
lib_handle = dylib_load(g_settings.libretro);
|
||||||
if (!lib_handle)
|
if (!lib_handle)
|
||||||
{
|
{
|
||||||
RARCH_ERR("Failed to open dynamic library: \"%s\"\n", g_settings.libretro);
|
RARCH_ERR("Failed to open dynamic library: \"%s\"\n",
|
||||||
|
g_settings.libretro);
|
||||||
rarch_fail(1, "load_dynamic()");
|
rarch_fail(1, "load_dynamic()");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -330,15 +344,15 @@ void libretro_get_current_core_pathname(char *name, size_t size)
|
|||||||
|
|
||||||
void init_libretro_sym(bool dummy)
|
void init_libretro_sym(bool dummy)
|
||||||
{
|
{
|
||||||
// Guarantee that we can do "dirty" casting.
|
/* Guarantee that we can do "dirty" casting.
|
||||||
// Every OS that this program supports should pass this ...
|
* Every OS that this program supports should pass this. */
|
||||||
rarch_assert(sizeof(void*) == sizeof(void (*)(void)));
|
rarch_assert(sizeof(void*) == sizeof(void (*)(void)));
|
||||||
|
|
||||||
if (!dummy)
|
if (!dummy)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DYNAMIC
|
#ifdef HAVE_DYNAMIC
|
||||||
// Try to verify that -lretro was not linked in from other modules
|
/* Try to verify that -lretro was not linked in from other modules
|
||||||
// since loading it dynamically and with -l will fail hard.
|
* since loading it dynamically and with -l will fail hard. */
|
||||||
function_t sym = dylib_proc(NULL, "retro_init");
|
function_t sym = dylib_proc(NULL, "retro_init");
|
||||||
if (sym)
|
if (sym)
|
||||||
{
|
{
|
||||||
@ -375,25 +389,26 @@ void uninit_libretro_sym(void)
|
|||||||
core_option_free(g_extern.system.core_options);
|
core_option_free(g_extern.system.core_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
// No longer valid.
|
/* No longer valid. */
|
||||||
free(g_extern.system.special);
|
free(g_extern.system.special);
|
||||||
free(g_extern.system.ports);
|
free(g_extern.system.ports);
|
||||||
memset(&g_extern.system, 0, sizeof(g_extern.system));
|
memset(&g_extern.system, 0, sizeof(g_extern.system));
|
||||||
g_extern.camera_active = false;
|
g_extern.camera_active = false;
|
||||||
g_extern.location_active = false;
|
g_extern.location_active = false;
|
||||||
|
|
||||||
// Performance counters no longer valid.
|
/* Performance counters no longer valid. */
|
||||||
retro_perf_clear();
|
retro_perf_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NEED_DYNAMIC
|
#ifdef NEED_DYNAMIC
|
||||||
// Platform independent dylib loading.
|
/* Platform independent dylib loading. */
|
||||||
dylib_t dylib_load(const char *path)
|
dylib_t dylib_load(const char *path)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
dylib_t lib = LoadLibrary(path);
|
dylib_t lib = LoadLibrary(path);
|
||||||
if (!lib)
|
if (!lib)
|
||||||
RARCH_ERR("Failed to load library, error code: 0x%x\n", (unsigned)GetLastError());
|
RARCH_ERR("Failed to load library, error code: 0x%x\n",
|
||||||
|
(unsigned)GetLastError());
|
||||||
return lib;
|
return lib;
|
||||||
#else
|
#else
|
||||||
dylib_t lib = dlopen(path, RTLD_LAZY);
|
dylib_t lib = dlopen(path, RTLD_LAZY);
|
||||||
@ -406,7 +421,8 @@ dylib_t dylib_load(const char *path)
|
|||||||
function_t dylib_proc(dylib_t lib, const char *proc)
|
function_t dylib_proc(dylib_t lib, const char *proc)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
function_t sym = (function_t)GetProcAddress(lib ? (HMODULE)lib : GetModuleHandle(NULL), proc);
|
function_t sym = (function_t)GetProcAddress(lib ?
|
||||||
|
(HMODULE)lib : GetModuleHandle(NULL), proc);
|
||||||
#else
|
#else
|
||||||
void *ptr_sym = NULL;
|
void *ptr_sym = NULL;
|
||||||
if (lib)
|
if (lib)
|
||||||
@ -421,7 +437,8 @@ function_t dylib_proc(dylib_t lib, const char *proc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dirty hack to workaround the non-legality of (void*) -> fn-pointer casts.
|
/* Dirty hack to workaround the non-legality of
|
||||||
|
* (void*) -> fn-pointer casts. */
|
||||||
function_t sym;
|
function_t sym;
|
||||||
memcpy(&sym, &ptr_sym, sizeof(void*));
|
memcpy(&sym, &ptr_sym, sizeof(void*));
|
||||||
#endif
|
#endif
|
||||||
@ -439,7 +456,8 @@ void dylib_close(dylib_t lib)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void rarch_log_libretro(enum retro_log_level level, const char *fmt, ...)
|
static void rarch_log_libretro(enum retro_log_level level,
|
||||||
|
const char *fmt, ...)
|
||||||
{
|
{
|
||||||
if ((unsigned)level < g_settings.libretro_log_level)
|
if ((unsigned)level < g_settings.libretro_log_level)
|
||||||
return;
|
return;
|
||||||
@ -475,11 +493,13 @@ static void rarch_log_libretro(enum retro_log_level level, const char *fmt, ...)
|
|||||||
bool rarch_environment_cb(unsigned cmd, void *data)
|
bool rarch_environment_cb(unsigned cmd, void *data)
|
||||||
{
|
{
|
||||||
unsigned p, id;
|
unsigned p, id;
|
||||||
|
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case RETRO_ENVIRONMENT_GET_OVERSCAN:
|
case RETRO_ENVIRONMENT_GET_OVERSCAN:
|
||||||
*(bool*)data = !g_settings.video.crop_overscan;
|
*(bool*)data = !g_settings.video.crop_overscan;
|
||||||
RARCH_LOG("Environ GET_OVERSCAN: %u\n", (unsigned)!g_settings.video.crop_overscan);
|
RARCH_LOG("Environ GET_OVERSCAN: %u\n",
|
||||||
|
(unsigned)!g_settings.video.crop_overscan);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RETRO_ENVIRONMENT_GET_CAN_DUPE:
|
case RETRO_ENVIRONMENT_GET_CAN_DUPE:
|
||||||
@ -516,13 +536,15 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
core_option_free(g_extern.system.core_options);
|
core_option_free(g_extern.system.core_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct retro_variable *vars = (const struct retro_variable*)data;
|
const struct retro_variable *vars =
|
||||||
|
(const struct retro_variable*)data;
|
||||||
|
|
||||||
const char *options_path = g_settings.core_options_path;
|
const char *options_path = g_settings.core_options_path;
|
||||||
char buf[PATH_MAX];
|
char buf[PATH_MAX];
|
||||||
if (!*options_path && *g_extern.config_path)
|
if (!*options_path && *g_extern.config_path)
|
||||||
{
|
{
|
||||||
fill_pathname_resolve_relative(buf, g_extern.config_path, "retroarch-core-options.cfg", sizeof(buf));
|
fill_pathname_resolve_relative(buf, g_extern.config_path,
|
||||||
|
"retroarch-core-options.cfg", sizeof(buf));
|
||||||
options_path = buf;
|
options_path = buf;
|
||||||
}
|
}
|
||||||
g_extern.system.core_options = core_option_new(options_path, vars);
|
g_extern.system.core_options = core_option_new(options_path, vars);
|
||||||
@ -568,32 +590,42 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
|
|
||||||
case RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL:
|
case RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL:
|
||||||
g_extern.system.performance_level = *(const unsigned*)data;
|
g_extern.system.performance_level = *(const unsigned*)data;
|
||||||
RARCH_LOG("Environ PERFORMANCE_LEVEL: %u.\n", g_extern.system.performance_level);
|
RARCH_LOG("Environ PERFORMANCE_LEVEL: %u.\n",
|
||||||
|
g_extern.system.performance_level);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY:
|
case RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY:
|
||||||
*(const char**)data = *g_settings.system_directory ? g_settings.system_directory : NULL;
|
*(const char**)data = *g_settings.system_directory ?
|
||||||
RARCH_LOG("Environ SYSTEM_DIRECTORY: \"%s\".\n", g_settings.system_directory);
|
g_settings.system_directory : NULL;
|
||||||
|
RARCH_LOG("Environ SYSTEM_DIRECTORY: \"%s\".\n",
|
||||||
|
g_settings.system_directory);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY:
|
case RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY:
|
||||||
*(const char**)data = *g_extern.savefile_dir ? g_extern.savefile_dir : NULL;
|
*(const char**)data = *g_extern.savefile_dir ?
|
||||||
RARCH_LOG("Environ SAVE_DIRECTORY: \"%s\".\n", g_extern.savefile_dir);
|
g_extern.savefile_dir : NULL;
|
||||||
|
RARCH_LOG("Environ SAVE_DIRECTORY: \"%s\".\n",
|
||||||
|
g_extern.savefile_dir);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RETRO_ENVIRONMENT_GET_USERNAME:
|
case RETRO_ENVIRONMENT_GET_USERNAME:
|
||||||
*(const char**)data = *g_settings.username ? g_settings.username : NULL;
|
*(const char**)data = *g_settings.username ?
|
||||||
RARCH_LOG("Environ GET_USERNAME: \"%s\".\n", g_settings.username);
|
g_settings.username : NULL;
|
||||||
|
RARCH_LOG("Environ GET_USERNAME: \"%s\".\n",
|
||||||
|
g_settings.username);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RETRO_ENVIRONMENT_GET_LANGUAGE:
|
case RETRO_ENVIRONMENT_GET_LANGUAGE:
|
||||||
*(unsigned *)data = g_settings.user_language;
|
*(unsigned *)data = g_settings.user_language;
|
||||||
RARCH_LOG("Environ GET_LANGUAGE: \"%d\".\n", g_settings.user_language);
|
RARCH_LOG("Environ GET_LANGUAGE: \"%d\".\n",
|
||||||
|
g_settings.user_language);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RETRO_ENVIRONMENT_SET_PIXEL_FORMAT:
|
case RETRO_ENVIRONMENT_SET_PIXEL_FORMAT:
|
||||||
{
|
{
|
||||||
enum retro_pixel_format pix_fmt = *(const enum retro_pixel_format*)data;
|
enum retro_pixel_format pix_fmt =
|
||||||
|
*(const enum retro_pixel_format*)data;
|
||||||
|
|
||||||
switch (pix_fmt)
|
switch (pix_fmt)
|
||||||
{
|
{
|
||||||
case RETRO_PIXEL_FORMAT_0RGB1555:
|
case RETRO_PIXEL_FORMAT_0RGB1555:
|
||||||
@ -616,21 +648,26 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
|
|
||||||
case RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS:
|
case RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS:
|
||||||
{
|
{
|
||||||
memset(g_extern.system.input_desc_btn, 0, sizeof(g_extern.system.input_desc_btn));
|
memset(g_extern.system.input_desc_btn, 0,
|
||||||
|
sizeof(g_extern.system.input_desc_btn));
|
||||||
|
|
||||||
|
const struct retro_input_descriptor *desc =
|
||||||
|
(const struct retro_input_descriptor*)data;
|
||||||
|
|
||||||
const struct retro_input_descriptor *desc = (const struct retro_input_descriptor*)data;
|
|
||||||
for (; desc->description; desc++)
|
for (; desc->description; desc++)
|
||||||
{
|
{
|
||||||
if (desc->port >= MAX_PLAYERS)
|
if (desc->port >= MAX_PLAYERS)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (desc->device != RETRO_DEVICE_JOYPAD) // Ignore all others for now.
|
/* Ignore all others for now. */
|
||||||
|
if (desc->device != RETRO_DEVICE_JOYPAD)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (desc->id >= RARCH_FIRST_CUSTOM_BIND)
|
if (desc->id >= RARCH_FIRST_CUSTOM_BIND)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
g_extern.system.input_desc_btn[desc->port][desc->id] = desc->description;
|
g_extern.system.input_desc_btn[desc->port][desc->id] =
|
||||||
|
desc->description;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *libretro_btn_desc[] = {
|
static const char *libretro_btn_desc[] = {
|
||||||
@ -660,21 +697,25 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
case RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK:
|
case RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK:
|
||||||
{
|
{
|
||||||
RARCH_LOG("Environ SET_KEYBOARD_CALLBACK.\n");
|
RARCH_LOG("Environ SET_KEYBOARD_CALLBACK.\n");
|
||||||
const struct retro_keyboard_callback *info = (const struct retro_keyboard_callback*)data;
|
const struct retro_keyboard_callback *info =
|
||||||
|
(const struct retro_keyboard_callback*)data;
|
||||||
g_extern.system.key_event = info->callback;
|
g_extern.system.key_event = info->callback;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE:
|
case RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE:
|
||||||
RARCH_LOG("Environ SET_DISK_CONTROL_INTERFACE.\n");
|
RARCH_LOG("Environ SET_DISK_CONTROL_INTERFACE.\n");
|
||||||
g_extern.system.disk_control = *(const struct retro_disk_control_callback*)data;
|
g_extern.system.disk_control =
|
||||||
|
*(const struct retro_disk_control_callback*)data;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RETRO_ENVIRONMENT_SET_HW_RENDER:
|
case RETRO_ENVIRONMENT_SET_HW_RENDER:
|
||||||
case RETRO_ENVIRONMENT_SET_HW_RENDER | RETRO_ENVIRONMENT_EXPERIMENTAL: // ABI compat
|
case RETRO_ENVIRONMENT_SET_HW_RENDER | RETRO_ENVIRONMENT_EXPERIMENTAL:
|
||||||
{
|
{
|
||||||
RARCH_LOG("Environ SET_HW_RENDER.\n");
|
RARCH_LOG("Environ SET_HW_RENDER.\n");
|
||||||
struct retro_hw_render_callback *cb = (struct retro_hw_render_callback*)data;
|
struct retro_hw_render_callback *cb =
|
||||||
|
(struct retro_hw_render_callback*)data;
|
||||||
|
|
||||||
switch (cb->context_type)
|
switch (cb->context_type)
|
||||||
{
|
{
|
||||||
case RETRO_HW_CONTEXT_NONE:
|
case RETRO_HW_CONTEXT_NONE:
|
||||||
@ -718,7 +759,8 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RETRO_HW_CONTEXT_OPENGL_CORE:
|
case RETRO_HW_CONTEXT_OPENGL_CORE:
|
||||||
RARCH_LOG("Requesting core OpenGL context (%u.%u).\n", cb->version_major, cb->version_minor);
|
RARCH_LOG("Requesting core OpenGL context (%u.%u).\n",
|
||||||
|
cb->version_major, cb->version_minor);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -729,8 +771,9 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
cb->get_current_framebuffer = driver_get_current_framebuffer;
|
cb->get_current_framebuffer = driver_get_current_framebuffer;
|
||||||
cb->get_proc_address = driver_get_proc_address;
|
cb->get_proc_address = driver_get_proc_address;
|
||||||
|
|
||||||
if (cmd & RETRO_ENVIRONMENT_EXPERIMENTAL) // Old ABI. Don't copy garbage.
|
if (cmd & RETRO_ENVIRONMENT_EXPERIMENTAL) /* Old ABI. Don't copy garbage. */
|
||||||
memcpy(&g_extern.system.hw_render_callback, cb, offsetof(struct retro_hw_render_callback, stencil));
|
memcpy(&g_extern.system.hw_render_callback,
|
||||||
|
cb, offsetof(struct retro_hw_render_callback, stencil));
|
||||||
else
|
else
|
||||||
memcpy(&g_extern.system.hw_render_callback, cb, sizeof(*cb));
|
memcpy(&g_extern.system.hw_render_callback, cb, sizeof(*cb));
|
||||||
break;
|
break;
|
||||||
@ -755,13 +798,15 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIXME - PS3 audio driver needs to be fixed so that threaded audio works correctly
|
/* FIXME - PS3 audio driver needs to be fixed so that threaded
|
||||||
//(audio is already on a thread for PS3 audio driver so that's probably the problem)
|
* audio works correctly (audio is already on a thread for PS3
|
||||||
|
* audio driver so that's probably the problem) */
|
||||||
#if defined(HAVE_THREADS) && !defined(__CELLOS_LV2__)
|
#if defined(HAVE_THREADS) && !defined(__CELLOS_LV2__)
|
||||||
case RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK:
|
case RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK:
|
||||||
{
|
{
|
||||||
RARCH_LOG("Environ SET_AUDIO_CALLBACK.\n");
|
RARCH_LOG("Environ SET_AUDIO_CALLBACK.\n");
|
||||||
const struct retro_audio_callback *info = (const struct retro_audio_callback*)data;
|
const struct retro_audio_callback *info =
|
||||||
|
(const struct retro_audio_callback*)data;
|
||||||
|
|
||||||
if (g_extern.rec) // A/V sync is a must.
|
if (g_extern.rec) // A/V sync is a must.
|
||||||
return false;
|
return false;
|
||||||
@ -781,11 +826,14 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
RARCH_LOG("Environ SET_FRAME_TIME_CALLBACK.\n");
|
RARCH_LOG("Environ SET_FRAME_TIME_CALLBACK.\n");
|
||||||
|
|
||||||
#ifdef HAVE_NETPLAY
|
#ifdef HAVE_NETPLAY
|
||||||
if (g_extern.netplay_enable) // retro_run() will be called in very strange and mysterious ways, have to disable it.
|
/* retro_run() will be called in very strange and
|
||||||
|
* mysterious ways, have to disable it. */
|
||||||
|
if (g_extern.netplay_enable)
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const struct retro_frame_time_callback *info = (const struct retro_frame_time_callback*)data;
|
const struct retro_frame_time_callback *info =
|
||||||
|
(const struct retro_frame_time_callback*)data;
|
||||||
g_extern.system.frame_time = *info;
|
g_extern.system.frame_time = *info;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -793,7 +841,8 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
case RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE:
|
case RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE:
|
||||||
{
|
{
|
||||||
RARCH_LOG("Environ GET_RUMBLE_INTERFACE.\n");
|
RARCH_LOG("Environ GET_RUMBLE_INTERFACE.\n");
|
||||||
struct retro_rumble_interface *iface = (struct retro_rumble_interface*)data;
|
struct retro_rumble_interface *iface =
|
||||||
|
(struct retro_rumble_interface*)data;
|
||||||
iface->set_rumble_state = driver_set_rumble_state;
|
iface->set_rumble_state = driver_set_rumble_state;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -802,7 +851,8 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
{
|
{
|
||||||
RARCH_LOG("Environ GET_INPUT_DEVICE_CAPABILITIES.\n");
|
RARCH_LOG("Environ GET_INPUT_DEVICE_CAPABILITIES.\n");
|
||||||
uint64_t *mask = (uint64_t*)data;
|
uint64_t *mask = (uint64_t*)data;
|
||||||
if (driver.input && driver.input->get_capabilities && driver.input_data)
|
if (driver.input &&
|
||||||
|
driver.input->get_capabilities && driver.input_data)
|
||||||
*mask = driver.input->get_capabilities(driver.input_data);
|
*mask = driver.input->get_capabilities(driver.input_data);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
@ -812,7 +862,8 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
case RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE:
|
case RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE:
|
||||||
{
|
{
|
||||||
RARCH_LOG("Environ GET_SENSOR_INTERFACE.\n");
|
RARCH_LOG("Environ GET_SENSOR_INTERFACE.\n");
|
||||||
struct retro_sensor_interface *iface = (struct retro_sensor_interface*)data;
|
struct retro_sensor_interface *iface =
|
||||||
|
(struct retro_sensor_interface*)data;
|
||||||
iface->set_sensor_state = driver_set_sensor_state;
|
iface->set_sensor_state = driver_set_sensor_state;
|
||||||
iface->get_sensor_input = driver_sensor_get_input;
|
iface->get_sensor_input = driver_sensor_get_input;
|
||||||
break;
|
break;
|
||||||
@ -821,7 +872,8 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
case RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE:
|
case RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE:
|
||||||
{
|
{
|
||||||
RARCH_LOG("Environ GET_CAMERA_INTERFACE.\n");
|
RARCH_LOG("Environ GET_CAMERA_INTERFACE.\n");
|
||||||
struct retro_camera_callback *cb = (struct retro_camera_callback*)data;
|
struct retro_camera_callback *cb =
|
||||||
|
(struct retro_camera_callback*)data;
|
||||||
cb->start = driver_camera_start;
|
cb->start = driver_camera_start;
|
||||||
cb->stop = driver_camera_stop;
|
cb->stop = driver_camera_stop;
|
||||||
g_extern.system.camera_callback = *cb;
|
g_extern.system.camera_callback = *cb;
|
||||||
@ -832,7 +884,8 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
case RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE:
|
case RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE:
|
||||||
{
|
{
|
||||||
RARCH_LOG("Environ GET_LOCATION_INTERFACE.\n");
|
RARCH_LOG("Environ GET_LOCATION_INTERFACE.\n");
|
||||||
struct retro_location_callback *cb = (struct retro_location_callback*)data;
|
struct retro_location_callback *cb =
|
||||||
|
(struct retro_location_callback*)data;
|
||||||
cb->start = driver_location_start;
|
cb->start = driver_location_start;
|
||||||
cb->stop = driver_location_stop;
|
cb->stop = driver_location_stop;
|
||||||
cb->get_position = driver_location_get_position;
|
cb->get_position = driver_location_get_position;
|
||||||
@ -857,32 +910,37 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
cb->get_time_usec = rarch_get_time_usec;
|
cb->get_time_usec = rarch_get_time_usec;
|
||||||
cb->get_cpu_features = rarch_get_cpu_features;
|
cb->get_cpu_features = rarch_get_cpu_features;
|
||||||
cb->get_perf_counter = rarch_get_perf_counter;
|
cb->get_perf_counter = rarch_get_perf_counter;
|
||||||
cb->perf_register = retro_perf_register; // libretro specific path.
|
cb->perf_register = retro_perf_register; /* libretro specific path. */
|
||||||
cb->perf_start = rarch_perf_start;
|
cb->perf_start = rarch_perf_start;
|
||||||
cb->perf_stop = rarch_perf_stop;
|
cb->perf_stop = rarch_perf_stop;
|
||||||
cb->perf_log = retro_perf_log; // libretro specific path.
|
cb->perf_log = retro_perf_log; /* libretro specific path. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY:
|
case RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY:
|
||||||
{
|
{
|
||||||
const char **dir = (const char**)data;
|
const char **dir = (const char**)data;
|
||||||
*dir = *g_settings.content_directory ? g_settings.content_directory : NULL;
|
*dir = *g_settings.content_directory ?
|
||||||
RARCH_LOG("Environ CONTENT_DIRECTORY: \"%s\".\n", g_settings.content_directory);
|
g_settings.content_directory : NULL;
|
||||||
|
RARCH_LOG("Environ CONTENT_DIRECTORY: \"%s\".\n",
|
||||||
|
g_settings.content_directory);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO:
|
case RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO:
|
||||||
{
|
{
|
||||||
RARCH_LOG("Environ SET_SYSTEM_AV_INFO.\n");
|
RARCH_LOG("Environ SET_SYSTEM_AV_INFO.\n");
|
||||||
return driver_update_system_av_info((const struct retro_system_av_info*)data);
|
return driver_update_system_av_info(
|
||||||
|
(const struct retro_system_av_info*)data);
|
||||||
}
|
}
|
||||||
|
|
||||||
case RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO:
|
case RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO:
|
||||||
{
|
{
|
||||||
RARCH_LOG("Environ SET_SUBSYSTEM_INFO.\n");
|
RARCH_LOG("Environ SET_SUBSYSTEM_INFO.\n");
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
const struct retro_subsystem_info *info = (const struct retro_subsystem_info*)data;
|
const struct retro_subsystem_info *info =
|
||||||
|
(const struct retro_subsystem_info*)data;
|
||||||
|
|
||||||
for (i = 0; info[i].ident; i++)
|
for (i = 0; info[i].ident; i++)
|
||||||
{
|
{
|
||||||
RARCH_LOG("Special game type: %s\n", info[i].desc);
|
RARCH_LOG("Special game type: %s\n", info[i].desc);
|
||||||
@ -892,16 +950,20 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
for (j = 0; j < info[i].num_roms; j++)
|
for (j = 0; j < info[i].num_roms; j++)
|
||||||
{
|
{
|
||||||
RARCH_LOG(" %s (%s)\n",
|
RARCH_LOG(" %s (%s)\n",
|
||||||
info[i].roms[j].desc, info[i].roms[j].required ? "required" : "optional");
|
info[i].roms[j].desc, info[i].roms[j].required ?
|
||||||
|
"required" : "optional");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(g_extern.system.special);
|
free(g_extern.system.special);
|
||||||
g_extern.system.special = (struct retro_subsystem_info*)calloc(i, sizeof(*g_extern.system.special));
|
g_extern.system.special = (struct retro_subsystem_info*)
|
||||||
|
calloc(i, sizeof(*g_extern.system.special));
|
||||||
|
|
||||||
if (!g_extern.system.special)
|
if (!g_extern.system.special)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
memcpy(g_extern.system.special, info, i * sizeof(*g_extern.system.special));
|
memcpy(g_extern.system.special, info,
|
||||||
|
i * sizeof(*g_extern.system.special));
|
||||||
g_extern.system.num_special = i;
|
g_extern.system.num_special = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -910,20 +972,25 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
{
|
{
|
||||||
RARCH_LOG("Environ SET_CONTROLLER_INFO.\n");
|
RARCH_LOG("Environ SET_CONTROLLER_INFO.\n");
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
const struct retro_controller_info *info = (const struct retro_controller_info*)data;
|
const struct retro_controller_info *info =
|
||||||
|
(const struct retro_controller_info*)data;
|
||||||
|
|
||||||
for (i = 0; info[i].types; i++)
|
for (i = 0; info[i].types; i++)
|
||||||
{
|
{
|
||||||
RARCH_LOG("Controller port: %u\n", i + 1);
|
RARCH_LOG("Controller port: %u\n", i + 1);
|
||||||
for (j = 0; j < info[i].num_types; j++)
|
for (j = 0; j < info[i].num_types; j++)
|
||||||
RARCH_LOG(" %s (ID: %u)\n", info[i].types[j].desc, info[i].types[j].id);
|
RARCH_LOG(" %s (ID: %u)\n", info[i].types[j].desc,
|
||||||
|
info[i].types[j].id);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(g_extern.system.ports);
|
free(g_extern.system.ports);
|
||||||
g_extern.system.ports = (struct retro_controller_info*)calloc(i, sizeof(*g_extern.system.ports));
|
g_extern.system.ports = (struct retro_controller_info*)
|
||||||
|
calloc(i, sizeof(*g_extern.system.ports));
|
||||||
if (!g_extern.system.ports)
|
if (!g_extern.system.ports)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
memcpy(g_extern.system.ports, info, i * sizeof(*g_extern.system.ports));
|
memcpy(g_extern.system.ports, info,
|
||||||
|
i * sizeof(*g_extern.system.ports));
|
||||||
g_extern.system.num_ports = i;
|
g_extern.system.num_ports = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -931,10 +998,12 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
case RETRO_ENVIRONMENT_SET_GEOMETRY:
|
case RETRO_ENVIRONMENT_SET_GEOMETRY:
|
||||||
{
|
{
|
||||||
RARCH_LOG("Environ SET_GEOMETRY.\n");
|
RARCH_LOG("Environ SET_GEOMETRY.\n");
|
||||||
const struct retro_game_geometry *in_geom = (const struct retro_game_geometry*)data;
|
const struct retro_game_geometry *in_geom =
|
||||||
|
(const struct retro_game_geometry*)data;
|
||||||
struct retro_game_geometry *geom = &g_extern.system.av_info.geometry;
|
struct retro_game_geometry *geom = &g_extern.system.av_info.geometry;
|
||||||
|
|
||||||
// Can potentially be called every frame, don't do anything unless required.
|
/* Can potentially be called every frame,
|
||||||
|
* don't do anything unless required. */
|
||||||
if (geom->base_width != in_geom->base_width ||
|
if (geom->base_width != in_geom->base_width ||
|
||||||
geom->base_height != in_geom->base_height ||
|
geom->base_height != in_geom->base_height ||
|
||||||
geom->aspect_ratio != in_geom->aspect_ratio)
|
geom->aspect_ratio != in_geom->aspect_ratio)
|
||||||
@ -945,20 +1014,22 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
RARCH_LOG("SET_GEOMETRY: %ux%u, aspect: %.3f.\n",
|
RARCH_LOG("SET_GEOMETRY: %ux%u, aspect: %.3f.\n",
|
||||||
geom->base_width, geom->base_height, geom->aspect_ratio);
|
geom->base_width, geom->base_height, geom->aspect_ratio);
|
||||||
|
|
||||||
// Forces recomputation of aspect ratios if using core-dependent aspect ratios.
|
/* Forces recomputation of aspect ratios if
|
||||||
|
* using core-dependent aspect ratios. */
|
||||||
rarch_main_command(RARCH_CMD_VIDEO_SET_ASPECT_RATIO);
|
rarch_main_command(RARCH_CMD_VIDEO_SET_ASPECT_RATIO);
|
||||||
|
|
||||||
// TODO: Figure out what to do, if anything, with recording.
|
/* TODO: Figure out what to do, if anything, with recording. */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private extensions for internal use, not part of libretro API.
|
/* Private extensions for internal use, not part of libretro API. */
|
||||||
case RETRO_ENVIRONMENT_SET_LIBRETRO_PATH:
|
case RETRO_ENVIRONMENT_SET_LIBRETRO_PATH:
|
||||||
RARCH_LOG("Environ (Private) SET_LIBRETRO_PATH.\n");
|
RARCH_LOG("Environ (Private) SET_LIBRETRO_PATH.\n");
|
||||||
|
|
||||||
if (path_file_exists((const char*)data))
|
if (path_file_exists((const char*)data))
|
||||||
strlcpy(g_settings.libretro, (const char*)data, sizeof(g_settings.libretro));
|
strlcpy(g_settings.libretro, (const char*)data,
|
||||||
|
sizeof(g_settings.libretro));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
@ -967,7 +1038,8 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
|||||||
case RETRO_ENVIRONMENT_EXEC_ESCAPE:
|
case RETRO_ENVIRONMENT_EXEC_ESCAPE:
|
||||||
|
|
||||||
if (data)
|
if (data)
|
||||||
strlcpy(g_extern.fullpath, (const char*)data, sizeof(g_extern.fullpath));
|
strlcpy(g_extern.fullpath, (const char*)data,
|
||||||
|
sizeof(g_extern.fullpath));
|
||||||
else
|
else
|
||||||
*g_extern.fullpath = '\0';
|
*g_extern.fullpath = '\0';
|
||||||
|
|
||||||
|
53
dynamic.h
53
dynamic.h
@ -34,67 +34,93 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void init_libretro_sym(bool dummy);
|
void init_libretro_sym(bool dummy);
|
||||||
|
|
||||||
void uninit_libretro_sym(void);
|
void uninit_libretro_sym(void);
|
||||||
|
|
||||||
typedef void *dylib_t;
|
typedef void *dylib_t;
|
||||||
|
|
||||||
#ifdef NEED_DYNAMIC
|
#ifdef NEED_DYNAMIC
|
||||||
typedef void (*function_t)(void);
|
typedef void (*function_t)(void);
|
||||||
|
|
||||||
dylib_t dylib_load(const char *path);
|
dylib_t dylib_load(const char *path);
|
||||||
|
|
||||||
void dylib_close(dylib_t lib);
|
void dylib_close(dylib_t lib);
|
||||||
|
|
||||||
function_t dylib_proc(dylib_t lib, const char *proc);
|
function_t dylib_proc(dylib_t lib, const char *proc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Sets environment callback in order to get statically known information from it.
|
/* Sets environment callback in order to get statically known
|
||||||
// Fetched via environment callbacks instead of retro_get_system_info(), as this info
|
* information from it.
|
||||||
// is part of extensions.
|
*
|
||||||
// Should only be called once right after core load to avoid overwriting
|
* Fetched via environment callbacks instead of
|
||||||
// the "real" environ callback.
|
* retro_get_system_info(), as this info is part of extensions.
|
||||||
//
|
*
|
||||||
// For statically linked cores, pass retro_set_environment as argument.
|
* Should only be called once right after core load to
|
||||||
|
* avoid overwriting the "real" environ callback.
|
||||||
|
*
|
||||||
|
* For statically linked cores, pass retro_set_environment as argument.
|
||||||
|
*/
|
||||||
void libretro_get_environment_info(void (*)(retro_environment_t), bool *load_no_content);
|
void libretro_get_environment_info(void (*)(retro_environment_t), bool *load_no_content);
|
||||||
|
|
||||||
#ifdef HAVE_DYNAMIC
|
#ifdef HAVE_DYNAMIC
|
||||||
// Gets system info from an arbitrary lib.
|
/* Gets system info from an arbitrary lib.
|
||||||
// The struct returned must be freed as strings are allocated dynamically.
|
* The struct returned must be freed as strings are allocated dynamically. */
|
||||||
bool libretro_get_system_info(const char *path, struct retro_system_info *info, bool *load_no_content);
|
bool libretro_get_system_info(const char *path, struct retro_system_info *info, bool *load_no_content);
|
||||||
|
|
||||||
void libretro_free_system_info(struct retro_system_info *info);
|
void libretro_free_system_info(struct retro_system_info *info);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Transforms a library id to a name suitable as a pathname.
|
/* Transforms a library id to a name suitable as a pathname. */
|
||||||
void libretro_get_current_core_pathname(char *name, size_t size);
|
void libretro_get_current_core_pathname(char *name, size_t size);
|
||||||
|
|
||||||
const struct retro_subsystem_info *libretro_find_subsystem_info(const struct retro_subsystem_info *info, unsigned num_info, const char *ident);
|
const struct retro_subsystem_info *libretro_find_subsystem_info(
|
||||||
const struct retro_controller_description *libretro_find_controller_description(const struct retro_controller_info *info, unsigned id);
|
const struct retro_subsystem_info *info,
|
||||||
|
unsigned num_info, const char *ident);
|
||||||
|
|
||||||
|
const struct retro_controller_description *
|
||||||
|
libretro_find_controller_description(
|
||||||
|
const struct retro_controller_info *info, unsigned id);
|
||||||
|
|
||||||
extern void (*pretro_init)(void);
|
extern void (*pretro_init)(void);
|
||||||
|
|
||||||
extern void (*pretro_deinit)(void);
|
extern void (*pretro_deinit)(void);
|
||||||
|
|
||||||
extern unsigned (*pretro_api_version)(void);
|
extern unsigned (*pretro_api_version)(void);
|
||||||
|
|
||||||
extern void (*pretro_get_system_info)(struct retro_system_info*);
|
extern void (*pretro_get_system_info)(struct retro_system_info*);
|
||||||
|
|
||||||
extern void (*pretro_get_system_av_info)(struct retro_system_av_info*);
|
extern void (*pretro_get_system_av_info)(struct retro_system_av_info*);
|
||||||
|
|
||||||
extern void (*pretro_set_environment)(retro_environment_t);
|
extern void (*pretro_set_environment)(retro_environment_t);
|
||||||
|
|
||||||
extern void (*pretro_set_video_refresh)(retro_video_refresh_t);
|
extern void (*pretro_set_video_refresh)(retro_video_refresh_t);
|
||||||
|
|
||||||
extern void (*pretro_set_audio_sample)(retro_audio_sample_t);
|
extern void (*pretro_set_audio_sample)(retro_audio_sample_t);
|
||||||
|
|
||||||
extern void (*pretro_set_audio_sample_batch)(retro_audio_sample_batch_t);
|
extern void (*pretro_set_audio_sample_batch)(retro_audio_sample_batch_t);
|
||||||
|
|
||||||
extern void (*pretro_set_input_poll)(retro_input_poll_t);
|
extern void (*pretro_set_input_poll)(retro_input_poll_t);
|
||||||
|
|
||||||
extern void (*pretro_set_input_state)(retro_input_state_t);
|
extern void (*pretro_set_input_state)(retro_input_state_t);
|
||||||
|
|
||||||
extern void (*pretro_set_controller_port_device)(unsigned, unsigned);
|
extern void (*pretro_set_controller_port_device)(unsigned, unsigned);
|
||||||
|
|
||||||
extern void (*pretro_reset)(void);
|
extern void (*pretro_reset)(void);
|
||||||
|
|
||||||
extern void (*pretro_run)(void);
|
extern void (*pretro_run)(void);
|
||||||
|
|
||||||
extern size_t (*pretro_serialize_size)(void);
|
extern size_t (*pretro_serialize_size)(void);
|
||||||
|
|
||||||
extern bool (*pretro_serialize)(void*, size_t);
|
extern bool (*pretro_serialize)(void*, size_t);
|
||||||
|
|
||||||
extern bool (*pretro_unserialize)(const void*, size_t);
|
extern bool (*pretro_unserialize)(const void*, size_t);
|
||||||
|
|
||||||
extern void (*pretro_cheat_reset)(void);
|
extern void (*pretro_cheat_reset)(void);
|
||||||
|
|
||||||
extern void (*pretro_cheat_set)(unsigned, bool, const char*);
|
extern void (*pretro_cheat_set)(unsigned, bool, const char*);
|
||||||
|
|
||||||
extern bool (*pretro_load_game)(const struct retro_game_info*);
|
extern bool (*pretro_load_game)(const struct retro_game_info*);
|
||||||
|
|
||||||
extern bool (*pretro_load_game_special)(unsigned, const struct retro_game_info*, size_t);
|
extern bool (*pretro_load_game_special)(unsigned, const struct retro_game_info*, size_t);
|
||||||
|
|
||||||
extern void (*pretro_unload_game)(void);
|
extern void (*pretro_unload_game)(void);
|
||||||
@ -102,6 +128,7 @@ extern void (*pretro_unload_game)(void);
|
|||||||
extern unsigned (*pretro_get_region)(void);
|
extern unsigned (*pretro_get_region)(void);
|
||||||
|
|
||||||
extern void *(*pretro_get_memory_data)(unsigned);
|
extern void *(*pretro_get_memory_data)(unsigned);
|
||||||
|
|
||||||
extern size_t (*pretro_get_memory_size)(unsigned);
|
extern size_t (*pretro_get_memory_size)(unsigned);
|
||||||
|
|
||||||
extern bool rarch_environment_cb(unsigned cmd, void *data);
|
extern bool rarch_environment_cb(unsigned cmd, void *data);
|
||||||
|
@ -38,23 +38,26 @@ unsigned libretro_dummy_retro_api_version(void)
|
|||||||
return RETRO_API_VERSION;
|
return RETRO_API_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
void libretro_dummy_retro_set_controller_port_device(unsigned port, unsigned device)
|
void libretro_dummy_retro_set_controller_port_device(
|
||||||
|
unsigned port, unsigned device)
|
||||||
{
|
{
|
||||||
(void)port;
|
(void)port;
|
||||||
(void)device;
|
(void)device;
|
||||||
}
|
}
|
||||||
|
|
||||||
void libretro_dummy_retro_get_system_info(struct retro_system_info *info)
|
void libretro_dummy_retro_get_system_info(
|
||||||
|
struct retro_system_info *info)
|
||||||
{
|
{
|
||||||
memset(info, 0, sizeof(*info));
|
memset(info, 0, sizeof(*info));
|
||||||
info->library_name = "No Core";
|
info->library_name = "No Core";
|
||||||
info->library_version = "";
|
info->library_version = "";
|
||||||
info->need_fullpath = false;
|
info->need_fullpath = false;
|
||||||
info->valid_extensions = ""; // Nothing.
|
info->valid_extensions = ""; /* Nothing. */
|
||||||
}
|
}
|
||||||
|
|
||||||
// Doesn't really matter, but need something sane.
|
/* Doesn't really matter, but need something sane. */
|
||||||
void libretro_dummy_retro_get_system_av_info(struct retro_system_av_info *info)
|
void libretro_dummy_retro_get_system_av_info(
|
||||||
|
struct retro_system_av_info *info)
|
||||||
{
|
{
|
||||||
info->timing.fps = 60.0;
|
info->timing.fps = 60.0;
|
||||||
info->timing.sample_rate = 30000.0;
|
info->timing.sample_rate = 30000.0;
|
||||||
@ -77,7 +80,7 @@ void libretro_dummy_retro_set_environment(retro_environment_t cb)
|
|||||||
{
|
{
|
||||||
dummy_environ_cb = cb;
|
dummy_environ_cb = cb;
|
||||||
|
|
||||||
// We know it's supported, it's internal to RetroArch.
|
/* We know it's supported, it's internal to RetroArch. */
|
||||||
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565;
|
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565;
|
||||||
dummy_environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt);
|
dummy_environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt);
|
||||||
}
|
}
|
||||||
@ -87,7 +90,8 @@ void libretro_dummy_retro_set_audio_sample(retro_audio_sample_t cb)
|
|||||||
dummy_audio_cb = cb;
|
dummy_audio_cb = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void libretro_dummy_retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)
|
void libretro_dummy_retro_set_audio_sample_batch(
|
||||||
|
retro_audio_sample_batch_t cb)
|
||||||
{
|
{
|
||||||
dummy_audio_batch_cb = cb;
|
dummy_audio_batch_cb = cb;
|
||||||
}
|
}
|
||||||
@ -119,7 +123,7 @@ void libretro_dummy_retro_run(void)
|
|||||||
dummy_video_cb(frame_buf, 320, 240, 640);
|
dummy_video_cb(frame_buf, 320, 240, 640);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should never be called, it's only used as a placeholder.
|
/* This should never be called, it's only used as a placeholder. */
|
||||||
bool libretro_dummy_retro_load_game(const struct retro_game_info *info)
|
bool libretro_dummy_retro_load_game(const struct retro_game_info *info)
|
||||||
{
|
{
|
||||||
(void)info;
|
(void)info;
|
||||||
@ -134,7 +138,8 @@ unsigned libretro_dummy_retro_get_region(void)
|
|||||||
return RETRO_REGION_NTSC;
|
return RETRO_REGION_NTSC;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool libretro_dummy_retro_load_game_special(unsigned type, const struct retro_game_info *info, size_t num)
|
bool libretro_dummy_retro_load_game_special(unsigned type,
|
||||||
|
const struct retro_game_info *info, size_t num)
|
||||||
{
|
{
|
||||||
(void)type;
|
(void)type;
|
||||||
(void)info;
|
(void)info;
|
||||||
@ -154,7 +159,8 @@ bool libretro_dummy_retro_serialize(void *data, size_t size)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool libretro_dummy_retro_unserialize(const void *data, size_t size)
|
bool libretro_dummy_retro_unserialize(const void *data,
|
||||||
|
size_t size)
|
||||||
{
|
{
|
||||||
(void)data;
|
(void)data;
|
||||||
(void)size;
|
(void)size;
|
||||||
@ -176,7 +182,8 @@ size_t libretro_dummy_retro_get_memory_size(unsigned id)
|
|||||||
void libretro_dummy_retro_cheat_reset(void)
|
void libretro_dummy_retro_cheat_reset(void)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void libretro_dummy_retro_cheat_set(unsigned index, bool enabled, const char *code)
|
void libretro_dummy_retro_cheat_set(unsigned index,
|
||||||
|
bool enabled, const char *code)
|
||||||
{
|
{
|
||||||
(void)index;
|
(void)index;
|
||||||
(void)enabled;
|
(void)enabled;
|
||||||
|
@ -22,37 +22,54 @@
|
|||||||
#include "libretro.h"
|
#include "libretro.h"
|
||||||
|
|
||||||
void libretro_dummy_retro_init(void);
|
void libretro_dummy_retro_init(void);
|
||||||
|
|
||||||
void libretro_dummy_retro_deinit(void);
|
void libretro_dummy_retro_deinit(void);
|
||||||
|
|
||||||
unsigned libretro_dummy_retro_api_version(void);
|
unsigned libretro_dummy_retro_api_version(void);
|
||||||
|
|
||||||
void libretro_dummy_retro_get_system_info(struct retro_system_info *info);
|
void libretro_dummy_retro_get_system_info(struct retro_system_info *info);
|
||||||
|
|
||||||
void libretro_dummy_retro_get_system_av_info(struct retro_system_av_info *info);
|
void libretro_dummy_retro_get_system_av_info(struct retro_system_av_info *info);
|
||||||
|
|
||||||
void libretro_dummy_retro_set_environment(retro_environment_t cb);
|
void libretro_dummy_retro_set_environment(retro_environment_t cb);
|
||||||
|
|
||||||
void libretro_dummy_retro_set_video_refresh(retro_video_refresh_t cb);
|
void libretro_dummy_retro_set_video_refresh(retro_video_refresh_t cb);
|
||||||
|
|
||||||
void libretro_dummy_retro_set_audio_sample(retro_audio_sample_t cb);
|
void libretro_dummy_retro_set_audio_sample(retro_audio_sample_t cb);
|
||||||
|
|
||||||
void libretro_dummy_retro_set_audio_sample_batch(retro_audio_sample_batch_t cb);
|
void libretro_dummy_retro_set_audio_sample_batch(retro_audio_sample_batch_t cb);
|
||||||
|
|
||||||
void libretro_dummy_retro_set_input_poll(retro_input_poll_t cb);
|
void libretro_dummy_retro_set_input_poll(retro_input_poll_t cb);
|
||||||
|
|
||||||
void libretro_dummy_retro_set_input_state(retro_input_state_t cb);
|
void libretro_dummy_retro_set_input_state(retro_input_state_t cb);
|
||||||
|
|
||||||
void libretro_dummy_retro_set_controller_port_device(unsigned port, unsigned device);
|
void libretro_dummy_retro_set_controller_port_device(unsigned port, unsigned device);
|
||||||
|
|
||||||
void libretro_dummy_retro_reset(void);
|
void libretro_dummy_retro_reset(void);
|
||||||
|
|
||||||
void libretro_dummy_retro_run(void);
|
void libretro_dummy_retro_run(void);
|
||||||
|
|
||||||
size_t libretro_dummy_retro_serialize_size(void);
|
size_t libretro_dummy_retro_serialize_size(void);
|
||||||
|
|
||||||
bool libretro_dummy_retro_serialize(void *data, size_t size);
|
bool libretro_dummy_retro_serialize(void *data, size_t size);
|
||||||
|
|
||||||
bool libretro_dummy_retro_unserialize(const void *data, size_t size);
|
bool libretro_dummy_retro_unserialize(const void *data, size_t size);
|
||||||
|
|
||||||
void libretro_dummy_retro_cheat_reset(void);
|
void libretro_dummy_retro_cheat_reset(void);
|
||||||
|
|
||||||
void libretro_dummy_retro_cheat_set(unsigned index, bool enabled, const char *code);
|
void libretro_dummy_retro_cheat_set(unsigned index, bool enabled, const char *code);
|
||||||
|
|
||||||
bool libretro_dummy_retro_load_game(const struct retro_game_info *game);
|
bool libretro_dummy_retro_load_game(const struct retro_game_info *game);
|
||||||
|
|
||||||
bool libretro_dummy_retro_load_game_special(unsigned game_type,
|
bool libretro_dummy_retro_load_game_special(unsigned game_type,
|
||||||
const struct retro_game_info *info, size_t num_info);
|
const struct retro_game_info *info, size_t num_info);
|
||||||
|
|
||||||
void libretro_dummy_retro_unload_game(void);
|
void libretro_dummy_retro_unload_game(void);
|
||||||
|
|
||||||
unsigned libretro_dummy_retro_get_region(void);
|
unsigned libretro_dummy_retro_get_region(void);
|
||||||
|
|
||||||
void *libretro_dummy_retro_get_memory_data(unsigned id);
|
void *libretro_dummy_retro_get_memory_data(unsigned id);
|
||||||
|
|
||||||
size_t libretro_dummy_retro_get_memory_size(unsigned id);
|
size_t libretro_dummy_retro_get_memory_size(unsigned id);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
127
file_path.c
127
file_path.c
@ -28,7 +28,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP)
|
#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP)
|
||||||
#include <unistd.h> //stat() is defined here
|
#include <unistd.h> /* stat() is defined here */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__CELLOS_LV2__)
|
#if defined(__CELLOS_LV2__)
|
||||||
@ -60,7 +60,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Dump stuff to file.
|
/* Dump to file. */
|
||||||
bool write_file(const char *path, const void *data, size_t size)
|
bool write_file(const char *path, const void *data, size_t size)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
@ -73,7 +73,7 @@ bool write_file(const char *path, const void *data, size_t size)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic file loader.
|
/* Generic file loader. */
|
||||||
long read_file(const char *path, void **buf)
|
long read_file(const char *path, void **buf)
|
||||||
{
|
{
|
||||||
long rc = 0, len = 0;
|
long rc = 0, len = 0;
|
||||||
@ -97,8 +97,9 @@ long read_file(const char *path, void **buf)
|
|||||||
RARCH_WARN("Didn't read whole file.\n");
|
RARCH_WARN("Didn't read whole file.\n");
|
||||||
|
|
||||||
*buf = rom_buf;
|
*buf = rom_buf;
|
||||||
// Allow for easy reading of strings to be safe.
|
|
||||||
// Will only work with sane character formatting (Unix).
|
/* Allow for easy reading of strings to be safe.
|
||||||
|
* Will only work with sane character formatting (Unix). */
|
||||||
((char*)rom_buf)[len] = '\0';
|
((char*)rom_buf)[len] = '\0';
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return rc;
|
return rc;
|
||||||
@ -111,7 +112,7 @@ error:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reads file content as one string.
|
/* Reads file content as one string. */
|
||||||
bool read_file_string(const char *path, char **buf)
|
bool read_file_string(const char *path, char **buf)
|
||||||
{
|
{
|
||||||
*buf = NULL;
|
*buf = NULL;
|
||||||
@ -122,10 +123,13 @@ bool read_file_string(const char *path, char **buf)
|
|||||||
if (!file)
|
if (!file)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
// ftell with "r" can be troublesome ...
|
/* ftell with "r" can be troublesome ...
|
||||||
// Haven't run into issues yet though.
|
* Haven't run into issues yet though. */
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
len = ftell(file) + 2; // Takes account of being able to read in EOF and '\0' at end.
|
|
||||||
|
/* Takes account of being able to read
|
||||||
|
* in EOF and '\0' at end. */
|
||||||
|
len = ftell(file) + 2;
|
||||||
rewind(file);
|
rewind(file);
|
||||||
|
|
||||||
*buf = (char*)calloc(len, sizeof(char));
|
*buf = (char*)calloc(len, sizeof(char));
|
||||||
@ -136,7 +140,8 @@ bool read_file_string(const char *path, char **buf)
|
|||||||
|
|
||||||
while (ptr && !feof(file))
|
while (ptr && !feof(file))
|
||||||
{
|
{
|
||||||
size_t bufsize = (size_t)(((ptrdiff_t)*buf + (ptrdiff_t)len) - (ptrdiff_t)ptr);
|
size_t bufsize = (size_t)(((ptrdiff_t)*buf +
|
||||||
|
(ptrdiff_t)len) - (ptrdiff_t)ptr);
|
||||||
fgets(ptr, bufsize, file);
|
fgets(ptr, bufsize, file);
|
||||||
|
|
||||||
ptr += strlen(ptr);
|
ptr += strlen(ptr);
|
||||||
@ -198,7 +203,8 @@ struct string_list *string_list_new(void)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool string_list_append(struct string_list *list, const char *elem, union string_list_elem_attr attr)
|
bool string_list_append(struct string_list *list, const char *elem,
|
||||||
|
union string_list_elem_attr attr)
|
||||||
{
|
{
|
||||||
if (list->size >= list->cap &&
|
if (list->size >= list->cap &&
|
||||||
!string_list_capacity(list, list->cap * 2))
|
!string_list_capacity(list, list->cap * 2))
|
||||||
@ -221,7 +227,8 @@ void string_list_set(struct string_list *list, unsigned index, const char *str)
|
|||||||
rarch_assert(list->elems[index].data = strdup(str));
|
rarch_assert(list->elems[index].data = strdup(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
void string_list_join_concat(char *buffer, size_t size, const struct string_list *list, const char *sep)
|
void string_list_join_concat(char *buffer, size_t size,
|
||||||
|
const struct string_list *list, const char *sep)
|
||||||
{
|
{
|
||||||
size_t len = strlen(buffer);
|
size_t len = strlen(buffer);
|
||||||
rarch_assert(len < size);
|
rarch_assert(len < size);
|
||||||
@ -287,7 +294,8 @@ bool string_list_find_elem(const struct string_list *list, const char *elem)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool string_list_find_elem_prefix(const struct string_list *list, const char *prefix, const char *elem)
|
bool string_list_find_elem_prefix(const struct string_list *list,
|
||||||
|
const char *prefix, const char *elem)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
if (!list)
|
if (!list)
|
||||||
@ -337,7 +345,7 @@ static int qstrcmp_dir(const void *a_, const void *b_)
|
|||||||
int a_dir = a->attr.b;
|
int a_dir = a->attr.b;
|
||||||
int b_dir = b->attr.b;
|
int b_dir = b->attr.b;
|
||||||
|
|
||||||
// Sort directories before files.
|
/* Sort directories before files. */
|
||||||
if (a_dir != b_dir)
|
if (a_dir != b_dir)
|
||||||
return b_dir - a_dir;
|
return b_dir - a_dir;
|
||||||
return strcasecmp(a->data, b->data);
|
return strcasecmp(a->data, b->data);
|
||||||
@ -352,8 +360,10 @@ void dir_list_sort(struct string_list *list, bool dir_first)
|
|||||||
dir_first ? qstrcmp_dir : qstrcmp_plain);
|
dir_first ? qstrcmp_dir : qstrcmp_plain);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32 // Because the API is just fucked up ...
|
#ifdef _WIN32
|
||||||
struct string_list *dir_list_new(const char *dir, const char *ext, bool include_dirs)
|
|
||||||
|
struct string_list *dir_list_new(const char *dir,
|
||||||
|
const char *ext, bool include_dirs)
|
||||||
{
|
{
|
||||||
struct string_list *list = string_list_new();
|
struct string_list *list = string_list_new();
|
||||||
if (!list)
|
if (!list)
|
||||||
@ -413,23 +423,25 @@ error:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static bool dirent_is_directory(const char *path, const struct dirent *entry)
|
static bool dirent_is_directory(const char *path,
|
||||||
|
const struct dirent *entry)
|
||||||
{
|
{
|
||||||
#if defined(PSP)
|
#if defined(PSP)
|
||||||
return (entry->d_stat.st_attr & FIO_SO_IFDIR) == FIO_SO_IFDIR;
|
return (entry->d_stat.st_attr & FIO_SO_IFDIR) == FIO_SO_IFDIR;
|
||||||
#elif defined(DT_DIR)
|
#elif defined(DT_DIR)
|
||||||
if (entry->d_type == DT_DIR)
|
if (entry->d_type == DT_DIR)
|
||||||
return true;
|
return true;
|
||||||
else if (entry->d_type == DT_UNKNOWN // This can happen on certain file systems.
|
else if (entry->d_type == DT_UNKNOWN /* This can happen on certain file systems. */
|
||||||
|| entry->d_type == DT_LNK)
|
|| entry->d_type == DT_LNK)
|
||||||
return path_is_directory(path);
|
return path_is_directory(path);
|
||||||
return false;
|
return false;
|
||||||
#else // dirent struct doesn't have d_type, do it the slow way ...
|
#else /* dirent struct doesn't have d_type, do it the slow way ... */
|
||||||
return path_is_directory(path);
|
return path_is_directory(path);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string_list *dir_list_new(const char *dir, const char *ext, bool include_dirs)
|
struct string_list *dir_list_new(const char *dir,
|
||||||
|
const char *ext, bool include_dirs)
|
||||||
{
|
{
|
||||||
DIR *directory = NULL;
|
DIR *directory = NULL;
|
||||||
const struct dirent *entry = NULL;
|
const struct dirent *entry = NULL;
|
||||||
@ -463,7 +475,8 @@ struct string_list *dir_list_new(const char *dir, const char *ext, bool include_
|
|||||||
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
|
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!is_dir && ext_list && !string_list_find_elem_prefix(ext_list, ".", file_ext))
|
if (!is_dir && ext_list
|
||||||
|
&& !string_list_find_elem_prefix(ext_list, ".", file_ext))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
attr.b = is_dir;
|
attr.b = is_dir;
|
||||||
@ -540,12 +553,14 @@ bool path_file_exists(const char *path)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname(char *out_path, const char *in_path, const char *replace, size_t size)
|
void fill_pathname(char *out_path, const char *in_path,
|
||||||
|
const char *replace, size_t size)
|
||||||
{
|
{
|
||||||
char tmp_path[PATH_MAX];
|
char tmp_path[PATH_MAX];
|
||||||
char *tok;
|
char *tok;
|
||||||
|
|
||||||
rarch_assert(strlcpy(tmp_path, in_path, sizeof(tmp_path)) < sizeof(tmp_path));
|
rarch_assert(strlcpy(tmp_path, in_path,
|
||||||
|
sizeof(tmp_path)) < sizeof(tmp_path));
|
||||||
if ((tok = (char*)strrchr(path_basename(tmp_path), '.')))
|
if ((tok = (char*)strrchr(path_basename(tmp_path), '.')))
|
||||||
*tok = '\0';
|
*tok = '\0';
|
||||||
|
|
||||||
@ -553,7 +568,8 @@ void fill_pathname(char *out_path, const char *in_path, const char *replace, siz
|
|||||||
rarch_assert(strlcat(out_path, replace, size) < size);
|
rarch_assert(strlcat(out_path, replace, size) < size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_noext(char *out_path, const char *in_path, const char *replace, size_t size)
|
void fill_pathname_noext(char *out_path, const char *in_path,
|
||||||
|
const char *replace, size_t size)
|
||||||
{
|
{
|
||||||
rarch_assert(strlcpy(out_path, in_path, size) < size);
|
rarch_assert(strlcpy(out_path, in_path, size) < size);
|
||||||
rarch_assert(strlcat(out_path, replace, size) < size);
|
rarch_assert(strlcat(out_path, replace, size) < size);
|
||||||
@ -572,8 +588,8 @@ static char *find_last_slash(const char *str)
|
|||||||
return (char*)slash;
|
return (char*)slash;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assumes path is a directory. Appends a slash
|
/* Assumes path is a directory. Appends a slash
|
||||||
// if not already there.
|
* if not already there. */
|
||||||
void fill_pathname_slash(char *path, size_t size)
|
void fill_pathname_slash(char *path, size_t size)
|
||||||
{
|
{
|
||||||
size_t path_len = strlen(path);
|
size_t path_len = strlen(path);
|
||||||
@ -589,7 +605,8 @@ void fill_pathname_slash(char *path, size_t size)
|
|||||||
rarch_assert(strlcat(path, path_default_slash(), size) < size);
|
rarch_assert(strlcat(path, path_default_slash(), size) < size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_dir(char *in_dir, const char *in_basename, const char *replace, size_t size)
|
void fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||||
|
const char *replace, size_t size)
|
||||||
{
|
{
|
||||||
fill_pathname_slash(in_dir, size);
|
fill_pathname_slash(in_dir, size);
|
||||||
const char *base = path_basename(in_basename);
|
const char *base = path_basename(in_basename);
|
||||||
@ -609,24 +626,28 @@ void fill_pathname_base(char *out, const char *in_path, size_t size)
|
|||||||
rarch_assert(strlcpy(out, ptr, size) < size);
|
rarch_assert(strlcpy(out, ptr, size) < size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_basedir(char *out_dir, const char *in_path, size_t size)
|
void fill_pathname_basedir(char *out_dir,
|
||||||
|
const char *in_path, size_t size)
|
||||||
{
|
{
|
||||||
rarch_assert(strlcpy(out_dir, in_path, size) < size);
|
rarch_assert(strlcpy(out_dir, in_path, size) < size);
|
||||||
path_basedir(out_dir);
|
path_basedir(out_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_parent_dir(char *out_dir, const char *in_dir, size_t size)
|
void fill_pathname_parent_dir(char *out_dir,
|
||||||
|
const char *in_dir, size_t size)
|
||||||
{
|
{
|
||||||
rarch_assert(strlcpy(out_dir, in_dir, size) < size);
|
rarch_assert(strlcpy(out_dir, in_dir, size) < size);
|
||||||
path_parent_dir(out_dir);
|
path_parent_dir(out_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_dated_filename(char *out_filename, const char *ext, size_t size)
|
void fill_dated_filename(char *out_filename,
|
||||||
|
const char *ext, size_t size)
|
||||||
{
|
{
|
||||||
time_t cur_time;
|
time_t cur_time;
|
||||||
time(&cur_time);
|
time(&cur_time);
|
||||||
|
|
||||||
strftime(out_filename, size, "RetroArch-%m%d-%H%M%S.", localtime(&cur_time));
|
strftime(out_filename, size,
|
||||||
|
"RetroArch-%m%d-%H%M%S.", localtime(&cur_time));
|
||||||
strlcat(out_filename, ext, size);
|
strlcat(out_filename, ext, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -664,7 +685,8 @@ bool path_is_absolute(const char *path)
|
|||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Many roads lead to Rome ...
|
// Many roads lead to Rome ...
|
||||||
return path[0] == '/' || (strstr(path, "\\\\") == path) || strstr(path, ":/") || strstr(path, ":\\") || strstr(path, ":\\\\");
|
return path[0] == '/' || (strstr(path, "\\\\") == path)
|
||||||
|
|| strstr(path, ":/") || strstr(path, ":\\") || strstr(path, ":\\\\");
|
||||||
#else
|
#else
|
||||||
return path[0] == '/';
|
return path[0] == '/';
|
||||||
#endif
|
#endif
|
||||||
@ -681,9 +703,11 @@ void path_resolve_realpath(char *buf, size_t size)
|
|||||||
strlcpy(buf, tmp, size);
|
strlcpy(buf, tmp, size);
|
||||||
#else
|
#else
|
||||||
rarch_assert(size >= PATH_MAX);
|
rarch_assert(size >= PATH_MAX);
|
||||||
// NOTE: realpath() expects at least PATH_MAX bytes in buf.
|
|
||||||
// Technically, PATH_MAX needn't be defined, but we rely on it anyways.
|
/* NOTE: realpath() expects at least PATH_MAX bytes in buf.
|
||||||
// POSIX 2008 can automatically allocate for you, but don't rely on that.
|
* Technically, PATH_MAX needn't be defined, but we rely on it anyways.
|
||||||
|
* POSIX 2008 can automatically allocate for you,
|
||||||
|
* but don't rely on that. */
|
||||||
if (!realpath(tmp, buf))
|
if (!realpath(tmp, buf))
|
||||||
strlcpy(buf, tmp, size);
|
strlcpy(buf, tmp, size);
|
||||||
#endif
|
#endif
|
||||||
@ -704,7 +728,8 @@ static bool path_mkdir_norecurse(const char *dir)
|
|||||||
#else
|
#else
|
||||||
ret = mkdir(dir, 0750);
|
ret = mkdir(dir, 0750);
|
||||||
#endif
|
#endif
|
||||||
if (ret < 0 && errno == EEXIST && path_is_directory(dir)) // Don't treat this as an error.
|
/* Don't treat this as an error. */
|
||||||
|
if (ret < 0 && errno == EEXIST && path_is_directory(dir))
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
RARCH_ERR("mkdir(%s) error: %s.\n", dir, strerror(errno));
|
RARCH_ERR("mkdir(%s) error: %s.\n", dir, strerror(errno));
|
||||||
@ -714,7 +739,8 @@ static bool path_mkdir_norecurse(const char *dir)
|
|||||||
bool path_mkdir(const char *dir)
|
bool path_mkdir(const char *dir)
|
||||||
{
|
{
|
||||||
const char *target = NULL;
|
const char *target = NULL;
|
||||||
char *basedir = strdup(dir); // Use heap. Real chance of stack overflow if we recurse too hard.
|
/* Use heap. Real chance of stack overflow if we recurse too hard. */
|
||||||
|
char *basedir = strdup(dir);
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
if (!basedir)
|
if (!basedir)
|
||||||
@ -750,7 +776,8 @@ end:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_resolve_relative(char *out_path, const char *in_refpath, const char *in_path, size_t size)
|
void fill_pathname_resolve_relative(char *out_path,
|
||||||
|
const char *in_refpath, const char *in_path, size_t size)
|
||||||
{
|
{
|
||||||
if (path_is_absolute(in_path))
|
if (path_is_absolute(in_path))
|
||||||
rarch_assert(strlcpy(out_path, in_path, size) < size);
|
rarch_assert(strlcpy(out_path, in_path, size) < size);
|
||||||
@ -762,7 +789,8 @@ void fill_pathname_resolve_relative(char *out_path, const char *in_refpath, cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_join(char *out_path, const char *dir, const char *path, size_t size)
|
void fill_pathname_join(char *out_path,
|
||||||
|
const char *dir, const char *path, size_t size)
|
||||||
{
|
{
|
||||||
rarch_assert(strlcpy(out_path, dir, size) < size);
|
rarch_assert(strlcpy(out_path, dir, size) < size);
|
||||||
|
|
||||||
@ -772,7 +800,8 @@ void fill_pathname_join(char *out_path, const char *dir, const char *path, size_
|
|||||||
rarch_assert(strlcat(out_path, path, size) < size);
|
rarch_assert(strlcat(out_path, path, size) < size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_expand_special(char *out_path, const char *in_path, size_t size)
|
void fill_pathname_expand_special(char *out_path,
|
||||||
|
const char *in_path, size_t size)
|
||||||
{
|
{
|
||||||
#if !defined(RARCH_CONSOLE)
|
#if !defined(RARCH_CONSOLE)
|
||||||
if (*in_path == '~')
|
if (*in_path == '~')
|
||||||
@ -811,7 +840,8 @@ void fill_pathname_expand_special(char *out_path, const char *in_path, size_t si
|
|||||||
rarch_assert(strlcpy(out_path, in_path, size) < size);
|
rarch_assert(strlcpy(out_path, in_path, size) < size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_abbreviate_special(char *out_path, const char *in_path, size_t size)
|
void fill_pathname_abbreviate_special(char *out_path,
|
||||||
|
const char *in_path, size_t size)
|
||||||
{
|
{
|
||||||
#if !defined(RARCH_CONSOLE)
|
#if !defined(RARCH_CONSOLE)
|
||||||
unsigned i;
|
unsigned i;
|
||||||
@ -821,10 +851,11 @@ void fill_pathname_abbreviate_special(char *out_path, const char *in_path, size_
|
|||||||
fill_pathname_application_path(application_dir, sizeof(application_dir));
|
fill_pathname_application_path(application_dir, sizeof(application_dir));
|
||||||
path_basedir(application_dir);
|
path_basedir(application_dir);
|
||||||
|
|
||||||
// application_dir could be zero-string. Safeguard against this.
|
/* application_dir could be zero-string. Safeguard against this.
|
||||||
|
*
|
||||||
|
* Keep application dir in front of home, moving app dir to a
|
||||||
|
* new location inside home would break otherwise. */
|
||||||
|
|
||||||
// Keep application dir in front of home, moving app dir to a new location inside
|
|
||||||
// home would break otherwise.
|
|
||||||
const char *candidates[3] = { application_dir, home, NULL };
|
const char *candidates[3] = { application_dir, home, NULL };
|
||||||
const char *notations[3] = { ":", "~", NULL };
|
const char *notations[3] = { ":", "~", NULL };
|
||||||
|
|
||||||
@ -846,7 +877,7 @@ void fill_pathname_abbreviate_special(char *out_path, const char *in_path, size_
|
|||||||
size--;
|
size--;
|
||||||
}
|
}
|
||||||
|
|
||||||
break; // Don't allow more abbrevs to take place.
|
break; /* Don't allow more abbrevs to take place. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -894,10 +925,12 @@ void fill_pathname_application_path(char *buf, size_t size)
|
|||||||
*buf = '\0';
|
*buf = '\0';
|
||||||
pid_t pid = getpid();
|
pid_t pid = getpid();
|
||||||
char link_path[PATH_MAX];
|
char link_path[PATH_MAX];
|
||||||
static const char *exts[] = { "exe", "file", "path/a.out" }; // Linux, BSD and Solaris paths. Not standardized.
|
/* Linux, BSD and Solaris paths. Not standardized. */
|
||||||
|
static const char *exts[] = { "exe", "file", "path/a.out" };
|
||||||
for (i = 0; i < ARRAY_SIZE(exts); i++)
|
for (i = 0; i < ARRAY_SIZE(exts); i++)
|
||||||
{
|
{
|
||||||
snprintf(link_path, sizeof(link_path), "/proc/%u/%s", (unsigned)pid, exts[i]);
|
snprintf(link_path, sizeof(link_path), "/proc/%u/%s",
|
||||||
|
(unsigned)pid, exts[i]);
|
||||||
ssize_t ret = readlink(link_path, buf, size - 1);
|
ssize_t ret = readlink(link_path, buf, size - 1);
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
{
|
{
|
||||||
|
@ -40,10 +40,12 @@
|
|||||||
#include "retroarch_logger.h"
|
#include "retroarch_logger.h"
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
// Some platforms do not set this value.
|
/* Some platforms do not set this value.
|
||||||
// Just assume a value. It's usually 4KiB.
|
* Just assume a value. It's usually 4KiB.
|
||||||
// Platforms with a known value (like Win32)
|
* Platforms with a known value (like Win32)
|
||||||
// set this value explicitly in platform specific headers.
|
* set this value explicitly in platform specific headers.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
#ifndef PATH_MAX
|
||||||
#define PATH_MAX 4096
|
#define PATH_MAX 4096
|
||||||
#endif
|
#endif
|
||||||
@ -121,13 +123,15 @@ static inline uint32_t swap_if_big32(uint32_t val)
|
|||||||
{
|
{
|
||||||
if (is_little_endian()) // Little-endian
|
if (is_little_endian()) // Little-endian
|
||||||
return val;
|
return val;
|
||||||
return (val >> 24) | ((val >> 8) & 0xFF00) | ((val << 8) & 0xFF0000) | (val << 24);
|
return (val >> 24) | ((val >> 8) & 0xFF00) |
|
||||||
|
((val << 8) & 0xFF0000) | (val << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t swap_if_little32(uint32_t val)
|
static inline uint32_t swap_if_little32(uint32_t val)
|
||||||
{
|
{
|
||||||
if (is_little_endian())
|
if (is_little_endian())
|
||||||
return (val >> 24) | ((val >> 8) & 0xFF00) | ((val << 8) & 0xFF0000) | (val << 24);
|
return (val >> 24) | ((val >> 8) & 0xFF00) |
|
||||||
|
((val << 8) & 0xFF0000) | (val << 24);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,9 +149,9 @@ static inline uint16_t swap_if_little16(uint16_t val)
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper macros and struct to keep track of many booleans.
|
/* Helper macros and struct to keep track of many booleans.
|
||||||
// To check for multiple bits, use &&, not &.
|
* To check for multiple bits, use &&, not &.
|
||||||
// For OR, | can be used.
|
* For OR, | can be used. */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint32_t data[8];
|
uint32_t data[8];
|
||||||
|
103
rewind.c
103
rewind.c
@ -79,14 +79,21 @@ struct state_manager
|
|||||||
{
|
{
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
uint8_t *head; // Reading and writing is done here.
|
/* Reading and writing is done here here. */
|
||||||
uint8_t *tail; // If head comes close to this, discard a frame.
|
uint8_t *head;
|
||||||
|
/* If head comes close to this, discard a frame. */
|
||||||
|
uint8_t *tail;
|
||||||
|
|
||||||
uint8_t *thisblock;
|
uint8_t *thisblock;
|
||||||
uint8_t *nextblock;
|
uint8_t *nextblock;
|
||||||
|
|
||||||
size_t blocksize; // This one is runded up from reset::blocksize.
|
/* This one is rounded up from reset::blocksize. */
|
||||||
size_t maxcompsize; // size_t + (blocksize + 131071) / 131072 * (blocksize + u16 + u16) + u16 + u32 + size_t (yes, the math is a bit ugly).
|
size_t blocksize;
|
||||||
|
|
||||||
|
/* size_t + (blocksize + 131071) / 131072 *
|
||||||
|
* (blocksize + u16 + u16) + u16 + u32 + size_t
|
||||||
|
* (yes, the math is a bit ugly). */
|
||||||
|
size_t maxcompsize;
|
||||||
|
|
||||||
unsigned entries;
|
unsigned entries;
|
||||||
bool thisblock_valid;
|
bool thisblock_valid;
|
||||||
@ -103,7 +110,8 @@ state_manager_t *state_manager_new(size_t state_size, size_t buffer_size)
|
|||||||
|
|
||||||
const int maxcblkcover = UINT16_MAX * sizeof(uint16_t);
|
const int maxcblkcover = UINT16_MAX * sizeof(uint16_t);
|
||||||
const int maxcblks = (state->blocksize + maxcblkcover - 1) / maxcblkcover;
|
const int maxcblks = (state->blocksize + maxcblkcover - 1) / maxcblkcover;
|
||||||
state->maxcompsize = state->blocksize + maxcblks * sizeof(uint16_t) * 2 + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(size_t) * 2;
|
state->maxcompsize = state->blocksize + maxcblks * sizeof(uint16_t) * 2 +
|
||||||
|
sizeof(uint16_t) + sizeof(uint32_t) + sizeof(size_t) * 2;
|
||||||
|
|
||||||
state->data = (uint8_t*)malloc(buffer_size);
|
state->data = (uint8_t*)malloc(buffer_size);
|
||||||
|
|
||||||
@ -112,12 +120,19 @@ state_manager_t *state_manager_new(size_t state_size, size_t buffer_size)
|
|||||||
if (!state->data || !state->thisblock || !state->nextblock)
|
if (!state->data || !state->thisblock || !state->nextblock)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
// Force in a different byte at the end, so we don't need to check bounds in the innermost loop (it's expensive).
|
/* Force in a different byte at the end, so we don't need to check
|
||||||
// There is also a large amount of data that's the same, to stop the other scan
|
* bounds in the innermost loop (it's expensive).
|
||||||
// There is also some padding at the end. This is so we don't read outside the buffer end if we're reading in large blocks;
|
*
|
||||||
// it doesn't make any difference to us, but sacrificing 16 bytes to get Valgrind happy is worth it.
|
* There is also a large amount of data that's the same, to stop the other scan
|
||||||
*(uint16_t*)(state->thisblock + state->blocksize + sizeof(uint16_t) * 3) = 0xFFFF;
|
* There is also some padding at the end. This is so we don't read outside the
|
||||||
*(uint16_t*)(state->nextblock + state->blocksize + sizeof(uint16_t) * 3) = 0x0000;
|
* buffer end if we're reading in large blocks;
|
||||||
|
*
|
||||||
|
* It doesn't make any difference to us, but sacrificing 16 bytes to get
|
||||||
|
* Valgrind happy is worth it. */
|
||||||
|
*(uint16_t*)(state->thisblock + state->blocksize + sizeof(uint16_t) * 3) =
|
||||||
|
0xFFFF;
|
||||||
|
*(uint16_t*)(state->nextblock + state->blocksize + sizeof(uint16_t) * 3) =
|
||||||
|
0x0000;
|
||||||
|
|
||||||
state->capacity = buffer_size;
|
state->capacity = buffer_size;
|
||||||
|
|
||||||
@ -160,8 +175,8 @@ bool state_manager_pop(state_manager_t *state, const void **data)
|
|||||||
const uint8_t *compressed = state->data + start + sizeof(size_t);
|
const uint8_t *compressed = state->data + start + sizeof(size_t);
|
||||||
uint8_t *out = state->thisblock;
|
uint8_t *out = state->thisblock;
|
||||||
|
|
||||||
// Begin decompression code
|
/* Begin decompression code
|
||||||
// out is the last pushed (or returned) state
|
* out is the last pushed (or returned) state */
|
||||||
const uint16_t *compressed16 = (const uint16_t*)compressed;
|
const uint16_t *compressed16 = (const uint16_t*)compressed;
|
||||||
uint16_t *out16 = (uint16_t*)out;
|
uint16_t *out16 = (uint16_t*)out;
|
||||||
|
|
||||||
@ -172,9 +187,12 @@ bool state_manager_pop(state_manager_t *state, const void **data)
|
|||||||
if (numchanged)
|
if (numchanged)
|
||||||
{
|
{
|
||||||
out16 += *compressed16++;
|
out16 += *compressed16++;
|
||||||
// We could do memcpy, but it seems that memcpy has a constant-per-call overhead that actually shows up.
|
|
||||||
// Our average size in here seems to be 8 or something.
|
/* We could do memcpy, but it seems that memcpy has a
|
||||||
// Therefore, we do something with lower overhead.
|
* constant-per-call overhead that actually shows up.
|
||||||
|
*
|
||||||
|
* Our average size in here seems to be 8 or something.
|
||||||
|
* Therefore, we do something with lower overhead. */
|
||||||
for (i = 0; i < numchanged; i++)
|
for (i = 0; i < numchanged; i++)
|
||||||
out16[i] = compressed16[i];
|
out16[i] = compressed16[i];
|
||||||
|
|
||||||
@ -190,7 +208,7 @@ bool state_manager_pop(state_manager_t *state, const void **data)
|
|||||||
out16 += numunchanged;
|
out16 += numunchanged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// End decompression code
|
/* End decompression code */
|
||||||
|
|
||||||
state->entries--;
|
state->entries--;
|
||||||
*data = state->thisblock;
|
*data = state->thisblock;
|
||||||
@ -199,8 +217,10 @@ bool state_manager_pop(state_manager_t *state, const void **data)
|
|||||||
|
|
||||||
void state_manager_push_where(state_manager_t *state, void **data)
|
void state_manager_push_where(state_manager_t *state, void **data)
|
||||||
{
|
{
|
||||||
// We need to ensure we have an uncompressed copy of the last pushed state, or we could
|
/* We need to ensure we have an uncompressed copy of the last
|
||||||
// end up applying a 'patch' to wrong savestate, and that'd blow up rather quickly.
|
* pushed state, or we could end up applying a 'patch' to wrong
|
||||||
|
* savestate, and that'd blow up rather quickly. */
|
||||||
|
|
||||||
if (!state->thisblock_valid)
|
if (!state->thisblock_valid)
|
||||||
{
|
{
|
||||||
const void *ignored;
|
const void *ignored;
|
||||||
@ -221,7 +241,10 @@ static inline int compat_ctz(unsigned x)
|
|||||||
return __builtin_ctz(x);
|
return __builtin_ctz(x);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Only checks at nibble granularity, because that's what we need.
|
|
||||||
|
/* Only checks at nibble granularity,
|
||||||
|
* because that's what we need. */
|
||||||
|
|
||||||
static inline int compat_ctz(unsigned x)
|
static inline int compat_ctz(unsigned x)
|
||||||
{
|
{
|
||||||
if (x & 0x000f)
|
if (x & 0x000f)
|
||||||
@ -237,7 +260,9 @@ static inline int compat_ctz(unsigned x)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
// There's no equivalent in libc, you'd think so ... std::mismatch exists, but it's not optimized at all. :(
|
/* There's no equivalent in libc, you'd think so ...
|
||||||
|
* std::mismatch exists, but it's not optimized at all. */
|
||||||
|
|
||||||
static inline size_t find_change(const uint16_t *a, const uint16_t *b)
|
static inline size_t find_change(const uint16_t *a, const uint16_t *b)
|
||||||
{
|
{
|
||||||
const __m128i *a128 = (const __m128i*)a;
|
const __m128i *a128 = (const __m128i*)a;
|
||||||
@ -250,9 +275,10 @@ static inline size_t find_change(const uint16_t *a, const uint16_t *b)
|
|||||||
__m128i c = _mm_cmpeq_epi32(v0, v1);
|
__m128i c = _mm_cmpeq_epi32(v0, v1);
|
||||||
|
|
||||||
uint32_t mask = _mm_movemask_epi8(c);
|
uint32_t mask = _mm_movemask_epi8(c);
|
||||||
if (mask != 0xffff) // Something has changed, figure out where.
|
if (mask != 0xffff) /* Something has changed, figure out where. */
|
||||||
{
|
{
|
||||||
size_t ret = (((uint8_t*)a128 - (uint8_t*)a) | (compat_ctz(~mask))) >> 1;
|
size_t ret = (((uint8_t*)a128 - (uint8_t*)a) |
|
||||||
|
(compat_ctz(~mask))) >> 1;
|
||||||
return ret | (a[ret] == b[ret]);
|
return ret | (a[ret] == b[ret]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,9 +332,14 @@ static inline size_t find_same(const uint16_t *a, const uint16_t *b)
|
|||||||
if (*a != *b)
|
if (*a != *b)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// With this, it's random whether two consecutive identical words are caught.
|
/* With this, it's random whether two consecutive identical
|
||||||
// Luckily, compression rate is the same for both cases, and three is always caught.
|
* words are caught.
|
||||||
// (We prefer to miss two-word blocks, anyways; fewer iterations of the outer loop, as well as in the decompressor.)
|
*
|
||||||
|
* Luckily, compression rate is the same for both cases, and
|
||||||
|
* three is always caught.
|
||||||
|
*
|
||||||
|
* (We prefer to miss two-word blocks, anyways; fewer iterations
|
||||||
|
* of the outer loop, as well as in the decompressor.) */
|
||||||
const uint32_t *a_big = (const uint32_t*)a;
|
const uint32_t *a_big = (const uint32_t*)a;
|
||||||
const uint32_t *b_big = (const uint32_t*)b;
|
const uint32_t *b_big = (const uint32_t*)b;
|
||||||
|
|
||||||
@ -340,7 +371,9 @@ recheckcapacity:;
|
|||||||
|
|
||||||
size_t headpos = state->head - state->data;
|
size_t headpos = state->head - state->data;
|
||||||
size_t tailpos = state->tail - state->data;
|
size_t tailpos = state->tail - state->data;
|
||||||
size_t remaining = (tailpos + state->capacity - sizeof(size_t) - headpos - 1) % state->capacity + 1;
|
size_t remaining = (tailpos + state->capacity -
|
||||||
|
sizeof(size_t) - headpos - 1) % state->capacity + 1;
|
||||||
|
|
||||||
if (remaining <= state->maxcompsize)
|
if (remaining <= state->maxcompsize)
|
||||||
{
|
{
|
||||||
state->tail = state->data + read_size_t(state->tail);
|
state->tail = state->data + read_size_t(state->tail);
|
||||||
@ -355,7 +388,8 @@ recheckcapacity:;
|
|||||||
const uint8_t *newb = state->nextblock;
|
const uint8_t *newb = state->nextblock;
|
||||||
uint8_t *compressed = state->head + sizeof(size_t);
|
uint8_t *compressed = state->head + sizeof(size_t);
|
||||||
|
|
||||||
// Begin compression code; 'compressed' will point to the end of the compressed data (excluding the prev pointer).
|
/* Begin compression code; 'compressed' will point to
|
||||||
|
* the end of the compressed data (excluding the prev pointer). */
|
||||||
const uint16_t *old16 = (const uint16_t*)oldb;
|
const uint16_t *old16 = (const uint16_t*)oldb;
|
||||||
const uint16_t *new16 = (const uint16_t*)newb;
|
const uint16_t *new16 = (const uint16_t*)newb;
|
||||||
uint16_t *compressed16 = (uint16_t*)compressed;
|
uint16_t *compressed16 = (uint16_t*)compressed;
|
||||||
@ -377,8 +411,9 @@ recheckcapacity:;
|
|||||||
{
|
{
|
||||||
if (skip > UINT32_MAX)
|
if (skip > UINT32_MAX)
|
||||||
{
|
{
|
||||||
// This will make it scan the entire thing again, but it only hits on 8GB unchanged
|
/* This will make it scan the entire thing again,
|
||||||
// data anyways, and if you're doing that, you've got bigger problems.
|
* but it only hits on 8GB unchanged data anyways,
|
||||||
|
* and if you're doing that, you've got bigger problems. */
|
||||||
skip = UINT32_MAX;
|
skip = UINT32_MAX;
|
||||||
}
|
}
|
||||||
*compressed16++ = 0;
|
*compressed16++ = 0;
|
||||||
@ -408,7 +443,7 @@ recheckcapacity:;
|
|||||||
compressed16[1] = 0;
|
compressed16[1] = 0;
|
||||||
compressed16[2] = 0;
|
compressed16[2] = 0;
|
||||||
compressed = (uint8_t*)(compressed16 + 3);
|
compressed = (uint8_t*)(compressed16 + 3);
|
||||||
// End compression code.
|
/* End compression code. */
|
||||||
|
|
||||||
if (compressed - state->data + state->maxcompsize > state->capacity)
|
if (compressed - state->data + state->maxcompsize > state->capacity)
|
||||||
{
|
{
|
||||||
@ -434,11 +469,13 @@ recheckcapacity:;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void state_manager_capacity(state_manager_t *state, unsigned *entries, size_t *bytes, bool *full)
|
void state_manager_capacity(state_manager_t *state,
|
||||||
|
unsigned *entries, size_t *bytes, bool *full)
|
||||||
{
|
{
|
||||||
size_t headpos = state->head - state->data;
|
size_t headpos = state->head - state->data;
|
||||||
size_t tailpos = state->tail - state->data;
|
size_t tailpos = state->tail - state->data;
|
||||||
size_t remaining = (tailpos + state->capacity - sizeof(size_t) - headpos - 1) % state->capacity + 1;
|
size_t remaining = (tailpos + state->capacity -
|
||||||
|
sizeof(size_t) - headpos - 1) % state->capacity + 1;
|
||||||
|
|
||||||
if (entries)
|
if (entries)
|
||||||
*entries = state->entries;
|
*entries = state->entries;
|
||||||
|
8
thread.h
8
thread.h
@ -30,27 +30,35 @@ typedef struct sthread sthread_t;
|
|||||||
|
|
||||||
/* Threading */
|
/* Threading */
|
||||||
sthread_t *sthread_create(void (*thread_func)(void*), void *userdata);
|
sthread_t *sthread_create(void (*thread_func)(void*), void *userdata);
|
||||||
|
|
||||||
int sthread_detach(sthread_t *thread);
|
int sthread_detach(sthread_t *thread);
|
||||||
|
|
||||||
void sthread_join(sthread_t *thread);
|
void sthread_join(sthread_t *thread);
|
||||||
|
|
||||||
/* Mutexes */
|
/* Mutexes */
|
||||||
typedef struct slock slock_t;
|
typedef struct slock slock_t;
|
||||||
|
|
||||||
slock_t *slock_new(void);
|
slock_t *slock_new(void);
|
||||||
|
|
||||||
void slock_free(slock_t *lock);
|
void slock_free(slock_t *lock);
|
||||||
|
|
||||||
void slock_lock(slock_t *lock);
|
void slock_lock(slock_t *lock);
|
||||||
|
|
||||||
void slock_unlock(slock_t *lock);
|
void slock_unlock(slock_t *lock);
|
||||||
|
|
||||||
/* Condition variables. */
|
/* Condition variables. */
|
||||||
typedef struct scond scond_t;
|
typedef struct scond scond_t;
|
||||||
|
|
||||||
scond_t *scond_new(void);
|
scond_t *scond_new(void);
|
||||||
|
|
||||||
void scond_free(scond_t *cond);
|
void scond_free(scond_t *cond);
|
||||||
|
|
||||||
void scond_wait(scond_t *cond, slock_t *lock);
|
void scond_wait(scond_t *cond, slock_t *lock);
|
||||||
|
|
||||||
bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us);
|
bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us);
|
||||||
|
|
||||||
int scond_broadcast(scond_t *cond);
|
int scond_broadcast(scond_t *cond);
|
||||||
|
|
||||||
void scond_signal(scond_t *cond);
|
void scond_signal(scond_t *cond);
|
||||||
|
|
||||||
#ifndef RARCH_INTERNAL
|
#ifndef RARCH_INTERNAL
|
||||||
|
Loading…
Reference in New Issue
Block a user