Cleanups, 80-char limit
This commit is contained in:
parent
ceb4e05e88
commit
e84e255013
|
@ -46,7 +46,8 @@ static void autosave_thread(void *data)
|
||||||
while (!save->quit)
|
while (!save->quit)
|
||||||
{
|
{
|
||||||
autosave_lock(save);
|
autosave_lock(save);
|
||||||
bool differ = memcmp(save->buffer, save->retro_buffer, save->bufsize) != 0;
|
bool differ = memcmp(save->buffer, save->retro_buffer,
|
||||||
|
save->bufsize) != 0;
|
||||||
if (differ)
|
if (differ)
|
||||||
memcpy(save->buffer, save->retro_buffer, save->bufsize);
|
memcpy(save->buffer, save->retro_buffer, save->bufsize);
|
||||||
autosave_unlock(save);
|
autosave_unlock(save);
|
||||||
|
@ -68,7 +69,8 @@ static void autosave_thread(void *data)
|
||||||
RARCH_LOG("SRAM changed ... autosaving ...\n");
|
RARCH_LOG("SRAM changed ... autosaving ...\n");
|
||||||
|
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
failed |= fwrite(save->buffer, 1, save->bufsize, file) != save->bufsize;
|
failed |= fwrite(save->buffer, 1, save->bufsize, file)
|
||||||
|
!= save->bufsize;
|
||||||
failed |= fflush(file) != 0;
|
failed |= fflush(file) != 0;
|
||||||
failed |= fclose(file) != 0;
|
failed |= fclose(file) != 0;
|
||||||
if (failed)
|
if (failed)
|
||||||
|
|
|
@ -20,7 +20,9 @@
|
||||||
|
|
||||||
typedef struct autosave autosave_t;
|
typedef struct autosave autosave_t;
|
||||||
|
|
||||||
autosave_t *autosave_new(const char *path, const void *data, size_t size, unsigned interval);
|
autosave_t *autosave_new(const char *path, const void *data,
|
||||||
|
size_t size, unsigned interval);
|
||||||
|
|
||||||
void autosave_lock(autosave_t *handle);
|
void autosave_lock(autosave_t *handle);
|
||||||
void autosave_unlock(autosave_t *handle);
|
void autosave_unlock(autosave_t *handle);
|
||||||
void autosave_free(autosave_t *handle);
|
void autosave_free(autosave_t *handle);
|
||||||
|
|
57
command.c
57
command.c
|
@ -71,7 +71,8 @@ static bool cmd_init_network(rarch_cmd_t *handle, uint16_t port)
|
||||||
if (!netplay_init_network())
|
if (!netplay_init_network())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
RARCH_LOG("Bringing up command interface on port %hu.\n", (unsigned short)port);
|
RARCH_LOG("Bringing up command interface on port %hu.\n",
|
||||||
|
(unsigned short)port);
|
||||||
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
#if defined(_WIN32) || defined(HAVE_SOCKET_LEGACY)
|
#if defined(_WIN32) || defined(HAVE_SOCKET_LEGACY)
|
||||||
|
@ -87,14 +88,16 @@ static bool cmd_init_network(rarch_cmd_t *handle, uint16_t port)
|
||||||
if (getaddrinfo(NULL, port_buf, &hints, &res) < 0)
|
if (getaddrinfo(NULL, port_buf, &hints, &res) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
handle->net_fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
handle->net_fd = socket(res->ai_family,
|
||||||
|
res->ai_socktype, res->ai_protocol);
|
||||||
if (handle->net_fd < 0)
|
if (handle->net_fd < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!socket_nonblock(handle->net_fd))
|
if (!socket_nonblock(handle->net_fd))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
setsockopt(handle->net_fd, SOL_SOCKET, SO_REUSEADDR, CONST_CAST &yes, sizeof(int));
|
setsockopt(handle->net_fd, SOL_SOCKET,
|
||||||
|
SO_REUSEADDR, CONST_CAST &yes, sizeof(int));
|
||||||
if (bind(handle->net_fd, res->ai_addr, res->ai_addrlen) < 0)
|
if (bind(handle->net_fd, res->ai_addr, res->ai_addrlen) < 0)
|
||||||
{
|
{
|
||||||
RARCH_ERR("Failed to bind socket.\n");
|
RARCH_ERR("Failed to bind socket.\n");
|
||||||
|
@ -124,7 +127,8 @@ static bool cmd_init_stdin(rarch_cmd_t *handle)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rarch_cmd_t *rarch_cmd_new(bool stdin_enable, bool network_enable, uint16_t port)
|
rarch_cmd_t *rarch_cmd_new(bool stdin_enable,
|
||||||
|
bool network_enable, uint16_t port)
|
||||||
{
|
{
|
||||||
rarch_cmd_t *handle = (rarch_cmd_t*)calloc(1, sizeof(*handle));
|
rarch_cmd_t *handle = (rarch_cmd_t*)calloc(1, sizeof(*handle));
|
||||||
if (!handle)
|
if (!handle)
|
||||||
|
@ -241,7 +245,8 @@ static const struct cmd_action_map action_map[] = {
|
||||||
{ "SET_SHADER", cmd_set_shader, "<shader path>" },
|
{ "SET_SHADER", cmd_set_shader, "<shader path>" },
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool command_get_arg(const char *tok, const char **arg, unsigned *index)
|
static bool command_get_arg(const char *tok,
|
||||||
|
const char **arg, unsigned *index)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
@ -344,7 +349,8 @@ static void network_cmd_poll(rarch_cmd_t *handle)
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
ssize_t ret = recvfrom(handle->net_fd, buf, sizeof(buf) - 1, 0, NULL, NULL);
|
ssize_t ret = recvfrom(handle->net_fd, buf,
|
||||||
|
sizeof(buf) - 1, 0, NULL, NULL);
|
||||||
|
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
|
@ -366,12 +372,12 @@ static size_t read_stdin(char *buf, size_t size)
|
||||||
if (hnd == INVALID_HANDLE_VALUE)
|
if (hnd == INVALID_HANDLE_VALUE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Check first if we're a pipe
|
/* Check first if we're a pipe
|
||||||
// (not console).
|
* (not console). */
|
||||||
DWORD avail = 0;
|
DWORD avail = 0;
|
||||||
bool echo = false;
|
bool echo = false;
|
||||||
|
|
||||||
// If not a pipe, check if we're running in a console.
|
/* If not a pipe, check if we're running in a console. */
|
||||||
if (!PeekNamedPipe(hnd, NULL, 0, NULL, &avail, NULL))
|
if (!PeekNamedPipe(hnd, NULL, 0, NULL, &avail, NULL))
|
||||||
{
|
{
|
||||||
DWORD mode = 0;
|
DWORD mode = 0;
|
||||||
|
@ -379,22 +385,25 @@ static size_t read_stdin(char *buf, size_t size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ((mode & (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT))
|
if ((mode & (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT))
|
||||||
&& !SetConsoleMode(hnd, mode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT)))
|
&& !SetConsoleMode(hnd,
|
||||||
|
mode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Win32, Y U NO SANE NONBLOCK READ!?
|
/* Win32, Y U NO SANE NONBLOCK READ!? */
|
||||||
DWORD has_read = 0;
|
DWORD has_read = 0;
|
||||||
INPUT_RECORD recs[256];
|
INPUT_RECORD recs[256];
|
||||||
if (!PeekConsoleInput(hnd, recs, sizeof(recs) / sizeof(recs[0]), &has_read))
|
if (!PeekConsoleInput(hnd, recs,
|
||||||
|
sizeof(recs) / sizeof(recs[0]), &has_read))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bool has_key = false;
|
bool has_key = false;
|
||||||
for (i = 0; i < has_read; i++)
|
for (i = 0; i < has_read; i++)
|
||||||
{
|
{
|
||||||
// Very crude, but should get the job done ...
|
/* Very crude, but should get the job done. */
|
||||||
if (recs[i].EventType == KEY_EVENT &&
|
if (recs[i].EventType == KEY_EVENT &&
|
||||||
recs[i].Event.KeyEvent.bKeyDown &&
|
recs[i].Event.KeyEvent.bKeyDown &&
|
||||||
(isgraph(recs[i].Event.KeyEvent.wVirtualKeyCode) || recs[i].Event.KeyEvent.wVirtualKeyCode == VK_RETURN))
|
(isgraph(recs[i].Event.KeyEvent.wVirtualKeyCode) ||
|
||||||
|
recs[i].Event.KeyEvent.wVirtualKeyCode == VK_RETURN))
|
||||||
{
|
{
|
||||||
has_key = true;
|
has_key = true;
|
||||||
echo = true;
|
echo = true;
|
||||||
|
@ -424,7 +433,8 @@ static size_t read_stdin(char *buf, size_t size)
|
||||||
if (buf[i] == '\r')
|
if (buf[i] == '\r')
|
||||||
buf[i] = '\n';
|
buf[i] = '\n';
|
||||||
|
|
||||||
// Console won't echo for us while in non-line mode, so do it manually ...
|
/* Console won't echo for us while in non-line mode,
|
||||||
|
* so do it manually ... */
|
||||||
if (echo)
|
if (echo)
|
||||||
{
|
{
|
||||||
HANDLE hnd_out = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE hnd_out = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
@ -438,6 +448,7 @@ static size_t read_stdin(char *buf, size_t size)
|
||||||
return has_read;
|
return has_read;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static size_t read_stdin(char *buf, size_t size)
|
static size_t read_stdin(char *buf, size_t size)
|
||||||
{
|
{
|
||||||
size_t has_read = 0;
|
size_t has_read = 0;
|
||||||
|
@ -466,7 +477,8 @@ static void stdin_cmd_poll(rarch_cmd_t *handle)
|
||||||
if (!handle->stdin_enable)
|
if (!handle->stdin_enable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ret = read_stdin(handle->stdin_buf + handle->stdin_buf_ptr, STDIN_BUF_SIZE - handle->stdin_buf_ptr - 1);
|
ret = read_stdin(handle->stdin_buf + handle->stdin_buf_ptr,
|
||||||
|
STDIN_BUF_SIZE - handle->stdin_buf_ptr - 1);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -477,8 +489,8 @@ static void stdin_cmd_poll(rarch_cmd_t *handle)
|
||||||
|
|
||||||
if (!last_newline)
|
if (!last_newline)
|
||||||
{
|
{
|
||||||
// We're receiving bogus data in pipe (no terminating newline),
|
/* We're receiving bogus data in pipe
|
||||||
// flush out the buffer.
|
* (no terminating newline), flush out the buffer. */
|
||||||
if (handle->stdin_buf_ptr + 1 >= STDIN_BUF_SIZE)
|
if (handle->stdin_buf_ptr + 1 >= STDIN_BUF_SIZE)
|
||||||
{
|
{
|
||||||
handle->stdin_buf_ptr = 0;
|
handle->stdin_buf_ptr = 0;
|
||||||
|
@ -493,7 +505,8 @@ static void stdin_cmd_poll(rarch_cmd_t *handle)
|
||||||
|
|
||||||
parse_msg(handle, handle->stdin_buf);
|
parse_msg(handle, handle->stdin_buf);
|
||||||
|
|
||||||
memmove(handle->stdin_buf, last_newline, handle->stdin_buf_ptr - msg_len);
|
memmove(handle->stdin_buf, last_newline,
|
||||||
|
handle->stdin_buf_ptr - msg_len);
|
||||||
handle->stdin_buf_ptr -= msg_len;
|
handle->stdin_buf_ptr -= msg_len;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -512,7 +525,8 @@ void rarch_cmd_poll(rarch_cmd_t *handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY)
|
#if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY)
|
||||||
static bool send_udp_packet(const char *host, uint16_t port, const char *msg)
|
static bool send_udp_packet(const char *host,
|
||||||
|
uint16_t port, const char *msg)
|
||||||
{
|
{
|
||||||
char port_buf[16];
|
char port_buf[16];
|
||||||
struct addrinfo hints, *res = NULL;
|
struct addrinfo hints, *res = NULL;
|
||||||
|
@ -621,7 +635,8 @@ bool network_cmd_send(const char *cmd_)
|
||||||
if (port_)
|
if (port_)
|
||||||
port = strtoul(port_, NULL, 0);
|
port = strtoul(port_, NULL, 0);
|
||||||
|
|
||||||
RARCH_LOG("Sending command: \"%s\" to %s:%hu\n", cmd, host, (unsigned short)port);
|
RARCH_LOG("Sending command: \"%s\" to %s:%hu\n",
|
||||||
|
cmd, host, (unsigned short)port);
|
||||||
|
|
||||||
ret = verify_command(cmd) && send_udp_packet(host, port, cmd);
|
ret = verify_command(cmd) && send_udp_packet(host, port, cmd);
|
||||||
free(command);
|
free(command);
|
||||||
|
|
|
@ -29,11 +29,15 @@ extern "C" {
|
||||||
|
|
||||||
typedef struct rarch_cmd rarch_cmd_t;
|
typedef struct rarch_cmd rarch_cmd_t;
|
||||||
|
|
||||||
rarch_cmd_t *rarch_cmd_new(bool stdin_enable, bool network_enable, uint16_t port);
|
rarch_cmd_t *rarch_cmd_new(bool stdin_enable,
|
||||||
|
bool network_enable, uint16_t port);
|
||||||
|
|
||||||
void rarch_cmd_free(rarch_cmd_t *handle);
|
void rarch_cmd_free(rarch_cmd_t *handle);
|
||||||
|
|
||||||
void rarch_cmd_poll(rarch_cmd_t *handle);
|
void rarch_cmd_poll(rarch_cmd_t *handle);
|
||||||
|
|
||||||
void rarch_cmd_set(rarch_cmd_t *handle, unsigned id);
|
void rarch_cmd_set(rarch_cmd_t *handle, unsigned id);
|
||||||
|
|
||||||
bool rarch_cmd_get(rarch_cmd_t *handle, unsigned id);
|
bool rarch_cmd_get(rarch_cmd_t *handle, unsigned id);
|
||||||
|
|
||||||
#if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY)
|
#if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY)
|
||||||
|
|
92
core_info.c
92
core_info.c
|
@ -26,7 +26,8 @@
|
||||||
|
|
||||||
static core_info_list_t *global_core_list;
|
static core_info_list_t *global_core_list;
|
||||||
|
|
||||||
static void core_info_list_resolve_all_extensions(core_info_list_t *core_info_list)
|
static void core_info_list_resolve_all_extensions(
|
||||||
|
core_info_list_t *core_info_list)
|
||||||
{
|
{
|
||||||
size_t i, all_ext_len = 0;
|
size_t i, all_ext_len = 0;
|
||||||
if (!core_info_list)
|
if (!core_info_list)
|
||||||
|
@ -50,7 +51,8 @@ static void core_info_list_resolve_all_extensions(core_info_list_t *core_info_li
|
||||||
{
|
{
|
||||||
if (core_info_list->list[i].supported_extensions)
|
if (core_info_list->list[i].supported_extensions)
|
||||||
{
|
{
|
||||||
strlcat(core_info_list->all_ext, core_info_list->list[i].supported_extensions, all_ext_len);
|
strlcat(core_info_list->all_ext,
|
||||||
|
core_info_list->list[i].supported_extensions, all_ext_len);
|
||||||
strlcat(core_info_list->all_ext, "|", all_ext_len);
|
strlcat(core_info_list->all_ext, "|", all_ext_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +60,8 @@ static void core_info_list_resolve_all_extensions(core_info_list_t *core_info_li
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void core_info_list_resolve_all_firmware(core_info_list_t *core_info_list)
|
static void core_info_list_resolve_all_firmware(
|
||||||
|
core_info_list_t *core_info_list)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
unsigned c;
|
unsigned c;
|
||||||
|
@ -76,7 +79,9 @@ static void core_info_list_resolve_all_firmware(core_info_list_t *core_info_list
|
||||||
if (!config_get_uint(info->data, "firmware_count", &count))
|
if (!config_get_uint(info->data, "firmware_count", &count))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
info->firmware = (core_info_firmware_t*)calloc(count, sizeof(*info->firmware));
|
info->firmware = (core_info_firmware_t*)
|
||||||
|
calloc(count, sizeof(*info->firmware));
|
||||||
|
|
||||||
if (!info->firmware)
|
if (!info->firmware)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -100,7 +105,8 @@ core_info_list_t *core_info_list_new(const char *modules_path)
|
||||||
size_t i;
|
size_t i;
|
||||||
core_info_t *core_info = NULL;
|
core_info_t *core_info = NULL;
|
||||||
core_info_list_t *core_info_list = NULL;
|
core_info_list_t *core_info_list = NULL;
|
||||||
struct string_list *contents = (struct string_list*)dir_list_new(modules_path, EXT_EXECUTABLES, false);
|
struct string_list *contents = (struct string_list*)
|
||||||
|
dir_list_new(modules_path, EXT_EXECUTABLES, false);
|
||||||
if (!contents)
|
if (!contents)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -123,7 +129,8 @@ core_info_list_t *core_info_list_new(const char *modules_path)
|
||||||
if (!core_info[i].path)
|
if (!core_info[i].path)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
fill_pathname_base(info_path_base, contents->elems[i].data, sizeof(info_path_base));
|
fill_pathname_base(info_path_base, contents->elems[i].data,
|
||||||
|
sizeof(info_path_base));
|
||||||
path_remove_extension(info_path_base);
|
path_remove_extension(info_path_base);
|
||||||
|
|
||||||
#if defined(RARCH_MOBILE) || defined(RARCH_CONSOLE)
|
#if defined(RARCH_MOBILE) || defined(RARCH_CONSOLE)
|
||||||
|
@ -134,7 +141,8 @@ core_info_list_t *core_info_list_new(const char *modules_path)
|
||||||
|
|
||||||
strlcat(info_path_base, ".info", sizeof(info_path_base));
|
strlcat(info_path_base, ".info", sizeof(info_path_base));
|
||||||
|
|
||||||
fill_pathname_join(info_path, (*g_settings.libretro_info_path) ? g_settings.libretro_info_path : modules_path,
|
fill_pathname_join(info_path, (*g_settings.libretro_info_path) ?
|
||||||
|
g_settings.libretro_info_path : modules_path,
|
||||||
info_path_base, sizeof(info_path));
|
info_path_base, sizeof(info_path));
|
||||||
|
|
||||||
core_info[i].data = config_file_new(info_path);
|
core_info[i].data = config_file_new(info_path);
|
||||||
|
@ -142,22 +150,32 @@ core_info_list_t *core_info_list_new(const char *modules_path)
|
||||||
if (core_info[i].data)
|
if (core_info[i].data)
|
||||||
{
|
{
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
config_get_string(core_info[i].data, "display_name", &core_info[i].display_name);
|
config_get_string(core_info[i].data, "display_name",
|
||||||
config_get_string(core_info[i].data, "systemname", &core_info[i].systemname);
|
&core_info[i].display_name);
|
||||||
|
config_get_string(core_info[i].data, "systemname",
|
||||||
|
&core_info[i].systemname);
|
||||||
config_get_uint(core_info[i].data, "firmware_count", &count);
|
config_get_uint(core_info[i].data, "firmware_count", &count);
|
||||||
core_info[i].firmware_count = count;
|
core_info[i].firmware_count = count;
|
||||||
if (config_get_string(core_info[i].data, "supported_extensions", &core_info[i].supported_extensions) &&
|
if (config_get_string(core_info[i].data, "supported_extensions",
|
||||||
|
&core_info[i].supported_extensions) &&
|
||||||
core_info[i].supported_extensions)
|
core_info[i].supported_extensions)
|
||||||
core_info[i].supported_extensions_list = string_split(core_info[i].supported_extensions, "|");
|
core_info[i].supported_extensions_list =
|
||||||
|
string_split(core_info[i].supported_extensions, "|");
|
||||||
|
|
||||||
if (config_get_string(core_info[i].data, "authors", &core_info[i].authors) &&
|
if (config_get_string(core_info[i].data, "authors",
|
||||||
|
&core_info[i].authors) &&
|
||||||
core_info[i].authors)
|
core_info[i].authors)
|
||||||
core_info[i].authors_list = string_split(core_info[i].authors, "|");
|
core_info[i].authors_list =
|
||||||
|
string_split(core_info[i].authors, "|");
|
||||||
|
|
||||||
if (config_get_string(core_info[i].data, "permissions", &core_info[i].permissions) &&
|
if (config_get_string(core_info[i].data, "permissions",
|
||||||
|
&core_info[i].permissions) &&
|
||||||
core_info[i].permissions)
|
core_info[i].permissions)
|
||||||
core_info[i].permissions_list = string_split(core_info[i].permissions, "|");
|
core_info[i].permissions_list =
|
||||||
if (config_get_string(core_info[i].data, "notes", &core_info[i].notes) &&
|
string_split(core_info[i].permissions, "|");
|
||||||
|
|
||||||
|
if (config_get_string(core_info[i].data, "notes",
|
||||||
|
&core_info[i].notes) &&
|
||||||
core_info[i].notes)
|
core_info[i].notes)
|
||||||
core_info[i].note_list = string_split(core_info[i].notes, "|");
|
core_info[i].note_list = string_split(core_info[i].notes, "|");
|
||||||
}
|
}
|
||||||
|
@ -227,7 +245,8 @@ size_t core_info_list_num_info_files(core_info_list_t *core_info_list)
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_info_list_get_display_name(core_info_list_t *core_info_list, const char *path, char *buf, size_t size)
|
bool core_info_list_get_display_name(core_info_list_t *core_info_list,
|
||||||
|
const char *path, char *buf, size_t size)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
if (!core_info_list)
|
if (!core_info_list)
|
||||||
|
@ -236,7 +255,8 @@ bool core_info_list_get_display_name(core_info_list_t *core_info_list, const cha
|
||||||
for (i = 0; i < core_info_list->count; i++)
|
for (i = 0; i < core_info_list->count; i++)
|
||||||
{
|
{
|
||||||
const core_info_t *info = &core_info_list->list[i];
|
const core_info_t *info = &core_info_list->list[i];
|
||||||
if (!strcmp(path_basename(info->path), path_basename(path)) && info->display_name)
|
if (!strcmp(path_basename(info->path), path_basename(path))
|
||||||
|
&& info->display_name)
|
||||||
{
|
{
|
||||||
strlcpy(buf, info->display_name, size);
|
strlcpy(buf, info->display_name, size);
|
||||||
return true;
|
return true;
|
||||||
|
@ -246,7 +266,8 @@ bool core_info_list_get_display_name(core_info_list_t *core_info_list, const cha
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_info_list_get_info(core_info_list_t *core_info_list, core_info_t *out_info, const char *path)
|
bool core_info_list_get_info(core_info_list_t *core_info_list,
|
||||||
|
core_info_t *out_info, const char *path)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
if (!core_info_list || !out_info)
|
if (!core_info_list || !out_info)
|
||||||
|
@ -267,14 +288,16 @@ bool core_info_list_get_info(core_info_list_t *core_info_list, core_info_t *out_
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_info_does_support_any_file(const core_info_t *core, const struct string_list *list)
|
bool core_info_does_support_any_file(const core_info_t *core,
|
||||||
|
const struct string_list *list)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
if (!list || !core || !core->supported_extensions_list)
|
if (!list || !core || !core->supported_extensions_list)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (i = 0; i < list->size; i++)
|
for (i = 0; i < list->size; i++)
|
||||||
if (string_list_find_elem_prefix(core->supported_extensions_list, ".", path_get_extension(list->elems[i].data)))
|
if (string_list_find_elem_prefix(core->supported_extensions_list,
|
||||||
|
".", path_get_extension(list->elems[i].data)))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -283,7 +306,8 @@ bool core_info_does_support_file(const core_info_t *core, const char *path)
|
||||||
{
|
{
|
||||||
if (!path || !core || !core->supported_extensions_list)
|
if (!path || !core || !core->supported_extensions_list)
|
||||||
return false;
|
return false;
|
||||||
return string_list_find_elem_prefix(core->supported_extensions_list, ".", path_get_extension(path));
|
return string_list_find_elem_prefix(
|
||||||
|
core->supported_extensions_list, ".", path_get_extension(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *core_info_list_get_all_extensions(core_info_list_t *core_info_list)
|
const char *core_info_list_get_all_extensions(core_info_list_t *core_info_list)
|
||||||
|
@ -293,7 +317,7 @@ const char *core_info_list_get_all_extensions(core_info_list_t *core_info_list)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// qsort_r() is not in standard C, sadly.
|
/* qsort_r() is not in standard C, sadly. */
|
||||||
static const char *core_info_tmp_path;
|
static const char *core_info_tmp_path;
|
||||||
static const struct string_list *core_info_tmp_list;
|
static const struct string_list *core_info_tmp_list;
|
||||||
|
|
||||||
|
@ -312,8 +336,8 @@ static int core_info_qsort_cmp(const void *a_, const void *b_)
|
||||||
return strcasecmp(a->display_name, b->display_name);
|
return strcasecmp(a->display_name, b->display_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_info_list_get_supported_cores(core_info_list_t *core_info_list, const char *path,
|
void core_info_list_get_supported_cores(core_info_list_t *core_info_list,
|
||||||
const core_info_t **infos, size_t *num_infos)
|
const char *path, const core_info_t **infos, size_t *num_infos)
|
||||||
{
|
{
|
||||||
if (!core_info_list)
|
if (!core_info_list)
|
||||||
return;
|
return;
|
||||||
|
@ -327,8 +351,10 @@ void core_info_list_get_supported_cores(core_info_list_t *core_info_list, const
|
||||||
core_info_tmp_list = list;
|
core_info_tmp_list = list;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Let supported core come first in list so we can return a pointer to them.
|
/* Let supported core come first in list so we can return
|
||||||
qsort(core_info_list->list, core_info_list->count, sizeof(core_info_t), core_info_qsort_cmp);
|
* a pointer to them. */
|
||||||
|
qsort(core_info_list->list, core_info_list->count,
|
||||||
|
sizeof(core_info_t), core_info_qsort_cmp);
|
||||||
|
|
||||||
size_t supported, i;
|
size_t supported, i;
|
||||||
supported = 0;
|
supported = 0;
|
||||||
|
@ -352,7 +378,8 @@ void core_info_list_get_supported_cores(core_info_list_t *core_info_list, const
|
||||||
*num_infos = supported;
|
*num_infos = supported;
|
||||||
}
|
}
|
||||||
|
|
||||||
static core_info_t *find_core_info(core_info_list_t *list, const char *core)
|
static core_info_t *find_core_info(core_info_list_t *list,
|
||||||
|
const char *core)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
@ -394,7 +421,8 @@ void core_info_list_update_missing_firmware(core_info_list_t *core_info_list,
|
||||||
{
|
{
|
||||||
if (info->firmware[i].path)
|
if (info->firmware[i].path)
|
||||||
{
|
{
|
||||||
fill_pathname_join(path, systemdir, info->firmware[i].path, sizeof(path));
|
fill_pathname_join(path, systemdir,
|
||||||
|
info->firmware[i].path, sizeof(path));
|
||||||
info->firmware[i].missing = !path_file_exists(path);
|
info->firmware[i].missing = !path_file_exists(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,7 +454,8 @@ void core_info_list_get_missing_firmware(core_info_list_t *core_info_list,
|
||||||
*num_firmware += info->firmware[i].missing;
|
*num_firmware += info->firmware[i].missing;
|
||||||
}
|
}
|
||||||
|
|
||||||
qsort(info->firmware, info->firmware_count, sizeof(*info->firmware), core_info_firmware_cmp);
|
qsort(info->firmware, info->firmware_count, sizeof(*info->firmware),
|
||||||
|
core_info_firmware_cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO - remove all of the functions below */
|
/* TODO - remove all of the functions below */
|
||||||
|
@ -462,7 +491,8 @@ bool core_info_get_custom_config(const char *core_id,
|
||||||
if (!core_id || !buf || !sizeof_buf)
|
if (!core_id || !buf || !sizeof_buf)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
fill_pathname_join(buf, g_defaults.menu_config_dir, path_basename(core_id), sizeof_buf);
|
fill_pathname_join(buf, g_defaults.menu_config_dir,
|
||||||
|
path_basename(core_id), sizeof_buf);
|
||||||
fill_pathname(buf, buf, ".cfg", sizeof_buf);
|
fill_pathname(buf, buf, ".cfg", sizeof_buf);
|
||||||
|
|
||||||
if (buf[0] == '\0')
|
if (buf[0] == '\0')
|
||||||
|
|
31
core_info.h
31
core_info.h
|
@ -30,7 +30,9 @@ typedef struct
|
||||||
{
|
{
|
||||||
char *path;
|
char *path;
|
||||||
char *desc;
|
char *desc;
|
||||||
bool missing; // Set once to avoid opening the same file several times.
|
/* Set once to avoid opening the same file
|
||||||
|
* several times. */
|
||||||
|
bool missing;
|
||||||
bool optional;
|
bool optional;
|
||||||
} core_info_firmware_t;
|
} core_info_firmware_t;
|
||||||
|
|
||||||
|
@ -65,14 +67,17 @@ void core_info_list_free(core_info_list_t *list);
|
||||||
|
|
||||||
size_t core_info_list_num_info_files(core_info_list_t *list);
|
size_t core_info_list_num_info_files(core_info_list_t *list);
|
||||||
|
|
||||||
bool core_info_does_support_file(const core_info_t *info, const char *path);
|
bool core_info_does_support_file(const core_info_t *info,
|
||||||
bool core_info_does_support_any_file(const core_info_t *info, const struct string_list *list);
|
const char *path);
|
||||||
|
|
||||||
// Non-reentrant, does not allocate. Returns pointer to internal state.
|
bool core_info_does_support_any_file(const core_info_t *info,
|
||||||
void core_info_list_get_supported_cores(core_info_list_t *list, const char *path,
|
const struct string_list *list);
|
||||||
const core_info_t **infos, size_t *num_infos);
|
|
||||||
|
|
||||||
// Non-reentrant, does not allocate. Returns pointer to internal state.
|
/* Non-reentrant, does not allocate. Returns pointer to internal state. */
|
||||||
|
void core_info_list_get_supported_cores(core_info_list_t *list,
|
||||||
|
const char *path, const core_info_t **infos, size_t *num_infos);
|
||||||
|
|
||||||
|
/* Non-reentrant, does not allocate. Returns pointer to internal state. */
|
||||||
void core_info_list_get_missing_firmware(core_info_list_t *list,
|
void core_info_list_get_missing_firmware(core_info_list_t *list,
|
||||||
const char *core, const char *systemdir,
|
const char *core, const char *systemdir,
|
||||||
const core_info_firmware_t **firmware, size_t *num_firmware);
|
const core_info_firmware_t **firmware, size_t *num_firmware);
|
||||||
|
@ -80,19 +85,23 @@ void core_info_list_get_missing_firmware(core_info_list_t *list,
|
||||||
void core_info_list_update_missing_firmware(core_info_list_t *list,
|
void core_info_list_update_missing_firmware(core_info_list_t *list,
|
||||||
const char *core, const char *systemdir);
|
const char *core, const char *systemdir);
|
||||||
|
|
||||||
// Shallow-copies internal state. Data in *info is invalidated when the core_info_list is freed.
|
/* Shallow-copies internal state. Data in *info is invalidated when the
|
||||||
bool core_info_list_get_info(core_info_list_t *list, core_info_t *info, const char *path);
|
* core_info_list is freed. */
|
||||||
|
bool core_info_list_get_info(core_info_list_t *list,
|
||||||
|
core_info_t *info, const char *path);
|
||||||
|
|
||||||
const char *core_info_list_get_all_extensions(core_info_list_t *list);
|
const char *core_info_list_get_all_extensions(core_info_list_t *list);
|
||||||
|
|
||||||
bool core_info_list_get_display_name(core_info_list_t *list, const char *path, char *buf, size_t size);
|
bool core_info_list_get_display_name(core_info_list_t *list,
|
||||||
|
const char *path, char *buf, size_t size);
|
||||||
|
|
||||||
void core_info_set_core_path(void);
|
void core_info_set_core_path(void);
|
||||||
|
|
||||||
core_info_list_t *core_info_list_get(void);
|
core_info_list_t *core_info_list_get(void);
|
||||||
const core_info_t *core_info_list_get_by_id(const char *core_id);
|
const core_info_t *core_info_list_get_by_id(const char *core_id);
|
||||||
|
|
||||||
bool core_info_get_custom_config(const char *core_id, char *buf, size_t sizeof_buf);
|
bool core_info_get_custom_config(const char *core_id,
|
||||||
|
char *buf, size_t sizeof_buf);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,8 @@ void core_option_get(core_option_manager_t *opt, struct retro_variable *var)
|
||||||
var->value = NULL;
|
var->value = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parse_variable(core_option_manager_t *opt, size_t index, const struct retro_variable *var)
|
static bool parse_variable(core_option_manager_t *opt, size_t index,
|
||||||
|
const struct retro_variable *var)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
struct core_option *option = (struct core_option*)&opt->opts[index];
|
struct core_option *option = (struct core_option*)&opt->opts[index];
|
||||||
|
@ -126,10 +127,12 @@ static bool parse_variable(core_option_manager_t *opt, size_t index, const struc
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
core_option_manager_t *core_option_new(const char *conf_path, const struct retro_variable *vars)
|
core_option_manager_t *core_option_new(const char *conf_path,
|
||||||
|
const struct retro_variable *vars)
|
||||||
{
|
{
|
||||||
const struct retro_variable *var;
|
const struct retro_variable *var;
|
||||||
core_option_manager_t *opt = (core_option_manager_t*)calloc(1, sizeof(*opt));
|
core_option_manager_t *opt = (core_option_manager_t*)
|
||||||
|
calloc(1, sizeof(*opt));
|
||||||
if (!opt)
|
if (!opt)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -200,12 +203,14 @@ const char *core_option_get_val(core_option_manager_t *opt, size_t index)
|
||||||
return option->vals->elems[option->index].data;
|
return option->vals->elems[option->index].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string_list *core_option_get_vals(core_option_manager_t *opt, size_t index)
|
struct string_list *core_option_get_vals(
|
||||||
|
core_option_manager_t *opt, size_t index)
|
||||||
{
|
{
|
||||||
return opt->opts[index].vals;
|
return opt->opts[index].vals;
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_option_set_val(core_option_manager_t *opt, size_t index, size_t val_index)
|
void core_option_set_val(core_option_manager_t *opt,
|
||||||
|
size_t index, size_t val_index)
|
||||||
{
|
{
|
||||||
struct core_option *option= (struct core_option*)&opt->opts[index];
|
struct core_option *option= (struct core_option*)&opt->opts[index];
|
||||||
option->index = val_index % option->vals->size;
|
option->index = val_index % option->vals->size;
|
||||||
|
@ -222,7 +227,8 @@ void core_option_next(core_option_manager_t *opt, size_t index)
|
||||||
void core_option_prev(core_option_manager_t *opt, size_t index)
|
void core_option_prev(core_option_manager_t *opt, size_t index)
|
||||||
{
|
{
|
||||||
struct core_option *option = (struct core_option*)&opt->opts[index];
|
struct core_option *option = (struct core_option*)&opt->opts[index];
|
||||||
option->index = (option->index + option->vals->size - 1) % option->vals->size;
|
option->index = (option->index + option->vals->size - 1) %
|
||||||
|
option->vals->size;
|
||||||
opt->updated = true;
|
opt->updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,29 +26,34 @@ extern "C" {
|
||||||
|
|
||||||
typedef struct core_option_manager core_option_manager_t;
|
typedef struct core_option_manager core_option_manager_t;
|
||||||
|
|
||||||
core_option_manager_t *core_option_new(const char *conf_path, const struct retro_variable *vars);
|
core_option_manager_t *core_option_new(const char *conf_path,
|
||||||
|
const struct retro_variable *vars);
|
||||||
|
|
||||||
bool core_option_updated(core_option_manager_t *opt);
|
bool core_option_updated(core_option_manager_t *opt);
|
||||||
void core_option_flush(core_option_manager_t *opt);
|
void core_option_flush(core_option_manager_t *opt);
|
||||||
void core_option_free(core_option_manager_t *opt);
|
void core_option_free(core_option_manager_t *opt);
|
||||||
|
|
||||||
void core_option_get(core_option_manager_t *opt, struct retro_variable *var);
|
void core_option_get(core_option_manager_t *opt, struct retro_variable *var);
|
||||||
|
|
||||||
// Returns total number of options.
|
/* Returns total number of options. */
|
||||||
size_t core_option_size(core_option_manager_t *opt);
|
size_t core_option_size(core_option_manager_t *opt);
|
||||||
|
|
||||||
// Gets description and current value for an option.
|
/* Gets description and current value for an option. */
|
||||||
const char *core_option_get_desc(core_option_manager_t *opt, size_t index);
|
const char *core_option_get_desc(core_option_manager_t *opt, size_t index);
|
||||||
const char *core_option_get_val(core_option_manager_t *opt, size_t index);
|
const char *core_option_get_val(core_option_manager_t *opt, size_t index);
|
||||||
|
|
||||||
// Helpers to present a list of options
|
/* Helpers to present a list of options */
|
||||||
struct string_list *core_option_get_vals(core_option_manager_t *opt, size_t index);
|
struct string_list *core_option_get_vals(
|
||||||
void core_option_set_val(core_option_manager_t *opt, size_t index, size_t val_index);
|
core_option_manager_t *opt, size_t index);
|
||||||
|
|
||||||
// Cycles through options for an option. Options wrap around.
|
void core_option_set_val(core_option_manager_t *opt,
|
||||||
|
size_t index, size_t val_index);
|
||||||
|
|
||||||
|
/* Cycles through options for an option. Options wrap around. */
|
||||||
void core_option_next(core_option_manager_t *opt, size_t index);
|
void core_option_next(core_option_manager_t *opt, size_t index);
|
||||||
void core_option_prev(core_option_manager_t *opt, size_t index);
|
void core_option_prev(core_option_manager_t *opt, size_t index);
|
||||||
|
|
||||||
// Sets default val for an option.
|
/* Sets default value for an option. */
|
||||||
void core_option_set_default(core_option_manager_t *opt, size_t index);
|
void core_option_set_default(core_option_manager_t *opt, size_t index);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
105
file.c
105
file.c
|
@ -63,19 +63,22 @@ static void patch_content(uint8_t **buf, ssize_t *size)
|
||||||
bool allow_ups = !g_extern.bps_pref && !g_extern.ips_pref;
|
bool allow_ups = !g_extern.bps_pref && !g_extern.ips_pref;
|
||||||
bool allow_ips = !g_extern.ups_pref && !g_extern.bps_pref;
|
bool allow_ips = !g_extern.ups_pref && !g_extern.bps_pref;
|
||||||
|
|
||||||
if (allow_ups && *g_extern.ups_name && (patch_size = read_file(g_extern.ups_name, &patch_data)) >= 0)
|
if (allow_ups && *g_extern.ups_name
|
||||||
|
&& (patch_size = read_file(g_extern.ups_name, &patch_data)) >= 0)
|
||||||
{
|
{
|
||||||
patch_desc = "UPS";
|
patch_desc = "UPS";
|
||||||
patch_path = g_extern.ups_name;
|
patch_path = g_extern.ups_name;
|
||||||
func = ups_apply_patch;
|
func = ups_apply_patch;
|
||||||
}
|
}
|
||||||
else if (allow_bps && *g_extern.bps_name && (patch_size = read_file(g_extern.bps_name, &patch_data)) >= 0)
|
else if (allow_bps && *g_extern.bps_name
|
||||||
|
&& (patch_size = read_file(g_extern.bps_name, &patch_data)) >= 0)
|
||||||
{
|
{
|
||||||
patch_desc = "BPS";
|
patch_desc = "BPS";
|
||||||
patch_path = g_extern.bps_name;
|
patch_path = g_extern.bps_name;
|
||||||
func = bps_apply_patch;
|
func = bps_apply_patch;
|
||||||
}
|
}
|
||||||
else if (allow_ips && *g_extern.ips_name && (patch_size = read_file(g_extern.ips_name, &patch_data)) >= 0)
|
else if (allow_ips && *g_extern.ips_name
|
||||||
|
&& (patch_size = read_file(g_extern.ips_name, &patch_data)) >= 0)
|
||||||
{
|
{
|
||||||
patch_desc = "IPS";
|
patch_desc = "IPS";
|
||||||
patch_path = g_extern.ips_name;
|
patch_path = g_extern.ips_name;
|
||||||
|
@ -87,9 +90,10 @@ static void patch_content(uint8_t **buf, ssize_t *size)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RARCH_LOG("Found %s file in \"%s\", attempting to patch ...\n", patch_desc, patch_path);
|
RARCH_LOG("Found %s file in \"%s\", attempting to patch ...\n",
|
||||||
|
patch_desc, patch_path);
|
||||||
|
|
||||||
size_t target_size = ret_size * 4; // Just to be sure ...
|
size_t target_size = ret_size * 4; /* Just to be sure. */
|
||||||
uint8_t *patched_content = (uint8_t*)malloc(target_size);
|
uint8_t *patched_content = (uint8_t*)malloc(target_size);
|
||||||
if (!patched_content)
|
if (!patched_content)
|
||||||
{
|
{
|
||||||
|
@ -97,14 +101,17 @@ static void patch_content(uint8_t **buf, ssize_t *size)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = func((const uint8_t*)patch_data, patch_size, ret_buf, ret_size, patched_content, &target_size);
|
err = func((const uint8_t*)patch_data, patch_size, ret_buf,
|
||||||
|
ret_size, patched_content, &target_size);
|
||||||
|
|
||||||
if (err == PATCH_SUCCESS)
|
if (err == PATCH_SUCCESS)
|
||||||
{
|
{
|
||||||
RARCH_LOG("Content patched successfully (%s).\n", patch_desc);
|
RARCH_LOG("Content patched successfully (%s).\n", patch_desc);
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
RARCH_ERR("Failed to patch %s: Error #%u\n", patch_desc, (unsigned)err);
|
RARCH_ERR("Failed to patch %s: Error #%u\n", patch_desc,
|
||||||
|
(unsigned)err);
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
|
@ -129,22 +136,22 @@ static ssize_t read_content_file(const char *path, void **buf)
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* Attempt to apply a patch. */
|
||||||
if (!g_extern.block_patch)
|
if (!g_extern.block_patch)
|
||||||
{
|
|
||||||
// Attempt to apply a patch.
|
|
||||||
patch_content(&ret_buf, &ret);
|
patch_content(&ret_buf, &ret);
|
||||||
}
|
|
||||||
|
|
||||||
g_extern.content_crc = crc32_calculate(ret_buf, ret);
|
g_extern.content_crc = crc32_calculate(ret_buf, ret);
|
||||||
sha256_hash(g_extern.sha256, ret_buf, ret);
|
sha256_hash(g_extern.sha256, ret_buf, ret);
|
||||||
|
|
||||||
RARCH_LOG("CRC32: 0x%x, SHA256: %s\n",
|
RARCH_LOG("CRC32: 0x%x, SHA256: %s\n",
|
||||||
(unsigned)g_extern.content_crc, g_extern.sha256);
|
(unsigned)g_extern.content_crc, g_extern.sha256);
|
||||||
*buf = ret_buf;
|
*buf = ret_buf;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to save valuable RAM data somewhere ...
|
/* Attempt to save valuable RAM data somewhere. */
|
||||||
static void dump_to_file_desperate(const void *data, size_t size, unsigned type)
|
static void dump_to_file_desperate(const void *data,
|
||||||
|
size_t size, unsigned type)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) && !defined(_XBOX)
|
#if defined(_WIN32) && !defined(_XBOX)
|
||||||
const char *base = getenv("APPDATA");
|
const char *base = getenv("APPDATA");
|
||||||
|
@ -230,10 +237,13 @@ bool load_state(const char *path)
|
||||||
struct sram_block *blocks = NULL;
|
struct sram_block *blocks = NULL;
|
||||||
unsigned num_blocks = 0;
|
unsigned num_blocks = 0;
|
||||||
|
|
||||||
if (g_settings.block_sram_overwrite && g_extern.savefiles && g_extern.savefiles->size)
|
if (g_settings.block_sram_overwrite && g_extern.savefiles
|
||||||
|
&& g_extern.savefiles->size)
|
||||||
{
|
{
|
||||||
RARCH_LOG("Blocking SRAM overwrite.\n");
|
RARCH_LOG("Blocking SRAM overwrite.\n");
|
||||||
blocks = (struct sram_block*)calloc(g_extern.savefiles->size, sizeof(*blocks));
|
blocks = (struct sram_block*)
|
||||||
|
calloc(g_extern.savefiles->size, sizeof(*blocks));
|
||||||
|
|
||||||
if (blocks)
|
if (blocks)
|
||||||
{
|
{
|
||||||
num_blocks = g_extern.savefiles->size;
|
num_blocks = g_extern.savefiles->size;
|
||||||
|
@ -249,7 +259,7 @@ bool load_state(const char *path)
|
||||||
if (blocks[i].size)
|
if (blocks[i].size)
|
||||||
blocks[i].data = malloc(blocks[i].size);
|
blocks[i].data = malloc(blocks[i].size);
|
||||||
|
|
||||||
// Backup current SRAM which is overwritten by unserialize.
|
/* Backup current SRAM which is overwritten by unserialize. */
|
||||||
for (i = 0; i < num_blocks; i++)
|
for (i = 0; i < num_blocks; i++)
|
||||||
{
|
{
|
||||||
if (blocks[i].data)
|
if (blocks[i].data)
|
||||||
|
@ -262,7 +272,7 @@ bool load_state(const char *path)
|
||||||
|
|
||||||
ret = pretro_unserialize(buf, size);
|
ret = pretro_unserialize(buf, size);
|
||||||
|
|
||||||
// Flush back :D
|
/* Flush back. */
|
||||||
for (i = 0; i < num_blocks; i++)
|
for (i = 0; i < num_blocks; i++)
|
||||||
{
|
{
|
||||||
if (blocks[i].data)
|
if (blocks[i].data)
|
||||||
|
@ -321,12 +331,15 @@ void save_ram_file(const char *path, int type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool load_content(const struct retro_subsystem_info *special, const struct string_list *content)
|
static bool load_content(const struct retro_subsystem_info *special,
|
||||||
|
const struct string_list *content)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
struct retro_game_info *info = (struct retro_game_info*)calloc(content->size, sizeof(*info));
|
struct retro_game_info *info = (struct retro_game_info*)
|
||||||
|
calloc(content->size, sizeof(*info));
|
||||||
|
|
||||||
if (!info)
|
if (!info)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -347,11 +360,17 @@ static bool load_content(const struct retro_subsystem_info *special, const struc
|
||||||
|
|
||||||
info[i].path = *path ? path : NULL;
|
info[i].path = *path ? path : NULL;
|
||||||
|
|
||||||
if (!need_fullpath && *path) // Load the content into memory.
|
if (!need_fullpath && *path)
|
||||||
{
|
{
|
||||||
|
/* Load the content into memory. */
|
||||||
RARCH_LOG("Loading content file: %s.\n", path);
|
RARCH_LOG("Loading content file: %s.\n", path);
|
||||||
// First content file is significant, attempt to do patching, CRC checking, etc ...
|
|
||||||
long size = i == 0 ? read_content_file(path, (void**)&info[i].data) : read_file(path, (void**)&info[i].data);
|
/* First content file is significant, attempt to do patching,
|
||||||
|
* CRC checking, etc. */
|
||||||
|
long size = i == 0 ?
|
||||||
|
read_content_file(path, (void**)&info[i].data) :
|
||||||
|
read_file(path, (void**)&info[i].data);
|
||||||
|
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
{
|
{
|
||||||
RARCH_ERR("Could not read content file \"%s\".\n", path);
|
RARCH_ERR("Could not read content file \"%s\".\n", path);
|
||||||
|
@ -392,12 +411,13 @@ bool init_content_file(void)
|
||||||
|
|
||||||
if (*g_extern.subsystem)
|
if (*g_extern.subsystem)
|
||||||
{
|
{
|
||||||
special = libretro_find_subsystem_info(g_extern.system.special, g_extern.system.num_special,
|
special = libretro_find_subsystem_info(g_extern.system.special,
|
||||||
g_extern.subsystem);
|
g_extern.system.num_special, g_extern.subsystem);
|
||||||
|
|
||||||
if (!special)
|
if (!special)
|
||||||
{
|
{
|
||||||
RARCH_ERR("Failed to find subsystem \"%s\" in libretro implementation.\n",
|
RARCH_ERR(
|
||||||
|
"Failed to find subsystem \"%s\" in libretro implementation.\n",
|
||||||
g_extern.subsystem);
|
g_extern.subsystem);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -409,13 +429,16 @@ bool init_content_file(void)
|
||||||
}
|
}
|
||||||
else if (special->num_roms && special->num_roms != g_extern.subsystem_fullpaths->size)
|
else if (special->num_roms && special->num_roms != g_extern.subsystem_fullpaths->size)
|
||||||
{
|
{
|
||||||
RARCH_ERR("libretro core requires %u content files for subsystem \"%s\", but %u content files were provided.\n", special->num_roms, special->desc,
|
RARCH_ERR("libretro core requires %u content files for subsystem \"%s\", but %u content files were provided.\n",
|
||||||
|
special->num_roms, special->desc,
|
||||||
(unsigned)g_extern.subsystem_fullpaths->size);
|
(unsigned)g_extern.subsystem_fullpaths->size);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!special->num_roms && g_extern.subsystem_fullpaths && g_extern.subsystem_fullpaths->size)
|
else if (!special->num_roms && g_extern.subsystem_fullpaths
|
||||||
|
&& g_extern.subsystem_fullpaths->size)
|
||||||
{
|
{
|
||||||
RARCH_ERR("libretro core takes no content for subsystem \"%s\", but %u content files were provided.\n", special->desc,
|
RARCH_ERR("libretro core takes no content for subsystem \"%s\", but %u content files were provided.\n",
|
||||||
|
special->desc,
|
||||||
(unsigned)g_extern.subsystem_fullpaths->size);
|
(unsigned)g_extern.subsystem_fullpaths->size);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -435,7 +458,8 @@ bool init_content_file(void)
|
||||||
attr.i = special->roms[i].block_extract;
|
attr.i = special->roms[i].block_extract;
|
||||||
attr.i |= special->roms[i].need_fullpath << 1;
|
attr.i |= special->roms[i].need_fullpath << 1;
|
||||||
attr.i |= special->roms[i].required << 2;
|
attr.i |= special->roms[i].required << 2;
|
||||||
string_list_append(content, g_extern.subsystem_fullpaths->elems[i].data, attr);
|
string_list_append(content,
|
||||||
|
g_extern.subsystem_fullpaths->elems[i].data, attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -443,14 +467,15 @@ bool init_content_file(void)
|
||||||
attr.i = g_extern.system.info.block_extract;
|
attr.i = g_extern.system.info.block_extract;
|
||||||
attr.i |= g_extern.system.info.need_fullpath << 1;
|
attr.i |= g_extern.system.info.need_fullpath << 1;
|
||||||
attr.i |= (!g_extern.system.no_content) << 2;
|
attr.i |= (!g_extern.system.no_content) << 2;
|
||||||
string_list_append(content, g_extern.libretro_no_content ? "" : g_extern.fullpath, attr);
|
string_list_append(content,
|
||||||
|
g_extern.libretro_no_content ? "" : g_extern.fullpath, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB
|
#ifdef HAVE_ZLIB
|
||||||
// Try to extract all content we're going to load if appropriate.
|
/* Try to extract all content we're going to load if appropriate. */
|
||||||
for (i = 0; i < content->size; i++)
|
for (i = 0; i < content->size; i++)
|
||||||
{
|
{
|
||||||
// block extract check
|
/* Block extract check. */
|
||||||
if (content->elems[i].attr.i & 1)
|
if (content->elems[i].attr.i & 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -463,21 +488,27 @@ bool init_content_file(void)
|
||||||
if (ext && !strcasecmp(ext, "zip"))
|
if (ext && !strcasecmp(ext, "zip"))
|
||||||
{
|
{
|
||||||
char temporary_content[PATH_MAX];
|
char temporary_content[PATH_MAX];
|
||||||
strlcpy(temporary_content, content->elems[i].data, sizeof(temporary_content));
|
strlcpy(temporary_content, content->elems[i].data,
|
||||||
if (!zlib_extract_first_content_file(temporary_content, sizeof(temporary_content), valid_ext,
|
sizeof(temporary_content));
|
||||||
*g_settings.extraction_directory ? g_settings.extraction_directory : NULL))
|
|
||||||
|
if (!zlib_extract_first_content_file(temporary_content,
|
||||||
|
sizeof(temporary_content), valid_ext,
|
||||||
|
*g_settings.extraction_directory ?
|
||||||
|
g_settings.extraction_directory : NULL))
|
||||||
{
|
{
|
||||||
RARCH_ERR("Failed to extract content from zipped file: %s.\n", temporary_content);
|
RARCH_ERR("Failed to extract content from zipped file: %s.\n",
|
||||||
|
temporary_content);
|
||||||
string_list_free(content);
|
string_list_free(content);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
string_list_set(content, i, temporary_content);
|
string_list_set(content, i, temporary_content);
|
||||||
string_list_append(g_extern.temporary_content, temporary_content, attr);
|
string_list_append(g_extern.temporary_content,
|
||||||
|
temporary_content, attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set attr to need_fullpath as appropriate.
|
/* Set attr to need_fullpath as appropriate. */
|
||||||
|
|
||||||
bool ret = load_content(special, content);
|
bool ret = load_content(special, content);
|
||||||
string_list_free(content);
|
string_list_free(content);
|
||||||
|
|
2
file.h
2
file.h
|
@ -27,7 +27,7 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Handles files related to libretro.
|
/* Handles files related to libretro. */
|
||||||
|
|
||||||
bool load_state(const char *path);
|
bool load_state(const char *path);
|
||||||
bool save_state(const char *path);
|
bool save_state(const char *path);
|
||||||
|
|
|
@ -71,7 +71,8 @@ void file_list_get_alt_at_offset(const file_list_t *list, size_t index,
|
||||||
|
|
||||||
void file_list_sort_on_alt(file_list_t *list);
|
void file_list_sort_on_alt(file_list_t *list);
|
||||||
|
|
||||||
bool file_list_search(const file_list_t *list, const char *needle, size_t *index);
|
bool file_list_search(const file_list_t *list, const char *needle,
|
||||||
|
size_t *index);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
136
file_path.h
136
file_path.h
|
@ -30,7 +30,6 @@ long read_file(const char *path, void **buf);
|
||||||
bool read_file_string(const char *path, char **buf);
|
bool read_file_string(const char *path, char **buf);
|
||||||
bool write_file(const char *path, const void *buf, size_t size);
|
bool write_file(const char *path, const void *buf, size_t size);
|
||||||
|
|
||||||
// Yep, this is C alright ;)
|
|
||||||
union string_list_elem_attr
|
union string_list_elem_attr
|
||||||
{
|
{
|
||||||
bool b;
|
bool b;
|
||||||
|
@ -51,94 +50,127 @@ struct string_list
|
||||||
size_t cap;
|
size_t cap;
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
||||||
void dir_list_sort(struct string_list *list, bool dir_first);
|
void dir_list_sort(struct string_list *list, bool dir_first);
|
||||||
void dir_list_free(struct string_list *list);
|
void dir_list_free(struct string_list *list);
|
||||||
bool string_list_find_elem(const struct string_list *list, const char *elem);
|
bool string_list_find_elem(const struct string_list *list, const char *elem);
|
||||||
bool string_list_find_elem_prefix(const struct string_list *list, const char *prefix, const char *elem);
|
bool string_list_find_elem_prefix(const struct string_list *list,
|
||||||
|
const char *prefix, const char *elem);
|
||||||
struct string_list *string_split(const char *str, const char *delim);
|
struct string_list *string_split(const char *str, const char *delim);
|
||||||
struct string_list *string_list_new(void);
|
struct string_list *string_list_new(void);
|
||||||
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);
|
||||||
void string_list_free(struct string_list *list);
|
void string_list_free(struct string_list *list);
|
||||||
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,
|
||||||
void string_list_set(struct string_list *list, unsigned index, const char *str);
|
const struct string_list *list, const char *sep);
|
||||||
|
void string_list_set(struct string_list *list, unsigned index,
|
||||||
|
const char *str);
|
||||||
|
|
||||||
bool path_is_directory(const char *path);
|
bool path_is_directory(const char *path);
|
||||||
bool path_file_exists(const char *path);
|
bool path_file_exists(const char *path);
|
||||||
|
|
||||||
// Gets extension of file. Only '.'s after the last slash are considered.
|
/* Gets extension of file. Only '.'s after the last slash are considered. */
|
||||||
const char *path_get_extension(const char *path);
|
const char *path_get_extension(const char *path);
|
||||||
|
|
||||||
bool path_mkdir(const char *dir);
|
bool path_mkdir(const char *dir);
|
||||||
|
|
||||||
// Removes all text after and including the last '.'.
|
/* Removes all text after and including the last '.'.
|
||||||
// Only '.'s after the last slash are considered.
|
* Only '.'s after the last slash are considered. */
|
||||||
char *path_remove_extension(char *path);
|
char *path_remove_extension(char *path);
|
||||||
|
|
||||||
// Returns basename from path.
|
/* Returns basename from path. */
|
||||||
const char *path_basename(const char *path);
|
const char *path_basename(const char *path);
|
||||||
|
|
||||||
// Extracts base directory by mutating path. Keeps trailing '/'.
|
/* Extracts base directory by mutating path.
|
||||||
|
* Keeps trailing '/'. */
|
||||||
void path_basedir(char *path);
|
void path_basedir(char *path);
|
||||||
|
|
||||||
// Extracts parent directory by mutating path.
|
/* Extracts parent directory by mutating path.
|
||||||
// Assumes that path is a directory. Keeps trailing '/'.
|
* Assumes that path is a directory. Keeps trailing '/'. */
|
||||||
void path_parent_dir(char *path);
|
void path_parent_dir(char *path);
|
||||||
|
|
||||||
// Turns relative paths into absolute path.
|
/* Turns relative paths into absolute path.
|
||||||
// If relative, rebases on current working dir.
|
* If relative, rebases on current working dir. */
|
||||||
void path_resolve_realpath(char *buf, size_t size);
|
void path_resolve_realpath(char *buf, size_t size);
|
||||||
|
|
||||||
bool path_is_absolute(const char *path);
|
bool path_is_absolute(const char *path);
|
||||||
|
|
||||||
// Path-name operations.
|
/* Path-name operations.
|
||||||
// If any of these operation are detected to overflow, the application will be terminated.
|
* If any of these operation are detected to overflow, the application will
|
||||||
|
* be terminated.
|
||||||
|
*
|
||||||
|
* Replaces filename extension with 'replace' and outputs result to out_path.
|
||||||
|
* The extension here is considered to be the string from the last '.'
|
||||||
|
* to the end.
|
||||||
|
*
|
||||||
|
* Only '.'s after the last slash are considered as extensions.
|
||||||
|
* If no '.' is present, in_path and replace will simply be concatenated.
|
||||||
|
* 'size' is buffer size of 'out_path'.
|
||||||
|
* E.g.: in_path = "/foo/bar/baz/boo.c", replace = ".asm" =>
|
||||||
|
* out_path = "/foo/bar/baz/boo.asm"
|
||||||
|
* E.g.: in_path = "/foo/bar/baz/boo.c", replace = "" =>
|
||||||
|
* out_path = "/foo/bar/baz/boo"
|
||||||
|
*/
|
||||||
|
void fill_pathname(char *out_path, const char *in_path,
|
||||||
|
const char *replace, size_t size);
|
||||||
|
|
||||||
// Replaces filename extension with 'replace' and outputs result to out_path.
|
void fill_dated_filename(char *out_filename,
|
||||||
// The extension here is considered to be the string from the last '.' to the end.
|
const char *ext, size_t size);
|
||||||
// Only '.'s after the last slash are considered as extensions.
|
|
||||||
// If no '.' is present, in_path and replace will simply be concatenated.
|
|
||||||
// 'size' is buffer size of 'out_path'.
|
|
||||||
// E.g.: in_path = "/foo/bar/baz/boo.c", replace = ".asm" => out_path = "/foo/bar/baz/boo.asm"
|
|
||||||
// E.g.: in_path = "/foo/bar/baz/boo.c", replace = "" => out_path = "/foo/bar/baz/boo"
|
|
||||||
void fill_pathname(char *out_path, const char *in_path, const char *replace, size_t size);
|
|
||||||
|
|
||||||
void fill_dated_filename(char *out_filename, const char *ext, size_t size);
|
/* Appends a filename extension 'replace' to 'in_path', and outputs
|
||||||
|
* result in 'out_path'.
|
||||||
|
*
|
||||||
|
* Assumes in_path has no extension. If an extension is still
|
||||||
|
* present in 'in_path', it will be ignored.
|
||||||
|
*
|
||||||
|
* 'size' is buffer size of 'out_path'. */
|
||||||
|
void fill_pathname_noext(char *out_path, const char *in_path,
|
||||||
|
const char *replace, size_t size);
|
||||||
|
|
||||||
// Appends a filename extension 'replace' to 'in_path', and outputs result in 'out_path'.
|
/* Appends basename of 'in_basename', to 'in_dir', along with 'replace'.
|
||||||
// Assumes in_path has no extension. If an extension is still present in 'in_path', it will be ignored.
|
* Basename of in_basename is the string after the last '/' or '\\',
|
||||||
// 'size' is buffer size of 'out_path'.
|
* i.e the filename without directories.
|
||||||
void fill_pathname_noext(char *out_path, const char *in_path, const char *replace, size_t size);
|
*
|
||||||
|
* If in_basename has no '/' or '\\', the whole 'in_basename' will be used.
|
||||||
|
* 'size' is buffer size of 'in_dir'.
|
||||||
|
*
|
||||||
|
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
|
||||||
|
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
void fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||||
|
const char *replace, size_t size);
|
||||||
|
|
||||||
// Appends basename of 'in_basename', to 'in_dir', along with 'replace'.
|
/* Copies basename of in_path into out_path. */
|
||||||
// Basename of in_basename is the string after the last '/' or '\\', i.e the filename without directories.
|
|
||||||
// If in_basename has no '/' or '\\', the whole 'in_basename' will be used.
|
|
||||||
// 'size' is buffer size of 'in_dir'.
|
|
||||||
// E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c", replace = ".asm" =>
|
|
||||||
// in_dir = "/tmp/some_dir/foo.c.asm"
|
|
||||||
void fill_pathname_dir(char *in_dir, const char *in_basename, const char *replace, size_t size);
|
|
||||||
|
|
||||||
// Copies basename of in_path into out_path.
|
|
||||||
void fill_pathname_base(char *out_path, const char *in_path, size_t size);
|
void fill_pathname_base(char *out_path, const char *in_path, size_t size);
|
||||||
|
|
||||||
// Copies base directory of in_path into out_path.
|
/* Copies base directory of in_path into out_path.
|
||||||
// If in_path is a path without any slashes (relative current directory), out_path will get path "./".
|
* If in_path is a path without any slashes (relative current directory),
|
||||||
|
* out_path will get path "./". */
|
||||||
void fill_pathname_basedir(char *out_path, const char *in_path, size_t size);
|
void fill_pathname_basedir(char *out_path, const char *in_path, size_t size);
|
||||||
|
|
||||||
// Copies parent directory of in_dir into out_dir.
|
/* Copies parent directory of in_dir into out_dir.
|
||||||
// Assumes in_dir is a directory. Keeps trailing '/'.
|
* Assumes in_dir is a directory. Keeps trailing '/'. */
|
||||||
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);
|
||||||
|
|
||||||
// Joins basedir of in_refpath together with in_path.
|
/* Joins basedir of in_refpath together with in_path.
|
||||||
// If in_path is an absolute path, out_path = in_path.
|
* If in_path is an absolute path, out_path = in_path.
|
||||||
// E.g.: in_refpath = "/foo/bar/baz.a", in_path = "foobar.cg", out_path = "/foo/bar/foobar.cg".
|
* E.g.: in_refpath = "/foo/bar/baz.a", in_path = "foobar.cg",
|
||||||
void fill_pathname_resolve_relative(char *out_path, const char *in_refpath, const char *in_path, size_t size);
|
* out_path = "/foo/bar/foobar.cg". */
|
||||||
|
void fill_pathname_resolve_relative(char *out_path, const char *in_refpath,
|
||||||
|
const char *in_path, size_t size);
|
||||||
|
|
||||||
// Joins a directory and path together. Makes sure not to get two consecutive slashes between dir and path.
|
/* Joins a directory and path together. Makes sure not to get
|
||||||
void fill_pathname_join(char *out_path, const char *dir, const char *path, size_t size);
|
* two consecutive slashes between dir and path. */
|
||||||
|
void fill_pathname_join(char *out_path, const char *dir,
|
||||||
|
const char *path, size_t size);
|
||||||
|
|
||||||
void fill_pathname_expand_special(char *out_path, const char *in_path, size_t size);
|
void fill_pathname_expand_special(char *out_path,
|
||||||
void fill_pathname_abbreviate_special(char *out_path, const char *in_path, size_t size);
|
const char *in_path, size_t size);
|
||||||
|
void fill_pathname_abbreviate_special(char *out_path,
|
||||||
|
const char *in_path, size_t size);
|
||||||
void fill_pathname_slash(char *path, size_t size);
|
void fill_pathname_slash(char *path, size_t size);
|
||||||
|
|
||||||
#ifndef RARCH_CONSOLE
|
#ifndef RARCH_CONSOLE
|
||||||
|
|
41
patch.c
41
patch.c
|
@ -13,8 +13,8 @@
|
||||||
* If not, see <http://www.gnu.org/licenses/>.
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// BPS/UPS/IPS implementation from bSNES (nall::).
|
/* BPS/UPS/IPS implementation from bSNES (nall::).
|
||||||
// Modified for RetroArch.
|
* Modified for RetroArch. */
|
||||||
|
|
||||||
#include "patch.h"
|
#include "patch.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
@ -91,7 +91,8 @@ patch_error_t bps_apply_patch(
|
||||||
bps.modify_checksum = ~0;
|
bps.modify_checksum = ~0;
|
||||||
bps.target_checksum = ~0;
|
bps.target_checksum = ~0;
|
||||||
|
|
||||||
if ((bps_read(&bps) != 'B') || (bps_read(&bps) != 'P') || (bps_read(&bps) != 'S') || (bps_read(&bps) != '1'))
|
if ((bps_read(&bps) != 'B') || (bps_read(&bps) != 'P') ||
|
||||||
|
(bps_read(&bps) != 'S') || (bps_read(&bps) != '1'))
|
||||||
return PATCH_PATCH_INVALID_HEADER;
|
return PATCH_PATCH_INVALID_HEADER;
|
||||||
|
|
||||||
size_t modify_source_size = bps_decode(&bps);
|
size_t modify_source_size = bps_decode(&bps);
|
||||||
|
@ -150,7 +151,9 @@ patch_error_t bps_apply_patch(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t modify_source_checksum = 0, modify_target_checksum = 0, modify_modify_checksum = 0;
|
uint32_t modify_source_checksum = 0, modify_target_checksum = 0,
|
||||||
|
modify_modify_checksum = 0;
|
||||||
|
|
||||||
for (i = 0; i < 32; i += 8)
|
for (i = 0; i < 32; i += 8)
|
||||||
modify_source_checksum |= bps_read(&bps) << i;
|
modify_source_checksum |= bps_read(&bps) << i;
|
||||||
for (i = 0; i < 32; i += 8)
|
for (i = 0; i < 32; i += 8)
|
||||||
|
@ -263,9 +266,11 @@ patch_error_t ups_apply_patch(
|
||||||
unsigned source_read_length = ups_decode(&data);
|
unsigned source_read_length = ups_decode(&data);
|
||||||
unsigned target_read_length = ups_decode(&data);
|
unsigned target_read_length = ups_decode(&data);
|
||||||
|
|
||||||
if (data.source_length != source_read_length && data.source_length != target_read_length)
|
if (data.source_length != source_read_length
|
||||||
|
&& data.source_length != target_read_length)
|
||||||
return PATCH_SOURCE_INVALID;
|
return PATCH_SOURCE_INVALID;
|
||||||
*targetlength = (data.source_length == source_read_length ? target_read_length : source_read_length);
|
*targetlength = (data.source_length == source_read_length ?
|
||||||
|
target_read_length : source_read_length);
|
||||||
if (data.target_length < *targetlength)
|
if (data.target_length < *targetlength)
|
||||||
return PATCH_TARGET_TOO_SMALL;
|
return PATCH_TARGET_TOO_SMALL;
|
||||||
data.target_length = *targetlength;
|
data.target_length = *targetlength;
|
||||||
|
@ -288,7 +293,9 @@ patch_error_t ups_apply_patch(
|
||||||
while (data.target_offset < data.target_length)
|
while (data.target_offset < data.target_length)
|
||||||
ups_target_write(&data, ups_source_read(&data));
|
ups_target_write(&data, ups_source_read(&data));
|
||||||
|
|
||||||
uint32_t patch_read_checksum = 0, source_read_checksum = 0, target_read_checksum = 0;
|
uint32_t patch_read_checksum = 0, source_read_checksum = 0,
|
||||||
|
target_read_checksum = 0;
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
source_read_checksum |= ups_patch_read(&data) << (i * 8);
|
source_read_checksum |= ups_patch_read(&data) << (i * 8);
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
|
@ -304,15 +311,19 @@ patch_error_t ups_apply_patch(
|
||||||
if (patch_result_checksum != patch_read_checksum)
|
if (patch_result_checksum != patch_read_checksum)
|
||||||
return PATCH_PATCH_INVALID;
|
return PATCH_PATCH_INVALID;
|
||||||
|
|
||||||
if (data.source_checksum == source_read_checksum && data.source_length == source_read_length)
|
if (data.source_checksum == source_read_checksum
|
||||||
|
&& data.source_length == source_read_length)
|
||||||
{
|
{
|
||||||
if (data.target_checksum == target_read_checksum && data.target_length == target_read_length)
|
if (data.target_checksum == target_read_checksum
|
||||||
|
&& data.target_length == target_read_length)
|
||||||
return PATCH_SUCCESS;
|
return PATCH_SUCCESS;
|
||||||
return PATCH_TARGET_INVALID;
|
return PATCH_TARGET_INVALID;
|
||||||
}
|
}
|
||||||
else if (data.source_checksum == target_read_checksum && data.source_length == target_read_length)
|
else if (data.source_checksum == target_read_checksum
|
||||||
|
&& data.source_length == target_read_length)
|
||||||
{
|
{
|
||||||
if (data.target_checksum == source_read_checksum && data.target_length == source_read_length)
|
if (data.target_checksum == source_read_checksum
|
||||||
|
&& data.target_length == source_read_length)
|
||||||
return PATCH_SUCCESS;
|
return PATCH_SUCCESS;
|
||||||
return PATCH_TARGET_INVALID;
|
return PATCH_TARGET_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -347,7 +358,7 @@ patch_error_t ips_apply_patch(
|
||||||
address |= patchdata[offset++] << 8;
|
address |= patchdata[offset++] << 8;
|
||||||
address |= patchdata[offset++] << 0;
|
address |= patchdata[offset++] << 0;
|
||||||
|
|
||||||
if (address == 0x454f46) // EOF
|
if (address == 0x454f46) /* EOF */
|
||||||
{
|
{
|
||||||
if (offset == patchlen)
|
if (offset == patchlen)
|
||||||
return PATCH_SUCCESS;
|
return PATCH_SUCCESS;
|
||||||
|
@ -367,7 +378,7 @@ patch_error_t ips_apply_patch(
|
||||||
unsigned length = patchdata[offset++] << 8;
|
unsigned length = patchdata[offset++] << 8;
|
||||||
length |= patchdata[offset++] << 0;
|
length |= patchdata[offset++] << 0;
|
||||||
|
|
||||||
if (length) // Copy
|
if (length) /* Copy */
|
||||||
{
|
{
|
||||||
if (offset > patchlen - length)
|
if (offset > patchlen - length)
|
||||||
break;
|
break;
|
||||||
|
@ -375,7 +386,7 @@ patch_error_t ips_apply_patch(
|
||||||
while (length--)
|
while (length--)
|
||||||
targetdata[address++] = patchdata[offset++];
|
targetdata[address++] = patchdata[offset++];
|
||||||
}
|
}
|
||||||
else // RLE
|
else /* RLE */
|
||||||
{
|
{
|
||||||
if (offset > patchlen - 3)
|
if (offset > patchlen - 3)
|
||||||
break;
|
break;
|
||||||
|
@ -383,7 +394,7 @@ patch_error_t ips_apply_patch(
|
||||||
length = patchdata[offset++] << 8;
|
length = patchdata[offset++] << 8;
|
||||||
length |= patchdata[offset++] << 0;
|
length |= patchdata[offset++] << 0;
|
||||||
|
|
||||||
if (length == 0) // Illegal
|
if (length == 0) /* Illegal */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
while (length--)
|
while (length--)
|
||||||
|
|
7
patch.h
7
patch.h
|
@ -19,8 +19,8 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
// BPS/UPS/IPS implementation from bSNES (nall::).
|
/* BPS/UPS/IPS implementation from bSNES (nall::).
|
||||||
// Modified for RetroArch.
|
* Modified for RetroArch. */
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -38,7 +38,8 @@ typedef enum
|
||||||
PATCH_PATCH_CHECKSUM_INVALID
|
PATCH_PATCH_CHECKSUM_INVALID
|
||||||
} patch_error_t;
|
} patch_error_t;
|
||||||
|
|
||||||
typedef patch_error_t (*patch_func_t)(const uint8_t*, size_t, const uint8_t*, size_t, uint8_t*, size_t*);
|
typedef patch_error_t (*patch_func_t)(const uint8_t*, size_t,
|
||||||
|
const uint8_t*, size_t, uint8_t*, size_t*);
|
||||||
|
|
||||||
patch_error_t bps_apply_patch(
|
patch_error_t bps_apply_patch(
|
||||||
const uint8_t *patch_data, size_t patch_length,
|
const uint8_t *patch_data, size_t patch_length,
|
||||||
|
|
8
rewind.h
8
rewind.h
|
@ -22,10 +22,16 @@
|
||||||
typedef struct state_manager state_manager_t;
|
typedef struct state_manager state_manager_t;
|
||||||
|
|
||||||
state_manager_t *state_manager_new(size_t state_size, size_t buffer_size);
|
state_manager_t *state_manager_new(size_t state_size, size_t buffer_size);
|
||||||
|
|
||||||
void state_manager_free(state_manager_t *state);
|
void state_manager_free(state_manager_t *state);
|
||||||
|
|
||||||
bool state_manager_pop(state_manager_t *state, const void **data);
|
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);
|
||||||
|
|
||||||
void state_manager_push_do(state_manager_t *state);
|
void state_manager_push_do(state_manager_t *state);
|
||||||
void state_manager_capacity(state_manager_t *state, unsigned int *entries, size_t *bytes, bool *full);
|
|
||||||
|
void state_manager_capacity(state_manager_t *state,
|
||||||
|
unsigned int *entries, size_t *bytes, bool *full);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
8
thread.h
8
thread.h
|
@ -24,16 +24,16 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Implements the bare minimum needed for RetroArch. :)
|
/* Implements the bare minimum needed for RetroArch. */
|
||||||
|
|
||||||
typedef struct sthread sthread_t;
|
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);
|
||||||
|
@ -42,7 +42,7 @@ 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);
|
||||||
|
|
Loading…
Reference in New Issue