mirror of
https://github.com/libretro/beetle-psx-libretro.git
synced 2024-11-23 08:49:47 +00:00
Update libretro-common
This commit is contained in:
parent
9839a46682
commit
4b1b114507
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2019 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (cdrom.c).
|
* The following license statement only applies to this file (cdrom.c).
|
||||||
@ -96,6 +96,7 @@ void increment_msf(unsigned char *min, unsigned char *sec, unsigned char *frame)
|
|||||||
*frame = (*frame < 74) ? (*frame + 1) : 0;
|
*frame = (*frame < 74) ? (*frame + 1) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
static void cdrom_print_sense_data(const unsigned char *sense, size_t len)
|
static void cdrom_print_sense_data(const unsigned char *sense, size_t len)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
@ -175,7 +176,7 @@ static void cdrom_print_sense_data(const unsigned char *sense, size_t len)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("[CDROM] Sense Key: %02X (%s)\n", key, sense_key_text);
|
printf("[CDROM] Sense Key: %02X (%s)\n", key, sense_key_text ? sense_key_text : "null");
|
||||||
printf("[CDROM] ASC: %02X\n", asc);
|
printf("[CDROM] ASC: %02X\n", asc);
|
||||||
printf("[CDROM] ASCQ: %02X\n", ascq);
|
printf("[CDROM] ASCQ: %02X\n", ascq);
|
||||||
|
|
||||||
@ -252,6 +253,7 @@ static void cdrom_print_sense_data(const unsigned char *sense, size_t len)
|
|||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(_XBOX)
|
#if defined(_WIN32) && !defined(_XBOX)
|
||||||
static int cdrom_send_command_win32(const libretro_vfs_implementation_file *stream, CDROM_CMD_Direction dir, void *buf, size_t len, unsigned char *cmd, size_t cmd_len, unsigned char *sense, size_t sense_len)
|
static int cdrom_send_command_win32(const libretro_vfs_implementation_file *stream, CDROM_CMD_Direction dir, void *buf, size_t len, unsigned char *cmd, size_t cmd_len, unsigned char *sense, size_t sense_len)
|
||||||
@ -519,7 +521,9 @@ retry:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
cdrom_print_sense_data(sense, sizeof(sense));
|
cdrom_print_sense_data(sense, sizeof(sense));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* INQUIRY/TEST/SENSE should never fail, don't retry. */
|
/* INQUIRY/TEST/SENSE should never fail, don't retry. */
|
||||||
/* READ ATIP seems to fail outright on some drives with pressed discs, skip retries. */
|
/* READ ATIP seems to fail outright on some drives with pressed discs, skip retries. */
|
||||||
@ -672,7 +676,9 @@ int cdrom_get_sense(libretro_vfs_implementation_file *stream, unsigned char *sen
|
|||||||
if (rv)
|
if (rv)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
cdrom_print_sense_data(buf, sizeof(buf));
|
cdrom_print_sense_data(buf, sizeof(buf));
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -931,23 +937,23 @@ int cdrom_read_subq(libretro_vfs_implementation_file *stream, unsigned char *buf
|
|||||||
if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point >= 1 && point <= 99)
|
if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point >= 1 && point <= 99)
|
||||||
{
|
{
|
||||||
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
|
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
|
||||||
printf("[CDROM] Track start time: (MSF %02u:%02u:%02u) ", (unsigned)pmin, (unsigned)psec, (unsigned)pframe);
|
printf("Track start time: (aMSF %02u:%02u:%02u) ", (unsigned)pmin, (unsigned)psec, (unsigned)pframe);
|
||||||
}
|
}
|
||||||
else if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point == 0xA0)
|
else if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point == 0xA0)
|
||||||
{
|
{
|
||||||
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
|
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
|
||||||
printf("[CDROM] First Track Number: %d ", pmin);
|
printf("First Track Number: %d ", pmin);
|
||||||
printf("[CDROM] Disc Type: %d ", psec);
|
printf("Disc Type: %d ", psec);
|
||||||
}
|
}
|
||||||
else if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point == 0xA1)
|
else if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point == 0xA1)
|
||||||
{
|
{
|
||||||
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
|
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
|
||||||
printf("[CDROM] Last Track Number: %d ", pmin);
|
printf("Last Track Number: %d ", pmin);
|
||||||
}
|
}
|
||||||
else if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point == 0xA2)
|
else if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point == 0xA2)
|
||||||
{
|
{
|
||||||
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
|
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
|
||||||
printf("[CDROM] Lead-out runtime: (MSF %02u:%02u:%02u) ", (unsigned)pmin, (unsigned)psec, (unsigned)pframe);
|
printf("Lead-out start time: (aMSF %02u:%02u:%02u) ", (unsigned)pmin, (unsigned)psec, (unsigned)pframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@ -992,10 +998,10 @@ static int cdrom_read_track_info(libretro_vfs_implementation_file *stream, unsig
|
|||||||
|
|
||||||
#ifdef CDROM_DEBUG
|
#ifdef CDROM_DEBUG
|
||||||
printf("[CDROM] Track %d Info: ", track);
|
printf("[CDROM] Track %d Info: ", track);
|
||||||
printf("[CDROM] Copy: %d ", (buf[5] & 0x10) > 0);
|
printf("Copy: %d ", (buf[5] & 0x10) > 0);
|
||||||
printf("[CDROM] Data Mode: %d ", toc->track[track - 1].mode);
|
printf("Data Mode: %d ", toc->track[track - 1].mode);
|
||||||
printf("[CDROM] LBA Start: %d (%d) ", lba, toc->track[track - 1].lba);
|
printf("LBA Start: %d (%d) ", lba, toc->track[track - 1].lba);
|
||||||
printf("[CDROM] Track Size: %d\n", track_size);
|
printf("Track Size: %d\n", track_size);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1329,24 +1335,35 @@ struct string_list* cdrom_get_available_drives(void)
|
|||||||
#if defined(__linux__) && !defined(ANDROID)
|
#if defined(__linux__) && !defined(ANDROID)
|
||||||
struct string_list *dir_list = dir_list_new("/dev", NULL, false, false, false, false);
|
struct string_list *dir_list = dir_list_new("/dev", NULL, false, false, false, false);
|
||||||
int i;
|
int i;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
if (!dir_list)
|
if (!dir_list)
|
||||||
return list;
|
return list;
|
||||||
|
|
||||||
for (i = 0; i < (int)dir_list->size; i++)
|
for (i = 0; i < (int)dir_list->size; i++)
|
||||||
{
|
{
|
||||||
if (strstr(dir_list->elems[i].data, "/dev/sg"))
|
if (string_starts_with_size(dir_list->elems[i].data, "/dev/sg",
|
||||||
|
STRLEN_CONST("/dev/sg")))
|
||||||
{
|
{
|
||||||
|
libretro_vfs_implementation_file *stream;
|
||||||
char drive_model[32] = {0};
|
char drive_model[32] = {0};
|
||||||
char drive_string[33] = {0};
|
char drive_string[33] = {0};
|
||||||
union string_list_elem_attr attr = {0};
|
union string_list_elem_attr attr = {0};
|
||||||
int dev_index = 0;
|
int dev_index = 0;
|
||||||
RFILE *file = filestream_open(dir_list->elems[i].data, RETRO_VFS_FILE_ACCESS_READ, 0);
|
RFILE *file = filestream_open(
|
||||||
libretro_vfs_implementation_file *stream;
|
dir_list->elems[i].data, RETRO_VFS_FILE_ACCESS_READ, 0);
|
||||||
bool is_cdrom = false;
|
bool is_cdrom = false;
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
|
{
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] Could not open %s, please check permissions.\n", dir_list->elems[i].data);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
stream = filestream_get_vfs_handle(file);
|
stream = filestream_get_vfs_handle(file);
|
||||||
cdrom_get_inquiry(stream, drive_model, sizeof(drive_model), &is_cdrom);
|
cdrom_get_inquiry(stream, drive_model, sizeof(drive_model), &is_cdrom);
|
||||||
@ -1355,7 +1372,8 @@ struct string_list* cdrom_get_available_drives(void)
|
|||||||
if (!is_cdrom)
|
if (!is_cdrom)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
sscanf(dir_list->elems[i].data + strlen("/dev/sg"), "%d", &dev_index);
|
sscanf(dir_list->elems[i].data + STRLEN_CONST("/dev/sg"),
|
||||||
|
"%d", &dev_index);
|
||||||
|
|
||||||
dev_index = '0' + dev_index;
|
dev_index = '0' + dev_index;
|
||||||
attr.i = dev_index;
|
attr.i = dev_index;
|
||||||
@ -1369,6 +1387,56 @@ struct string_list* cdrom_get_available_drives(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
char *buf = NULL;
|
||||||
|
int64_t len = 0;
|
||||||
|
|
||||||
|
if (filestream_read_file("/proc/modules", (void**)&buf, &len))
|
||||||
|
{
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
bool found = false;
|
||||||
|
#endif
|
||||||
|
struct string_list *mods = string_split(buf, "\n");
|
||||||
|
|
||||||
|
if (mods)
|
||||||
|
{
|
||||||
|
for (i = 0; i < mods->size; i++)
|
||||||
|
{
|
||||||
|
if (strcasestr(mods->elems[i].data, "sg "))
|
||||||
|
{
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
found = true;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string_list_free(mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
printf("[CDROM] No sg devices found but kernel module is loaded.\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("[CDROM] No sg devices found and sg kernel module is not loaded.\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("[CDROM] No sg devices found, could not check if sg kernel module is loaded.\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
string_list_free(dir_list);
|
string_list_free(dir_list);
|
||||||
#endif
|
#endif
|
||||||
#if defined(_WIN32) && !defined(_XBOX)
|
#if defined(_WIN32) && !defined(_XBOX)
|
||||||
@ -1444,9 +1512,7 @@ bool cdrom_is_media_inserted(libretro_vfs_implementation_file *stream)
|
|||||||
bool cdrom_drive_has_media(const char drive)
|
bool cdrom_drive_has_media(const char drive)
|
||||||
{
|
{
|
||||||
RFILE *file;
|
RFILE *file;
|
||||||
char cdrom_path_bin[256];
|
char cdrom_path_bin[256] = {0};
|
||||||
|
|
||||||
cdrom_path_bin[0] = '\0';
|
|
||||||
|
|
||||||
cdrom_device_fillpath(cdrom_path_bin, sizeof(cdrom_path_bin), drive, 1, false);
|
cdrom_device_fillpath(cdrom_path_bin, sizeof(cdrom_path_bin), drive, 1, false);
|
||||||
|
|
||||||
@ -1640,8 +1706,11 @@ void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char tra
|
|||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
pos = strlcpy(path, "cdrom://drive", len);
|
pos = strlcpy(path, "cdrom://drive", len);
|
||||||
|
|
||||||
if (len > pos)
|
if (len > pos + 1)
|
||||||
|
{
|
||||||
path[pos++] = drive;
|
path[pos++] = drive;
|
||||||
|
path[pos] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
pos = strlcat(path, ".cue", len);
|
pos = strlcat(path, ".cue", len);
|
||||||
#endif
|
#endif
|
||||||
@ -1652,8 +1721,11 @@ void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char tra
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
pos = strlcpy(path, "cdrom://", len);
|
pos = strlcpy(path, "cdrom://", len);
|
||||||
|
|
||||||
if (len > pos)
|
if (len > pos + 1)
|
||||||
|
{
|
||||||
path[pos++] = drive;
|
path[pos++] = drive;
|
||||||
|
path[pos] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
pos += snprintf(path + pos, len - pos, ":/drive-track%02d.bin", track);
|
pos += snprintf(path + pos, len - pos, ":/drive-track%02d.bin", track);
|
||||||
#else
|
#else
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (compat_posix_string.c).
|
* The following license statement only applies to this file (compat_posix_string.c).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (compat_snprintf.c).
|
* The following license statement only applies to this file (compat_snprintf.c).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (compat_strcasestr.c).
|
* The following license statement only applies to this file (compat_strcasestr.c).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (compat_strl.c).
|
* The following license statement only applies to this file (compat_strl.c).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (fopen_utf8.c).
|
* The following license statement only applies to this file (fopen_utf8.c).
|
||||||
@ -36,9 +36,7 @@
|
|||||||
|
|
||||||
void *fopen_utf8(const char * filename, const char * mode)
|
void *fopen_utf8(const char * filename, const char * mode)
|
||||||
{
|
{
|
||||||
#if defined(_XBOX)
|
#if defined(LEGACY_WIN32)
|
||||||
return fopen(filename, mode);
|
|
||||||
#elif defined(LEGACY_WIN32)
|
|
||||||
FILE *ret = NULL;
|
FILE *ret = NULL;
|
||||||
char * filename_local = utf8_to_local_string_alloc(filename);
|
char * filename_local = utf8_to_local_string_alloc(filename);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (encoding_utf.c).
|
* The following license statement only applies to this file (encoding_utf.c).
|
||||||
@ -37,6 +37,8 @@
|
|||||||
#include <xtl.h>
|
#include <xtl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define UTF8_WALKBYTE(string) (*((*(string))++))
|
||||||
|
|
||||||
static unsigned leading_ones(uint8_t c)
|
static unsigned leading_ones(uint8_t c)
|
||||||
{
|
{
|
||||||
unsigned ones = 0;
|
unsigned ones = 0;
|
||||||
@ -89,13 +91,14 @@ size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
|
|||||||
bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
|
bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
|
||||||
const uint16_t *in, size_t in_size)
|
const uint16_t *in, size_t in_size)
|
||||||
{
|
{
|
||||||
static uint8_t kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
|
||||||
size_t out_pos = 0;
|
size_t out_pos = 0;
|
||||||
size_t in_pos = 0;
|
size_t in_pos = 0;
|
||||||
|
static const
|
||||||
|
uint8_t utf8_limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
unsigned numAdds;
|
unsigned num_adds;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
|
|
||||||
if (in_pos == in_size)
|
if (in_pos == in_size)
|
||||||
@ -124,21 +127,21 @@ bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
|
|||||||
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
|
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (numAdds = 1; numAdds < 5; numAdds++)
|
for (num_adds = 1; num_adds < 5; num_adds++)
|
||||||
if (value < (((uint32_t)1) << (numAdds * 5 + 6)))
|
if (value < (((uint32_t)1) << (num_adds * 5 + 6)))
|
||||||
break;
|
break;
|
||||||
if (out)
|
if (out)
|
||||||
out[out_pos] = (char)(kUtf8Limits[numAdds - 1]
|
out[out_pos] = (char)(utf8_limits[num_adds - 1]
|
||||||
+ (value >> (6 * numAdds)));
|
+ (value >> (6 * num_adds)));
|
||||||
out_pos++;
|
out_pos++;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
numAdds--;
|
num_adds--;
|
||||||
if (out)
|
if (out)
|
||||||
out[out_pos] = (char)(0x80
|
out[out_pos] = (char)(0x80
|
||||||
+ ((value >> (6 * numAdds)) & 0x3F));
|
+ ((value >> (6 * num_adds)) & 0x3F));
|
||||||
out_pos++;
|
out_pos++;
|
||||||
}while (numAdds != 0);
|
}while (num_adds != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_chars = out_pos;
|
*out_chars = out_pos;
|
||||||
@ -166,13 +169,15 @@ size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars)
|
|||||||
while (*sb && chars-- > 0)
|
while (*sb && chars-- > 0)
|
||||||
{
|
{
|
||||||
sb++;
|
sb++;
|
||||||
while ((*sb & 0xC0) == 0x80) sb++;
|
while ((*sb & 0xC0) == 0x80)
|
||||||
|
sb++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((size_t)(sb - sb_org) > d_len-1 /* NUL */)
|
if ((size_t)(sb - sb_org) > d_len-1 /* NUL */)
|
||||||
{
|
{
|
||||||
sb = sb_org + d_len-1;
|
sb = sb_org + d_len-1;
|
||||||
while ((*sb & 0xC0) == 0x80) sb--;
|
while ((*sb & 0xC0) == 0x80)
|
||||||
|
sb--;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(d, sb_org, sb-sb_org);
|
memcpy(d, sb_org, sb-sb_org);
|
||||||
@ -184,14 +189,18 @@ size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars)
|
|||||||
const char *utf8skip(const char *str, size_t chars)
|
const char *utf8skip(const char *str, size_t chars)
|
||||||
{
|
{
|
||||||
const uint8_t *strb = (const uint8_t*)str;
|
const uint8_t *strb = (const uint8_t*)str;
|
||||||
|
|
||||||
if (!chars)
|
if (!chars)
|
||||||
return str;
|
return str;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
strb++;
|
strb++;
|
||||||
while ((*strb & 0xC0)==0x80) strb++;
|
while ((*strb & 0xC0)==0x80)
|
||||||
|
strb++;
|
||||||
chars--;
|
chars--;
|
||||||
}while (chars);
|
}while (chars);
|
||||||
|
|
||||||
return (const char*)strb;
|
return (const char*)strb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,24 +220,22 @@ size_t utf8len(const char *string)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define utf8_walkbyte(string) (*((*(string))++))
|
|
||||||
|
|
||||||
/* Does not validate the input, returns garbage if it's not UTF-8. */
|
/* Does not validate the input, returns garbage if it's not UTF-8. */
|
||||||
uint32_t utf8_walk(const char **string)
|
uint32_t utf8_walk(const char **string)
|
||||||
{
|
{
|
||||||
uint8_t first = utf8_walkbyte(string);
|
uint8_t first = UTF8_WALKBYTE(string);
|
||||||
uint32_t ret = 0;
|
uint32_t ret = 0;
|
||||||
|
|
||||||
if (first < 128)
|
if (first < 128)
|
||||||
return first;
|
return first;
|
||||||
|
|
||||||
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
ret = (ret << 6) | (UTF8_WALKBYTE(string) & 0x3F);
|
||||||
if (first >= 0xE0)
|
if (first >= 0xE0)
|
||||||
{
|
{
|
||||||
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
ret = (ret << 6) | (UTF8_WALKBYTE(string) & 0x3F);
|
||||||
if (first >= 0xF0)
|
if (first >= 0xF0)
|
||||||
{
|
{
|
||||||
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
ret = (ret << 6) | (UTF8_WALKBYTE(string) & 0x3F);
|
||||||
return ret | (first & 7) << 18;
|
return ret | (first & 7) << 18;
|
||||||
}
|
}
|
||||||
return ret | (first & 15) << 12;
|
return ret | (first & 15) << 12;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2019 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (file_path.c).
|
* The following license statement only applies to this file (file_path.c).
|
||||||
@ -32,8 +32,7 @@
|
|||||||
#include <file/file_path.h>
|
#include <file/file_path.h>
|
||||||
#include <retro_assert.h>
|
#include <retro_assert.h>
|
||||||
#include <string/stdstring.h>
|
#include <string/stdstring.h>
|
||||||
#define VFS_FRONTEND
|
#include <time/rtime.h>
|
||||||
#include <vfs/vfs_implementation.h>
|
|
||||||
|
|
||||||
/* TODO: There are probably some unnecessary things on this huge include list now but I'm too afraid to touch it */
|
/* TODO: There are probably some unnecessary things on this huge include list now but I'm too afraid to touch it */
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
@ -46,7 +45,6 @@
|
|||||||
#include <compat/strl.h>
|
#include <compat/strl.h>
|
||||||
#include <compat/posix_string.h>
|
#include <compat/posix_string.h>
|
||||||
#endif
|
#endif
|
||||||
#include <compat/strcasestr.h>
|
|
||||||
#include <retro_miscellaneous.h>
|
#include <retro_miscellaneous.h>
|
||||||
#include <encodings/utf.h>
|
#include <encodings/utf.h>
|
||||||
|
|
||||||
@ -82,12 +80,7 @@
|
|||||||
#include <pspkernel.h>
|
#include <pspkernel.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PS2)
|
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||||
#include <fileXio_rpc.h>
|
|
||||||
#include <fileXio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__CELLOS_LV2__)
|
|
||||||
#include <cell/cell_fs.h>
|
#include <cell/cell_fs.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -95,7 +88,7 @@
|
|||||||
#define FIO_S_ISDIR SCE_S_ISDIR
|
#define FIO_S_ISDIR SCE_S_ISDIR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP) || defined(PS2)
|
#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
|
||||||
|
|
||||||
@ -114,137 +107,6 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static retro_vfs_stat_t path_stat_cb = NULL;
|
|
||||||
static retro_vfs_mkdir_t path_mkdir_cb = NULL;
|
|
||||||
|
|
||||||
void path_vfs_init(const struct retro_vfs_interface_info* vfs_info)
|
|
||||||
{
|
|
||||||
const struct retro_vfs_interface*
|
|
||||||
vfs_iface = vfs_info->iface;
|
|
||||||
|
|
||||||
path_stat_cb = NULL;
|
|
||||||
path_mkdir_cb = NULL;
|
|
||||||
|
|
||||||
if (vfs_info->required_interface_version < PATH_REQUIRED_VFS_VERSION || !vfs_iface)
|
|
||||||
return;
|
|
||||||
|
|
||||||
path_stat_cb = vfs_iface->stat;
|
|
||||||
path_mkdir_cb = vfs_iface->mkdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define path_stat_internal(path, size) ((path_stat_cb != NULL) ? path_stat_cb((path), (size)) : retro_vfs_stat_impl((path), (size)))
|
|
||||||
|
|
||||||
#define path_mkdir_norecurse(dir) ((path_mkdir_cb != NULL) ? path_mkdir_cb((dir)) : retro_vfs_mkdir_impl((dir)))
|
|
||||||
|
|
||||||
int path_stat(const char *path)
|
|
||||||
{
|
|
||||||
return path_stat_internal(path, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* path_is_directory:
|
|
||||||
* @path : path
|
|
||||||
*
|
|
||||||
* Checks if path is a directory.
|
|
||||||
*
|
|
||||||
* Returns: true (1) if path is a directory, otherwise false (0).
|
|
||||||
*/
|
|
||||||
bool path_is_directory(const char *path)
|
|
||||||
{
|
|
||||||
return (path_stat_internal(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool path_is_character_special(const char *path)
|
|
||||||
{
|
|
||||||
return (path_stat_internal(path, NULL) & RETRO_VFS_STAT_IS_CHARACTER_SPECIAL) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool path_is_valid(const char *path)
|
|
||||||
{
|
|
||||||
return (path_stat_internal(path, NULL) & RETRO_VFS_STAT_IS_VALID) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t path_get_size(const char *path)
|
|
||||||
{
|
|
||||||
int32_t filesize = 0;
|
|
||||||
if (path_stat_internal(path, &filesize) != 0)
|
|
||||||
return filesize;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* path_mkdir:
|
|
||||||
* @dir : directory
|
|
||||||
*
|
|
||||||
* Create directory on filesystem.
|
|
||||||
*
|
|
||||||
* Returns: true (1) if directory could be created, otherwise false (0).
|
|
||||||
**/
|
|
||||||
bool path_mkdir(const char *dir)
|
|
||||||
{
|
|
||||||
bool sret = false;
|
|
||||||
bool norecurse = false;
|
|
||||||
char *basedir = NULL;
|
|
||||||
|
|
||||||
if (!(dir && *dir))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* Use heap. Real chance of stack
|
|
||||||
* overflow if we recurse too hard. */
|
|
||||||
basedir = strdup(dir);
|
|
||||||
|
|
||||||
if (!basedir)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
path_parent_dir(basedir);
|
|
||||||
|
|
||||||
if (!*basedir || !strcmp(basedir, dir))
|
|
||||||
{
|
|
||||||
free(basedir);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(GEKKO)
|
|
||||||
{
|
|
||||||
size_t len = strlen(basedir);
|
|
||||||
|
|
||||||
/* path_parent_dir() keeps the trailing slash.
|
|
||||||
* On Wii, mkdir() fails if the path has a
|
|
||||||
* trailing slash...
|
|
||||||
* We must therefore remove it. */
|
|
||||||
if (len > 0)
|
|
||||||
if (basedir[len - 1] == '/')
|
|
||||||
basedir[len - 1] = '\0';
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (path_is_directory(basedir))
|
|
||||||
norecurse = true;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sret = path_mkdir(basedir);
|
|
||||||
|
|
||||||
if (sret)
|
|
||||||
norecurse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(basedir);
|
|
||||||
|
|
||||||
if (norecurse)
|
|
||||||
{
|
|
||||||
int ret = path_mkdir_norecurse(dir);
|
|
||||||
|
|
||||||
/* Don't treat this as an error. */
|
|
||||||
if (ret == -2 && path_is_directory(dir))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return (ret == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* path_get_archive_delim:
|
* path_get_archive_delim:
|
||||||
* @path : path
|
* @path : path
|
||||||
@ -257,26 +119,48 @@ bool path_mkdir(const char *dir)
|
|||||||
*/
|
*/
|
||||||
const char *path_get_archive_delim(const char *path)
|
const char *path_get_archive_delim(const char *path)
|
||||||
{
|
{
|
||||||
const char *last = find_last_slash(path);
|
const char *last_slash = find_last_slash(path);
|
||||||
const char *delim = NULL;
|
const char *delim = NULL;
|
||||||
|
char buf[5];
|
||||||
|
|
||||||
if (!last)
|
buf[0] = '\0';
|
||||||
|
|
||||||
|
if (!last_slash)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Test if it's .zip */
|
/* Find delimiter position */
|
||||||
delim = strcasestr(last, ".zip#");
|
delim = strrchr(last_slash, '#');
|
||||||
|
|
||||||
if (!delim) /* If it's not a .zip, test if it's .apk */
|
if (!delim)
|
||||||
delim = strcasestr(last, ".apk#");
|
return NULL;
|
||||||
|
|
||||||
if (delim)
|
/* Check whether this is a known archive type
|
||||||
return delim + 4;
|
* > Note: The code duplication here is
|
||||||
|
* deliberate, to maximise performance */
|
||||||
|
if (delim - last_slash > 4)
|
||||||
|
{
|
||||||
|
strlcpy(buf, delim - 4, sizeof(buf));
|
||||||
|
buf[4] = '\0';
|
||||||
|
|
||||||
/* If it's not a .zip or .apk file, test if it's .7z */
|
string_to_lower(buf);
|
||||||
delim = strcasestr(last, ".7z#");
|
|
||||||
|
|
||||||
if (delim)
|
/* Check if this is a '.zip', '.apk' or '.7z' file */
|
||||||
return delim + 3;
|
if (string_is_equal(buf, ".zip") ||
|
||||||
|
string_is_equal(buf, ".apk") ||
|
||||||
|
string_is_equal(buf + 1, ".7z"))
|
||||||
|
return delim;
|
||||||
|
}
|
||||||
|
else if (delim - last_slash > 3)
|
||||||
|
{
|
||||||
|
strlcpy(buf, delim - 3, sizeof(buf));
|
||||||
|
buf[3] = '\0';
|
||||||
|
|
||||||
|
string_to_lower(buf);
|
||||||
|
|
||||||
|
/* Check if this is a '.7z' file */
|
||||||
|
if (string_is_equal(buf, ".7z"))
|
||||||
|
return delim;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -335,9 +219,12 @@ bool path_is_compressed_file(const char* path)
|
|||||||
{
|
{
|
||||||
const char *ext = path_get_extension(path);
|
const char *ext = path_get_extension(path);
|
||||||
|
|
||||||
if ( strcasestr(ext, "zip")
|
if (string_is_empty(ext))
|
||||||
|| strcasestr(ext, "apk")
|
return false;
|
||||||
|| strcasestr(ext, "7z"))
|
|
||||||
|
if (string_is_equal_noncase(ext, "zip") ||
|
||||||
|
string_is_equal_noncase(ext, "apk") ||
|
||||||
|
string_is_equal_noncase(ext, "7z"))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -393,11 +280,11 @@ void fill_pathname(char *out_path, const char *in_path,
|
|||||||
* present in 'in_path', it will be ignored.
|
* present in 'in_path', it will be ignored.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void fill_pathname_noext(char *out_path, const char *in_path,
|
size_t fill_pathname_noext(char *out_path, const char *in_path,
|
||||||
const char *replace, size_t size)
|
const char *replace, size_t size)
|
||||||
{
|
{
|
||||||
strlcpy(out_path, in_path, size);
|
strlcpy(out_path, in_path, size);
|
||||||
strlcat(out_path, replace, size);
|
return strlcat(out_path, replace, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *find_last_slash(const char *str)
|
char *find_last_slash(const char *str)
|
||||||
@ -427,7 +314,7 @@ void fill_pathname_slash(char *path, size_t size)
|
|||||||
|
|
||||||
if (!last_slash)
|
if (!last_slash)
|
||||||
{
|
{
|
||||||
strlcat(path, path_default_slash(), size);
|
strlcat(path, PATH_DEFAULT_SLASH(), size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,12 +322,8 @@ void fill_pathname_slash(char *path, size_t size)
|
|||||||
/* Try to preserve slash type. */
|
/* Try to preserve slash type. */
|
||||||
if (last_slash != (path + path_len - 1))
|
if (last_slash != (path + path_len - 1))
|
||||||
{
|
{
|
||||||
char join_str[2];
|
path[path_len] = last_slash[0];
|
||||||
|
path[path_len+1] = '\0';
|
||||||
join_str[0] = '\0';
|
|
||||||
|
|
||||||
strlcpy(join_str, last_slash, sizeof(join_str));
|
|
||||||
strlcat(path, join_str, size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,7 +344,7 @@ void fill_pathname_slash(char *path, size_t size)
|
|||||||
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
|
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
|
||||||
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
|
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
|
||||||
**/
|
**/
|
||||||
void fill_pathname_dir(char *in_dir, const char *in_basename,
|
size_t fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||||
const char *replace, size_t size)
|
const char *replace, size_t size)
|
||||||
{
|
{
|
||||||
const char *base = NULL;
|
const char *base = NULL;
|
||||||
@ -469,7 +352,7 @@ void fill_pathname_dir(char *in_dir, const char *in_basename,
|
|||||||
fill_pathname_slash(in_dir, size);
|
fill_pathname_slash(in_dir, size);
|
||||||
base = path_basename(in_basename);
|
base = path_basename(in_basename);
|
||||||
strlcat(in_dir, base, size);
|
strlcat(in_dir, base, size);
|
||||||
strlcat(in_dir, replace, size);
|
return strlcat(in_dir, replace, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -480,14 +363,14 @@ void fill_pathname_dir(char *in_dir, const char *in_basename,
|
|||||||
*
|
*
|
||||||
* Copies basename of @in_path into @out_path.
|
* Copies basename of @in_path into @out_path.
|
||||||
**/
|
**/
|
||||||
void fill_pathname_base(char *out, const char *in_path, size_t size)
|
size_t fill_pathname_base(char *out, const char *in_path, size_t size)
|
||||||
{
|
{
|
||||||
const char *ptr = path_basename(in_path);
|
const char *ptr = path_basename(in_path);
|
||||||
|
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
ptr = in_path;
|
ptr = in_path;
|
||||||
|
|
||||||
strlcpy(out, ptr, size);
|
return strlcpy(out, ptr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_base_noext(char *out,
|
void fill_pathname_base_noext(char *out,
|
||||||
@ -497,12 +380,12 @@ void fill_pathname_base_noext(char *out,
|
|||||||
path_remove_extension(out);
|
path_remove_extension(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_base_ext(char *out,
|
size_t fill_pathname_base_ext(char *out,
|
||||||
const char *in_path, const char *ext,
|
const char *in_path, const char *ext,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
fill_pathname_base_noext(out, in_path, size);
|
fill_pathname_base_noext(out, in_path, size);
|
||||||
strlcat(out, ext, size);
|
return strlcat(out, ext, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -597,15 +480,17 @@ void fill_pathname_parent_dir(char *out_dir,
|
|||||||
* E.g.:
|
* E.g.:
|
||||||
* out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
|
* out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
|
||||||
**/
|
**/
|
||||||
void fill_dated_filename(char *out_filename,
|
size_t fill_dated_filename(char *out_filename,
|
||||||
const char *ext, size_t size)
|
const char *ext, size_t size)
|
||||||
{
|
{
|
||||||
time_t cur_time = time(NULL);
|
time_t cur_time = time(NULL);
|
||||||
const struct tm* tm_ = localtime(&cur_time);
|
struct tm tm_;
|
||||||
|
|
||||||
|
rtime_localtime(&cur_time, &tm_);
|
||||||
|
|
||||||
strftime(out_filename, size,
|
strftime(out_filename, size,
|
||||||
"RetroArch-%m%d-%H%M%S", tm_);
|
"RetroArch-%m%d-%H%M%S", &tm_);
|
||||||
strlcat(out_filename, ext, size);
|
return strlcat(out_filename, ext, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -625,19 +510,21 @@ void fill_str_dated_filename(char *out_filename,
|
|||||||
const char *in_str, const char *ext, size_t size)
|
const char *in_str, const char *ext, size_t size)
|
||||||
{
|
{
|
||||||
char format[256];
|
char format[256];
|
||||||
|
struct tm tm_;
|
||||||
time_t cur_time = time(NULL);
|
time_t cur_time = time(NULL);
|
||||||
const struct tm* tm_ = localtime(&cur_time);
|
|
||||||
|
|
||||||
format[0] = '\0';
|
format[0] = '\0';
|
||||||
|
|
||||||
|
rtime_localtime(&cur_time, &tm_);
|
||||||
|
|
||||||
if (string_is_empty(ext))
|
if (string_is_empty(ext))
|
||||||
{
|
{
|
||||||
strftime(format, sizeof(format), "-%y%m%d-%H%M%S", tm_);
|
strftime(format, sizeof(format), "-%y%m%d-%H%M%S", &tm_);
|
||||||
fill_pathname_noext(out_filename, in_str, format, size);
|
fill_pathname_noext(out_filename, in_str, format, size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strftime(format, sizeof(format), "-%y%m%d-%H%M%S.", tm_);
|
strftime(format, sizeof(format), "-%y%m%d-%H%M%S.", &tm_);
|
||||||
|
|
||||||
fill_pathname_join_concat_noext(out_filename,
|
fill_pathname_join_concat_noext(out_filename,
|
||||||
in_str, format, ext,
|
in_str, format, ext,
|
||||||
@ -655,6 +542,7 @@ void fill_str_dated_filename(char *out_filename,
|
|||||||
void path_basedir(char *path)
|
void path_basedir(char *path)
|
||||||
{
|
{
|
||||||
char *last = NULL;
|
char *last = NULL;
|
||||||
|
|
||||||
if (strlen(path) < 2)
|
if (strlen(path) < 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -663,7 +551,7 @@ void path_basedir(char *path)
|
|||||||
if (last)
|
if (last)
|
||||||
last[1] = '\0';
|
last[1] = '\0';
|
||||||
else
|
else
|
||||||
snprintf(path, 3, ".%s", path_default_slash());
|
snprintf(path, 3, "." PATH_DEFAULT_SLASH());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -683,7 +571,7 @@ void path_parent_dir(char *path)
|
|||||||
|
|
||||||
len = strlen(path);
|
len = strlen(path);
|
||||||
|
|
||||||
if (len && path_char_is_slash(path[len - 1]))
|
if (len && PATH_CHAR_IS_SLASH(path[len - 1]))
|
||||||
{
|
{
|
||||||
bool path_was_absolute = path_is_absolute(path);
|
bool path_was_absolute = path_is_absolute(path);
|
||||||
|
|
||||||
@ -738,53 +626,157 @@ const char *path_basename(const char *path)
|
|||||||
**/
|
**/
|
||||||
bool path_is_absolute(const char *path)
|
bool path_is_absolute(const char *path)
|
||||||
{
|
{
|
||||||
|
if (string_is_empty(path))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (path[0] == '/')
|
if (path[0] == '/')
|
||||||
return true;
|
return true;
|
||||||
#ifdef _WIN32
|
|
||||||
/* Many roads lead to Rome ... */
|
#if defined(_WIN32)
|
||||||
if (( strstr(path, "\\\\") == path)
|
/* Many roads lead to Rome...
|
||||||
|| strstr(path, ":/")
|
* Note: Drive letter can only be 1 character long */
|
||||||
|| strstr(path, ":\\")
|
if (string_starts_with_size(path, "\\\\", STRLEN_CONST("\\\\")) ||
|
||||||
|| strstr(path, ":\\\\"))
|
string_starts_with_size(path + 1, ":/", STRLEN_CONST(":/")) ||
|
||||||
|
string_starts_with_size(path + 1, ":\\", STRLEN_CONST(":\\")))
|
||||||
return true;
|
return true;
|
||||||
#elif defined(__wiiu__)
|
#elif defined(__wiiu__) || defined(VITA)
|
||||||
if (strstr(path, ":/"))
|
{
|
||||||
|
const char *seperator = strchr(path, ':');
|
||||||
|
if (seperator && (seperator[1] == '/'))
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* path_resolve_realpath:
|
* path_resolve_realpath:
|
||||||
* @buf : buffer for path
|
* @buf : input and output buffer for path
|
||||||
* @size : size of buffer
|
* @size : size of buffer
|
||||||
|
* @resolve_symlinks : whether to resolve symlinks or not
|
||||||
*
|
*
|
||||||
* Turns relative paths into absolute paths and
|
* Resolves use of ".", "..", multiple slashes etc in absolute paths.
|
||||||
* resolves use of "." and ".." in absolute paths.
|
*
|
||||||
* If relative, rebases on current working dir.
|
* Relative paths are rebased on the current working dir.
|
||||||
|
*
|
||||||
|
* Returns: @buf if successful, NULL otherwise.
|
||||||
|
* Note: Not implemented on consoles
|
||||||
|
* Note: Symlinks are only resolved on Unix-likes
|
||||||
|
* Note: The current working dir might not be what you expect,
|
||||||
|
* e.g. on Android it is "/"
|
||||||
|
* Use of fill_pathname_resolve_relative() should be prefered
|
||||||
**/
|
**/
|
||||||
void path_resolve_realpath(char *buf, size_t size)
|
char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks)
|
||||||
{
|
{
|
||||||
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
|
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
|
||||||
char tmp[PATH_MAX_LENGTH];
|
char tmp[PATH_MAX_LENGTH];
|
||||||
|
|
||||||
tmp[0] = '\0';
|
|
||||||
|
|
||||||
strlcpy(tmp, buf, sizeof(tmp));
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
strlcpy(tmp, buf, sizeof(tmp));
|
||||||
if (!_fullpath(buf, tmp, size))
|
if (!_fullpath(buf, tmp, size))
|
||||||
|
{
|
||||||
strlcpy(buf, tmp, size);
|
strlcpy(buf, tmp, size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
#else
|
#else
|
||||||
|
size_t t;
|
||||||
|
char *p;
|
||||||
|
const char *next;
|
||||||
|
const char *buf_end;
|
||||||
|
|
||||||
|
if (resolve_symlinks)
|
||||||
|
{
|
||||||
|
strlcpy(tmp, buf, sizeof(tmp));
|
||||||
|
|
||||||
/* NOTE: realpath() expects at least PATH_MAX_LENGTH bytes in buf.
|
/* NOTE: realpath() expects at least PATH_MAX_LENGTH bytes in buf.
|
||||||
* Technically, PATH_MAX_LENGTH needn't be defined, but we rely on it anyways.
|
* Technically, PATH_MAX_LENGTH needn't be defined, but we rely on it anyways.
|
||||||
* POSIX 2008 can automatically allocate for you,
|
* POSIX 2008 can automatically allocate for you,
|
||||||
* but don't rely on that. */
|
* but don't rely on that. */
|
||||||
if (!realpath(tmp, buf))
|
if (!realpath(tmp, buf))
|
||||||
|
{
|
||||||
strlcpy(buf, tmp, size);
|
strlcpy(buf, tmp, size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
t = 0; /* length of output */
|
||||||
|
buf_end = buf + strlen(buf);
|
||||||
|
|
||||||
|
if (!path_is_absolute(buf))
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
/* rebase on working directory */
|
||||||
|
if (!getcwd(tmp, PATH_MAX_LENGTH-1))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
len = strlen(tmp);
|
||||||
|
t += len;
|
||||||
|
|
||||||
|
if (tmp[len-1] != '/')
|
||||||
|
tmp[t++] = '/';
|
||||||
|
|
||||||
|
if (string_is_empty(buf))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* UNIX paths can start with multiple '/', copy those */
|
||||||
|
for (p = buf; *p == '/'; p++)
|
||||||
|
tmp[t++] = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* p points to just after a slash while 'next' points to the next slash
|
||||||
|
* if there are no slashes, they point relative to where one would be */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
next = strchr(p, '/');
|
||||||
|
if (!next)
|
||||||
|
next = buf_end;
|
||||||
|
|
||||||
|
if ((next - p == 2 && p[0] == '.' && p[1] == '.'))
|
||||||
|
{
|
||||||
|
p += 3;
|
||||||
|
|
||||||
|
/* fail for illegal /.., //.. etc */
|
||||||
|
if (t == 1 || tmp[t-2] == '/')
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* delete previous segment in tmp by adjusting size t
|
||||||
|
* tmp[t-1] == '/', find '/' before that */
|
||||||
|
t = t-2;
|
||||||
|
while (tmp[t] != '/')
|
||||||
|
t--;
|
||||||
|
t++;
|
||||||
|
}
|
||||||
|
else if (next - p == 1 && p[0] == '.')
|
||||||
|
p += 2;
|
||||||
|
else if (next - p == 0)
|
||||||
|
p += 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* fail when truncating */
|
||||||
|
if (t + next-p+1 > PATH_MAX_LENGTH-1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while (p <= next)
|
||||||
|
tmp[t++] = *p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
while (next < buf_end);
|
||||||
|
|
||||||
|
end:
|
||||||
|
tmp[t] = '\0';
|
||||||
|
strlcpy(buf, tmp, size);
|
||||||
|
return buf;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -801,10 +793,10 @@ void path_resolve_realpath(char *buf, size_t size)
|
|||||||
*
|
*
|
||||||
* E.g. path /a/b/e/f.cg with base /a/b/c/d/ turns into ../../e/f.cg
|
* E.g. path /a/b/e/f.cg with base /a/b/c/d/ turns into ../../e/f.cg
|
||||||
**/
|
**/
|
||||||
void path_relative_to(char *out,
|
size_t path_relative_to(char *out,
|
||||||
const char *path, const char *base, size_t size)
|
const char *path, const char *base, size_t size)
|
||||||
{
|
{
|
||||||
unsigned i;
|
size_t i, j;
|
||||||
const char *trimmed_path, *trimmed_base;
|
const char *trimmed_path, *trimmed_base;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -812,24 +804,24 @@ void path_relative_to(char *out,
|
|||||||
if (strlen(path) >= 2 && strlen(base) >= 2
|
if (strlen(path) >= 2 && strlen(base) >= 2
|
||||||
&& path[1] == ':' && base[1] == ':'
|
&& path[1] == ':' && base[1] == ':'
|
||||||
&& path[0] != base[0])
|
&& path[0] != base[0])
|
||||||
{
|
return strlcpy(out, path, size);
|
||||||
out[0] = '\0';
|
|
||||||
strlcat(out, path, size);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Trim common beginning */
|
/* Trim common beginning */
|
||||||
for (i = 0; path[i] && base[i] && path[i] == base[i]; )
|
for (i = 0, j = 0; path[i] && base[i] && path[i] == base[i]; i++)
|
||||||
i++;
|
if (path[i] == PATH_DEFAULT_SLASH_C())
|
||||||
trimmed_path = path+i;
|
j = i + 1;
|
||||||
|
|
||||||
|
trimmed_path = path+j;
|
||||||
trimmed_base = base+i;
|
trimmed_base = base+i;
|
||||||
|
|
||||||
/* Each segment of base turns into ".." */
|
/* Each segment of base turns into ".." */
|
||||||
out[0] = '\0';
|
out[0] = '\0';
|
||||||
for (i = 0; trimmed_base[i]; i++)
|
for (i = 0; trimmed_base[i]; i++)
|
||||||
if (trimmed_base[i] == '/' || trimmed_base[i] == '\\')
|
if (trimmed_base[i] == PATH_DEFAULT_SLASH_C())
|
||||||
strlcat(out, "../", size); /* Use '/' as universal separator */
|
strlcat(out, ".." PATH_DEFAULT_SLASH(), size);
|
||||||
strlcat(out, trimmed_path, size);
|
|
||||||
|
return strlcat(out, trimmed_path, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -855,7 +847,7 @@ void fill_pathname_resolve_relative(char *out_path,
|
|||||||
|
|
||||||
fill_pathname_basedir(out_path, in_refpath, size);
|
fill_pathname_basedir(out_path, in_refpath, size);
|
||||||
strlcat(out_path, in_path, size);
|
strlcat(out_path, in_path, size);
|
||||||
path_resolve_realpath(out_path, size);
|
path_resolve_realpath(out_path, size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -869,7 +861,7 @@ void fill_pathname_resolve_relative(char *out_path,
|
|||||||
* Makes sure not to get two consecutive slashes
|
* Makes sure not to get two consecutive slashes
|
||||||
* between directory and path.
|
* between directory and path.
|
||||||
**/
|
**/
|
||||||
void fill_pathname_join(char *out_path,
|
size_t fill_pathname_join(char *out_path,
|
||||||
const char *dir, const char *path, size_t size)
|
const char *dir, const char *path, size_t size)
|
||||||
{
|
{
|
||||||
if (out_path != dir)
|
if (out_path != dir)
|
||||||
@ -878,10 +870,10 @@ void fill_pathname_join(char *out_path,
|
|||||||
if (*out_path)
|
if (*out_path)
|
||||||
fill_pathname_slash(out_path, size);
|
fill_pathname_slash(out_path, size);
|
||||||
|
|
||||||
strlcat(out_path, path, size);
|
return strlcat(out_path, path, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_join_special_ext(char *out_path,
|
size_t fill_pathname_join_special_ext(char *out_path,
|
||||||
const char *dir, const char *path,
|
const char *dir, const char *path,
|
||||||
const char *last, const char *ext,
|
const char *last, const char *ext,
|
||||||
size_t size)
|
size_t size)
|
||||||
@ -891,25 +883,25 @@ void fill_pathname_join_special_ext(char *out_path,
|
|||||||
fill_pathname_slash(out_path, size);
|
fill_pathname_slash(out_path, size);
|
||||||
|
|
||||||
strlcat(out_path, last, size);
|
strlcat(out_path, last, size);
|
||||||
strlcat(out_path, ext, size);
|
return strlcat(out_path, ext, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_join_concat_noext(char *out_path,
|
size_t fill_pathname_join_concat_noext(char *out_path,
|
||||||
const char *dir, const char *path,
|
const char *dir, const char *path,
|
||||||
const char *concat,
|
const char *concat,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
fill_pathname_noext(out_path, dir, path, size);
|
fill_pathname_noext(out_path, dir, path, size);
|
||||||
strlcat(out_path, concat, size);
|
return strlcat(out_path, concat, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_join_concat(char *out_path,
|
size_t fill_pathname_join_concat(char *out_path,
|
||||||
const char *dir, const char *path,
|
const char *dir, const char *path,
|
||||||
const char *concat,
|
const char *concat,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
fill_pathname_join(out_path, dir, path, size);
|
fill_pathname_join(out_path, dir, path, size);
|
||||||
strlcat(out_path, concat, size);
|
return strlcat(out_path, concat, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_join_noext(char *out_path,
|
void fill_pathname_join_noext(char *out_path,
|
||||||
@ -930,7 +922,7 @@ void fill_pathname_join_noext(char *out_path,
|
|||||||
* Joins a directory (@dir) and path (@path) together
|
* Joins a directory (@dir) and path (@path) together
|
||||||
* using the given delimiter (@delim).
|
* using the given delimiter (@delim).
|
||||||
**/
|
**/
|
||||||
void fill_pathname_join_delim(char *out_path, const char *dir,
|
size_t fill_pathname_join_delim(char *out_path, const char *dir,
|
||||||
const char *path, const char delim, size_t size)
|
const char *path, const char delim, size_t size)
|
||||||
{
|
{
|
||||||
size_t copied;
|
size_t copied;
|
||||||
@ -944,15 +936,16 @@ void fill_pathname_join_delim(char *out_path, const char *dir,
|
|||||||
out_path[copied+1] = '\0';
|
out_path[copied+1] = '\0';
|
||||||
|
|
||||||
if (path)
|
if (path)
|
||||||
strlcat(out_path, path, size);
|
copied = strlcat(out_path, path, size);
|
||||||
|
return copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
size_t fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
||||||
const char *path, const char delim, const char *concat,
|
const char *path, const char delim, const char *concat,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
fill_pathname_join_delim(out_path, dir, path, delim, size);
|
fill_pathname_join_delim(out_path, dir, path, delim, size);
|
||||||
strlcat(out_path, concat, size);
|
return strlcat(out_path, concat, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -970,7 +963,7 @@ void fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
|||||||
* E.g.: "/path/to/game.img" -> game.img
|
* E.g.: "/path/to/game.img" -> game.img
|
||||||
* "/path/to/myarchive.7z#folder/to/game.img" -> game.img
|
* "/path/to/myarchive.7z#folder/to/game.img" -> game.img
|
||||||
*/
|
*/
|
||||||
void fill_short_pathname_representation(char* out_rep,
|
size_t fill_short_pathname_representation(char* out_rep,
|
||||||
const char *in_path, size_t size)
|
const char *in_path, size_t size)
|
||||||
{
|
{
|
||||||
char path_short[PATH_MAX_LENGTH];
|
char path_short[PATH_MAX_LENGTH];
|
||||||
@ -980,7 +973,7 @@ void fill_short_pathname_representation(char* out_rep,
|
|||||||
fill_pathname(path_short, path_basename(in_path), "",
|
fill_pathname(path_short, path_basename(in_path), "",
|
||||||
sizeof(path_short));
|
sizeof(path_short));
|
||||||
|
|
||||||
strlcpy(out_rep, path_short, size);
|
return strlcpy(out_rep, path_short, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_short_pathname_representation_noext(char* out_rep,
|
void fill_short_pathname_representation_noext(char* out_rep,
|
||||||
@ -1011,9 +1004,9 @@ void fill_pathname_expand_special(char *out_path,
|
|||||||
out_path += src_size;
|
out_path += src_size;
|
||||||
size -= src_size;
|
size -= src_size;
|
||||||
|
|
||||||
if (!path_char_is_slash(out_path[-1]))
|
if (!PATH_CHAR_IS_SLASH(out_path[-1]))
|
||||||
{
|
{
|
||||||
src_size = strlcpy(out_path, path_default_slash(), size);
|
src_size = strlcpy(out_path, PATH_DEFAULT_SLASH(), size);
|
||||||
retro_assert(src_size < size);
|
retro_assert(src_size < size);
|
||||||
|
|
||||||
out_path += src_size;
|
out_path += src_size;
|
||||||
@ -1042,9 +1035,9 @@ void fill_pathname_expand_special(char *out_path,
|
|||||||
out_path += src_size;
|
out_path += src_size;
|
||||||
size -= src_size;
|
size -= src_size;
|
||||||
|
|
||||||
if (!path_char_is_slash(out_path[-1]))
|
if (!PATH_CHAR_IS_SLASH(out_path[-1]))
|
||||||
{
|
{
|
||||||
src_size = strlcpy(out_path, path_default_slash(), size);
|
src_size = strlcpy(out_path, PATH_DEFAULT_SLASH(), size);
|
||||||
retro_assert(src_size < size);
|
retro_assert(src_size < size);
|
||||||
|
|
||||||
out_path += src_size;
|
out_path += src_size;
|
||||||
@ -1068,10 +1061,11 @@ void fill_pathname_abbreviate_special(char *out_path,
|
|||||||
unsigned i;
|
unsigned i;
|
||||||
const char *candidates[3];
|
const char *candidates[3];
|
||||||
const char *notations[3];
|
const char *notations[3];
|
||||||
char *application_dir = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
char application_dir[PATH_MAX_LENGTH];
|
||||||
char *home_dir = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
|
char home_dir[PATH_MAX_LENGTH];
|
||||||
|
|
||||||
application_dir[0] = '\0';
|
application_dir[0] = '\0';
|
||||||
|
home_dir[0] = '\0';
|
||||||
|
|
||||||
/* application_dir could be zero-string. Safeguard against this.
|
/* application_dir could be zero-string. Safeguard against this.
|
||||||
*
|
*
|
||||||
@ -1088,15 +1082,13 @@ void fill_pathname_abbreviate_special(char *out_path,
|
|||||||
notations [1] = "~";
|
notations [1] = "~";
|
||||||
notations [2] = NULL;
|
notations [2] = NULL;
|
||||||
|
|
||||||
fill_pathname_application_dir(application_dir,
|
fill_pathname_application_dir(application_dir, sizeof(application_dir));
|
||||||
PATH_MAX_LENGTH * sizeof(char));
|
fill_pathname_home_dir(home_dir, sizeof(home_dir));
|
||||||
fill_pathname_home_dir(home_dir,
|
|
||||||
PATH_MAX_LENGTH * sizeof(char));
|
|
||||||
|
|
||||||
for (i = 0; candidates[i]; i++)
|
for (i = 0; candidates[i]; i++)
|
||||||
{
|
{
|
||||||
if (!string_is_empty(candidates[i]) &&
|
if (!string_is_empty(candidates[i]) &&
|
||||||
strstr(in_path, candidates[i]) == in_path)
|
string_starts_with(in_path, candidates[i]))
|
||||||
{
|
{
|
||||||
size_t src_size = strlcpy(out_path, notations[i], size);
|
size_t src_size = strlcpy(out_path, notations[i], size);
|
||||||
|
|
||||||
@ -1106,10 +1098,10 @@ void fill_pathname_abbreviate_special(char *out_path,
|
|||||||
size -= src_size;
|
size -= src_size;
|
||||||
in_path += strlen(candidates[i]);
|
in_path += strlen(candidates[i]);
|
||||||
|
|
||||||
if (!path_char_is_slash(*in_path))
|
if (!PATH_CHAR_IS_SLASH(*in_path))
|
||||||
{
|
{
|
||||||
retro_assert(strlcpy(out_path,
|
retro_assert(strlcpy(out_path,
|
||||||
path_default_slash(), size) < size);
|
PATH_DEFAULT_SLASH(), size) < size);
|
||||||
out_path++;
|
out_path++;
|
||||||
size--;
|
size--;
|
||||||
}
|
}
|
||||||
@ -1118,8 +1110,6 @@ void fill_pathname_abbreviate_special(char *out_path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(application_dir);
|
|
||||||
free(home_dir);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
retro_assert(strlcpy(out_path, in_path, size) < size);
|
retro_assert(strlcpy(out_path, in_path, size) < size);
|
||||||
@ -1150,7 +1140,7 @@ void path_basedir_wrapper(char *path)
|
|||||||
if (last)
|
if (last)
|
||||||
last[1] = '\0';
|
last[1] = '\0';
|
||||||
else
|
else
|
||||||
snprintf(path, 3, ".%s", path_default_slash());
|
snprintf(path, 3, "." PATH_DEFAULT_SLASH());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
|
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
|
||||||
@ -1197,10 +1187,27 @@ void fill_pathname_application_path(char *s, size_t len)
|
|||||||
CFURLRef bundle_url = CFBundleCopyBundleURL(bundle);
|
CFURLRef bundle_url = CFBundleCopyBundleURL(bundle);
|
||||||
CFStringRef bundle_path = CFURLCopyPath(bundle_url);
|
CFStringRef bundle_path = CFURLCopyPath(bundle_url);
|
||||||
CFStringGetCString(bundle_path, s, len, kCFStringEncodingUTF8);
|
CFStringGetCString(bundle_path, s, len, kCFStringEncodingUTF8);
|
||||||
|
#ifdef HAVE_COCOATOUCH
|
||||||
|
{
|
||||||
|
/* This needs to be done so that the path becomes
|
||||||
|
* /private/var/... and this
|
||||||
|
* is used consistently throughout for the iOS bundle path */
|
||||||
|
char resolved_bundle_dir_buf[PATH_MAX_LENGTH] = {0};
|
||||||
|
if (realpath(s, resolved_bundle_dir_buf))
|
||||||
|
{
|
||||||
|
strlcpy(s, resolved_bundle_dir_buf, len - 1);
|
||||||
|
strlcat(s, "/", len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
CFRelease(bundle_path);
|
CFRelease(bundle_path);
|
||||||
CFRelease(bundle_url);
|
CFRelease(bundle_url);
|
||||||
|
#ifndef HAVE_COCOATOUCH
|
||||||
|
/* Not sure what this does but it breaks
|
||||||
|
* stuff for iOS, so skipping */
|
||||||
retro_assert(strlcat(s, "nobin", len) < len);
|
retro_assert(strlcat(s, "nobin", len) < len);
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#elif defined(__HAIKU__)
|
#elif defined(__HAIKU__)
|
||||||
@ -1273,17 +1280,17 @@ void fill_pathname_home_dir(char *s, size_t len)
|
|||||||
|
|
||||||
bool is_path_accessible_using_standard_io(const char *path)
|
bool is_path_accessible_using_standard_io(const char *path)
|
||||||
{
|
{
|
||||||
|
bool result = true;
|
||||||
#ifdef __WINRT__
|
#ifdef __WINRT__
|
||||||
bool result;
|
|
||||||
size_t path_sizeof = PATH_MAX_LENGTH * sizeof(char);
|
size_t path_sizeof = PATH_MAX_LENGTH * sizeof(char);
|
||||||
char *relative_path_abbrev = (char*)malloc(path_sizeof);
|
char *relative_path_abbrev = (char*)malloc(path_sizeof);
|
||||||
fill_pathname_abbreviate_special(relative_path_abbrev, path, path_sizeof);
|
fill_pathname_abbreviate_special(relative_path_abbrev, path, path_sizeof);
|
||||||
|
|
||||||
result = strlen(relative_path_abbrev) >= 2 && (relative_path_abbrev[0] == ':' || relative_path_abbrev[0] == '~') && path_char_is_slash(relative_path_abbrev[1]);
|
result = (strlen(relative_path_abbrev) >= 2 )
|
||||||
|
&& (relative_path_abbrev[0] == ':' || relative_path_abbrev[0] == '~')
|
||||||
|
&& PATH_CHAR_IS_SLASH(relative_path_abbrev[1]);
|
||||||
|
|
||||||
free(relative_path_abbrev);
|
free(relative_path_abbrev);
|
||||||
return result;
|
|
||||||
#else
|
|
||||||
return true;
|
|
||||||
#endif
|
#endif
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2019 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (retro_dirent.c).
|
* The following license statement only applies to this file (retro_dirent.c).
|
||||||
@ -61,7 +61,7 @@ void dirent_vfs_init(const struct retro_vfs_interface_info* vfs_info)
|
|||||||
|
|
||||||
struct RDIR *retro_opendir_include_hidden(const char *name, bool include_hidden)
|
struct RDIR *retro_opendir_include_hidden(const char *name, bool include_hidden)
|
||||||
{
|
{
|
||||||
if (dirent_opendir_cb != NULL)
|
if (dirent_opendir_cb)
|
||||||
return (struct RDIR *)dirent_opendir_cb(name, include_hidden);
|
return (struct RDIR *)dirent_opendir_cb(name, include_hidden);
|
||||||
return (struct RDIR *)retro_vfs_opendir_impl(name, include_hidden);
|
return (struct RDIR *)retro_vfs_opendir_impl(name, include_hidden);
|
||||||
}
|
}
|
||||||
@ -79,14 +79,14 @@ bool retro_dirent_error(struct RDIR *rdir)
|
|||||||
|
|
||||||
int retro_readdir(struct RDIR *rdir)
|
int retro_readdir(struct RDIR *rdir)
|
||||||
{
|
{
|
||||||
if (dirent_readdir_cb != NULL)
|
if (dirent_readdir_cb)
|
||||||
return dirent_readdir_cb((struct retro_vfs_dir_handle *)rdir);
|
return dirent_readdir_cb((struct retro_vfs_dir_handle *)rdir);
|
||||||
return retro_vfs_readdir_impl((struct retro_vfs_dir_handle *)rdir);
|
return retro_vfs_readdir_impl((struct retro_vfs_dir_handle *)rdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *retro_dirent_get_name(struct RDIR *rdir)
|
const char *retro_dirent_get_name(struct RDIR *rdir)
|
||||||
{
|
{
|
||||||
if (dirent_dirent_get_name_cb != NULL)
|
if (dirent_dirent_get_name_cb)
|
||||||
return dirent_dirent_get_name_cb((struct retro_vfs_dir_handle *)rdir);
|
return dirent_dirent_get_name_cb((struct retro_vfs_dir_handle *)rdir);
|
||||||
return retro_vfs_dirent_get_name_impl((struct retro_vfs_dir_handle *)rdir);
|
return retro_vfs_dirent_get_name_impl((struct retro_vfs_dir_handle *)rdir);
|
||||||
}
|
}
|
||||||
@ -104,14 +104,14 @@ const char *retro_dirent_get_name(struct RDIR *rdir)
|
|||||||
*/
|
*/
|
||||||
bool retro_dirent_is_dir(struct RDIR *rdir, const char *unused)
|
bool retro_dirent_is_dir(struct RDIR *rdir, const char *unused)
|
||||||
{
|
{
|
||||||
if (dirent_dirent_is_dir_cb != NULL)
|
if (dirent_dirent_is_dir_cb)
|
||||||
return dirent_dirent_is_dir_cb((struct retro_vfs_dir_handle *)rdir);
|
return dirent_dirent_is_dir_cb((struct retro_vfs_dir_handle *)rdir);
|
||||||
return retro_vfs_dirent_is_dir_impl((struct retro_vfs_dir_handle *)rdir);
|
return retro_vfs_dirent_is_dir_impl((struct retro_vfs_dir_handle *)rdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
void retro_closedir(struct RDIR *rdir)
|
void retro_closedir(struct RDIR *rdir)
|
||||||
{
|
{
|
||||||
if (dirent_closedir_cb != NULL)
|
if (dirent_closedir_cb)
|
||||||
dirent_closedir_cb((struct retro_vfs_dir_handle *)rdir);
|
dirent_closedir_cb((struct retro_vfs_dir_handle *)rdir);
|
||||||
else
|
else
|
||||||
retro_vfs_closedir_impl((struct retro_vfs_dir_handle *)rdir);
|
retro_vfs_closedir_impl((struct retro_vfs_dir_handle *)rdir);
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
License statement applies to this file (glgen.py) only.
|
License statement applies to this file (glgen.py) only.
|
||||||
"""
|
|
||||||
|
|
||||||
"""
|
|
||||||
Permission is hereby granted, free of charge,
|
Permission is hereby granted, free of charge,
|
||||||
to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||||
to deal in the Software without restriction, including without limitation the rights to
|
to deal in the Software without restriction, including without limitation the rights to
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this libretro SDK code part (glsym).
|
* The following license statement only applies to this libretro SDK code part (glsym).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this libretro SDK code part (glsym).
|
* The following license statement only applies to this libretro SDK code part (glsym).
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
License statement applies to this file (glgen.py) only.
|
License statement applies to this file (glgen.py) only.
|
||||||
"""
|
|
||||||
|
|
||||||
"""
|
|
||||||
Permission is hereby granted, free of charge,
|
Permission is hereby granted, free of charge,
|
||||||
to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||||
to deal in the Software without restriction, including without limitation the rights to
|
to deal in the Software without restriction, including without limitation the rights to
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (rhash.c).
|
* The following license statement only applies to this file (rhash.c).
|
||||||
@ -307,7 +307,22 @@ uint32_t crc32_calculate(const uint8_t *data, size_t length)
|
|||||||
/* Define the circular shift macro */
|
/* Define the circular shift macro */
|
||||||
#define SHA1CircularShift(bits,word) ((((word) << (bits)) & 0xFFFFFFFF) | ((word) >> (32-(bits))))
|
#define SHA1CircularShift(bits,word) ((((word) << (bits)) & 0xFFFFFFFF) | ((word) >> (32-(bits))))
|
||||||
|
|
||||||
static void SHA1Reset(SHA1Context *context)
|
struct sha1_context
|
||||||
|
{
|
||||||
|
unsigned Message_Digest[5]; /* Message Digest (output) */
|
||||||
|
|
||||||
|
unsigned Length_Low; /* Message length in bits */
|
||||||
|
unsigned Length_High; /* Message length in bits */
|
||||||
|
|
||||||
|
unsigned char Message_Block[64]; /* 512-bit message blocks */
|
||||||
|
int Message_Block_Index; /* Index into message block array */
|
||||||
|
|
||||||
|
int Computed; /* Is the digest computed? */
|
||||||
|
int Corrupted; /* Is the message digest corruped? */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void SHA1Reset(struct sha1_context *context)
|
||||||
{
|
{
|
||||||
if (!context)
|
if (!context)
|
||||||
return;
|
return;
|
||||||
@ -326,7 +341,7 @@ static void SHA1Reset(SHA1Context *context)
|
|||||||
context->Corrupted = 0;
|
context->Corrupted = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SHA1ProcessMessageBlock(SHA1Context *context)
|
static void SHA1ProcessMessageBlock(struct sha1_context *context)
|
||||||
{
|
{
|
||||||
const unsigned K[] = /* Constants defined in SHA-1 */
|
const unsigned K[] = /* Constants defined in SHA-1 */
|
||||||
{
|
{
|
||||||
@ -418,7 +433,7 @@ static void SHA1ProcessMessageBlock(SHA1Context *context)
|
|||||||
context->Message_Block_Index = 0;
|
context->Message_Block_Index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SHA1PadMessage(SHA1Context *context)
|
static void SHA1PadMessage(struct sha1_context *context)
|
||||||
{
|
{
|
||||||
if (!context)
|
if (!context)
|
||||||
return;
|
return;
|
||||||
@ -455,7 +470,7 @@ static void SHA1PadMessage(SHA1Context *context)
|
|||||||
SHA1ProcessMessageBlock(context);
|
SHA1ProcessMessageBlock(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int SHA1Result(SHA1Context *context)
|
static int SHA1Result(struct sha1_context *context)
|
||||||
{
|
{
|
||||||
if (context->Corrupted)
|
if (context->Corrupted)
|
||||||
return 0;
|
return 0;
|
||||||
@ -469,7 +484,7 @@ static int SHA1Result(SHA1Context *context)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SHA1Input(SHA1Context *context,
|
static void SHA1Input(struct sha1_context *context,
|
||||||
const unsigned char *message_array,
|
const unsigned char *message_array,
|
||||||
unsigned length)
|
unsigned length)
|
||||||
{
|
{
|
||||||
@ -508,7 +523,7 @@ static void SHA1Input(SHA1Context *context,
|
|||||||
|
|
||||||
int sha1_calculate(const char *path, char *result)
|
int sha1_calculate(const char *path, char *result)
|
||||||
{
|
{
|
||||||
SHA1Context sha;
|
struct sha1_context sha;
|
||||||
unsigned char buff[4096];
|
unsigned char buff[4096];
|
||||||
int rv = 1;
|
int rv = 1;
|
||||||
RFILE *fd = filestream_open(path,
|
RFILE *fd = filestream_open(path,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (boolean.h).
|
* The following license statement only applies to this file (boolean.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2019 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (cdrom.h).
|
* The following license statement only applies to this file (cdrom.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (apple_compat.h).
|
* The following license statement only applies to this file (apple_compat.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (fnmatch.h).
|
* The following license statement only applies to this file (fnmatch.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (fopen_utf8.h).
|
* The following license statement only applies to this file (fopen_utf8.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (getopt.h).
|
* The following license statement only applies to this file (getopt.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (intrinsics.h).
|
* The following license statement only applies to this file (intrinsics.h).
|
||||||
@ -41,7 +41,7 @@ RETRO_BEGIN_DECLS
|
|||||||
/* Count Leading Zero, unsigned 16bit input value */
|
/* Count Leading Zero, unsigned 16bit input value */
|
||||||
static INLINE unsigned compat_clz_u16(uint16_t val)
|
static INLINE unsigned compat_clz_u16(uint16_t val)
|
||||||
{
|
{
|
||||||
#if defined(__GNUC__) && !defined(PS2)
|
#if defined(__GNUC__)
|
||||||
return __builtin_clz(val << 16 | 0x8000);
|
return __builtin_clz(val << 16 | 0x8000);
|
||||||
#else
|
#else
|
||||||
unsigned ret = 0;
|
unsigned ret = 0;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (msvc.h).
|
* The following license statement only applies to this file (msvc.h).
|
||||||
@ -31,6 +31,7 @@ extern "C" {
|
|||||||
|
|
||||||
/* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */
|
/* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */
|
||||||
#if _MSC_VER < 1900
|
#if _MSC_VER < 1900
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#ifndef snprintf
|
#ifndef snprintf
|
||||||
#define snprintf c99_snprintf_retro__
|
#define snprintf c99_snprintf_retro__
|
||||||
@ -41,6 +42,7 @@ extern "C" {
|
|||||||
|
|
||||||
/* Pre-MSVC 2008 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
|
/* Pre-MSVC 2008 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
|
||||||
#if _MSC_VER < 1500
|
#if _MSC_VER < 1500
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#ifndef vsnprintf
|
#ifndef vsnprintf
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (posix_string.h).
|
* The following license statement only applies to this file (posix_string.h).
|
||||||
@ -29,10 +29,6 @@
|
|||||||
#include <compat/msvc.h>
|
#include <compat/msvc.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PS2)
|
|
||||||
#include <compat_ctype.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RETRO_BEGIN_DECLS
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (strcasestr.h).
|
* The following license statement only applies to this file (strcasestr.h).
|
||||||
@ -25,10 +25,6 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#if defined(PS2)
|
|
||||||
#include <compat_ctype.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
|
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
|
||||||
#include "../../../config.h"
|
#include "../../../config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (strl.h).
|
* The following license statement only applies to this file (strl.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (utf.h).
|
* The following license statement only applies to this file (utf.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2019 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (file_path.h).
|
* The following license statement only applies to this file (file_path.h).
|
||||||
@ -147,14 +147,22 @@ void path_parent_dir(char *path);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* path_resolve_realpath:
|
* path_resolve_realpath:
|
||||||
* @buf : buffer for path
|
* @buf : input and output buffer for path
|
||||||
* @size : size of buffer
|
* @size : size of buffer
|
||||||
|
* @resolve_symlinks : whether to resolve symlinks or not
|
||||||
*
|
*
|
||||||
* Turns relative paths into absolute paths and
|
* Resolves use of ".", "..", multiple slashes etc in absolute paths.
|
||||||
* resolves use of "." and ".." in absolute paths.
|
*
|
||||||
* If relative, rebases on current working dir.
|
* Relative paths are rebased on the current working dir.
|
||||||
|
*
|
||||||
|
* Returns: @buf if successful, NULL otherwise.
|
||||||
|
* Note: Not implemented on consoles
|
||||||
|
* Note: Symlinks are only resolved on Unix-likes
|
||||||
|
* Note: The current working dir might not be what you expect,
|
||||||
|
* e.g. on Android it is "/"
|
||||||
|
* Use of fill_pathname_resolve_relative() should be prefered
|
||||||
**/
|
**/
|
||||||
void path_resolve_realpath(char *buf, size_t size);
|
char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* path_relative_to:
|
* path_relative_to:
|
||||||
@ -170,7 +178,7 @@ void path_resolve_realpath(char *buf, size_t size);
|
|||||||
*
|
*
|
||||||
* E.g. path /a/b/e/f.cgp with base /a/b/c/d/ turns into ../../e/f.cgp
|
* E.g. path /a/b/e/f.cgp with base /a/b/c/d/ turns into ../../e/f.cgp
|
||||||
**/
|
**/
|
||||||
void path_relative_to(char *out, const char *path, const char *base, size_t size);
|
size_t path_relative_to(char *out, const char *path, const char *base, size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* path_is_absolute:
|
* path_is_absolute:
|
||||||
@ -218,7 +226,7 @@ void fill_pathname(char *out_path, const char *in_path,
|
|||||||
* E.g.:
|
* E.g.:
|
||||||
* out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
|
* out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
|
||||||
**/
|
**/
|
||||||
void fill_dated_filename(char *out_filename,
|
size_t fill_dated_filename(char *out_filename,
|
||||||
const char *ext, size_t size);
|
const char *ext, size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -251,7 +259,7 @@ void fill_str_dated_filename(char *out_filename,
|
|||||||
* present in 'in_path', it will be ignored.
|
* present in 'in_path', it will be ignored.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void fill_pathname_noext(char *out_path, const char *in_path,
|
size_t fill_pathname_noext(char *out_path, const char *in_path,
|
||||||
const char *replace, size_t size);
|
const char *replace, size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -281,7 +289,7 @@ char *find_last_slash(const char *str);
|
|||||||
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
|
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
|
||||||
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
|
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
|
||||||
**/
|
**/
|
||||||
void fill_pathname_dir(char *in_dir, const char *in_basename,
|
size_t fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||||
const char *replace, size_t size);
|
const char *replace, size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -292,12 +300,12 @@ void fill_pathname_dir(char *in_dir, const char *in_basename,
|
|||||||
*
|
*
|
||||||
* Copies basename of @in_path into @out_path.
|
* Copies basename of @in_path into @out_path.
|
||||||
**/
|
**/
|
||||||
void fill_pathname_base(char *out_path, const char *in_path, size_t size);
|
size_t fill_pathname_base(char *out_path, const char *in_path, size_t size);
|
||||||
|
|
||||||
void fill_pathname_base_noext(char *out_dir,
|
void fill_pathname_base_noext(char *out_dir,
|
||||||
const char *in_path, size_t size);
|
const char *in_path, size_t size);
|
||||||
|
|
||||||
void fill_pathname_base_ext(char *out,
|
size_t fill_pathname_base_ext(char *out,
|
||||||
const char *in_path, const char *ext,
|
const char *in_path, const char *ext,
|
||||||
size_t size);
|
size_t size);
|
||||||
|
|
||||||
@ -368,20 +376,20 @@ void fill_pathname_resolve_relative(char *out_path, const char *in_refpath,
|
|||||||
* Makes sure not to get two consecutive slashes
|
* Makes sure not to get two consecutive slashes
|
||||||
* between directory and path.
|
* between directory and path.
|
||||||
**/
|
**/
|
||||||
void fill_pathname_join(char *out_path, const char *dir,
|
size_t fill_pathname_join(char *out_path, const char *dir,
|
||||||
const char *path, size_t size);
|
const char *path, size_t size);
|
||||||
|
|
||||||
void fill_pathname_join_special_ext(char *out_path,
|
size_t fill_pathname_join_special_ext(char *out_path,
|
||||||
const char *dir, const char *path,
|
const char *dir, const char *path,
|
||||||
const char *last, const char *ext,
|
const char *last, const char *ext,
|
||||||
size_t size);
|
size_t size);
|
||||||
|
|
||||||
void fill_pathname_join_concat_noext(char *out_path,
|
size_t fill_pathname_join_concat_noext(char *out_path,
|
||||||
const char *dir, const char *path,
|
const char *dir, const char *path,
|
||||||
const char *concat,
|
const char *concat,
|
||||||
size_t size);
|
size_t size);
|
||||||
|
|
||||||
void fill_pathname_join_concat(char *out_path,
|
size_t fill_pathname_join_concat(char *out_path,
|
||||||
const char *dir, const char *path,
|
const char *dir, const char *path,
|
||||||
const char *concat,
|
const char *concat,
|
||||||
size_t size);
|
size_t size);
|
||||||
@ -400,10 +408,10 @@ void fill_pathname_join_noext(char *out_path,
|
|||||||
* Joins a directory (@dir) and path (@path) together
|
* Joins a directory (@dir) and path (@path) together
|
||||||
* using the given delimiter (@delim).
|
* using the given delimiter (@delim).
|
||||||
**/
|
**/
|
||||||
void fill_pathname_join_delim(char *out_path, const char *dir,
|
size_t fill_pathname_join_delim(char *out_path, const char *dir,
|
||||||
const char *path, const char delim, size_t size);
|
const char *path, const char delim, size_t size);
|
||||||
|
|
||||||
void fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
size_t fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
||||||
const char *path, const char delim, const char *concat,
|
const char *path, const char delim, const char *concat,
|
||||||
size_t size);
|
size_t size);
|
||||||
|
|
||||||
@ -422,7 +430,7 @@ void fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
|||||||
* E.g.: "/path/to/game.img" -> game.img
|
* E.g.: "/path/to/game.img" -> game.img
|
||||||
* "/path/to/myarchive.7z#folder/to/game.img" -> game.img
|
* "/path/to/myarchive.7z#folder/to/game.img" -> game.img
|
||||||
*/
|
*/
|
||||||
void fill_short_pathname_representation(char* out_rep,
|
size_t fill_short_pathname_representation(char* out_rep,
|
||||||
const char *in_path, size_t size);
|
const char *in_path, size_t size);
|
||||||
|
|
||||||
void fill_short_pathname_representation_noext(char* out_rep,
|
void fill_short_pathname_representation_noext(char* out_rep,
|
||||||
@ -452,9 +460,9 @@ void path_basedir_wrapper(char *path);
|
|||||||
* Returns: true (1) if character is a slash, otherwise false (0).
|
* Returns: true (1) if character is a slash, otherwise false (0).
|
||||||
*/
|
*/
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define path_char_is_slash(c) (((c) == '/') || ((c) == '\\'))
|
#define PATH_CHAR_IS_SLASH(c) (((c) == '/') || ((c) == '\\'))
|
||||||
#else
|
#else
|
||||||
#define path_char_is_slash(c) ((c) == '/')
|
#define PATH_CHAR_IS_SLASH(c) ((c) == '/')
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -465,11 +473,11 @@ void path_basedir_wrapper(char *path);
|
|||||||
* Returns: default slash separator.
|
* Returns: default slash separator.
|
||||||
*/
|
*/
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define path_default_slash() "\\"
|
#define PATH_DEFAULT_SLASH() "\\"
|
||||||
#define path_default_slash_c() '\\'
|
#define PATH_DEFAULT_SLASH_C() '\\'
|
||||||
#else
|
#else
|
||||||
#define path_default_slash() "/"
|
#define PATH_DEFAULT_SLASH() "/"
|
||||||
#define path_default_slash_c() '/'
|
#define PATH_DEFAULT_SLASH_C() '/'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,8 +32,8 @@
|
|||||||
RETRO_BEGIN_DECLS
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
#ifdef HAVE_OPENGLES2
|
#ifdef HAVE_OPENGLES2
|
||||||
typedef GLfloat GLdouble;
|
typedef double GLdouble;
|
||||||
typedef GLclampf GLclampd;
|
typedef double GLclampd;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_OPENGLES2)
|
#if defined(HAVE_OPENGLES2)
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
|
|
||||||
#include <glsm/glsm.h>
|
#include <glsm/glsm.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_GLSYM_PRIVATE
|
||||||
|
#include "glsym_private.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <retro_common_api.h>
|
#include <retro_common_api.h>
|
||||||
|
|
||||||
RETRO_BEGIN_DECLS
|
RETRO_BEGIN_DECLS
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this libretro SDK code part (glsym).
|
* The following license statement only applies to this libretro SDK code part (glsym).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this libretro SDK code part (glsym).
|
* The following license statement only applies to this libretro SDK code part (glsym).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this libretro SDK code part (glsym).
|
* The following license statement only applies to this libretro SDK code part (glsym).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this libretro SDK code part (glsym).
|
* The following license statement only applies to this libretro SDK code part (glsym).
|
||||||
@ -28,55 +28,7 @@
|
|||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(IOS)
|
#include "rglgen_private_headers.h"
|
||||||
|
|
||||||
#if defined(HAVE_OPENGLES3)
|
|
||||||
#include <OpenGLES/ES3/gl.h>
|
|
||||||
#include <OpenGLES/ES3/glext.h>
|
|
||||||
#else
|
|
||||||
#include <OpenGLES/ES2/gl.h>
|
|
||||||
#include <OpenGLES/ES2/glext.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
#include <compat/apple_compat.h>
|
|
||||||
#if MAC_OS_X_VERSION_10_7
|
|
||||||
#include <OpenGL/gl3.h>
|
|
||||||
#include <OpenGL/gl3ext.h>
|
|
||||||
#else
|
|
||||||
#include <OpenGL/gl.h>
|
|
||||||
#include <OpenGL/glext.h>
|
|
||||||
#endif
|
|
||||||
#elif defined(HAVE_PSGL)
|
|
||||||
#include <PSGL/psgl.h>
|
|
||||||
#include <GLES/glext.h>
|
|
||||||
#elif defined(HAVE_OPENGL_MODERN)
|
|
||||||
#include <GL3/gl3.h>
|
|
||||||
#include <GL3/gl3ext.h>
|
|
||||||
#elif defined(HAVE_OPENGLES3)
|
|
||||||
#include <GLES3/gl3.h>
|
|
||||||
#define __gl2_h_
|
|
||||||
#include <GLES2/gl2ext.h>
|
|
||||||
#elif defined(HAVE_OPENGLES2)
|
|
||||||
#include <GLES2/gl2.h>
|
|
||||||
#include <GLES2/gl2ext.h>
|
|
||||||
#elif defined(HAVE_OPENGLES1)
|
|
||||||
#include <GLES/gl.h>
|
|
||||||
#include <GLES/glext.h>
|
|
||||||
#else
|
|
||||||
#if defined(_WIN32) && !defined(_XBOX)
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
#ifndef HAVE_LIBNX
|
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <GL/glext.h>
|
|
||||||
#else
|
|
||||||
/* We need to avoid including <GL/gl.h> on this platform */
|
|
||||||
#include "switch/nx_gl.h"
|
|
||||||
#include <GL/glext.h>
|
|
||||||
#endif /* SWITCH */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef GL_MAP_WRITE_BIT
|
#ifndef GL_MAP_WRITE_BIT
|
||||||
#define GL_MAP_WRITE_BIT 0x0002
|
#define GL_MAP_WRITE_BIT 0x0002
|
||||||
|
@ -279,6 +279,9 @@ enum retro_language
|
|||||||
RETRO_LANGUAGE_GREEK = 17,
|
RETRO_LANGUAGE_GREEK = 17,
|
||||||
RETRO_LANGUAGE_TURKISH = 18,
|
RETRO_LANGUAGE_TURKISH = 18,
|
||||||
RETRO_LANGUAGE_SLOVAK = 19,
|
RETRO_LANGUAGE_SLOVAK = 19,
|
||||||
|
RETRO_LANGUAGE_PERSIAN = 20,
|
||||||
|
RETRO_LANGUAGE_HEBREW = 21,
|
||||||
|
RETRO_LANGUAGE_ASTURIAN = 22,
|
||||||
RETRO_LANGUAGE_LAST,
|
RETRO_LANGUAGE_LAST,
|
||||||
|
|
||||||
/* Ensure sizeof(enum) == sizeof(int) */
|
/* Ensure sizeof(enum) == sizeof(int) */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this libretro API header (libretro_vulkan.h)
|
* The following license statement only applies to this libretro API header (libretro_vulkan.h)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (dir_list.h).
|
* The following license statement only applies to this file (dir_list.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (string_list.h).
|
* The following license statement only applies to this file (string_list.h).
|
||||||
@ -41,6 +41,7 @@ union string_list_elem_attr
|
|||||||
struct string_list_elem
|
struct string_list_elem
|
||||||
{
|
{
|
||||||
char *data;
|
char *data;
|
||||||
|
void *userdata;
|
||||||
union string_list_elem_attr attr;
|
union string_list_elem_attr attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -87,6 +88,19 @@ bool string_list_find_elem_prefix(const struct string_list *list,
|
|||||||
*/
|
*/
|
||||||
struct string_list *string_split(const char *str, const char *delim);
|
struct string_list *string_split(const char *str, const char *delim);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_separate:
|
||||||
|
* @str : string to turn into a string list
|
||||||
|
* @delim : delimiter character to use for separating the string.
|
||||||
|
*
|
||||||
|
* Creates a new string list based on string @str, delimited by @delim.
|
||||||
|
* Includes empty strings - i.e. two adjacent delimiters will resolve
|
||||||
|
* to a string list element of "".
|
||||||
|
*
|
||||||
|
* Returns: new string list if successful, otherwise NULL.
|
||||||
|
*/
|
||||||
|
struct string_list *string_separate(char *str, const char *delim);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* string_list_new:
|
* string_list_new:
|
||||||
*
|
*
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (float_minmax.h).
|
* The following license statement only applies to this file (float_minmax.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (memalign.h).
|
* The following license statement only applies to this file (memalign.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (memmap.h).
|
* The following license statement only applies to this file (memmap.h).
|
||||||
@ -26,7 +26,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#if defined(__CELLOS_LV2__) || defined(PSP) || defined(PS2) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH)
|
#if defined(__CELLOS_LV2__) || defined(PSP) || defined(PS2) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH) || defined(HAVE_LIBNX)
|
||||||
/* No mman available */
|
/* No mman available */
|
||||||
#elif defined(_WIN32) && !defined(_XBOX)
|
#elif defined(_WIN32) && !defined(_XBOX)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (retro_assert.h).
|
* The following license statement only applies to this file (retro_assert.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (retro_common.h).
|
* The following license statement only applies to this file (retro_common.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (retro_common_api.h).
|
* The following license statement only applies to this file (retro_common_api.h).
|
||||||
@ -89,7 +89,9 @@ typedef int ssize_t;
|
|||||||
/* C++11 says this one isn't needed, but apparently (some versions of) mingw require it anyways */
|
/* C++11 says this one isn't needed, but apparently (some versions of) mingw require it anyways */
|
||||||
/* https://stackoverflow.com/questions/8132399/how-to-printf-uint64-t-fails-with-spurious-trailing-in-format */
|
/* https://stackoverflow.com/questions/8132399/how-to-printf-uint64-t-fails-with-spurious-trailing-in-format */
|
||||||
/* https://github.com/libretro/RetroArch/issues/6009 */
|
/* https://github.com/libretro/RetroArch/issues/6009 */
|
||||||
#define __STDC_FORMAT_MACROS
|
#ifndef __STDC_FORMAT_MACROS
|
||||||
|
#define __STDC_FORMAT_MACROS 1
|
||||||
|
#endif
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#endif
|
#endif
|
||||||
#ifndef PRId64
|
#ifndef PRId64
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2019 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (retro_dirent.h).
|
* The following license statement only applies to this file (retro_dirent.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (retro_endianness.h).
|
* The following license statement only applies to this file (retro_endianness.h).
|
||||||
@ -31,40 +31,100 @@
|
|||||||
#define SWAP16 _byteswap_ushort
|
#define SWAP16 _byteswap_ushort
|
||||||
#define SWAP32 _byteswap_ulong
|
#define SWAP32 _byteswap_ulong
|
||||||
#else
|
#else
|
||||||
#define SWAP16(x) ((uint16_t)( \
|
static INLINE uint16_t SWAP16(uint16_t x)
|
||||||
(((uint16_t)(x) & 0x00ff) << 8) | \
|
{
|
||||||
(((uint16_t)(x) & 0xff00) >> 8) \
|
return ((x & 0x00ff) << 8) |
|
||||||
))
|
((x & 0xff00) >> 8);
|
||||||
#define SWAP32(x) ((uint32_t)( \
|
}
|
||||||
(((uint32_t)(x) & 0x000000ff) << 24) | \
|
|
||||||
(((uint32_t)(x) & 0x0000ff00) << 8) | \
|
static INLINE uint32_t SWAP32(uint32_t x)
|
||||||
(((uint32_t)(x) & 0x00ff0000) >> 8) | \
|
{
|
||||||
(((uint32_t)(x) & 0xff000000) >> 24) \
|
return ((x & 0x000000ff) << 24) |
|
||||||
))
|
((x & 0x0000ff00) << 8) |
|
||||||
|
((x & 0x00ff0000) >> 8) |
|
||||||
|
((x & 0xff000000) >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER <= 1200
|
#if defined(_MSC_VER) && _MSC_VER <= 1200
|
||||||
#define SWAP64(val) \
|
static INLINE uint64_t SWAP64(uint64_t val)
|
||||||
((((uint64_t)(val) & 0x00000000000000ff) << 56) \
|
{
|
||||||
| (((uint64_t)(val) & 0x000000000000ff00) << 40) \
|
return
|
||||||
| (((uint64_t)(val) & 0x0000000000ff0000) << 24) \
|
((val & 0x00000000000000ff) << 56)
|
||||||
| (((uint64_t)(val) & 0x00000000ff000000) << 8) \
|
| ((val & 0x000000000000ff00) << 40)
|
||||||
| (((uint64_t)(val) & 0x000000ff00000000) >> 8) \
|
| ((val & 0x0000000000ff0000) << 24)
|
||||||
| (((uint64_t)(val) & 0x0000ff0000000000) >> 24) \
|
| ((val & 0x00000000ff000000) << 8)
|
||||||
| (((uint64_t)(val) & 0x00ff000000000000) >> 40) \
|
| ((val & 0x000000ff00000000) >> 8)
|
||||||
| (((uint64_t)(val) & 0xff00000000000000) >> 56))
|
| ((val & 0x0000ff0000000000) >> 24)
|
||||||
|
| ((val & 0x00ff000000000000) >> 40)
|
||||||
|
| ((val & 0xff00000000000000) >> 56);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
#define SWAP64(val) \
|
static INLINE uint64_t SWAP64(uint64_t val)
|
||||||
((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \
|
{
|
||||||
| (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \
|
return ((val & 0x00000000000000ffULL) << 56)
|
||||||
| (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \
|
| ((val & 0x000000000000ff00ULL) << 40)
|
||||||
| (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \
|
| ((val & 0x0000000000ff0000ULL) << 24)
|
||||||
| (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \
|
| ((val & 0x00000000ff000000ULL) << 8)
|
||||||
| (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \
|
| ((val & 0x000000ff00000000ULL) >> 8)
|
||||||
| (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \
|
| ((val & 0x0000ff0000000000ULL) >> 24)
|
||||||
| (((uint64_t)(val) & 0xff00000000000000ULL) >> 56))
|
| ((val & 0x00ff000000000000ULL) >> 40)
|
||||||
|
| ((val & 0xff00000000000000ULL) >> 56);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (LSB_FIRST) || defined (MSB_FIRST)
|
||||||
|
# warning Defining MSB_FIRST and LSB_FIRST in compile options is deprecated
|
||||||
|
# undef LSB_FIRST
|
||||||
|
# undef MSB_FIRST
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(_XBOX)
|
||||||
|
#include <winsock2.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#if _M_IX86 || _M_AMD64 || _M_ARM || _M_ARM64
|
||||||
|
#define LSB_FIRST 1
|
||||||
|
#elif _M_PPC
|
||||||
|
#define MSB_FIRST 1
|
||||||
|
#else
|
||||||
|
/* MSVC can run on _M_ALPHA and _M_IA64 too, but they're both bi-endian; need to find what mode MSVC runs them at */
|
||||||
|
#error "unknown platform, can't determine endianness"
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
#define MSB_FIRST 1
|
||||||
|
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
|
#define LSB_FIRST 1
|
||||||
|
#else
|
||||||
|
#error "Invalid endianness macros"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MSB_FIRST) && defined(LSB_FIRST)
|
||||||
|
# error "Bug in LSB_FIRST/MSB_FIRST definition"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(MSB_FIRST) && !defined(LSB_FIRST)
|
||||||
|
# error "Bug in LSB_FIRST/MSB_FIRST definition"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MSB_FIRST
|
||||||
|
# define RETRO_IS_BIG_ENDIAN 1
|
||||||
|
# define RETRO_IS_LITTLE_ENDIAN 0
|
||||||
|
/* For compatibility */
|
||||||
|
# define WORDS_BIGENDIAN 1
|
||||||
|
#else
|
||||||
|
# define RETRO_IS_BIG_ENDIAN 0
|
||||||
|
# define RETRO_IS_LITTLE_ENDIAN 1
|
||||||
|
/* For compatibility */
|
||||||
|
# undef WORDS_BIGENDIAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* is_little_endian:
|
* is_little_endian:
|
||||||
*
|
*
|
||||||
@ -73,23 +133,7 @@
|
|||||||
* Returns: greater than 0 if little-endian,
|
* Returns: greater than 0 if little-endian,
|
||||||
* otherwise big-endian.
|
* otherwise big-endian.
|
||||||
**/
|
**/
|
||||||
#if defined(MSB_FIRST)
|
#define is_little_endian() RETRO_IS_LITTLE_ENDIAN
|
||||||
#define is_little_endian() (0)
|
|
||||||
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
|
|
||||||
#define is_little_endian() (1)
|
|
||||||
#else
|
|
||||||
static INLINE uint8_t is_little_endian(void)
|
|
||||||
{
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint16_t x;
|
|
||||||
uint8_t y[2];
|
|
||||||
} u;
|
|
||||||
|
|
||||||
u.x = 1;
|
|
||||||
return u.y[0];
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* swap_if_big64:
|
* swap_if_big64:
|
||||||
@ -101,17 +145,10 @@ static INLINE uint8_t is_little_endian(void)
|
|||||||
* otherwise returns same value.
|
* otherwise returns same value.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#if defined(MSB_FIRST)
|
#if RETRO_IS_BIG_ENDIAN
|
||||||
#define swap_if_big64(val) (SWAP64(val))
|
#define swap_if_big64(val) (SWAP64(val))
|
||||||
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
|
#elif RETRO_IS_LITTLE_ENDIAN
|
||||||
#define swap_if_big64(val) (val)
|
#define swap_if_big64(val) (val)
|
||||||
#else
|
|
||||||
static INLINE uint64_t swap_if_big64(uint64_t val)
|
|
||||||
{
|
|
||||||
if (is_little_endian())
|
|
||||||
return val;
|
|
||||||
return SWAP64(val);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,17 +161,10 @@ static INLINE uint64_t swap_if_big64(uint64_t val)
|
|||||||
* otherwise returns same value.
|
* otherwise returns same value.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#if defined(MSB_FIRST)
|
#if RETRO_IS_BIG_ENDIAN
|
||||||
#define swap_if_big32(val) (SWAP32(val))
|
#define swap_if_big32(val) (SWAP32(val))
|
||||||
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
|
#elif RETRO_IS_LITTLE_ENDIAN
|
||||||
#define swap_if_big32(val) (val)
|
#define swap_if_big32(val) (val)
|
||||||
#else
|
|
||||||
static INLINE uint32_t swap_if_big32(uint32_t val)
|
|
||||||
{
|
|
||||||
if (is_little_endian())
|
|
||||||
return val;
|
|
||||||
return SWAP32(val);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -147,17 +177,10 @@ static INLINE uint32_t swap_if_big32(uint32_t val)
|
|||||||
* otherwise returns same value.
|
* otherwise returns same value.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#if defined(MSB_FIRST)
|
#if RETRO_IS_BIG_ENDIAN
|
||||||
#define swap_if_little64(val) (val)
|
#define swap_if_little64(val) (val)
|
||||||
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
|
#elif RETRO_IS_LITTLE_ENDIAN
|
||||||
#define swap_if_little64(val) (SWAP64(val))
|
#define swap_if_little64(val) (SWAP64(val))
|
||||||
#else
|
|
||||||
static INLINE uint64_t swap_if_little64(uint64_t val)
|
|
||||||
{
|
|
||||||
if (is_little_endian())
|
|
||||||
return SWAP64(val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,17 +193,10 @@ static INLINE uint64_t swap_if_little64(uint64_t val)
|
|||||||
* otherwise returns same value.
|
* otherwise returns same value.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#if defined(MSB_FIRST)
|
#if RETRO_IS_BIG_ENDIAN
|
||||||
#define swap_if_little32(val) (val)
|
#define swap_if_little32(val) (val)
|
||||||
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
|
#elif RETRO_IS_LITTLE_ENDIAN
|
||||||
#define swap_if_little32(val) (SWAP32(val))
|
#define swap_if_little32(val) (SWAP32(val))
|
||||||
#else
|
|
||||||
static INLINE uint32_t swap_if_little32(uint32_t val)
|
|
||||||
{
|
|
||||||
if (is_little_endian())
|
|
||||||
return SWAP32(val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -193,17 +209,10 @@ static INLINE uint32_t swap_if_little32(uint32_t val)
|
|||||||
* otherwise returns same value.
|
* otherwise returns same value.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#if defined(MSB_FIRST)
|
#if RETRO_IS_BIG_ENDIAN
|
||||||
#define swap_if_big16(val) (SWAP16(val))
|
#define swap_if_big16(val) (SWAP16(val))
|
||||||
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
|
#elif RETRO_IS_LITTLE_ENDIAN
|
||||||
#define swap_if_big16(val) (val)
|
#define swap_if_big16(val) (val)
|
||||||
#else
|
|
||||||
static INLINE uint16_t swap_if_big16(uint16_t val)
|
|
||||||
{
|
|
||||||
if (is_little_endian())
|
|
||||||
return val;
|
|
||||||
return SWAP16(val);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -216,17 +225,10 @@ static INLINE uint16_t swap_if_big16(uint16_t val)
|
|||||||
* otherwise returns same value.
|
* otherwise returns same value.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#if defined(MSB_FIRST)
|
#if RETRO_IS_BIG_ENDIAN
|
||||||
#define swap_if_little16(val) (val)
|
#define swap_if_little16(val) (val)
|
||||||
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
|
#elif RETRO_IS_LITTLE_ENDIAN
|
||||||
#define swap_if_little16(val) (SWAP16(val))
|
#define swap_if_little16(val) (SWAP16(val))
|
||||||
#else
|
|
||||||
static INLINE uint16_t swap_if_little16(uint16_t val)
|
|
||||||
{
|
|
||||||
if (is_little_endian())
|
|
||||||
return SWAP16(val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -255,4 +257,326 @@ static INLINE uint32_t load32be(const uint32_t *addr)
|
|||||||
return swap_if_little32(*addr);
|
return swap_if_little32(*addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_cpu_to_le16:
|
||||||
|
* @val : unsigned 16-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned 16-bit value from system to little-endian.
|
||||||
|
*
|
||||||
|
* Returns: Little-endian representation of val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define retro_cpu_to_le16(val) swap_if_big16(val)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_cpu_to_le32:
|
||||||
|
* @val : unsigned 32-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned 32-bit value from system to little-endian.
|
||||||
|
*
|
||||||
|
* Returns: Little-endian representation of val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define retro_cpu_to_le32(val) swap_if_big32(val)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_cpu_to_le64:
|
||||||
|
* @val : unsigned 64-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned 64-bit value from system to little-endian.
|
||||||
|
*
|
||||||
|
* Returns: Little-endian representation of val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define retro_cpu_to_le64(val) swap_if_big64(val)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_le_to_cpu16:
|
||||||
|
* @val : unsigned 16-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned 16-bit value from little-endian to native.
|
||||||
|
*
|
||||||
|
* Returns: Native representation of little-endian val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define retro_le_to_cpu16(val) swap_if_big16(val)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_le_to_cpu32:
|
||||||
|
* @val : unsigned 32-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned 32-bit value from little-endian to native.
|
||||||
|
*
|
||||||
|
* Returns: Native representation of little-endian val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define retro_le_to_cpu32(val) swap_if_big32(val)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_le_to_cpu16:
|
||||||
|
* @val : unsigned 64-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned 64-bit value from little-endian to native.
|
||||||
|
*
|
||||||
|
* Returns: Native representation of little-endian val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define retro_le_to_cpu64(val) swap_if_big64(val)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_cpu_to_be16:
|
||||||
|
* @val : unsigned 16-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned 16-bit value from system to big-endian.
|
||||||
|
*
|
||||||
|
* Returns: Big-endian representation of val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define retro_cpu_to_be16(val) swap_if_little16(val)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_cpu_to_be32:
|
||||||
|
* @val : unsigned 32-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned 32-bit value from system to big-endian.
|
||||||
|
*
|
||||||
|
* Returns: Big-endian representation of val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define retro_cpu_to_be32(val) swap_if_little32(val)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_cpu_to_be64:
|
||||||
|
* @val : unsigned 64-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned 64-bit value from system to big-endian.
|
||||||
|
*
|
||||||
|
* Returns: Big-endian representation of val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define retro_cpu_to_be64(val) swap_if_little64(val)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_be_to_cpu16:
|
||||||
|
* @val : unsigned 16-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned 16-bit value from big-endian to native.
|
||||||
|
*
|
||||||
|
* Returns: Native representation of big-endian val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define retro_be_to_cpu16(val) swap_if_little16(val)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_be_to_cpu32:
|
||||||
|
* @val : unsigned 32-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned 32-bit value from big-endian to native.
|
||||||
|
*
|
||||||
|
* Returns: Native representation of big-endian val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define retro_be_to_cpu32(val) swap_if_little32(val)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_be_to_cpu64:
|
||||||
|
* @val : unsigned 64-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned 64-bit value from big-endian to native.
|
||||||
|
*
|
||||||
|
* Returns: Native representation of big-endian val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define retro_be_to_cpu64(val) swap_if_little64(val)
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
/* This attribute means that the same memory may be referred through
|
||||||
|
pointers to different size of the object (aliasing). E.g. that u8 *
|
||||||
|
and u32 * may actually be pointing to the same object. */
|
||||||
|
#define MAY_ALIAS __attribute__((__may_alias__))
|
||||||
|
#else
|
||||||
|
#define MAY_ALIAS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct retro_unaligned_uint16_s
|
||||||
|
{
|
||||||
|
uint16_t val;
|
||||||
|
} MAY_ALIAS;
|
||||||
|
struct retro_unaligned_uint32_s
|
||||||
|
{
|
||||||
|
uint32_t val;
|
||||||
|
} MAY_ALIAS;
|
||||||
|
struct retro_unaligned_uint64_s
|
||||||
|
{
|
||||||
|
uint64_t val;
|
||||||
|
} MAY_ALIAS;
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
typedef struct retro_unaligned_uint16_s retro_unaligned_uint16_t;
|
||||||
|
typedef struct retro_unaligned_uint32_s retro_unaligned_uint32_t;
|
||||||
|
typedef struct retro_unaligned_uint64_s retro_unaligned_uint64_t;
|
||||||
|
|
||||||
|
/* L-value references to unaligned pointers. */
|
||||||
|
#define retro_unaligned16(p) (((retro_unaligned_uint16_t *)p)->val)
|
||||||
|
#define retro_unaligned32(p) (((retro_unaligned_uint32_t *)p)->val)
|
||||||
|
#define retro_unaligned64(p) (((retro_unaligned_uint64_t *)p)->val)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_get_unaligned_16be:
|
||||||
|
* @addr : pointer to unsigned 16-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned unaligned 16-bit value from big-endian to native.
|
||||||
|
*
|
||||||
|
* Returns: Native representation of big-endian val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
static INLINE uint16_t retro_get_unaligned_16be(void *addr) {
|
||||||
|
return retro_be_to_cpu16(retro_unaligned16(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_get_unaligned_32be:
|
||||||
|
* @addr : pointer to unsigned 32-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned unaligned 32-bit value from big-endian to native.
|
||||||
|
*
|
||||||
|
* Returns: Native representation of big-endian val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
static INLINE uint32_t retro_get_unaligned_32be(void *addr) {
|
||||||
|
return retro_be_to_cpu32(retro_unaligned32(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_get_unaligned_64be:
|
||||||
|
* @addr : pointer to unsigned 64-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned unaligned 64-bit value from big-endian to native.
|
||||||
|
*
|
||||||
|
* Returns: Native representation of big-endian val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
static INLINE uint64_t retro_get_unaligned_64be(void *addr) {
|
||||||
|
return retro_be_to_cpu64(retro_unaligned64(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_get_unaligned_16le:
|
||||||
|
* @addr : pointer to unsigned 16-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned unaligned 16-bit value from little-endian to native.
|
||||||
|
*
|
||||||
|
* Returns: Native representation of little-endian val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
static INLINE uint16_t retro_get_unaligned_16le(void *addr) {
|
||||||
|
return retro_le_to_cpu16(retro_unaligned16(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_get_unaligned_32le:
|
||||||
|
* @addr : pointer to unsigned 32-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned unaligned 32-bit value from little-endian to native.
|
||||||
|
*
|
||||||
|
* Returns: Native representation of little-endian val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
static INLINE uint32_t retro_get_unaligned_32le(void *addr) {
|
||||||
|
return retro_le_to_cpu32(retro_unaligned32(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_get_unaligned_64le:
|
||||||
|
* @addr : pointer to unsigned 64-bit value
|
||||||
|
*
|
||||||
|
* Convert unsigned unaligned 64-bit value from little-endian to native.
|
||||||
|
*
|
||||||
|
* Returns: Native representation of little-endian val.
|
||||||
|
**/
|
||||||
|
|
||||||
|
static INLINE uint64_t retro_get_unaligned_64le(void *addr) {
|
||||||
|
return retro_le_to_cpu64(retro_unaligned64(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_set_unaligned_16le:
|
||||||
|
* @addr : pointer to unsigned 16-bit value
|
||||||
|
* @val : value to store
|
||||||
|
*
|
||||||
|
* Convert native value to unsigned unaligned 16-bit little-endian value
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
static INLINE void retro_set_unaligned_16le(void *addr, uint16_t v) {
|
||||||
|
retro_unaligned16(addr) = retro_cpu_to_le16(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_set_unaligned_32le:
|
||||||
|
* @addr : pointer to unsigned 32-bit value
|
||||||
|
* @val : value to store
|
||||||
|
*
|
||||||
|
* Convert native value to unsigned unaligned 32-bit little-endian value
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
static INLINE void retro_set_unaligned_32le(void *addr, uint32_t v) {
|
||||||
|
retro_unaligned32(addr) = retro_cpu_to_le32(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_set_unaligned_32le:
|
||||||
|
* @addr : pointer to unsigned 32-bit value
|
||||||
|
* @val : value to store
|
||||||
|
*
|
||||||
|
* Convert native value to unsigned unaligned 32-bit little-endian value
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
static INLINE void retro_set_unaligned_64le(void *addr, uint64_t v) {
|
||||||
|
retro_unaligned64(addr) = retro_cpu_to_le64(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_set_unaligned_16be:
|
||||||
|
* @addr : pointer to unsigned 16-bit value
|
||||||
|
* @val : value to store
|
||||||
|
*
|
||||||
|
* Convert native value to unsigned unaligned 16-bit big-endian value
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
static INLINE void retro_set_unaligned_16be(void *addr, uint16_t v) {
|
||||||
|
retro_unaligned16(addr) = retro_cpu_to_be16(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_set_unaligned_32be:
|
||||||
|
* @addr : pointer to unsigned 32-bit value
|
||||||
|
* @val : value to store
|
||||||
|
*
|
||||||
|
* Convert native value to unsigned unaligned 32-bit big-endian value
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
static INLINE void retro_set_unaligned_32be(void *addr, uint32_t v) {
|
||||||
|
retro_unaligned32(addr) = retro_cpu_to_be32(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retro_set_unaligned_32be:
|
||||||
|
* @addr : pointer to unsigned 32-bit value
|
||||||
|
* @val : value to store
|
||||||
|
*
|
||||||
|
* Convert native value to unsigned unaligned 32-bit big-endian value
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
static INLINE void retro_set_unaligned_64be(void *addr, uint64_t v) {
|
||||||
|
retro_unaligned64(addr) = retro_cpu_to_be64(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (retro_environment.h).
|
* The following license statement only applies to this file (retro_environment.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (retro_inline.h).
|
* The following license statement only applies to this file (retro_inline.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (retro_math.h).
|
* The following license statement only applies to this file (retro_math.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (retro_miscellaneous.h).
|
* The following license statement only applies to this file (retro_miscellaneous.h).
|
||||||
@ -39,7 +39,7 @@
|
|||||||
#include <Xtl.h>
|
#include <Xtl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__CELLOS_LV2__)
|
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||||
#include <sys/fs_external.h>
|
#include <sys/fs_external.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PATH_MAX_LENGTH
|
#ifndef PATH_MAX_LENGTH
|
||||||
#if defined(__CELLOS_LV2__)
|
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||||
#define PATH_MAX_LENGTH CELL_FS_MAX_FS_PATH_LENGTH
|
#define PATH_MAX_LENGTH CELL_FS_MAX_FS_PATH_LENGTH
|
||||||
#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(ORBIS)
|
#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(ORBIS)
|
||||||
#define PATH_MAX_LENGTH 512
|
#define PATH_MAX_LENGTH 512
|
||||||
@ -106,8 +106,8 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
|
|||||||
#define BIT16_GET(a, bit) (((a) >> ((bit) & 15)) & 1)
|
#define BIT16_GET(a, bit) (((a) >> ((bit) & 15)) & 1)
|
||||||
#define BIT16_CLEAR_ALL(a) ((a) = 0)
|
#define BIT16_CLEAR_ALL(a) ((a) = 0)
|
||||||
|
|
||||||
#define BIT32_SET(a, bit) ((a) |= (1 << ((bit) & 31)))
|
#define BIT32_SET(a, bit) ((a) |= (UINT32_C(1) << ((bit) & 31)))
|
||||||
#define BIT32_CLEAR(a, bit) ((a) &= ~(1 << ((bit) & 31)))
|
#define BIT32_CLEAR(a, bit) ((a) &= ~(UINT32_C(1) << ((bit) & 31)))
|
||||||
#define BIT32_GET(a, bit) (((a) >> ((bit) & 31)) & 1)
|
#define BIT32_GET(a, bit) (((a) >> ((bit) & 31)) & 1)
|
||||||
#define BIT32_CLEAR_ALL(a) ((a) = 0)
|
#define BIT32_CLEAR_ALL(a) ((a) = 0)
|
||||||
|
|
||||||
@ -116,8 +116,8 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
|
|||||||
#define BIT64_GET(a, bit) (((a) >> ((bit) & 63)) & 1)
|
#define BIT64_GET(a, bit) (((a) >> ((bit) & 63)) & 1)
|
||||||
#define BIT64_CLEAR_ALL(a) ((a) = 0)
|
#define BIT64_CLEAR_ALL(a) ((a) = 0)
|
||||||
|
|
||||||
#define BIT128_SET(a, bit) ((a).data[(bit) >> 5] |= (1 << ((bit) & 31)))
|
#define BIT128_SET(a, bit) ((a).data[(bit) >> 5] |= (UINT32_C(1) << ((bit) & 31)))
|
||||||
#define BIT128_CLEAR(a, bit) ((a).data[(bit) >> 5] &= ~(1 << ((bit) & 31)))
|
#define BIT128_CLEAR(a, bit) ((a).data[(bit) >> 5] &= ~(UINT32_C(1) << ((bit) & 31)))
|
||||||
#define BIT128_GET(a, bit) (((a).data[(bit) >> 5] >> ((bit) & 31)) & 1)
|
#define BIT128_GET(a, bit) (((a).data[(bit) >> 5] >> ((bit) & 31)) & 1)
|
||||||
#define BIT128_CLEAR_ALL(a) memset(&(a), 0, sizeof(a))
|
#define BIT128_CLEAR_ALL(a) memset(&(a), 0, sizeof(a))
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (retro_timers.h).
|
* The following license statement only applies to this file (retro_timers.h).
|
||||||
@ -37,8 +37,6 @@
|
|||||||
#include <pspthreadman.h>
|
#include <pspthreadman.h>
|
||||||
#elif defined(VITA)
|
#elif defined(VITA)
|
||||||
#include <psp2/kernel/threadmgr.h>
|
#include <psp2/kernel/threadmgr.h>
|
||||||
#elif defined(PS2)
|
|
||||||
#include <SDL/SDL_timer.h>
|
|
||||||
#elif defined(_3DS)
|
#elif defined(_3DS)
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
#else
|
#else
|
||||||
@ -68,7 +66,7 @@ extern int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
|
|||||||
|
|
||||||
static int nanosleepDOS(const struct timespec *rqtp, struct timespec *rmtp)
|
static int nanosleepDOS(const struct timespec *rqtp, struct timespec *rmtp)
|
||||||
{
|
{
|
||||||
usleep(1000000 * rqtp->tv_sec + rqtp->tv_nsec / 1000);
|
usleep(1000000L * rqtp->tv_sec + rqtp->tv_nsec / 1000);
|
||||||
|
|
||||||
if (rmtp)
|
if (rmtp)
|
||||||
rmtp->tv_sec = rmtp->tv_nsec=0;
|
rmtp->tv_sec = rmtp->tv_nsec=0;
|
||||||
@ -91,8 +89,6 @@ static INLINE void retro_sleep(unsigned msec)
|
|||||||
sys_timer_usleep(1000 * msec);
|
sys_timer_usleep(1000 * msec);
|
||||||
#elif defined(PSP) || defined(VITA)
|
#elif defined(PSP) || defined(VITA)
|
||||||
sceKernelDelayThread(1000 * msec);
|
sceKernelDelayThread(1000 * msec);
|
||||||
#elif defined(PS2)
|
|
||||||
SDL_Delay(msec);
|
|
||||||
#elif defined(_3DS)
|
#elif defined(_3DS)
|
||||||
svcSleepThread(1000000 * (s64)msec);
|
svcSleepThread(1000000 * (s64)msec);
|
||||||
#elif defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
#elif defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (rhash.h).
|
* The following license statement only applies to this file (rhash.h).
|
||||||
@ -20,31 +20,8 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
#ifndef __LIBRETRO_SDK_HASH_H
|
||||||
* sha1.h
|
#define __LIBRETRO_SDK_HASH_H
|
||||||
*
|
|
||||||
* Copyright (C) 1998, 2009
|
|
||||||
* Paul E. Jones <paulej@packetizer.com>
|
|
||||||
* All Rights Reserved
|
|
||||||
*
|
|
||||||
*****************************************************************************
|
|
||||||
* $Id: sha1.h 12 2009-06-22 19:34:25Z paulej $
|
|
||||||
*****************************************************************************
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This class implements the Secure Hashing Standard as defined
|
|
||||||
* in FIPS PUB 180-1 published April 17, 1995.
|
|
||||||
*
|
|
||||||
* Many of the variable names in the SHA1Context, especially the
|
|
||||||
* single character names, were used because those were the names
|
|
||||||
* used in the publication.
|
|
||||||
*
|
|
||||||
* Please read the file sha1.c for more information.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __RARCH_HASH_H
|
|
||||||
#define __RARCH_HASH_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@ -70,20 +47,6 @@ RETRO_BEGIN_DECLS
|
|||||||
**/
|
**/
|
||||||
void sha256_hash(char *out, const uint8_t *in, size_t size);
|
void sha256_hash(char *out, const uint8_t *in, size_t size);
|
||||||
|
|
||||||
typedef struct SHA1Context
|
|
||||||
{
|
|
||||||
unsigned Message_Digest[5]; /* Message Digest (output) */
|
|
||||||
|
|
||||||
unsigned Length_Low; /* Message length in bits */
|
|
||||||
unsigned Length_High; /* Message length in bits */
|
|
||||||
|
|
||||||
unsigned char Message_Block[64]; /* 512-bit message blocks */
|
|
||||||
int Message_Block_Index; /* Index into message block array */
|
|
||||||
|
|
||||||
int Computed; /* Is the digest computed? */
|
|
||||||
int Corrupted; /* Is the message digest corruped? */
|
|
||||||
} SHA1Context;
|
|
||||||
|
|
||||||
int sha1_calculate(const char *path, char *result);
|
int sha1_calculate(const char *path, char *result);
|
||||||
|
|
||||||
uint32_t djb2_calculate(const char *str);
|
uint32_t djb2_calculate(const char *str);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (rthreads.h).
|
* The following license statement only applies to this file (rthreads.h).
|
||||||
@ -131,6 +131,15 @@ void slock_free(slock_t *lock);
|
|||||||
**/
|
**/
|
||||||
void slock_lock(slock_t *lock);
|
void slock_lock(slock_t *lock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* slock_try_lock:
|
||||||
|
* @lock : pointer to mutex object
|
||||||
|
*
|
||||||
|
* Attempts to lock a mutex. If a mutex is already locked by
|
||||||
|
* another thread, return false. If the lock is acquired, return true.
|
||||||
|
**/
|
||||||
|
bool slock_try_lock(slock_t *lock);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* slock_unlock:
|
* slock_unlock:
|
||||||
* @lock : pointer to mutex object
|
* @lock : pointer to mutex object
|
||||||
@ -236,11 +245,25 @@ void *sthread_tls_get(sthread_tls_t *tls);
|
|||||||
/**
|
/**
|
||||||
* @brief Binds thread specific data to a key
|
* @brief Binds thread specific data to a key
|
||||||
* @param tls
|
* @param tls
|
||||||
* @return whether the operation suceeded or not
|
* @return Whether the operation suceeded or not
|
||||||
*/
|
*/
|
||||||
bool sthread_tls_set(sthread_tls_t *tls, const void *data);
|
bool sthread_tls_set(sthread_tls_t *tls, const void *data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief Get thread ID of specified thread
|
||||||
|
* @param thread
|
||||||
|
* @return The ID of the specified thread
|
||||||
|
*/
|
||||||
|
uintptr_t sthread_get_thread_id(sthread_t *thread);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief Get thread ID of the current thread
|
||||||
|
* @param
|
||||||
|
* @return The ID of the current thread
|
||||||
|
*/
|
||||||
|
uintptr_t sthread_get_current_thread_id(void);
|
||||||
|
|
||||||
RETRO_END_DECLS
|
RETRO_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (file_stream.h).
|
* The following license statement only applies to this file (file_stream.h).
|
||||||
@ -105,6 +105,7 @@ const char *filestream_get_path(RFILE *stream);
|
|||||||
|
|
||||||
bool filestream_exists(const char *path);
|
bool filestream_exists(const char *path);
|
||||||
|
|
||||||
|
/* Returned pointer must be freed by the caller. */
|
||||||
char* filestream_getline(RFILE *stream);
|
char* filestream_getline(RFILE *stream);
|
||||||
|
|
||||||
libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream);
|
libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (file_stream_transforms.h).
|
* The following license statement only applies to this file (file_stream_transforms.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2019 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (stdstring.h).
|
* The following license statement only applies to this file (stdstring.h).
|
||||||
@ -45,31 +45,40 @@ static INLINE bool string_is_equal(const char *a, const char *b)
|
|||||||
return (a && b) ? !strcmp(a, b) : false;
|
return (a && b) ? !strcmp(a, b) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static INLINE bool string_starts_with_size(const char *str, const char *prefix,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
return (str && prefix) ? !strncmp(prefix, str, size) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE bool string_starts_with(const char *str, const char *prefix)
|
||||||
|
{
|
||||||
|
return (str && prefix) ? !strncmp(prefix, str, strlen(prefix)) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE bool string_ends_with_size(const char *str, const char *suffix,
|
||||||
|
size_t str_len, size_t suffix_len)
|
||||||
|
{
|
||||||
|
return (str_len < suffix_len) ? false :
|
||||||
|
!memcmp(suffix, str + (str_len - suffix_len), suffix_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE bool string_ends_with(const char *str, const char *suffix)
|
||||||
|
{
|
||||||
|
if (!str || !suffix)
|
||||||
|
return false;
|
||||||
|
return string_ends_with_size(str, suffix, strlen(str), strlen(suffix));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define STRLEN_CONST(x) ((sizeof((x))-1))
|
#define STRLEN_CONST(x) ((sizeof((x))-1))
|
||||||
|
|
||||||
#define string_is_not_equal(a, b) !string_is_equal((a), (b))
|
#define string_is_not_equal(a, b) !string_is_equal((a), (b))
|
||||||
|
|
||||||
#define string_add_pair_open(s, size) strlcat((s), " (", (size))
|
|
||||||
#define string_add_pair_close(s, size) strlcat((s), ")", (size))
|
|
||||||
#define string_add_bracket_open(s, size) strlcat((s), "{", (size))
|
|
||||||
#define string_add_bracket_close(s, size) strlcat((s), "}", (size))
|
|
||||||
#define string_add_single_quote(s, size) strlcat((s), "'", (size))
|
|
||||||
#define string_add_quote(s, size) strlcat((s), "\"", (size))
|
|
||||||
#define string_add_colon(s, size) strlcat((s), ":", (size))
|
|
||||||
#define string_add_glob_open(s, size) strlcat((s), "glob('*", (size))
|
|
||||||
#define string_add_glob_close(s, size) strlcat((s), "*')", (size))
|
|
||||||
|
|
||||||
#define string_is_not_equal_fast(a, b, size) (memcmp(a, b, size) != 0)
|
#define string_is_not_equal_fast(a, b, size) (memcmp(a, b, size) != 0)
|
||||||
#define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0)
|
#define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0)
|
||||||
|
|
||||||
static INLINE void string_add_between_pairs(char *s, const char *str,
|
|
||||||
size_t size)
|
|
||||||
{
|
|
||||||
string_add_pair_open(s, size);
|
|
||||||
strlcat(s, str, size);
|
|
||||||
string_add_pair_close(s, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static INLINE bool string_is_equal_case_insensitive(const char *a,
|
static INLINE bool string_is_equal_case_insensitive(const char *a,
|
||||||
const char *b)
|
const char *b)
|
||||||
{
|
{
|
||||||
@ -129,6 +138,45 @@ char *string_trim_whitespace(char *const s);
|
|||||||
char *word_wrap(char *buffer, const char *string,
|
char *word_wrap(char *buffer, const char *string,
|
||||||
int line_width, bool unicode, unsigned max_lines);
|
int line_width, bool unicode, unsigned max_lines);
|
||||||
|
|
||||||
|
/* Splits string into tokens seperated by 'delim'
|
||||||
|
* > Returned token string must be free()'d
|
||||||
|
* > Returns NULL if token is not found
|
||||||
|
* > After each call, 'str' is set to the position after the
|
||||||
|
* last found token
|
||||||
|
* > Tokens *include* empty strings
|
||||||
|
* Usage example:
|
||||||
|
* char *str = "1,2,3,4,5,6,7,,,10,";
|
||||||
|
* char **str_ptr = &str;
|
||||||
|
* char *token = NULL;
|
||||||
|
* while ((token = string_tokenize(str_ptr, ",")))
|
||||||
|
* {
|
||||||
|
* printf("%s\n", token);
|
||||||
|
* free(token);
|
||||||
|
* token = NULL;
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
char* string_tokenize(char **str, const char *delim);
|
||||||
|
|
||||||
|
/* Removes every instance of character 'c' from 'str' */
|
||||||
|
void string_remove_all_chars(char *str, char c);
|
||||||
|
|
||||||
|
/* Replaces every instance of character 'find' in 'str'
|
||||||
|
* with character 'replace' */
|
||||||
|
void string_replace_all_chars(char *str, char find, char replace);
|
||||||
|
|
||||||
|
/* Converts string to unsigned integer.
|
||||||
|
* Returns 0 if string is invalid */
|
||||||
|
unsigned string_to_unsigned(const char *str);
|
||||||
|
|
||||||
|
/* Converts hexadecimal string to unsigned integer.
|
||||||
|
* Handles optional leading '0x'.
|
||||||
|
* Returns 0 if string is invalid */
|
||||||
|
unsigned string_hex_to_unsigned(const char *str);
|
||||||
|
|
||||||
|
char *string_init(const char *src);
|
||||||
|
|
||||||
|
void string_set(char **string, const char *src);
|
||||||
|
|
||||||
RETRO_END_DECLS
|
RETRO_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2019 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (vfs_implementation.h).
|
* The following license statement only applies to this file (vfs_implementation.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2019 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (vfs_implementation.h).
|
* The following license statement only applies to this file (vfs_implementation.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2019 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (vfs_implementation_cdrom.h).
|
* The following license statement only applies to this file (vfs_implementation_cdrom.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (dir_list.c).
|
* The following license statement only applies to this file (dir_list.c).
|
||||||
@ -116,10 +116,21 @@ static int dir_list_read(const char *dir,
|
|||||||
char file_path[PATH_MAX_LENGTH];
|
char file_path[PATH_MAX_LENGTH];
|
||||||
const char *name = retro_dirent_get_name(entry);
|
const char *name = retro_dirent_get_name(entry);
|
||||||
|
|
||||||
if (!include_hidden && *name == '.')
|
if (name[0] == '.')
|
||||||
|
{
|
||||||
|
/* Do not include hidden files and directories */
|
||||||
|
if (!include_hidden)
|
||||||
continue;
|
continue;
|
||||||
if (!strcmp(name, ".") || !strcmp(name, ".."))
|
|
||||||
|
/* char-wise comparisons to avoid string comparison */
|
||||||
|
|
||||||
|
/* Do not include current dir */
|
||||||
|
if (name[1] == '\0')
|
||||||
continue;
|
continue;
|
||||||
|
/* Do not include parent dir */
|
||||||
|
if (name[1] == '.' && name[2] == '\0')
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
file_path[0] = '\0';
|
file_path[0] = '\0';
|
||||||
fill_pathname_join(file_path, dir, name, sizeof(file_path));
|
fill_pathname_join(file_path, dir, name, sizeof(file_path));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (string_list.c).
|
* The following license statement only applies to this file (string_list.c).
|
||||||
@ -47,7 +47,10 @@ void string_list_free(struct string_list *list)
|
|||||||
{
|
{
|
||||||
if (list->elems[i].data)
|
if (list->elems[i].data)
|
||||||
free(list->elems[i].data);
|
free(list->elems[i].data);
|
||||||
|
if (list->elems[i].userdata)
|
||||||
|
free(list->elems[i].userdata);
|
||||||
list->elems[i].data = NULL;
|
list->elems[i].data = NULL;
|
||||||
|
list->elems[i].userdata = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(list->elems);
|
free(list->elems);
|
||||||
@ -92,11 +95,15 @@ static bool string_list_capacity(struct string_list *list, size_t cap)
|
|||||||
struct string_list *string_list_new(void)
|
struct string_list *string_list_new(void)
|
||||||
{
|
{
|
||||||
struct string_list *list = (struct string_list*)
|
struct string_list *list = (struct string_list*)
|
||||||
calloc(1, sizeof(*list));
|
malloc(sizeof(*list));
|
||||||
|
|
||||||
if (!list)
|
if (!list)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
list->elems = NULL;
|
||||||
|
list->size = 0;
|
||||||
|
list->cap = 0;
|
||||||
|
|
||||||
if (!string_list_capacity(list, 32))
|
if (!string_list_capacity(list, 32))
|
||||||
{
|
{
|
||||||
string_list_free(list);
|
string_list_free(list);
|
||||||
@ -256,6 +263,59 @@ error:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_separate:
|
||||||
|
* @str : string to turn into a string list
|
||||||
|
* @delim : delimiter character to use for separating the string.
|
||||||
|
*
|
||||||
|
* Creates a new string list based on string @str, delimited by @delim.
|
||||||
|
* Includes empty strings - i.e. two adjacent delimiters will resolve
|
||||||
|
* to a string list element of "".
|
||||||
|
*
|
||||||
|
* Returns: new string list if successful, otherwise NULL.
|
||||||
|
*/
|
||||||
|
struct string_list *string_separate(char *str, const char *delim)
|
||||||
|
{
|
||||||
|
char *token = NULL;
|
||||||
|
char **str_ptr = NULL;
|
||||||
|
struct string_list *list = NULL;
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
if (!str || string_is_empty(delim))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
str_ptr = &str;
|
||||||
|
list = string_list_new();
|
||||||
|
|
||||||
|
if (!list)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
token = string_tokenize(str_ptr, delim);
|
||||||
|
while (token)
|
||||||
|
{
|
||||||
|
union string_list_elem_attr attr;
|
||||||
|
|
||||||
|
attr.i = 0;
|
||||||
|
|
||||||
|
if (!string_list_append(list, token, attr))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
free(token);
|
||||||
|
token = NULL;
|
||||||
|
|
||||||
|
token = string_tokenize(str_ptr, delim);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (token)
|
||||||
|
free(token);
|
||||||
|
if (list)
|
||||||
|
string_list_free(list);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* string_list_find_elem:
|
* string_list_find_elem:
|
||||||
* @list : pointer to string list
|
* @list : pointer to string list
|
||||||
@ -320,13 +380,16 @@ struct string_list *string_list_clone(
|
|||||||
const struct string_list *src)
|
const struct string_list *src)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
struct string_list_elem *elems = NULL;
|
struct string_list_elem
|
||||||
struct string_list *dest = (struct string_list*)
|
*elems = NULL;
|
||||||
calloc(1, sizeof(struct string_list));
|
struct string_list
|
||||||
|
*dest = (struct string_list*)
|
||||||
|
malloc(sizeof(struct string_list));
|
||||||
|
|
||||||
if (!dest)
|
if (!dest)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
dest->elems = NULL;
|
||||||
dest->size = src->size;
|
dest->size = src->size;
|
||||||
dest->cap = src->cap;
|
dest->cap = src->cap;
|
||||||
if (dest->cap < dest->size)
|
if (dest->cap < dest->size)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (memalign.c).
|
* The following license statement only applies to this file (memalign.c).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (gx_pthread.h).
|
* The following license statement only applies to this file (gx_pthread.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2017 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (psp_pthread.h).
|
* The following license statement only applies to this file (psp_pthread.h).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (rthreads.c).
|
* The following license statement only applies to this file (rthreads.c).
|
||||||
@ -191,12 +191,12 @@ sthread_t *sthread_create_with_priority(void (*thread_func)(void*), void *userda
|
|||||||
#endif
|
#endif
|
||||||
bool thread_created = false;
|
bool thread_created = false;
|
||||||
struct thread_data *data = NULL;
|
struct thread_data *data = NULL;
|
||||||
sthread_t *thread = (sthread_t*)calloc(1, sizeof(*thread));
|
sthread_t *thread = (sthread_t*)malloc(sizeof(*thread));
|
||||||
|
|
||||||
if (!thread)
|
if (!thread)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
data = (struct thread_data*)calloc(1, sizeof(*data));
|
data = (struct thread_data*)malloc(sizeof(*data));
|
||||||
if (!data)
|
if (!data)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -204,9 +204,12 @@ sthread_t *sthread_create_with_priority(void (*thread_func)(void*), void *userda
|
|||||||
data->userdata = userdata;
|
data->userdata = userdata;
|
||||||
|
|
||||||
#ifdef USE_WIN32_THREADS
|
#ifdef USE_WIN32_THREADS
|
||||||
thread->thread = CreateThread(NULL, 0, thread_wrap, data, 0, &thread->id);
|
thread->id = 0;
|
||||||
|
thread->thread = CreateThread(NULL, 0, thread_wrap,
|
||||||
|
data, 0, &thread->id);
|
||||||
thread_created = !!thread->thread;
|
thread_created = !!thread->thread;
|
||||||
#else
|
#else
|
||||||
|
thread->id = 0;
|
||||||
|
|
||||||
#ifdef HAVE_THREAD_ATTR
|
#ifdef HAVE_THREAD_ATTR
|
||||||
pthread_attr_init(&thread_attr);
|
pthread_attr_init(&thread_attr);
|
||||||
@ -268,7 +271,9 @@ int sthread_detach(sthread_t *thread)
|
|||||||
free(thread);
|
free(thread);
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
return pthread_detach(thread->id);
|
int ret = pthread_detach(thread->id);
|
||||||
|
free(thread);
|
||||||
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,6 +335,7 @@ slock_t *slock_new(void)
|
|||||||
if (!lock)
|
if (!lock)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_WIN32_THREADS
|
#ifdef USE_WIN32_THREADS
|
||||||
InitializeCriticalSection(&lock->lock);
|
InitializeCriticalSection(&lock->lock);
|
||||||
mutex_created = true;
|
mutex_created = true;
|
||||||
@ -385,6 +391,24 @@ void slock_lock(slock_t *lock)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* slock_try_lock:
|
||||||
|
* @lock : pointer to mutex object
|
||||||
|
*
|
||||||
|
* Attempts to lock a mutex. If a mutex is already locked by
|
||||||
|
* another thread, return false. If the lock is acquired, return true.
|
||||||
|
**/
|
||||||
|
bool slock_try_lock(slock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock)
|
||||||
|
return false;
|
||||||
|
#ifdef USE_WIN32_THREADS
|
||||||
|
return TryEnterCriticalSection(&lock->lock);
|
||||||
|
#else
|
||||||
|
return pthread_mutex_trylock(&lock->lock)==0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* slock_unlock:
|
* slock_unlock:
|
||||||
* @lock : pointer to mutex object
|
* @lock : pointer to mutex object
|
||||||
@ -419,7 +443,6 @@ scond_t *scond_new(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
#ifdef USE_WIN32_THREADS
|
#ifdef USE_WIN32_THREADS
|
||||||
|
|
||||||
/* This is very complex because recreating condition variable semantics
|
/* This is very complex because recreating condition variable semantics
|
||||||
* with Win32 parts is not easy.
|
* with Win32 parts is not easy.
|
||||||
*
|
*
|
||||||
@ -446,7 +469,8 @@ scond_t *scond_new(void)
|
|||||||
* Note: We might could simplify this using vista+ condition variables,
|
* Note: We might could simplify this using vista+ condition variables,
|
||||||
* but we wanted an XP compatible solution. */
|
* but we wanted an XP compatible solution. */
|
||||||
cond->event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
cond->event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
if (!cond->event) goto error;
|
if (!cond->event)
|
||||||
|
goto error;
|
||||||
cond->hot_potato = CreateEvent(NULL, FALSE, FALSE, NULL);
|
cond->hot_potato = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
if (!cond->hot_potato)
|
if (!cond->hot_potato)
|
||||||
{
|
{
|
||||||
@ -455,9 +479,6 @@ scond_t *scond_new(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
InitializeCriticalSection(&cond->cs);
|
InitializeCriticalSection(&cond->cs);
|
||||||
cond->waiters = cond->wakens = 0;
|
|
||||||
cond->head = NULL;
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
if (pthread_cond_init(&cond->cond, NULL) != 0)
|
if (pthread_cond_init(&cond->cond, NULL) != 0)
|
||||||
goto error;
|
goto error;
|
||||||
@ -851,7 +872,7 @@ bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us)
|
|||||||
now.tv_sec = s;
|
now.tv_sec = s;
|
||||||
now.tv_nsec = n;
|
now.tv_nsec = n;
|
||||||
#elif defined(PS2)
|
#elif defined(PS2)
|
||||||
int tickms = clock();
|
int tickms = ps2_clock();
|
||||||
now.tv_sec = tickms/1000;
|
now.tv_sec = tickms/1000;
|
||||||
now.tv_nsec = tickms * 1000;
|
now.tv_nsec = tickms * 1000;
|
||||||
#elif defined(__mips__) || defined(VITA) || defined(_3DS)
|
#elif defined(__mips__) || defined(VITA) || defined(_3DS)
|
||||||
@ -921,3 +942,19 @@ bool sthread_tls_set(sthread_tls_t *tls, const void *data)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uintptr_t sthread_get_thread_id(sthread_t *thread)
|
||||||
|
{
|
||||||
|
if (!thread)
|
||||||
|
return 0;
|
||||||
|
return (uintptr_t)thread->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t sthread_get_current_thread_id(void)
|
||||||
|
{
|
||||||
|
#ifdef USE_WIN32_THREADS
|
||||||
|
return (uintptr_t)GetCurrentThreadId();
|
||||||
|
#else
|
||||||
|
return (uintptr_t)pthread_self();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (xenon_sdl_threads.c).
|
* The following license statement only applies to this file (xenon_sdl_threads.c).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (file_stream.c).
|
* The following license statement only applies to this file (file_stream.c).
|
||||||
@ -111,7 +111,11 @@ bool filestream_exists(const char *path)
|
|||||||
if (!dummy)
|
if (!dummy)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
filestream_close(dummy);
|
if (filestream_close(dummy) != 0)
|
||||||
|
if (dummy)
|
||||||
|
free(dummy);
|
||||||
|
|
||||||
|
dummy = NULL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +123,7 @@ int64_t filestream_get_size(RFILE *stream)
|
|||||||
{
|
{
|
||||||
int64_t output;
|
int64_t output;
|
||||||
|
|
||||||
if (filestream_size_cb != NULL)
|
if (filestream_size_cb)
|
||||||
output = filestream_size_cb(stream->hfile);
|
output = filestream_size_cb(stream->hfile);
|
||||||
else
|
else
|
||||||
output = retro_vfs_file_size_impl((libretro_vfs_implementation_file*)stream->hfile);
|
output = retro_vfs_file_size_impl((libretro_vfs_implementation_file*)stream->hfile);
|
||||||
@ -134,7 +138,7 @@ int64_t filestream_truncate(RFILE *stream, int64_t length)
|
|||||||
{
|
{
|
||||||
int64_t output;
|
int64_t output;
|
||||||
|
|
||||||
if (filestream_truncate_cb != NULL)
|
if (filestream_truncate_cb)
|
||||||
output = filestream_truncate_cb(stream->hfile, length);
|
output = filestream_truncate_cb(stream->hfile, length);
|
||||||
else
|
else
|
||||||
output = retro_vfs_file_truncate_impl((libretro_vfs_implementation_file*)stream->hfile, length);
|
output = retro_vfs_file_truncate_impl((libretro_vfs_implementation_file*)stream->hfile, length);
|
||||||
@ -159,7 +163,7 @@ RFILE *filestream_open(const char *path, unsigned mode, unsigned hints)
|
|||||||
struct retro_vfs_file_handle *fp = NULL;
|
struct retro_vfs_file_handle *fp = NULL;
|
||||||
RFILE* output = NULL;
|
RFILE* output = NULL;
|
||||||
|
|
||||||
if (filestream_open_cb != NULL)
|
if (filestream_open_cb)
|
||||||
fp = (struct retro_vfs_file_handle*)
|
fp = (struct retro_vfs_file_handle*)
|
||||||
filestream_open_cb(path, mode, hints);
|
filestream_open_cb(path, mode, hints);
|
||||||
else
|
else
|
||||||
@ -203,9 +207,7 @@ char *filestream_gets(RFILE *stream, char *s, size_t len)
|
|||||||
int filestream_getc(RFILE *stream)
|
int filestream_getc(RFILE *stream)
|
||||||
{
|
{
|
||||||
char c = 0;
|
char c = 0;
|
||||||
if (!stream)
|
if (stream && filestream_read(stream, &c, 1) == 1)
|
||||||
return EOF;
|
|
||||||
if (filestream_read(stream, &c, 1) == 1)
|
|
||||||
return (int)(unsigned char)c;
|
return (int)(unsigned char)c;
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
@ -215,7 +217,6 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
|
|||||||
char buf[4096];
|
char buf[4096];
|
||||||
char subfmt[64];
|
char subfmt[64];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
const char * bufiter = buf;
|
const char * bufiter = buf;
|
||||||
int64_t startpos = filestream_tell(stream);
|
int64_t startpos = filestream_tell(stream);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -233,7 +234,6 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
|
|||||||
if (*format == '%')
|
if (*format == '%')
|
||||||
{
|
{
|
||||||
int sublen;
|
int sublen;
|
||||||
|
|
||||||
char* subfmtiter = subfmt;
|
char* subfmtiter = subfmt;
|
||||||
bool asterisk = false;
|
bool asterisk = false;
|
||||||
|
|
||||||
@ -247,15 +247,21 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
|
|||||||
*subfmtiter++ = *format++;
|
*subfmtiter++ = *format++;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (isdigit(*format)) *subfmtiter++ = *format++; /* width */
|
while (isdigit(*format))
|
||||||
|
*subfmtiter++ = *format++; /* width */
|
||||||
|
|
||||||
/* length */
|
/* length */
|
||||||
if (*format == 'h' || *format == 'l')
|
if (*format == 'h' || *format == 'l')
|
||||||
{
|
{
|
||||||
if (format[1] == format[0]) *subfmtiter++ = *format++;
|
if (format[1] == format[0])
|
||||||
|
*subfmtiter++ = *format++;
|
||||||
*subfmtiter++ = *format++;
|
*subfmtiter++ = *format++;
|
||||||
}
|
}
|
||||||
else if (*format == 'j' || *format == 'z' || *format == 't' || *format == 'L')
|
else if (
|
||||||
|
*format == 'j' ||
|
||||||
|
*format == 'z' ||
|
||||||
|
*format == 't' ||
|
||||||
|
*format == 'L')
|
||||||
{
|
{
|
||||||
*subfmtiter++ = *format++;
|
*subfmtiter++ = *format++;
|
||||||
}
|
}
|
||||||
@ -263,10 +269,12 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
|
|||||||
/* specifier - always a single character (except ]) */
|
/* specifier - always a single character (except ]) */
|
||||||
if (*format == '[')
|
if (*format == '[')
|
||||||
{
|
{
|
||||||
while (*format != ']') *subfmtiter++ = *format++;
|
while (*format != ']')
|
||||||
|
*subfmtiter++ = *format++;
|
||||||
*subfmtiter++ = *format++;
|
*subfmtiter++ = *format++;
|
||||||
}
|
}
|
||||||
else *subfmtiter++ = *format++;
|
else
|
||||||
|
*subfmtiter++ = *format++;
|
||||||
|
|
||||||
*subfmtiter++ = '%';
|
*subfmtiter++ = '%';
|
||||||
*subfmtiter++ = 'n';
|
*subfmtiter++ = 'n';
|
||||||
@ -275,11 +283,17 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
|
|||||||
if (sizeof(void*) != sizeof(long*)) abort(); /* all pointers must have the same size */
|
if (sizeof(void*) != sizeof(long*)) abort(); /* all pointers must have the same size */
|
||||||
if (asterisk)
|
if (asterisk)
|
||||||
{
|
{
|
||||||
if (sscanf(bufiter, subfmt, &sublen) != 0) break;
|
int v = sscanf(bufiter, subfmt, &sublen);
|
||||||
|
if (v == EOF)
|
||||||
|
return EOF;
|
||||||
|
if (v != 0) break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (sscanf(bufiter, subfmt, va_arg(args, void*), &sublen) != 1) break;
|
int v = sscanf(bufiter, subfmt, va_arg(args, void*), &sublen);
|
||||||
|
if (v == EOF)
|
||||||
|
return EOF;
|
||||||
|
if (v != 1) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret++;
|
ret++;
|
||||||
@ -309,7 +323,7 @@ int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position)
|
|||||||
{
|
{
|
||||||
int64_t output;
|
int64_t output;
|
||||||
|
|
||||||
if (filestream_seek_cb != NULL)
|
if (filestream_seek_cb)
|
||||||
output = filestream_seek_cb(stream->hfile, offset, seek_position);
|
output = filestream_seek_cb(stream->hfile, offset, seek_position);
|
||||||
else
|
else
|
||||||
output = retro_vfs_file_seek_impl((libretro_vfs_implementation_file*)stream->hfile, offset, seek_position);
|
output = retro_vfs_file_seek_impl((libretro_vfs_implementation_file*)stream->hfile, offset, seek_position);
|
||||||
@ -330,7 +344,7 @@ int64_t filestream_tell(RFILE *stream)
|
|||||||
{
|
{
|
||||||
int64_t output;
|
int64_t output;
|
||||||
|
|
||||||
if (filestream_size_cb != NULL)
|
if (filestream_size_cb)
|
||||||
output = filestream_tell_cb(stream->hfile);
|
output = filestream_tell_cb(stream->hfile);
|
||||||
else
|
else
|
||||||
output = retro_vfs_file_tell_impl((libretro_vfs_implementation_file*)stream->hfile);
|
output = retro_vfs_file_tell_impl((libretro_vfs_implementation_file*)stream->hfile);
|
||||||
@ -354,7 +368,7 @@ int64_t filestream_read(RFILE *stream, void *s, int64_t len)
|
|||||||
{
|
{
|
||||||
int64_t output;
|
int64_t output;
|
||||||
|
|
||||||
if (filestream_read_cb != NULL)
|
if (filestream_read_cb)
|
||||||
output = filestream_read_cb(stream->hfile, s, len);
|
output = filestream_read_cb(stream->hfile, s, len);
|
||||||
else
|
else
|
||||||
output = retro_vfs_file_read_impl(
|
output = retro_vfs_file_read_impl(
|
||||||
@ -372,7 +386,7 @@ int filestream_flush(RFILE *stream)
|
|||||||
{
|
{
|
||||||
int output;
|
int output;
|
||||||
|
|
||||||
if (filestream_flush_cb != NULL)
|
if (filestream_flush_cb)
|
||||||
output = filestream_flush_cb(stream->hfile);
|
output = filestream_flush_cb(stream->hfile);
|
||||||
else
|
else
|
||||||
output = retro_vfs_file_flush_impl((libretro_vfs_implementation_file*)stream->hfile);
|
output = retro_vfs_file_flush_impl((libretro_vfs_implementation_file*)stream->hfile);
|
||||||
@ -385,7 +399,7 @@ int filestream_flush(RFILE *stream)
|
|||||||
|
|
||||||
int filestream_delete(const char *path)
|
int filestream_delete(const char *path)
|
||||||
{
|
{
|
||||||
if (filestream_remove_cb != NULL)
|
if (filestream_remove_cb)
|
||||||
return filestream_remove_cb(path);
|
return filestream_remove_cb(path);
|
||||||
|
|
||||||
return retro_vfs_file_remove_impl(path);
|
return retro_vfs_file_remove_impl(path);
|
||||||
@ -393,7 +407,7 @@ int filestream_delete(const char *path)
|
|||||||
|
|
||||||
int filestream_rename(const char *old_path, const char *new_path)
|
int filestream_rename(const char *old_path, const char *new_path)
|
||||||
{
|
{
|
||||||
if (filestream_rename_cb != NULL)
|
if (filestream_rename_cb)
|
||||||
return filestream_rename_cb(old_path, new_path);
|
return filestream_rename_cb(old_path, new_path);
|
||||||
|
|
||||||
return retro_vfs_file_rename_impl(old_path, new_path);
|
return retro_vfs_file_rename_impl(old_path, new_path);
|
||||||
@ -401,7 +415,7 @@ int filestream_rename(const char *old_path, const char *new_path)
|
|||||||
|
|
||||||
const char* filestream_get_path(RFILE *stream)
|
const char* filestream_get_path(RFILE *stream)
|
||||||
{
|
{
|
||||||
if (filestream_get_path_cb != NULL)
|
if (filestream_get_path_cb)
|
||||||
return filestream_get_path_cb(stream->hfile);
|
return filestream_get_path_cb(stream->hfile);
|
||||||
|
|
||||||
return retro_vfs_file_get_path_impl((libretro_vfs_implementation_file*)stream->hfile);
|
return retro_vfs_file_get_path_impl((libretro_vfs_implementation_file*)stream->hfile);
|
||||||
@ -411,7 +425,7 @@ int64_t filestream_write(RFILE *stream, const void *s, int64_t len)
|
|||||||
{
|
{
|
||||||
int64_t output;
|
int64_t output;
|
||||||
|
|
||||||
if (filestream_write_cb != NULL)
|
if (filestream_write_cb)
|
||||||
output = filestream_write_cb(stream->hfile, s, len);
|
output = filestream_write_cb(stream->hfile, s, len);
|
||||||
else
|
else
|
||||||
output = retro_vfs_file_write_impl((libretro_vfs_implementation_file*)stream->hfile, s, len);
|
output = retro_vfs_file_write_impl((libretro_vfs_implementation_file*)stream->hfile, s, len);
|
||||||
@ -433,7 +447,8 @@ int filestream_putc(RFILE *stream, int c)
|
|||||||
int filestream_vprintf(RFILE *stream, const char* format, va_list args)
|
int filestream_vprintf(RFILE *stream, const char* format, va_list args)
|
||||||
{
|
{
|
||||||
static char buffer[8 * 1024];
|
static char buffer[8 * 1024];
|
||||||
int64_t num_chars = vsprintf(buffer, format, args);
|
int64_t num_chars = vsnprintf(buffer, sizeof(buffer),
|
||||||
|
format, args);
|
||||||
|
|
||||||
if (num_chars < 0)
|
if (num_chars < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -465,7 +480,7 @@ int filestream_close(RFILE *stream)
|
|||||||
int output;
|
int output;
|
||||||
struct retro_vfs_file_handle* fp = stream->hfile;
|
struct retro_vfs_file_handle* fp = stream->hfile;
|
||||||
|
|
||||||
if (filestream_close_cb != NULL)
|
if (filestream_close_cb)
|
||||||
output = filestream_close_cb(fp);
|
output = filestream_close_cb(fp);
|
||||||
else
|
else
|
||||||
output = retro_vfs_file_close_impl((libretro_vfs_implementation_file*)fp);
|
output = retro_vfs_file_close_impl((libretro_vfs_implementation_file*)fp);
|
||||||
@ -497,8 +512,8 @@ int64_t filestream_read_file(const char *path, void **buf, int64_t *len)
|
|||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
*buf = NULL;
|
||||||
goto error;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
content_buf_size = filestream_get_size(file);
|
content_buf_size = filestream_get_size(file);
|
||||||
@ -515,12 +530,11 @@ int64_t filestream_read_file(const char *path, void **buf, int64_t *len)
|
|||||||
|
|
||||||
ret = filestream_read(file, content_buf, (int64_t)content_buf_size);
|
ret = filestream_read(file, content_buf, (int64_t)content_buf_size);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
|
||||||
fprintf(stderr, "Failed to read %s: %s\n", path, strerror(errno));
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
|
|
||||||
filestream_close(file);
|
if (filestream_close(file) != 0)
|
||||||
|
if (file)
|
||||||
|
free(file);
|
||||||
|
|
||||||
*buf = content_buf;
|
*buf = content_buf;
|
||||||
|
|
||||||
@ -535,7 +549,8 @@ int64_t filestream_read_file(const char *path, void **buf, int64_t *len)
|
|||||||
|
|
||||||
error:
|
error:
|
||||||
if (file)
|
if (file)
|
||||||
filestream_close(file);
|
if (filestream_close(file) != 0)
|
||||||
|
free(file);
|
||||||
if (content_buf)
|
if (content_buf)
|
||||||
free(content_buf);
|
free(content_buf);
|
||||||
if (len)
|
if (len)
|
||||||
@ -564,7 +579,9 @@ bool filestream_write_file(const char *path, const void *data, int64_t size)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
ret = filestream_write(file, data, size);
|
ret = filestream_write(file, data, size);
|
||||||
filestream_close(file);
|
if (filestream_close(file) != 0)
|
||||||
|
if (file)
|
||||||
|
free(file);
|
||||||
|
|
||||||
if (ret != size)
|
if (ret != size)
|
||||||
return false;
|
return false;
|
||||||
@ -572,6 +589,7 @@ bool filestream_write_file(const char *path, const void *data, int64_t size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returned pointer must be freed by the caller. */
|
||||||
char* filestream_getline(RFILE *stream)
|
char* filestream_getline(RFILE *stream)
|
||||||
{
|
{
|
||||||
char *newline_tmp = NULL;
|
char *newline_tmp = NULL;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (file_stream_transforms.c).
|
* The following license statement only applies to this file (file_stream_transforms.c).
|
||||||
@ -99,7 +99,7 @@ int64_t rfseek(RFILE* stream, int64_t offset, int origin)
|
|||||||
int64_t rfread(void* buffer,
|
int64_t rfread(void* buffer,
|
||||||
size_t elem_size, size_t elem_count, RFILE* stream)
|
size_t elem_size, size_t elem_count, RFILE* stream)
|
||||||
{
|
{
|
||||||
return filestream_read(stream, buffer, elem_size * elem_count);
|
return (filestream_read(stream, buffer, elem_size * elem_count) / elem_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *rfgets(char *buffer, int maxCount, RFILE* stream)
|
char *rfgets(char *buffer, int maxCount, RFILE* stream)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (stdstring.c).
|
* The following license statement only applies to this file (stdstring.c).
|
||||||
@ -26,6 +26,18 @@
|
|||||||
#include <string/stdstring.h>
|
#include <string/stdstring.h>
|
||||||
#include <encodings/utf.h>
|
#include <encodings/utf.h>
|
||||||
|
|
||||||
|
char *string_init(const char *src)
|
||||||
|
{
|
||||||
|
return src ? strdup(src) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void string_set(char **string, const char *src)
|
||||||
|
{
|
||||||
|
free(*string);
|
||||||
|
*string = src ? strdup(src) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
char *string_to_upper(char *s)
|
char *string_to_upper(char *s)
|
||||||
{
|
{
|
||||||
char *cs = (char *)s;
|
char *cs = (char *)s;
|
||||||
@ -237,3 +249,148 @@ char *word_wrap(char* buffer, const char *string, int line_width, bool unicode,
|
|||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Splits string into tokens seperated by 'delim'
|
||||||
|
* > Returned token string must be free()'d
|
||||||
|
* > Returns NULL if token is not found
|
||||||
|
* > After each call, 'str' is set to the position after the
|
||||||
|
* last found token
|
||||||
|
* > Tokens *include* empty strings
|
||||||
|
* Usage example:
|
||||||
|
* char *str = "1,2,3,4,5,6,7,,,10,";
|
||||||
|
* char **str_ptr = &str;
|
||||||
|
* char *token = NULL;
|
||||||
|
* while ((token = string_tokenize(str_ptr, ",")))
|
||||||
|
* {
|
||||||
|
* printf("%s\n", token);
|
||||||
|
* free(token);
|
||||||
|
* token = NULL;
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
char* string_tokenize(char **str, const char *delim)
|
||||||
|
{
|
||||||
|
/* Taken from https://codereview.stackexchange.com/questions/216956/strtok-function-thread-safe-supports-empty-tokens-doesnt-change-string# */
|
||||||
|
char *str_ptr = NULL;
|
||||||
|
char *delim_ptr = NULL;
|
||||||
|
char *token = NULL;
|
||||||
|
size_t token_len = 0;
|
||||||
|
|
||||||
|
/* Sanity checks */
|
||||||
|
if (!str || string_is_empty(delim))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
str_ptr = *str;
|
||||||
|
|
||||||
|
/* Note: we don't check string_is_empty() here,
|
||||||
|
* empty strings are valid */
|
||||||
|
if (!str_ptr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Search for delimiter */
|
||||||
|
delim_ptr = strstr(str_ptr, delim);
|
||||||
|
|
||||||
|
if (delim_ptr)
|
||||||
|
token_len = delim_ptr - str_ptr;
|
||||||
|
else
|
||||||
|
token_len = strlen(str_ptr);
|
||||||
|
|
||||||
|
/* Allocate token string */
|
||||||
|
token = (char *)malloc((token_len + 1) * sizeof(char));
|
||||||
|
|
||||||
|
if (!token)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Copy token */
|
||||||
|
strlcpy(token, str_ptr, (token_len + 1) * sizeof(char));
|
||||||
|
token[token_len] = '\0';
|
||||||
|
|
||||||
|
/* Update input string pointer */
|
||||||
|
*str = delim_ptr ? delim_ptr + strlen(delim) : NULL;
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Removes every instance of character 'c' from 'str' */
|
||||||
|
void string_remove_all_chars(char *str, char c)
|
||||||
|
{
|
||||||
|
char *read_ptr = NULL;
|
||||||
|
char *write_ptr = NULL;
|
||||||
|
|
||||||
|
if (string_is_empty(str))
|
||||||
|
return;
|
||||||
|
|
||||||
|
read_ptr = str;
|
||||||
|
write_ptr = str;
|
||||||
|
|
||||||
|
while (*read_ptr != '\0')
|
||||||
|
{
|
||||||
|
*write_ptr = *read_ptr++;
|
||||||
|
write_ptr += (*write_ptr != c) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*write_ptr = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Replaces every instance of character 'find' in 'str'
|
||||||
|
* with character 'replace' */
|
||||||
|
void string_replace_all_chars(char *str, char find, char replace)
|
||||||
|
{
|
||||||
|
char *str_ptr = str;
|
||||||
|
|
||||||
|
if (string_is_empty(str))
|
||||||
|
return;
|
||||||
|
|
||||||
|
while ((str_ptr = strchr(str_ptr, find)))
|
||||||
|
*str_ptr++ = replace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Converts string to unsigned integer.
|
||||||
|
* Returns 0 if string is invalid */
|
||||||
|
unsigned string_to_unsigned(const char *str)
|
||||||
|
{
|
||||||
|
const char *ptr = NULL;
|
||||||
|
|
||||||
|
if (string_is_empty(str))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (ptr = str; *ptr != '\0'; ptr++)
|
||||||
|
{
|
||||||
|
if (!isdigit(*ptr))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (unsigned)strtoul(str, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Converts hexadecimal string to unsigned integer.
|
||||||
|
* Handles optional leading '0x'.
|
||||||
|
* Returns 0 if string is invalid */
|
||||||
|
unsigned string_hex_to_unsigned(const char *str)
|
||||||
|
{
|
||||||
|
const char *hex_str = str;
|
||||||
|
const char *ptr = NULL;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (string_is_empty(str))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Remove leading '0x', if required */
|
||||||
|
len = strlen(str);
|
||||||
|
|
||||||
|
if (len >= 2)
|
||||||
|
if ((str[0] == '0') &&
|
||||||
|
((str[1] == 'x') || (str[1] == 'X')))
|
||||||
|
hex_str = str + 2;
|
||||||
|
|
||||||
|
if (string_is_empty(hex_str))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Check for valid characters */
|
||||||
|
for (ptr = hex_str; *ptr != '\0'; ptr++)
|
||||||
|
{
|
||||||
|
if (!isxdigit(*ptr))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (unsigned)strtoul(hex_str, NULL, 16);
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2019 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (vfs_implementation.c).
|
* The following license statement only applies to this file (vfs_implementation.c).
|
||||||
@ -51,10 +51,6 @@
|
|||||||
# if defined(PSP)
|
# if defined(PSP)
|
||||||
# include <pspiofilemgr.h>
|
# include <pspiofilemgr.h>
|
||||||
# endif
|
# endif
|
||||||
# if defined(PS2)
|
|
||||||
# include <fileXio_rpc.h>
|
|
||||||
# include <fileXio_cdvd.h>
|
|
||||||
# endif
|
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# if !defined(VITA)
|
# if !defined(VITA)
|
||||||
@ -68,7 +64,7 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __CELLOS_LV2__
|
#if defined (__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||||
#include <cell/cell_fs.h>
|
#include <cell/cell_fs.h>
|
||||||
#define O_RDONLY CELL_FS_O_RDONLY
|
#define O_RDONLY CELL_FS_O_RDONLY
|
||||||
#define O_WRONLY CELL_FS_O_WRONLY
|
#define O_WRONLY CELL_FS_O_WRONLY
|
||||||
@ -93,16 +89,13 @@
|
|||||||
# if defined(PSP)
|
# if defined(PSP)
|
||||||
# include <pspiofilemgr.h>
|
# include <pspiofilemgr.h>
|
||||||
# endif
|
# endif
|
||||||
# if defined(PS2)
|
|
||||||
# include <fileXio_rpc.h>
|
|
||||||
# endif
|
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# include <dirent.h>
|
# include <dirent.h>
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP) || defined(PS2)
|
#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
|
||||||
|
|
||||||
@ -146,12 +139,7 @@
|
|||||||
#include <pspkernel.h>
|
#include <pspkernel.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PS2)
|
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||||
#include <fileXio_rpc.h>
|
|
||||||
#include <fileXio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__CELLOS_LV2__)
|
|
||||||
#include <cell/cell_fs.h>
|
#include <cell/cell_fs.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -172,7 +160,7 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(_XBOX)
|
#if defined(_WIN32)
|
||||||
#if !defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER >= 1400)
|
#if !defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||||
#define ATLEAST_VC2005
|
#define ATLEAST_VC2005
|
||||||
#endif
|
#endif
|
||||||
@ -189,9 +177,17 @@
|
|||||||
#include <vfs/vfs_implementation_cdrom.h>
|
#include <vfs/vfs_implementation_cdrom.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE - 0) >= 200112) || (defined(__POSIX_VISIBLE) && __POSIX_VISIBLE >= 200112) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112) || __USE_LARGEFILE
|
||||||
|
#ifndef HAVE_64BIT_OFFSETS
|
||||||
|
#define HAVE_64BIT_OFFSETS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#define RFILE_HINT_UNBUFFERED (1 << 8)
|
#define RFILE_HINT_UNBUFFERED (1 << 8)
|
||||||
|
|
||||||
int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, int64_t offset, int whence)
|
int64_t retro_vfs_file_seek_internal(
|
||||||
|
libretro_vfs_implementation_file *stream,
|
||||||
|
int64_t offset, int whence)
|
||||||
{
|
{
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return -1;
|
return -1;
|
||||||
@ -202,19 +198,9 @@ int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, i
|
|||||||
if (stream->scheme == VFS_SCHEME_CDROM)
|
if (stream->scheme == VFS_SCHEME_CDROM)
|
||||||
return retro_vfs_file_seek_cdrom(stream, offset, whence);
|
return retro_vfs_file_seek_cdrom(stream, offset, whence);
|
||||||
#endif
|
#endif
|
||||||
/* VC2005 and up have a special 64-bit fseek */
|
|
||||||
#ifdef ATLEAST_VC2005
|
#ifdef ATLEAST_VC2005
|
||||||
|
/* VC2005 and up have a special 64-bit fseek */
|
||||||
return _fseeki64(stream->fp, offset, whence);
|
return _fseeki64(stream->fp, offset, whence);
|
||||||
#elif defined(__CELLOS_LV2__) || defined(_MSC_VER) && _MSC_VER <= 1310
|
|
||||||
return fseek(stream->fp, (long)offset, whence);
|
|
||||||
#elif defined(PS2)
|
|
||||||
{
|
|
||||||
int64_t ret = fileXioLseek(fileno(stream->fp), (off_t)offset, whence);
|
|
||||||
/* fileXioLseek could return positive numbers */
|
|
||||||
if (ret > 0)
|
|
||||||
return 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#elif defined(ORBIS)
|
#elif defined(ORBIS)
|
||||||
{
|
{
|
||||||
int ret = orbisLseek(stream->fd, offset, whence);
|
int ret = orbisLseek(stream->fd, offset, whence);
|
||||||
@ -222,8 +208,10 @@ int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, i
|
|||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#elif defined(HAVE_64BIT_OFFSETS)
|
||||||
return fseeko(stream->fp, (off_t)offset, whence);
|
return fseeko(stream->fp, (off_t)offset, whence);
|
||||||
|
#else
|
||||||
|
return fseek(stream->fp, (long)offset, whence);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
||||||
@ -282,29 +270,61 @@ int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, i
|
|||||||
libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
||||||
const char *path, unsigned mode, unsigned hints)
|
const char *path, unsigned mode, unsigned hints)
|
||||||
{
|
{
|
||||||
int flags = 0;
|
#if defined(VFS_FRONTEND) || defined(HAVE_CDROM)
|
||||||
const char *mode_str = NULL;
|
|
||||||
int path_len = (int)strlen(path);
|
int path_len = (int)strlen(path);
|
||||||
libretro_vfs_implementation_file *stream = (libretro_vfs_implementation_file*)
|
#endif
|
||||||
calloc(1, sizeof(*stream));
|
|
||||||
|
|
||||||
#ifdef VFS_FRONTEND
|
#ifdef VFS_FRONTEND
|
||||||
const char *dumb_prefix = "vfsonly://";
|
const char *dumb_prefix = "vfsonly://";
|
||||||
size_t dumb_prefix_siz = strlen(dumb_prefix);
|
size_t dumb_prefix_siz = STRLEN_CONST("vfsonly://");
|
||||||
int dumb_prefix_len = (int)dumb_prefix_siz;
|
int dumb_prefix_len = (int)dumb_prefix_siz;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CDROM
|
||||||
|
const char *cdrom_prefix = "cdrom://";
|
||||||
|
size_t cdrom_prefix_siz = STRLEN_CONST("cdrom://");
|
||||||
|
int cdrom_prefix_len = (int)cdrom_prefix_siz;
|
||||||
|
#endif
|
||||||
|
int flags = 0;
|
||||||
|
const char *mode_str = NULL;
|
||||||
|
libretro_vfs_implementation_file *stream =
|
||||||
|
(libretro_vfs_implementation_file*)
|
||||||
|
malloc(sizeof(*stream));
|
||||||
|
|
||||||
|
if (!stream)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
stream->fd = 0;
|
||||||
|
stream->hints = hints;
|
||||||
|
stream->size = 0;
|
||||||
|
stream->buf = NULL;
|
||||||
|
stream->fp = NULL;
|
||||||
|
#ifdef _WIN32
|
||||||
|
stream->fh = 0;
|
||||||
|
#endif
|
||||||
|
stream->orig_path = NULL;
|
||||||
|
stream->mappos = 0;
|
||||||
|
stream->mapsize = 0;
|
||||||
|
stream->mapped = NULL;
|
||||||
|
stream->scheme = VFS_SCHEME_NONE;
|
||||||
|
|
||||||
|
#ifdef VFS_FRONTEND
|
||||||
if (path_len >= dumb_prefix_len)
|
if (path_len >= dumb_prefix_len)
|
||||||
{
|
|
||||||
if (!memcmp(path, dumb_prefix, dumb_prefix_len))
|
if (!memcmp(path, dumb_prefix, dumb_prefix_len))
|
||||||
path += dumb_prefix_siz;
|
path += dumb_prefix_siz;
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_CDROM
|
#ifdef HAVE_CDROM
|
||||||
{
|
stream->cdrom.cue_buf = NULL;
|
||||||
const char *cdrom_prefix = "cdrom://";
|
stream->cdrom.cue_len = 0;
|
||||||
size_t cdrom_prefix_siz = strlen(cdrom_prefix);
|
stream->cdrom.byte_pos = 0;
|
||||||
int cdrom_prefix_len = (int)cdrom_prefix_siz;
|
stream->cdrom.drive = 0;
|
||||||
|
stream->cdrom.cur_min = 0;
|
||||||
|
stream->cdrom.cur_sec = 0;
|
||||||
|
stream->cdrom.cur_frame = 0;
|
||||||
|
stream->cdrom.cur_track = 0;
|
||||||
|
stream->cdrom.cur_lba = 0;
|
||||||
|
stream->cdrom.last_frame_lba = 0;
|
||||||
|
stream->cdrom.last_frame[0] = '\0';
|
||||||
|
stream->cdrom.last_frame_valid = false;
|
||||||
|
|
||||||
if (path_len > cdrom_prefix_len)
|
if (path_len > cdrom_prefix_len)
|
||||||
{
|
{
|
||||||
@ -314,15 +334,8 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
|||||||
stream->scheme = VFS_SCHEME_CDROM;
|
stream->scheme = VFS_SCHEME_CDROM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!stream)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
(void)flags;
|
|
||||||
|
|
||||||
stream->hints = hints;
|
|
||||||
stream->orig_path = strdup(path);
|
stream->orig_path = strdup(path);
|
||||||
|
|
||||||
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
||||||
@ -348,9 +361,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
|||||||
|
|
||||||
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||||
#if !defined(ORBIS)
|
#if !defined(ORBIS)
|
||||||
#if defined(PS2)
|
#if !defined(_WIN32)
|
||||||
flags |= FIO_S_IRUSR | FIO_S_IWUSR;
|
|
||||||
#elif !defined(_WIN32)
|
|
||||||
flags |= S_IRUSR | S_IWUSR;
|
flags |= S_IRUSR | S_IWUSR;
|
||||||
#else
|
#else
|
||||||
flags |= O_BINARY;
|
flags |= O_BINARY;
|
||||||
@ -362,9 +373,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
|||||||
mode_str = "w+b";
|
mode_str = "w+b";
|
||||||
flags = O_RDWR | O_CREAT | O_TRUNC;
|
flags = O_RDWR | O_CREAT | O_TRUNC;
|
||||||
#if !defined(ORBIS)
|
#if !defined(ORBIS)
|
||||||
#if defined(PS2)
|
#if !defined(_WIN32)
|
||||||
flags |= FIO_S_IRUSR | FIO_S_IWUSR;
|
|
||||||
#elif !defined(_WIN32)
|
|
||||||
flags |= S_IRUSR | S_IWUSR;
|
flags |= S_IRUSR | S_IWUSR;
|
||||||
#else
|
#else
|
||||||
flags |= O_BINARY;
|
flags |= O_BINARY;
|
||||||
@ -378,9 +387,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
|||||||
|
|
||||||
flags = O_RDWR;
|
flags = O_RDWR;
|
||||||
#if !defined(ORBIS)
|
#if !defined(ORBIS)
|
||||||
#if defined(PS2)
|
#if !defined(_WIN32)
|
||||||
flags |= FIO_S_IRUSR | FIO_S_IWUSR;
|
|
||||||
#elif !defined(_WIN32)
|
|
||||||
flags |= S_IRUSR | S_IWUSR;
|
flags |= S_IRUSR | S_IWUSR;
|
||||||
#else
|
#else
|
||||||
flags |= O_BINARY;
|
flags |= O_BINARY;
|
||||||
@ -430,13 +437,16 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
|||||||
*
|
*
|
||||||
* https://www.freebsd.org/cgi/man.cgi?query=setvbuf&apropos=0&sektion=0&manpath=FreeBSD+11.1-RELEASE&arch=default&format=html
|
* https://www.freebsd.org/cgi/man.cgi?query=setvbuf&apropos=0&sektion=0&manpath=FreeBSD+11.1-RELEASE&arch=default&format=html
|
||||||
*
|
*
|
||||||
* If the size argument is not zero but buf is NULL, a buffer of the given size will be allocated immediately, and
|
* If the size argument is not zero but buf is NULL,
|
||||||
|
* a buffer of the given size will be allocated immediately, and
|
||||||
* released on close. This is an extension to ANSI C.
|
* released on close. This is an extension to ANSI C.
|
||||||
*
|
*
|
||||||
* Since C89 does not support specifying a null buffer with a non-zero size, we create and track our own buffer for it.
|
* Since C89 does not support specifying a NULL buffer
|
||||||
|
* with a non-zero size, we create and track our own buffer for it.
|
||||||
*/
|
*/
|
||||||
/* TODO: this is only useful for a few platforms, find which and add ifdef */
|
/* TODO: this is only useful for a few platforms,
|
||||||
#if !defined(PS2) && !defined(PSP)
|
* find which and add ifdef */
|
||||||
|
#if !defined(PSP)
|
||||||
if (stream->scheme != VFS_SCHEME_CDROM)
|
if (stream->scheme != VFS_SCHEME_CDROM)
|
||||||
{
|
{
|
||||||
stream->buf = (char*)calloc(1, 0x4000);
|
stream->buf = (char*)calloc(1, 0x4000);
|
||||||
@ -535,10 +545,8 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream)
|
|||||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||||
{
|
{
|
||||||
if (stream->fp)
|
if (stream->fp)
|
||||||
{
|
|
||||||
fclose(stream->fp);
|
fclose(stream->fp);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
||||||
@ -628,9 +636,11 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* VC2005 and up have a special 64-bit ftell */
|
|
||||||
#ifdef ATLEAST_VC2005
|
#ifdef ATLEAST_VC2005
|
||||||
|
/* VC2005 and up have a special 64-bit ftell */
|
||||||
return _ftelli64(stream->fp);
|
return _ftelli64(stream->fp);
|
||||||
|
#elif defined(HAVE_64BIT_OFFSETS)
|
||||||
|
return ftello(stream->fp);
|
||||||
#else
|
#else
|
||||||
return ftell(stream->fp);
|
return ftell(stream->fp);
|
||||||
#endif
|
#endif
|
||||||
@ -639,7 +649,8 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream)
|
|||||||
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
||||||
/* Need to check stream->mapped because this function
|
/* Need to check stream->mapped because this function
|
||||||
* is called in filestream_open() */
|
* is called in filestream_open() */
|
||||||
if (stream->mapped && stream->hints & RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS)
|
if (stream->mapped && stream->hints &
|
||||||
|
RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS)
|
||||||
return stream->mappos;
|
return stream->mappos;
|
||||||
#endif
|
#endif
|
||||||
if (lseek(stream->fd, 0, SEEK_CUR) < 0)
|
if (lseek(stream->fd, 0, SEEK_CUR) < 0)
|
||||||
@ -863,12 +874,12 @@ const char *retro_vfs_file_get_path_impl(
|
|||||||
|
|
||||||
int retro_vfs_stat_impl(const char *path, int32_t *size)
|
int retro_vfs_stat_impl(const char *path, int32_t *size)
|
||||||
{
|
{
|
||||||
|
bool is_dir = false;
|
||||||
|
bool is_character_special = false;
|
||||||
#if defined(VITA) || defined(PSP)
|
#if defined(VITA) || defined(PSP)
|
||||||
/* Vita / PSP */
|
/* Vita / PSP */
|
||||||
SceIoStat buf;
|
SceIoStat buf;
|
||||||
int stat_ret;
|
int dir_ret;
|
||||||
bool is_dir = false;
|
|
||||||
bool is_character_special = false;
|
|
||||||
char *tmp = NULL;
|
char *tmp = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
@ -880,22 +891,18 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
|
|||||||
if (tmp[len-1] == '/')
|
if (tmp[len-1] == '/')
|
||||||
tmp[len-1] = '\0';
|
tmp[len-1] = '\0';
|
||||||
|
|
||||||
stat_ret = sceIoGetstat(tmp, &buf);
|
dir_ret = sceIoGetstat(tmp, &buf);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
if (stat_ret < 0)
|
if (dir_ret < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (size)
|
if (size)
|
||||||
*size = (int32_t)buf.st_size;
|
*size = (int32_t)buf.st_size;
|
||||||
|
|
||||||
is_dir = FIO_S_ISDIR(buf.st_mode);
|
is_dir = FIO_S_ISDIR(buf.st_mode);
|
||||||
|
|
||||||
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
|
|
||||||
|
|
||||||
#elif defined(ORBIS)
|
#elif defined(ORBIS)
|
||||||
/* Orbis */
|
/* Orbis */
|
||||||
bool is_dir, is_character_special;
|
int dir_ret = 0;
|
||||||
int dir_ret;
|
|
||||||
|
|
||||||
if (!path || !*path)
|
if (!path || !*path)
|
||||||
return 0;
|
return 0;
|
||||||
@ -908,47 +915,8 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
|
|||||||
orbisDclose(dir_ret);
|
orbisDclose(dir_ret);
|
||||||
|
|
||||||
is_character_special = S_ISCHR(buf.st_mode);
|
is_character_special = S_ISCHR(buf.st_mode);
|
||||||
|
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||||
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
|
|
||||||
|
|
||||||
#elif defined(PS2)
|
|
||||||
/* PS2 */
|
|
||||||
iox_stat_t buf;
|
|
||||||
bool is_dir;
|
|
||||||
bool is_character_special = false;
|
|
||||||
char *tmp = NULL;
|
|
||||||
size_t len = 0;
|
|
||||||
|
|
||||||
if (!path || !*path)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
tmp = strdup(path);
|
|
||||||
len = strlen(tmp);
|
|
||||||
if (tmp[len-1] == '/')
|
|
||||||
tmp[len-1] = '\0';
|
|
||||||
|
|
||||||
fileXioGetStat(tmp, &buf);
|
|
||||||
free(tmp);
|
|
||||||
|
|
||||||
if (size)
|
|
||||||
*size = (int32_t)buf.size;
|
|
||||||
|
|
||||||
if (!buf.mode)
|
|
||||||
{
|
|
||||||
/* if fileXioGetStat fails */
|
|
||||||
int dir_ret = fileXioDopen(path);
|
|
||||||
is_dir = dir_ret > 0;
|
|
||||||
fileXioDclose(dir_ret);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
is_dir = FIO_S_ISDIR(buf.mode);
|
|
||||||
|
|
||||||
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
|
|
||||||
|
|
||||||
#elif defined(__CELLOS_LV2__)
|
|
||||||
/* CellOS Lv2 */
|
/* CellOS Lv2 */
|
||||||
bool is_dir;
|
|
||||||
bool is_character_special = false;
|
|
||||||
CellFsStat buf;
|
CellFsStat buf;
|
||||||
|
|
||||||
if (!path || !*path)
|
if (!path || !*path)
|
||||||
@ -961,14 +929,10 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
|
|||||||
|
|
||||||
is_dir = ((buf.st_mode & S_IFMT) == S_IFDIR);
|
is_dir = ((buf.st_mode & S_IFMT) == S_IFDIR);
|
||||||
|
|
||||||
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
|
|
||||||
|
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
/* Windows */
|
/* Windows */
|
||||||
bool is_dir;
|
|
||||||
DWORD file_info;
|
DWORD file_info;
|
||||||
struct _stat buf;
|
struct _stat buf;
|
||||||
bool is_character_special = false;
|
|
||||||
#if defined(LEGACY_WIN32)
|
#if defined(LEGACY_WIN32)
|
||||||
char *path_local = NULL;
|
char *path_local = NULL;
|
||||||
#else
|
#else
|
||||||
@ -1004,12 +968,8 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
|
|||||||
*size = (int32_t)buf.st_size;
|
*size = (int32_t)buf.st_size;
|
||||||
|
|
||||||
is_dir = (file_info & FILE_ATTRIBUTE_DIRECTORY);
|
is_dir = (file_info & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
|
||||||
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* Every other platform */
|
/* Every other platform */
|
||||||
bool is_dir, is_character_special;
|
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
|
|
||||||
if (!path || !*path)
|
if (!path || !*path)
|
||||||
@ -1022,9 +982,8 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
|
|||||||
|
|
||||||
is_dir = S_ISDIR(buf.st_mode);
|
is_dir = S_ISDIR(buf.st_mode);
|
||||||
is_character_special = S_ISCHR(buf.st_mode);
|
is_character_special = S_ISCHR(buf.st_mode);
|
||||||
|
|
||||||
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
|
|
||||||
#endif
|
#endif
|
||||||
|
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(VITA)
|
#if defined(VITA)
|
||||||
@ -1041,21 +1000,19 @@ int retro_vfs_mkdir_impl(const char *dir)
|
|||||||
#ifdef LEGACY_WIN32
|
#ifdef LEGACY_WIN32
|
||||||
int ret = _mkdir(dir);
|
int ret = _mkdir(dir);
|
||||||
#else
|
#else
|
||||||
wchar_t *dirW = utf8_to_utf16_string_alloc(dir);
|
wchar_t *dir_w = utf8_to_utf16_string_alloc(dir);
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (dirW)
|
if (dir_w)
|
||||||
{
|
{
|
||||||
ret = _wmkdir(dirW);
|
ret = _wmkdir(dir_w);
|
||||||
free(dirW);
|
free(dir_w);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#elif defined(IOS)
|
#elif defined(IOS)
|
||||||
int ret = mkdir(dir, 0755);
|
int ret = mkdir(dir, 0755);
|
||||||
#elif defined(VITA) || defined(PSP)
|
#elif defined(VITA) || defined(PSP)
|
||||||
int ret = sceIoMkdir(dir, 0777);
|
int ret = sceIoMkdir(dir, 0777);
|
||||||
#elif defined(PS2)
|
|
||||||
int ret = fileXioMkdir(dir, 0777);
|
|
||||||
#elif defined(ORBIS)
|
#elif defined(ORBIS)
|
||||||
int ret = orbisMkdir(dir, 0755);
|
int ret = orbisMkdir(dir, 0755);
|
||||||
#elif defined(__QNX__)
|
#elif defined(__QNX__)
|
||||||
@ -1088,10 +1045,7 @@ struct libretro_vfs_implementation_dir
|
|||||||
#elif defined(VITA) || defined(PSP)
|
#elif defined(VITA) || defined(PSP)
|
||||||
SceUID directory;
|
SceUID directory;
|
||||||
SceIoDirent entry;
|
SceIoDirent entry;
|
||||||
#elif defined(PS2)
|
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||||
int directory;
|
|
||||||
iox_dirent_t entry;
|
|
||||||
#elif defined(__CELLOS_LV2__)
|
|
||||||
CellFsErrno error;
|
CellFsErrno error;
|
||||||
int directory;
|
int directory;
|
||||||
CellFsDirent entry;
|
CellFsDirent entry;
|
||||||
@ -1108,20 +1062,22 @@ static bool dirent_check_error(libretro_vfs_implementation_dir *rdir)
|
|||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return (rdir->directory == INVALID_HANDLE_VALUE);
|
return (rdir->directory == INVALID_HANDLE_VALUE);
|
||||||
#elif defined(VITA) || defined(PSP) || defined(PS2) || defined(ORBIS)
|
#elif defined(VITA) || defined(PSP) || defined(ORBIS)
|
||||||
return (rdir->directory < 0);
|
return (rdir->directory < 0);
|
||||||
#elif defined(__CELLOS_LV2__)
|
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||||
return (rdir->error != CELL_FS_SUCCEEDED);
|
return (rdir->error != CELL_FS_SUCCEEDED);
|
||||||
#else
|
#else
|
||||||
return !(rdir->directory);
|
return !(rdir->directory);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool include_hidden)
|
libretro_vfs_implementation_dir *retro_vfs_opendir_impl(
|
||||||
|
const char *name, bool include_hidden)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
unsigned path_len;
|
unsigned path_len;
|
||||||
char path_buf[1024];
|
char path_buf[1024];
|
||||||
|
size_t copied = 0;
|
||||||
#if defined(LEGACY_WIN32)
|
#if defined(LEGACY_WIN32)
|
||||||
char *path_local = NULL;
|
char *path_local = NULL;
|
||||||
#else
|
#else
|
||||||
@ -1145,11 +1101,14 @@ libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool i
|
|||||||
path_buf[0] = '\0';
|
path_buf[0] = '\0';
|
||||||
path_len = strlen(name);
|
path_len = strlen(name);
|
||||||
|
|
||||||
|
copied = strlcpy(path_buf, name, sizeof(path_buf));
|
||||||
|
|
||||||
/* Non-NT platforms don't like extra slashes in the path */
|
/* Non-NT platforms don't like extra slashes in the path */
|
||||||
if (name[path_len - 1] == '\\')
|
if (name[path_len - 1] != '\\')
|
||||||
snprintf(path_buf, sizeof(path_buf), "%s*", name);
|
path_buf[copied++] = '\\';
|
||||||
else
|
|
||||||
snprintf(path_buf, sizeof(path_buf), "%s\\*", name);
|
path_buf[copied] = '*';
|
||||||
|
path_buf[copied+1] = '\0';
|
||||||
|
|
||||||
#if defined(LEGACY_WIN32)
|
#if defined(LEGACY_WIN32)
|
||||||
path_local = utf8_to_local_string_alloc(path_buf);
|
path_local = utf8_to_local_string_alloc(path_buf);
|
||||||
@ -1167,12 +1126,10 @@ libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool i
|
|||||||
|
|
||||||
#elif defined(VITA) || defined(PSP)
|
#elif defined(VITA) || defined(PSP)
|
||||||
rdir->directory = sceIoDopen(name);
|
rdir->directory = sceIoDopen(name);
|
||||||
#elif defined(PS2)
|
|
||||||
rdir->directory = ps2fileXioDopen(name);
|
|
||||||
#elif defined(_3DS)
|
#elif defined(_3DS)
|
||||||
rdir->directory = !string_is_empty(name) ? opendir(name) : NULL;
|
rdir->directory = !string_is_empty(name) ? opendir(name) : NULL;
|
||||||
rdir->entry = NULL;
|
rdir->entry = NULL;
|
||||||
#elif defined(__CELLOS_LV2__)
|
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||||
rdir->error = cellFsOpendir(name, &rdir->directory);
|
rdir->error = cellFsOpendir(name, &rdir->directory);
|
||||||
#elif defined(ORBIS)
|
#elif defined(ORBIS)
|
||||||
rdir->directory = orbisDopen(name);
|
rdir->directory = orbisDopen(name);
|
||||||
@ -1209,12 +1166,7 @@ bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir *rdir)
|
|||||||
return (rdir->directory != INVALID_HANDLE_VALUE);
|
return (rdir->directory != INVALID_HANDLE_VALUE);
|
||||||
#elif defined(VITA) || defined(PSP)
|
#elif defined(VITA) || defined(PSP)
|
||||||
return (sceIoDread(rdir->directory, &rdir->entry) > 0);
|
return (sceIoDread(rdir->directory, &rdir->entry) > 0);
|
||||||
#elif defined(PS2)
|
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||||
iox_dirent_t record;
|
|
||||||
int ret = ps2fileXioDread(rdir->directory, &record);
|
|
||||||
rdir->entry = record;
|
|
||||||
return ( ret > 0);
|
|
||||||
#elif defined(__CELLOS_LV2__)
|
|
||||||
uint64_t nread;
|
uint64_t nread;
|
||||||
rdir->error = cellFsReaddir(rdir->directory, &rdir->entry, &nread);
|
rdir->error = cellFsReaddir(rdir->directory, &rdir->entry, &nread);
|
||||||
return (nread != 0);
|
return (nread != 0);
|
||||||
@ -1229,27 +1181,20 @@ const char *retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir *rdir
|
|||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#if defined(LEGACY_WIN32)
|
#if defined(LEGACY_WIN32)
|
||||||
char *name_local = local_to_utf8_string_alloc(rdir->entry.cFileName);
|
char *name = local_to_utf8_string_alloc(rdir->entry.cFileName);
|
||||||
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
|
|
||||||
strlcpy(rdir->entry.cFileName, name_local, sizeof(rdir->entry.cFileName));
|
|
||||||
|
|
||||||
if (name_local)
|
|
||||||
free(name_local);
|
|
||||||
#else
|
#else
|
||||||
char *name = utf16_to_utf8_string_alloc(rdir->entry.cFileName);
|
char *name = utf16_to_utf8_string_alloc(rdir->entry.cFileName);
|
||||||
|
#endif
|
||||||
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
|
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
|
||||||
strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName));
|
strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName));
|
||||||
|
|
||||||
if (name)
|
if (name)
|
||||||
free(name);
|
free(name);
|
||||||
#endif
|
|
||||||
return (char*)rdir->entry.cFileName;
|
return (char*)rdir->entry.cFileName;
|
||||||
#elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) || defined(ORBIS)
|
#elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) && !defined(__PSL1GHT__) || defined(ORBIS)
|
||||||
return rdir->entry.d_name;
|
return rdir->entry.d_name;
|
||||||
#elif defined(PS2)
|
|
||||||
return rdir->entry.name;
|
|
||||||
#else
|
#else
|
||||||
|
if (!rdir || !rdir->entry)
|
||||||
|
return NULL;
|
||||||
return rdir->entry->d_name;
|
return rdir->entry->d_name;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -1266,10 +1211,7 @@ bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *rdir)
|
|||||||
#elif defined(VITA)
|
#elif defined(VITA)
|
||||||
return SCE_S_ISDIR(entry->d_stat.st_mode);
|
return SCE_S_ISDIR(entry->d_stat.st_mode);
|
||||||
#endif
|
#endif
|
||||||
#elif defined(PS2)
|
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||||
const iox_dirent_t *entry = (const iox_dirent_t*)&rdir->entry;
|
|
||||||
return FIO_S_ISDIR(entry->stat.mode);
|
|
||||||
#elif defined(__CELLOS_LV2__)
|
|
||||||
CellFsDirent *entry = (CellFsDirent*)&rdir->entry;
|
CellFsDirent *entry = (CellFsDirent*)&rdir->entry;
|
||||||
return (entry->d_type == CELL_FS_TYPE_DIRECTORY);
|
return (entry->d_type == CELL_FS_TYPE_DIRECTORY);
|
||||||
#elif defined(ORBIS)
|
#elif defined(ORBIS)
|
||||||
@ -1308,9 +1250,7 @@ int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *rdir)
|
|||||||
FindClose(rdir->directory);
|
FindClose(rdir->directory);
|
||||||
#elif defined(VITA) || defined(PSP)
|
#elif defined(VITA) || defined(PSP)
|
||||||
sceIoDclose(rdir->directory);
|
sceIoDclose(rdir->directory);
|
||||||
#elif defined(PS2)
|
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||||
ps2fileXioDclose(rdir->directory);
|
|
||||||
#elif defined(__CELLOS_LV2__)
|
|
||||||
rdir->error = cellFsClosedir(rdir->directory);
|
rdir->error = cellFsClosedir(rdir->directory);
|
||||||
#elif defined(ORBIS)
|
#elif defined(ORBIS)
|
||||||
orbisDclose(rdir->directory);
|
orbisDclose(rdir->directory);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2019 The RetroArch team
|
/* Copyright (C) 2010-2020 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (vfs_implementation_cdrom.c).
|
* The following license statement only applies to this file (vfs_implementation_cdrom.c).
|
||||||
@ -30,6 +30,7 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* TODO/FIXME - static global variable */
|
||||||
static cdrom_toc_t vfs_cdrom_toc = {0};
|
static cdrom_toc_t vfs_cdrom_toc = {0};
|
||||||
|
|
||||||
const cdrom_toc_t* retro_vfs_file_get_cdrom_toc(void)
|
const cdrom_toc_t* retro_vfs_file_get_cdrom_toc(void)
|
||||||
@ -37,7 +38,9 @@ const cdrom_toc_t* retro_vfs_file_get_cdrom_toc(void)
|
|||||||
return &vfs_cdrom_toc;
|
return &vfs_cdrom_toc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t retro_vfs_file_seek_cdrom(libretro_vfs_implementation_file *stream, int64_t offset, int whence)
|
int64_t retro_vfs_file_seek_cdrom(
|
||||||
|
libretro_vfs_implementation_file *stream,
|
||||||
|
int64_t offset, int whence)
|
||||||
{
|
{
|
||||||
const char *ext = path_get_extension(stream->orig_path);
|
const char *ext = path_get_extension(stream->orig_path);
|
||||||
|
|
||||||
@ -57,7 +60,10 @@ int64_t retro_vfs_file_seek_cdrom(libretro_vfs_implementation_file *stream, int6
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CDROM_DEBUG
|
#ifdef CDROM_DEBUG
|
||||||
printf("[CDROM] Seek: Path %s Offset %" PRIu64 " is now at %" PRIu64 "\n", stream->orig_path, offset, stream->cdrom.byte_pos);
|
printf("[CDROM] Seek: Path %s Offset %" PRIu64 " is now at %" PRIu64 "\n",
|
||||||
|
stream->orig_path,
|
||||||
|
offset,
|
||||||
|
stream->cdrom.byte_pos);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -67,44 +73,48 @@ int64_t retro_vfs_file_seek_cdrom(libretro_vfs_implementation_file *stream, int6
|
|||||||
unsigned char min = 0;
|
unsigned char min = 0;
|
||||||
unsigned char sec = 0;
|
unsigned char sec = 0;
|
||||||
unsigned char frame = 0;
|
unsigned char frame = 0;
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
const char *seek_type = "SEEK_SET";
|
const char *seek_type = "SEEK_SET";
|
||||||
|
#endif
|
||||||
(void)seek_type;
|
|
||||||
|
|
||||||
switch (whence)
|
switch (whence)
|
||||||
{
|
{
|
||||||
case SEEK_CUR:
|
case SEEK_CUR:
|
||||||
{
|
{
|
||||||
unsigned new_lba;
|
unsigned new_lba;
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
seek_type = "SEEK_CUR";
|
||||||
|
#endif
|
||||||
stream->cdrom.byte_pos += offset;
|
stream->cdrom.byte_pos += offset;
|
||||||
new_lba = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352);
|
new_lba = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352);
|
||||||
seek_type = "SEEK_CUR";
|
|
||||||
|
|
||||||
cdrom_lba_to_msf(new_lba, &min, &sec, &frame);
|
cdrom_lba_to_msf(new_lba, &min, &sec, &frame);
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case SEEK_END:
|
case SEEK_END:
|
||||||
{
|
{
|
||||||
ssize_t pregap_lba_len = (vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].audio ? 0 : (vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba_start));
|
ssize_t pregap_lba_len = (vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].audio
|
||||||
|
? 0
|
||||||
|
: (vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba_start));
|
||||||
ssize_t lba_len = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_size - pregap_lba_len;
|
ssize_t lba_len = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_size - pregap_lba_len;
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
seek_type = "SEEK_END";
|
||||||
|
#endif
|
||||||
|
|
||||||
cdrom_lba_to_msf(lba_len + lba, &min, &sec, &frame);
|
cdrom_lba_to_msf(lba_len + lba, &min, &sec, &frame);
|
||||||
|
|
||||||
stream->cdrom.byte_pos = lba_len * 2352;
|
stream->cdrom.byte_pos = lba_len * 2352;
|
||||||
seek_type = "SEEK_END";
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case SEEK_SET:
|
case SEEK_SET:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
seek_type = "SEEK_SET";
|
seek_type = "SEEK_SET";
|
||||||
|
#endif
|
||||||
stream->cdrom.byte_pos = offset;
|
stream->cdrom.byte_pos = offset;
|
||||||
cdrom_lba_to_msf(vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352), &min, &sec, &frame);
|
cdrom_lba_to_msf(vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352), &min, &sec, &frame);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->cdrom.cur_min = min;
|
stream->cdrom.cur_min = min;
|
||||||
@ -113,7 +123,16 @@ int64_t retro_vfs_file_seek_cdrom(libretro_vfs_implementation_file *stream, int6
|
|||||||
stream->cdrom.cur_lba = cdrom_msf_to_lba(min, sec, frame);
|
stream->cdrom.cur_lba = cdrom_msf_to_lba(min, sec, frame);
|
||||||
|
|
||||||
#ifdef CDROM_DEBUG
|
#ifdef CDROM_DEBUG
|
||||||
printf("[CDROM] Seek %s: Path %s Offset %" PRIu64 " is now at %" PRIu64 " (MSF %02u:%02u:%02u) (LBA %u)...\n", seek_type, stream->orig_path, offset, stream->cdrom.byte_pos, (unsigned)stream->cdrom.cur_min, (unsigned)stream->cdrom.cur_sec, (unsigned)stream->cdrom.cur_frame, stream->cdrom.cur_lba);
|
printf(
|
||||||
|
"[CDROM] Seek %s: Path %s Offset %" PRIu64 " is now at %" PRIu64 " (MSF %02u:%02u:%02u) (LBA %u)...\n",
|
||||||
|
seek_type,
|
||||||
|
stream->orig_path,
|
||||||
|
offset,
|
||||||
|
stream->cdrom.byte_pos,
|
||||||
|
(unsigned)stream->cdrom.cur_min,
|
||||||
|
(unsigned)stream->cdrom.cur_sec,
|
||||||
|
(unsigned)stream->cdrom.cur_frame,
|
||||||
|
stream->cdrom.cur_lba);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -134,14 +153,15 @@ void retro_vfs_file_open_cdrom(
|
|||||||
|
|
||||||
stream->cdrom.cur_track = 1;
|
stream->cdrom.cur_track = 1;
|
||||||
|
|
||||||
if (!string_is_equal_noncase(ext, "cue") && !string_is_equal_noncase(ext, "bin"))
|
if ( !string_is_equal_noncase(ext, "cue")
|
||||||
|
&& !string_is_equal_noncase(ext, "bin"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (path_len >= strlen("drive1-track01.bin"))
|
if (path_len >= STRLEN_CONST("drive1-track01.bin"))
|
||||||
{
|
{
|
||||||
if (!memcmp(path, "drive", strlen("drive")))
|
if (!memcmp(path, "drive", STRLEN_CONST("drive")))
|
||||||
{
|
{
|
||||||
if (!memcmp(path + 6, "-track", strlen("-track")))
|
if (!memcmp(path + 6, "-track", STRLEN_CONST("-track")))
|
||||||
{
|
{
|
||||||
if (sscanf(path + 12, "%02u", (unsigned*)&stream->cdrom.cur_track))
|
if (sscanf(path + 12, "%02u", (unsigned*)&stream->cdrom.cur_track))
|
||||||
{
|
{
|
||||||
@ -154,9 +174,9 @@ void retro_vfs_file_open_cdrom(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path_len >= strlen("drive1.cue"))
|
if (path_len >= STRLEN_CONST("drive1.cue"))
|
||||||
{
|
{
|
||||||
if (!memcmp(path, "drive", strlen("drive")))
|
if (!memcmp(path, "drive", STRLEN_CONST("drive")))
|
||||||
{
|
{
|
||||||
if (path[5] >= '0' && path[5] <= '9')
|
if (path[5] >= '0' && path[5] <= '9')
|
||||||
{
|
{
|
||||||
@ -184,7 +204,12 @@ void retro_vfs_file_open_cdrom(
|
|||||||
stream->cdrom.cue_buf = NULL;
|
stream->cdrom.cue_buf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdrom_write_cue(stream, &stream->cdrom.cue_buf, &stream->cdrom.cue_len, stream->cdrom.drive, &vfs_cdrom_toc.num_tracks, &vfs_cdrom_toc);
|
cdrom_write_cue(stream,
|
||||||
|
&stream->cdrom.cue_buf,
|
||||||
|
&stream->cdrom.cue_len,
|
||||||
|
stream->cdrom.drive,
|
||||||
|
&vfs_cdrom_toc.num_tracks,
|
||||||
|
&vfs_cdrom_toc);
|
||||||
cdrom_get_timeouts(stream, &vfs_cdrom_toc.timeouts);
|
cdrom_get_timeouts(stream, &vfs_cdrom_toc.timeouts);
|
||||||
|
|
||||||
#ifdef CDROM_DEBUG
|
#ifdef CDROM_DEBUG
|
||||||
@ -206,12 +231,13 @@ void retro_vfs_file_open_cdrom(
|
|||||||
size_t path_len = strlen(path);
|
size_t path_len = strlen(path);
|
||||||
const char *ext = path_get_extension(path);
|
const char *ext = path_get_extension(path);
|
||||||
|
|
||||||
if (!string_is_equal_noncase(ext, "cue") && !string_is_equal_noncase(ext, "bin"))
|
if ( !string_is_equal_noncase(ext, "cue")
|
||||||
|
&& !string_is_equal_noncase(ext, "bin"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (path_len >= strlen("d:/drive-track01.bin"))
|
if (path_len >= STRLEN_CONST("d:/drive-track01.bin"))
|
||||||
{
|
{
|
||||||
if (!memcmp(path + 1, ":/drive-track", strlen(":/drive-track")))
|
if (!memcmp(path + 1, ":/drive-track", STRLEN_CONST(":/drive-track")))
|
||||||
{
|
{
|
||||||
if (sscanf(path + 14, "%02u", (unsigned*)&stream->cdrom.cur_track))
|
if (sscanf(path + 14, "%02u", (unsigned*)&stream->cdrom.cur_track))
|
||||||
{
|
{
|
||||||
@ -223,9 +249,9 @@ void retro_vfs_file_open_cdrom(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path_len >= strlen("d:/drive.cue"))
|
if (path_len >= STRLEN_CONST("d:/drive.cue"))
|
||||||
{
|
{
|
||||||
if (!memcmp(path + 1, ":/drive", strlen(":/drive")))
|
if (!memcmp(path + 1, ":/drive", STRLEN_CONST(":/drive")))
|
||||||
{
|
{
|
||||||
if ((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z'))
|
if ((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z'))
|
||||||
{
|
{
|
||||||
@ -240,7 +266,13 @@ void retro_vfs_file_open_cdrom(
|
|||||||
printf("[CDROM] Open: Path %s URI %s\n", cdrom_path, path);
|
printf("[CDROM] Open: Path %s URI %s\n", cdrom_path, path);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
stream->fh = CreateFile(cdrom_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
stream->fh = CreateFile(cdrom_path,
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
NULL,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
if (stream->fh == INVALID_HANDLE_VALUE)
|
if (stream->fh == INVALID_HANDLE_VALUE)
|
||||||
return;
|
return;
|
||||||
@ -253,8 +285,14 @@ void retro_vfs_file_open_cdrom(
|
|||||||
stream->cdrom.cue_buf = NULL;
|
stream->cdrom.cue_buf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdrom_write_cue(stream, &stream->cdrom.cue_buf, &stream->cdrom.cue_len, stream->cdrom.drive, &vfs_cdrom_toc.num_tracks, &vfs_cdrom_toc);
|
cdrom_write_cue(stream,
|
||||||
cdrom_get_timeouts(stream, &vfs_cdrom_toc.timeouts);
|
&stream->cdrom.cue_buf,
|
||||||
|
&stream->cdrom.cue_len,
|
||||||
|
stream->cdrom.drive,
|
||||||
|
&vfs_cdrom_toc.num_tracks,
|
||||||
|
&vfs_cdrom_toc);
|
||||||
|
cdrom_get_timeouts(stream,
|
||||||
|
&vfs_cdrom_toc.timeouts);
|
||||||
|
|
||||||
#ifdef CDROM_DEBUG
|
#ifdef CDROM_DEBUG
|
||||||
if (string_is_empty(stream->cdrom.cue_buf))
|
if (string_is_empty(stream->cdrom.cue_buf))
|
||||||
@ -340,10 +378,14 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
|
|||||||
|
|
||||||
if (string_is_equal_noncase(ext, "cue"))
|
if (string_is_equal_noncase(ext, "cue"))
|
||||||
{
|
{
|
||||||
if (len < stream->cdrom.cue_len - stream->cdrom.byte_pos)
|
if ((int64_t)len >= (int64_t)stream->cdrom.cue_len
|
||||||
{
|
- stream->cdrom.byte_pos)
|
||||||
|
len = stream->cdrom.cue_len - stream->cdrom.byte_pos - 1;
|
||||||
#ifdef CDROM_DEBUG
|
#ifdef CDROM_DEBUG
|
||||||
printf("[CDROM] Read: Reading %" PRIu64 " bytes from cuesheet starting at %" PRIu64 "...\n", len, stream->cdrom.byte_pos);
|
printf(
|
||||||
|
"[CDROM] Read: Reading %" PRIu64 " bytes from cuesheet starting at %" PRIu64 "...\n",
|
||||||
|
len,
|
||||||
|
stream->cdrom.byte_pos);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
memcpy(s, stream->cdrom.cue_buf + stream->cdrom.byte_pos, len);
|
memcpy(s, stream->cdrom.cue_buf + stream->cdrom.byte_pos, len);
|
||||||
@ -351,41 +393,54 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
|
|||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef CDROM_DEBUG
|
|
||||||
printf("[CDROM] Read: Reading %" PRIu64 " bytes from cuesheet starting at %" PRIu64 " failed.\n", len, stream->cdrom.byte_pos);
|
|
||||||
fflush(stdout);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (string_is_equal_noncase(ext, "bin"))
|
else if (string_is_equal_noncase(ext, "bin"))
|
||||||
{
|
{
|
||||||
size_t skip = stream->cdrom.byte_pos % 2352;
|
|
||||||
unsigned char min = 0;
|
unsigned char min = 0;
|
||||||
unsigned char sec = 0;
|
unsigned char sec = 0;
|
||||||
unsigned char frame = 0;
|
unsigned char frame = 0;
|
||||||
unsigned char rmin = 0;
|
unsigned char rmin = 0;
|
||||||
unsigned char rsec = 0;
|
unsigned char rsec = 0;
|
||||||
unsigned char rframe = 0;
|
unsigned char rframe = 0;
|
||||||
|
size_t skip = stream->cdrom.byte_pos % 2352;
|
||||||
|
|
||||||
if (stream->cdrom.byte_pos >= vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes)
|
if (stream->cdrom.byte_pos >=
|
||||||
|
vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (stream->cdrom.byte_pos + len > vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes)
|
if (stream->cdrom.byte_pos + len >
|
||||||
len -= (stream->cdrom.byte_pos + len) - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes;
|
vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes)
|
||||||
|
len -= (stream->cdrom.byte_pos + len)
|
||||||
|
- vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes;
|
||||||
|
|
||||||
cdrom_lba_to_msf(stream->cdrom.cur_lba, &min, &sec, &frame);
|
cdrom_lba_to_msf(stream->cdrom.cur_lba, &min, &sec, &frame);
|
||||||
cdrom_lba_to_msf(stream->cdrom.cur_lba - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba, &rmin, &rsec, &rframe);
|
cdrom_lba_to_msf(stream->cdrom.cur_lba
|
||||||
|
- vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba,
|
||||||
|
&rmin, &rsec, &rframe);
|
||||||
|
|
||||||
#ifdef CDROM_DEBUG
|
#ifdef CDROM_DEBUG
|
||||||
printf("[CDROM] Read: Reading %" PRIu64 " bytes from %s starting at byte offset %" PRIu64 " (rMSF %02u:%02u:%02u aMSF %02u:%02u:%02u) (LBA %u) skip %" PRIu64 "...\n", len, stream->orig_path, stream->cdrom.byte_pos, (unsigned)rmin, (unsigned)rsec, (unsigned)rframe, (unsigned)min, (unsigned)sec, (unsigned)frame, stream->cdrom.cur_lba, skip);
|
printf(
|
||||||
|
"[CDROM] Read: Reading %" PRIu64 " bytes from %s starting at byte offset %" PRIu64 " (rMSF %02u:%02u:%02u aMSF %02u:%02u:%02u) (LBA %u) skip %" PRIu64 "...\n",
|
||||||
|
len,
|
||||||
|
stream->orig_path,
|
||||||
|
stream->cdrom.byte_pos,
|
||||||
|
(unsigned)rmin,
|
||||||
|
(unsigned)rsec,
|
||||||
|
(unsigned)rframe,
|
||||||
|
(unsigned)min,
|
||||||
|
(unsigned)sec,
|
||||||
|
(unsigned)frame,
|
||||||
|
stream->cdrom.cur_lba,
|
||||||
|
skip);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rv = cdrom_read(stream, &vfs_cdrom_toc.timeouts, min, sec, frame, s, (size_t)len, skip);
|
#if 1
|
||||||
/*rv = cdrom_read_lba(stream, stream->cdrom.cur_lba, s, (size_t)len, skip);*/
|
rv = cdrom_read(stream, &vfs_cdrom_toc.timeouts, min, sec,
|
||||||
|
frame, s, (size_t)len, skip);
|
||||||
|
#else
|
||||||
|
rv = cdrom_read_lba(stream, stream->cdrom.cur_lba, s,
|
||||||
|
(size_t)len, skip);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (rv)
|
if (rv)
|
||||||
{
|
{
|
||||||
@ -397,12 +452,28 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
|
|||||||
}
|
}
|
||||||
|
|
||||||
stream->cdrom.byte_pos += len;
|
stream->cdrom.byte_pos += len;
|
||||||
stream->cdrom.cur_lba = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352);
|
stream->cdrom.cur_lba =
|
||||||
|
vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba
|
||||||
|
+ (stream->cdrom.byte_pos / 2352);
|
||||||
|
|
||||||
cdrom_lba_to_msf(stream->cdrom.cur_lba, &stream->cdrom.cur_min, &stream->cdrom.cur_sec, &stream->cdrom.cur_frame);
|
cdrom_lba_to_msf(stream->cdrom.cur_lba,
|
||||||
|
&stream->cdrom.cur_min,
|
||||||
|
&stream->cdrom.cur_sec,
|
||||||
|
&stream->cdrom.cur_frame);
|
||||||
|
|
||||||
#ifdef CDROM_DEBUG
|
#ifdef CDROM_DEBUG
|
||||||
printf("[CDROM] read %" PRIu64 " bytes, position is now: %" PRIu64 " (MSF %02u:%02u:%02u) (LBA %u)\n", len, stream->cdrom.byte_pos, (unsigned)stream->cdrom.cur_min, (unsigned)stream->cdrom.cur_sec, (unsigned)stream->cdrom.cur_frame, cdrom_msf_to_lba(stream->cdrom.cur_min, stream->cdrom.cur_sec, stream->cdrom.cur_frame));
|
printf(
|
||||||
|
"[CDROM] read %" PRIu64 " bytes, position is now: %" PRIu64 " (MSF %02u:%02u:%02u) (LBA %u)\n",
|
||||||
|
len,
|
||||||
|
stream->cdrom.byte_pos,
|
||||||
|
(unsigned)stream->cdrom.cur_min,
|
||||||
|
(unsigned)stream->cdrom.cur_sec,
|
||||||
|
(unsigned)stream->cdrom.cur_frame,
|
||||||
|
cdrom_msf_to_lba(
|
||||||
|
stream->cdrom.cur_min,
|
||||||
|
stream->cdrom.cur_sec,
|
||||||
|
stream->cdrom.cur_frame)
|
||||||
|
);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -417,7 +488,8 @@ int retro_vfs_file_error_cdrom(libretro_vfs_implementation_file *stream)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const vfs_cdrom_t* retro_vfs_file_get_cdrom_position(const libretro_vfs_implementation_file *stream)
|
const vfs_cdrom_t* retro_vfs_file_get_cdrom_position(
|
||||||
|
const libretro_vfs_implementation_file *stream)
|
||||||
{
|
{
|
||||||
return &stream->cdrom;
|
return &stream->cdrom;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user