Cleanups - 80-char limit

This commit is contained in:
twinaphex 2014-09-02 05:57:53 +02:00
parent 4a2d3cbd4b
commit 0856091296
8 changed files with 398 additions and 193 deletions

232
dynamic.c
View File

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

View File

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

View File

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

View File

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

View File

@ -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)
{ {

View File

@ -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
View File

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

View File

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