mirror of
https://github.com/libretro/beetle-psx-libretro.git
synced 2024-11-23 08:49:47 +00:00
Revert "Updated to current libretro-common (#901)"
This reverts commit eaa6bc0852
.
This commit is contained in:
parent
eaa6bc0852
commit
b88c724a28
@ -1346,9 +1346,9 @@ struct string_list* cdrom_get_available_drives(void)
|
|||||||
if (string_starts_with_size(dir_list->elems[i].data, "/dev/sg",
|
if (string_starts_with_size(dir_list->elems[i].data, "/dev/sg",
|
||||||
STRLEN_CONST("/dev/sg")))
|
STRLEN_CONST("/dev/sg")))
|
||||||
{
|
{
|
||||||
char drive_string[33];
|
|
||||||
libretro_vfs_implementation_file *stream;
|
libretro_vfs_implementation_file *stream;
|
||||||
char drive_model[32] = {0};
|
char drive_model[32] = {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(
|
RFILE *file = filestream_open(
|
||||||
@ -1380,9 +1380,9 @@ struct string_list* cdrom_get_available_drives(void)
|
|||||||
attr.i = dev_index;
|
attr.i = dev_index;
|
||||||
|
|
||||||
if (!string_is_empty(drive_model))
|
if (!string_is_empty(drive_model))
|
||||||
strlcpy(drive_string, drive_model, sizeof(drive_string));
|
strlcat(drive_string, drive_model, sizeof(drive_string));
|
||||||
else
|
else
|
||||||
strlcpy(drive_string, "Unknown Drive", sizeof(drive_string));
|
strlcat(drive_string, "Unknown Drive", sizeof(drive_string));
|
||||||
|
|
||||||
string_list_append(list, drive_string, attr);
|
string_list_append(list, drive_string, attr);
|
||||||
}
|
}
|
||||||
@ -1404,7 +1404,7 @@ struct string_list* cdrom_get_available_drives(void)
|
|||||||
|
|
||||||
if (string_split_noalloc(&mods, buf, "\n"))
|
if (string_split_noalloc(&mods, buf, "\n"))
|
||||||
{
|
{
|
||||||
for (i = 0; i < (int)mods.size; i++)
|
for (i = 0; i < mods.size; i++)
|
||||||
{
|
{
|
||||||
if (strcasestr(mods.elems[i].data, "sg "))
|
if (strcasestr(mods.elems[i].data, "sg "))
|
||||||
{
|
{
|
||||||
@ -1446,7 +1446,7 @@ struct string_list* cdrom_get_available_drives(void)
|
|||||||
DWORD drive_mask = GetLogicalDrives();
|
DWORD drive_mask = GetLogicalDrives();
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < (int)(sizeof(DWORD) * 8); i++)
|
for (i = 0; i < sizeof(DWORD) * 8; i++)
|
||||||
{
|
{
|
||||||
char path[] = {"a:\\"};
|
char path[] = {"a:\\"};
|
||||||
char cdrom_path[] = {"cdrom://a:/drive-track01.bin"};
|
char cdrom_path[] = {"cdrom://a:/drive-track01.bin"};
|
||||||
@ -1460,14 +1460,15 @@ struct string_list* cdrom_get_available_drives(void)
|
|||||||
|
|
||||||
if (GetDriveType(path) != DRIVE_CDROM)
|
if (GetDriveType(path) != DRIVE_CDROM)
|
||||||
continue;
|
continue;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
char drive_string[33];
|
|
||||||
libretro_vfs_implementation_file *stream;
|
|
||||||
bool is_cdrom = false;
|
|
||||||
char drive_model[32] = {0};
|
char drive_model[32] = {0};
|
||||||
|
char drive_string[33] = {0};
|
||||||
union string_list_elem_attr attr = {0};
|
union string_list_elem_attr attr = {0};
|
||||||
RFILE *file = filestream_open(cdrom_path, RETRO_VFS_FILE_ACCESS_READ, 0);
|
RFILE *file = filestream_open(cdrom_path, RETRO_VFS_FILE_ACCESS_READ, 0);
|
||||||
|
libretro_vfs_implementation_file *stream;
|
||||||
|
bool is_cdrom = false;
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1481,9 +1482,9 @@ struct string_list* cdrom_get_available_drives(void)
|
|||||||
attr.i = path[0];
|
attr.i = path[0];
|
||||||
|
|
||||||
if (!string_is_empty(drive_model))
|
if (!string_is_empty(drive_model))
|
||||||
strlcpy(drive_string, drive_model, sizeof(drive_string));
|
strlcat(drive_string, drive_model, sizeof(drive_string));
|
||||||
else
|
else
|
||||||
strlcpy(drive_string, "Unknown Drive", sizeof(drive_string));
|
strlcat(drive_string, "Unknown Drive", sizeof(drive_string));
|
||||||
|
|
||||||
string_list_append(list, drive_string, attr);
|
string_list_append(list, drive_string, attr);
|
||||||
}
|
}
|
||||||
@ -1523,7 +1524,9 @@ bool cdrom_drive_has_media(const char drive)
|
|||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
libretro_vfs_implementation_file *stream = filestream_get_vfs_handle(file);
|
libretro_vfs_implementation_file *stream = filestream_get_vfs_handle(file);
|
||||||
bool has_media = cdrom_is_media_inserted(stream);
|
bool has_media = false;
|
||||||
|
|
||||||
|
has_media = cdrom_is_media_inserted(stream);
|
||||||
|
|
||||||
filestream_close(file);
|
filestream_close(file);
|
||||||
|
|
||||||
@ -1535,14 +1538,14 @@ bool cdrom_drive_has_media(const char drive)
|
|||||||
|
|
||||||
bool cdrom_set_read_cache(libretro_vfs_implementation_file *stream, bool enabled)
|
bool cdrom_set_read_cache(libretro_vfs_implementation_file *stream, bool enabled)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
/* MMC Command: MODE SENSE (10) and MODE SELECT (10) */
|
/* MMC Command: MODE SENSE (10) and MODE SELECT (10) */
|
||||||
unsigned char cdb_sense_changeable[] = {0x5A, 0, 0x48, 0, 0, 0, 0, 0, 0x14, 0};
|
unsigned char cdb_sense_changeable[] = {0x5A, 0, 0x48, 0, 0, 0, 0, 0, 0x14, 0};
|
||||||
unsigned char cdb_sense[] = {0x5A, 0, 0x8, 0, 0, 0, 0, 0, 0x14, 0};
|
unsigned char cdb_sense[] = {0x5A, 0, 0x8, 0, 0, 0, 0, 0, 0x14, 0};
|
||||||
unsigned char cdb_select[] = {0x55, 0x10, 0, 0, 0, 0, 0, 0, 0x14, 0};
|
unsigned char cdb_select[] = {0x55, 0x10, 0, 0, 0, 0, 0, 0, 0x14, 0};
|
||||||
unsigned char buf[20] = {0};
|
unsigned char buf[20] = {0};
|
||||||
int rv = cdrom_send_command(stream, DIRECTION_IN, buf, sizeof(buf),
|
int rv, i;
|
||||||
cdb_sense_changeable, sizeof(cdb_sense_changeable), 0);
|
|
||||||
|
rv = cdrom_send_command(stream, DIRECTION_IN, buf, sizeof(buf), cdb_sense_changeable, sizeof(cdb_sense_changeable), 0);
|
||||||
|
|
||||||
#ifdef CDROM_DEBUG
|
#ifdef CDROM_DEBUG
|
||||||
printf("[CDROM] mode sense changeable status code %d\n", rv);
|
printf("[CDROM] mode sense changeable status code %d\n", rv);
|
||||||
@ -1578,7 +1581,9 @@ bool cdrom_set_read_cache(libretro_vfs_implementation_file *stream, bool enabled
|
|||||||
printf("Mode sense data for caching mode page: ");
|
printf("Mode sense data for caching mode page: ");
|
||||||
|
|
||||||
for (i = 0; i < (int)sizeof(buf); i++)
|
for (i = 0; i < (int)sizeof(buf); i++)
|
||||||
|
{
|
||||||
printf("%02X ", buf[i]);
|
printf("%02X ", buf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
@ -1640,7 +1645,9 @@ bool cdrom_get_timeouts(libretro_vfs_implementation_file *stream, cdrom_group_ti
|
|||||||
printf("Mode sense data for timeout groups: ");
|
printf("Mode sense data for timeout groups: ");
|
||||||
|
|
||||||
for (i = 0; i < (int)sizeof(buf); i++)
|
for (i = 0; i < (int)sizeof(buf); i++)
|
||||||
|
{
|
||||||
printf("%02X ", buf[i]);
|
printf("%02X ", buf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
@ -1673,10 +1680,7 @@ bool cdrom_has_atip(libretro_vfs_implementation_file *stream)
|
|||||||
atip_len = buf[0] << 8 | buf[1];
|
atip_len = buf[0] << 8 | buf[1];
|
||||||
|
|
||||||
#ifdef CDROM_DEBUG
|
#ifdef CDROM_DEBUG
|
||||||
printf("ATIP Length %d, Disc Type %d, Disc Sub-Type %d\n",
|
printf("ATIP Length %d, Disc Type %d, Disc Sub-Type %d\n", atip_len, (buf[6] >> 6) & 0x1, ((buf[6] >> 5) & 0x1) << 2 | ((buf[6] >> 4) & 0x1) << 1 | ((buf[6] >> 3) & 0x1) << 0);
|
||||||
atip_len,
|
|
||||||
(buf[6] >> 6) & 0x1,
|
|
||||||
((buf[6] >> 5) & 0x1) << 2 | ((buf[6] >> 4) & 0x1) << 1 | ((buf[6] >> 3) & 0x1) << 0);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (atip_len < 5)
|
if (atip_len < 5)
|
||||||
@ -1687,23 +1691,30 @@ bool cdrom_has_atip(libretro_vfs_implementation_file *stream)
|
|||||||
|
|
||||||
void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char track, bool is_cue)
|
void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char track, bool is_cue)
|
||||||
{
|
{
|
||||||
|
size_t pos = 0;
|
||||||
|
|
||||||
if (!path || len == 0)
|
if (!path || len == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (is_cue)
|
if (is_cue)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
size_t pos = strlcpy(path, "cdrom://", len);
|
pos = strlcpy(path, "cdrom://", len);
|
||||||
|
|
||||||
if (len > pos)
|
if (len > pos)
|
||||||
path[pos++] = drive;
|
path[pos++] = drive;
|
||||||
|
|
||||||
pos = strlcat(path, ":/drive.cue", len);
|
pos = strlcat(path, ":/drive.cue", len);
|
||||||
#else
|
#else
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
size_t pos = strlcpy(path, "cdrom://drive", len);
|
pos = strlcpy(path, "cdrom://drive", len);
|
||||||
|
|
||||||
if (len > pos + 1)
|
if (len > pos + 1)
|
||||||
{
|
{
|
||||||
path[pos++] = drive;
|
path[pos++] = drive;
|
||||||
path[pos] = '\0';
|
path[pos] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = strlcat(path, ".cue", len);
|
pos = strlcat(path, ".cue", len);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -1711,18 +1722,22 @@ void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char tra
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
size_t pos = strlcpy(path, "cdrom://", len);
|
pos = strlcpy(path, "cdrom://", len);
|
||||||
|
|
||||||
if (len > pos + 1)
|
if (len > pos + 1)
|
||||||
{
|
{
|
||||||
path[pos++] = drive;
|
path[pos++] = drive;
|
||||||
path[pos] = '\0';
|
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
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
size_t pos = strlcpy(path, "cdrom://drive", len);
|
pos = strlcpy(path, "cdrom://drive", len);
|
||||||
|
|
||||||
if (len > pos)
|
if (len > pos)
|
||||||
path[pos++] = drive;
|
path[pos++] = drive;
|
||||||
|
|
||||||
pos += snprintf(path + pos, len - pos, "-track%02d.bin", track);
|
pos += snprintf(path + pos, len - pos, "-track%02d.bin", track);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -60,3 +60,10 @@ size_t strlcat(char *dest, const char *source, size_t size)
|
|||||||
return len + strlcpy(dest, source, size);
|
return len + strlcpy(dest, source, size);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char *strldup(const char *s, size_t n)
|
||||||
|
{
|
||||||
|
char *dst = (char*)malloc(sizeof(char) * (n + 1));
|
||||||
|
strlcpy(dst, s, n);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <locale.h>
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
@ -69,31 +68,6 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Time format strings with AM-PM designation require special
|
|
||||||
* handling due to platform dependence */
|
|
||||||
void strftime_am_pm(char *s, size_t len, const char* format,
|
|
||||||
const void *ptr)
|
|
||||||
{
|
|
||||||
char *local = NULL;
|
|
||||||
const struct tm *timeptr = (const struct tm*)ptr;
|
|
||||||
|
|
||||||
/* Ensure correct locale is set
|
|
||||||
* > Required for localised AM/PM strings */
|
|
||||||
setlocale(LC_TIME, "");
|
|
||||||
|
|
||||||
strftime(s, len, format, timeptr);
|
|
||||||
#if !(defined(__linux__) && !defined(ANDROID))
|
|
||||||
if ((local = local_to_utf8_string_alloc(s)))
|
|
||||||
{
|
|
||||||
if (!string_is_empty(local))
|
|
||||||
strlcpy(s, local, len);
|
|
||||||
|
|
||||||
free(local);
|
|
||||||
local = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new linked list with one node in it
|
* Create a new linked list with one node in it
|
||||||
* The path on this node will be set to NULL
|
* The path on this node will be set to NULL
|
||||||
@ -198,9 +172,9 @@ const char *path_get_archive_delim(const char *path)
|
|||||||
string_to_lower(buf);
|
string_to_lower(buf);
|
||||||
|
|
||||||
/* Check if this is a '.zip', '.apk' or '.7z' file */
|
/* Check if this is a '.zip', '.apk' or '.7z' file */
|
||||||
if ( string_is_equal(buf, ".zip")
|
if (string_is_equal(buf, ".zip") ||
|
||||||
|| string_is_equal(buf, ".apk")
|
string_is_equal(buf, ".apk") ||
|
||||||
|| string_is_equal(buf + 1, ".7z"))
|
string_is_equal(buf + 1, ".7z"))
|
||||||
return delim;
|
return delim;
|
||||||
}
|
}
|
||||||
else if (delim - path > 3)
|
else if (delim - path > 3)
|
||||||
@ -328,16 +302,14 @@ bool path_is_compressed_file(const char* path)
|
|||||||
size_t fill_pathname(char *out_path, const char *in_path,
|
size_t fill_pathname(char *out_path, const char *in_path,
|
||||||
const char *replace, size_t size)
|
const char *replace, size_t size)
|
||||||
{
|
{
|
||||||
size_t _len;
|
|
||||||
char tmp_path[PATH_MAX_LENGTH];
|
char tmp_path[PATH_MAX_LENGTH];
|
||||||
char *tok = NULL;
|
char *tok = NULL;
|
||||||
strlcpy(tmp_path, in_path, sizeof(tmp_path));
|
strlcpy(tmp_path, in_path, sizeof(tmp_path));
|
||||||
if ((tok = (char*)strrchr(path_basename(tmp_path), '.')))
|
if ((tok = (char*)strrchr(path_basename(tmp_path), '.')))
|
||||||
*tok = '\0';
|
*tok = '\0';
|
||||||
|
|
||||||
_len = strlcpy(out_path, tmp_path, size);
|
strlcpy(out_path, tmp_path, size);
|
||||||
_len += strlcpy(out_path + _len, replace, size - _len);
|
return strlcat(out_path, replace, size);
|
||||||
return _len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -347,19 +319,20 @@ size_t fill_pathname(char *out_path, const char *in_path,
|
|||||||
* @size : size of path
|
* @size : size of path
|
||||||
*
|
*
|
||||||
* Find last slash in path. Tries to find
|
* Find last slash in path. Tries to find
|
||||||
* a backslash as used for Windows paths,
|
* a backslash on Windows too which takes precedence
|
||||||
* otherwise checks for a regular slash.
|
* over regular slash.
|
||||||
|
|
||||||
* @return pointer to last slash/backslash found in @str.
|
* @return pointer to last slash/backslash found in @str.
|
||||||
**/
|
**/
|
||||||
char *find_last_slash(const char *str)
|
char *find_last_slash(const char *str)
|
||||||
{
|
{
|
||||||
const char *slash = strrchr(str, '/');
|
const char *slash = strrchr(str, '/');
|
||||||
|
#ifdef _WIN32
|
||||||
const char *backslash = strrchr(str, '\\');
|
const char *backslash = strrchr(str, '\\');
|
||||||
|
|
||||||
if (!slash || (backslash > slash))
|
if (!slash || (backslash > slash))
|
||||||
return (char*)backslash;
|
return (char*)backslash;
|
||||||
else
|
#endif
|
||||||
return (char*)slash;
|
return (char*)slash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,20 +344,24 @@ char *find_last_slash(const char *str)
|
|||||||
* Assumes path is a directory. Appends a slash
|
* Assumes path is a directory. Appends a slash
|
||||||
* if not already there.
|
* if not already there.
|
||||||
**/
|
**/
|
||||||
size_t fill_pathname_slash(char *path, size_t size)
|
void fill_pathname_slash(char *path, size_t size)
|
||||||
{
|
{
|
||||||
size_t path_len;
|
size_t path_len;
|
||||||
const char *last_slash = find_last_slash(path);
|
const char *last_slash = find_last_slash(path);
|
||||||
|
|
||||||
if (!last_slash)
|
if (!last_slash)
|
||||||
return strlcat(path, PATH_DEFAULT_SLASH(), size);
|
{
|
||||||
|
strlcat(path, PATH_DEFAULT_SLASH(), size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
path_len = strlen(path);
|
path_len = strlen(path);
|
||||||
/* Try to preserve slash type. */
|
/* Try to preserve slash type. */
|
||||||
if (last_slash != (path + path_len - 1))
|
if (last_slash != (path + path_len - 1))
|
||||||
{
|
{
|
||||||
path[path_len] = last_slash[0];
|
path[path_len] = last_slash[0];
|
||||||
path[++path_len] = '\0';
|
path[path_len+1] = '\0';
|
||||||
}
|
}
|
||||||
return path_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -407,11 +384,12 @@ size_t fill_pathname_slash(char *path, size_t size)
|
|||||||
size_t 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)
|
||||||
{
|
{
|
||||||
size_t _len = fill_pathname_slash(in_dir, size);
|
const char *base = NULL;
|
||||||
const char *base = path_basename(in_basename);
|
|
||||||
_len += strlcpy(in_dir + _len, base, size - _len);
|
fill_pathname_slash(in_dir, size);
|
||||||
_len += strlcpy(in_dir + _len, replace, size - _len);
|
base = path_basename(in_basename);
|
||||||
return _len;
|
strlcat(in_dir, base, size);
|
||||||
|
return strlcat(in_dir, replace, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -536,14 +514,14 @@ void fill_pathname_parent_dir(char *out_dir,
|
|||||||
size_t 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)
|
||||||
{
|
{
|
||||||
size_t _len;
|
|
||||||
struct tm tm_;
|
|
||||||
time_t cur_time = time(NULL);
|
time_t cur_time = time(NULL);
|
||||||
|
struct tm tm_;
|
||||||
|
|
||||||
rtime_localtime(&cur_time, &tm_);
|
rtime_localtime(&cur_time, &tm_);
|
||||||
_len = strftime(out_filename, size,
|
|
||||||
|
strftime(out_filename, size,
|
||||||
"RetroArch-%m%d-%H%M%S", &tm_);
|
"RetroArch-%m%d-%H%M%S", &tm_);
|
||||||
_len += strlcpy(out_filename + _len, ext, size - _len);
|
return strlcat(out_filename, ext, size);
|
||||||
return _len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -564,24 +542,21 @@ size_t fill_dated_filename(char *out_filename,
|
|||||||
size_t fill_str_dated_filename(char *out_filename,
|
size_t 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)
|
||||||
{
|
{
|
||||||
struct tm tm_;
|
|
||||||
char format[NAME_MAX_LENGTH];
|
char format[NAME_MAX_LENGTH];
|
||||||
size_t _len = 0;
|
struct tm tm_;
|
||||||
time_t cur_time = time(NULL);
|
time_t cur_time = time(NULL);
|
||||||
|
|
||||||
rtime_localtime(&cur_time, &tm_);
|
rtime_localtime(&cur_time, &tm_);
|
||||||
_len = strlcpy(out_filename, in_str, size);
|
|
||||||
|
strlcpy(out_filename, in_str, size);
|
||||||
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_);
|
||||||
_len += strlcpy(out_filename + _len, format, size - _len);
|
return strlcat(out_filename, format, size);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
strftime(format, sizeof(format), "-%y%m%d-%H%M%S.", &tm_);
|
strftime(format, sizeof(format), "-%y%m%d-%H%M%S.", &tm_);
|
||||||
_len += strlcpy(out_filename + _len, format, size - _len);
|
strlcat(out_filename, format, size);
|
||||||
_len += strlcpy(out_filename + _len, ext, size - _len);
|
return strlcat(out_filename, ext, size);
|
||||||
}
|
|
||||||
return _len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -651,12 +626,18 @@ void path_parent_dir(char *path, size_t len)
|
|||||||
**/
|
**/
|
||||||
const char *path_basename(const char *path)
|
const char *path_basename(const char *path)
|
||||||
{
|
{
|
||||||
/* We cut either at the first compression-related hash,
|
/* We cut at the first compression-related hash */
|
||||||
* or we cut at the last slash */
|
const char *delim = path_get_archive_delim(path);
|
||||||
const char *ptr = NULL;
|
if (delim)
|
||||||
if ( (ptr = path_get_archive_delim(path))
|
return delim + 1;
|
||||||
|| (ptr = find_last_slash(path)))
|
|
||||||
return ptr + 1;
|
{
|
||||||
|
/* We cut at the last slash */
|
||||||
|
const char *last = find_last_slash(path);
|
||||||
|
if (last)
|
||||||
|
return last + 1;
|
||||||
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -689,10 +670,12 @@ const char *path_basename_nocompression(const char *path)
|
|||||||
**/
|
**/
|
||||||
bool path_is_absolute(const char *path)
|
bool path_is_absolute(const char *path)
|
||||||
{
|
{
|
||||||
if (!string_is_empty(path))
|
if (string_is_empty(path))
|
||||||
{
|
return false;
|
||||||
|
|
||||||
if (path[0] == '/')
|
if (path[0] == '/')
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
/* Many roads lead to Rome...
|
/* Many roads lead to Rome...
|
||||||
* Note: Drive letter can only be 1 character long */
|
* Note: Drive letter can only be 1 character long */
|
||||||
@ -705,7 +688,6 @@ bool path_is_absolute(const char *path)
|
|||||||
return (seperator && (seperator[1] == '/'));
|
return (seperator && (seperator[1] == '/'));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -823,7 +805,7 @@ char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks)
|
|||||||
|
|
||||||
/* delete previous segment in tmp by adjusting size t
|
/* delete previous segment in tmp by adjusting size t
|
||||||
* tmp[t-1] == '/', find '/' before that */
|
* tmp[t-1] == '/', find '/' before that */
|
||||||
t -= 2;
|
t = t-2;
|
||||||
while (tmp[t] != '/')
|
while (tmp[t] != '/')
|
||||||
t--;
|
t--;
|
||||||
t++;
|
t++;
|
||||||
@ -954,13 +936,11 @@ void fill_pathname_resolve_relative(char *out_path,
|
|||||||
size_t 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)
|
||||||
{
|
{
|
||||||
size_t _len = 0;
|
|
||||||
if (out_path != dir)
|
if (out_path != dir)
|
||||||
_len = strlcpy(out_path, dir, size);
|
strlcpy(out_path, dir, size);
|
||||||
if (*out_path)
|
if (*out_path)
|
||||||
_len = fill_pathname_slash(out_path, size);
|
fill_pathname_slash(out_path, size);
|
||||||
_len += strlcpy(out_path + _len, path, size - _len);
|
return strlcat(out_path, path, size);
|
||||||
return _len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -995,18 +975,17 @@ size_t fill_pathname_join_special(char *out_path,
|
|||||||
if (last_slash != (out_path + len - 1))
|
if (last_slash != (out_path + len - 1))
|
||||||
{
|
{
|
||||||
out_path[len] = last_slash[0];
|
out_path[len] = last_slash[0];
|
||||||
out_path[++len] = '\0';
|
out_path[len+1] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out_path[len] = PATH_DEFAULT_SLASH_C();
|
out_path[len] = PATH_DEFAULT_SLASH_C();
|
||||||
out_path[++len] = '\0';
|
out_path[len+1] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
len += strlcpy(out_path + len, path, size - len);
|
return strlcat(out_path, path, size);
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t fill_pathname_join_special_ext(char *out_path,
|
size_t fill_pathname_join_special_ext(char *out_path,
|
||||||
@ -1014,12 +993,12 @@ size_t fill_pathname_join_special_ext(char *out_path,
|
|||||||
const char *last, const char *ext,
|
const char *last, const char *ext,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
size_t _len = fill_pathname_join(out_path, dir, path, size);
|
fill_pathname_join(out_path, dir, path, size);
|
||||||
if (*out_path)
|
if (*out_path)
|
||||||
_len = fill_pathname_slash(out_path, size);
|
fill_pathname_slash(out_path, size);
|
||||||
_len += strlcpy(out_path + _len, last, size - _len);
|
|
||||||
_len += strlcpy(out_path + _len, ext, size - _len);
|
strlcat(out_path, last, size);
|
||||||
return _len;
|
return strlcat(out_path, ext, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1036,19 +1015,19 @@ size_t fill_pathname_join_special_ext(char *out_path,
|
|||||||
size_t 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 _len;
|
size_t copied;
|
||||||
/* Behavior of strlcpy is undefined if dst and src overlap */
|
/* behavior of strlcpy is undefined if dst and src overlap */
|
||||||
if (out_path == dir)
|
if (out_path == dir)
|
||||||
_len = strlen(dir);
|
copied = strlen(dir);
|
||||||
else
|
else
|
||||||
_len = strlcpy(out_path, dir, size);
|
copied = strlcpy(out_path, dir, size);
|
||||||
|
|
||||||
out_path[_len] = delim;
|
out_path[copied] = delim;
|
||||||
out_path[_len+1] = '\0';
|
out_path[copied+1] = '\0';
|
||||||
|
|
||||||
if (path)
|
if (path)
|
||||||
return strlcat(out_path, path, size);
|
return strlcat(out_path, path, size);
|
||||||
return _len;
|
return copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t fill_pathname_expand_special(char *out_path,
|
size_t fill_pathname_expand_special(char *out_path,
|
||||||
@ -1156,12 +1135,12 @@ size_t fill_pathname_abbreviate_special(char *out_path,
|
|||||||
*
|
*
|
||||||
* Leaf function.
|
* Leaf function.
|
||||||
*
|
*
|
||||||
* Changes the slashes to the correct kind for the OS
|
* Changes the slashes to the correct kind for the os
|
||||||
* So forward slash on linux and backslash on Windows
|
* So forward slash on linux and backslash on Windows
|
||||||
**/
|
**/
|
||||||
void pathname_conform_slashes_to_os(char *path)
|
void pathname_conform_slashes_to_os(char *path)
|
||||||
{
|
{
|
||||||
/* Conform slashes to OS standard so we get proper matching */
|
/* Conform slashes to os standard so we get proper matching */
|
||||||
char *p;
|
char *p;
|
||||||
for (p = path; *p; p++)
|
for (p = path; *p; p++)
|
||||||
if (*p == '/' || *p == '\\')
|
if (*p == '/' || *p == '\\')
|
||||||
@ -1179,7 +1158,7 @@ void pathname_conform_slashes_to_os(char *path)
|
|||||||
**/
|
**/
|
||||||
void pathname_make_slashes_portable(char *path)
|
void pathname_make_slashes_portable(char *path)
|
||||||
{
|
{
|
||||||
/* Conform slashes to OS standard so we get proper matching */
|
/* Conform slashes to os standard so we get proper matching */
|
||||||
char *p;
|
char *p;
|
||||||
for (p = path; *p; p++)
|
for (p = path; *p; p++)
|
||||||
if (*p == '/' || *p == '\\')
|
if (*p == '/' || *p == '\\')
|
||||||
@ -1356,7 +1335,7 @@ void fill_pathname_application_path(char *s, size_t len)
|
|||||||
{
|
{
|
||||||
size_t _len = strlcpy(s, resolved_bundle_dir_buf, len - 1);
|
size_t _len = strlcpy(s, resolved_bundle_dir_buf, len - 1);
|
||||||
s[_len ] = '/';
|
s[_len ] = '/';
|
||||||
s[++_len] = '\0';
|
s[_len+1] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -131,6 +131,7 @@ struct gl_cached_state
|
|||||||
GLenum func;
|
GLenum func;
|
||||||
} depthfunc;
|
} depthfunc;
|
||||||
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool used;
|
bool used;
|
||||||
@ -334,6 +335,7 @@ void rglTexSubImage2D(
|
|||||||
width, height, format, type, pixels);
|
width, height, format, type, pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void rglGetBufferSubData( GLenum target,
|
void rglGetBufferSubData( GLenum target,
|
||||||
GLintptr offset,
|
GLintptr offset,
|
||||||
GLsizeiptr size,
|
GLsizeiptr size,
|
||||||
@ -644,18 +646,18 @@ void rglBlendFunc(GLenum sfactor, GLenum dfactor)
|
|||||||
* Core in:
|
* Core in:
|
||||||
* OpenGL : 1.4
|
* OpenGL : 1.4
|
||||||
*/
|
*/
|
||||||
void rglBlendFuncSeparate(GLenum sfactor, GLenum dfactor)
|
void rglBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
|
||||||
{
|
{
|
||||||
#ifdef GLSM_DEBUG
|
#ifdef GLSM_DEBUG
|
||||||
log_cb(RETRO_LOG_INFO, "glBlendFuncSeparate.\n");
|
log_cb(RETRO_LOG_INFO, "glBlendFuncSeparate.\n");
|
||||||
#endif
|
#endif
|
||||||
glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL);
|
glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL);
|
||||||
gl_state.blendfunc_separate.used = true;
|
gl_state.blendfunc_separate.used = true;
|
||||||
gl_state.blendfunc_separate.srcRGB = sfactor;
|
gl_state.blendfunc_separate.srcRGB = srcRGB;
|
||||||
gl_state.blendfunc_separate.dstRGB = dfactor;
|
gl_state.blendfunc_separate.dstRGB = dstRGB;
|
||||||
gl_state.blendfunc_separate.srcAlpha = sfactor;
|
gl_state.blendfunc_separate.srcAlpha = srcAlpha;
|
||||||
gl_state.blendfunc_separate.dstAlpha = dfactor;
|
gl_state.blendfunc_separate.dstAlpha = dstAlpha;
|
||||||
glBlendFunc(sfactor, dfactor);
|
glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -896,6 +898,7 @@ void rglCompressedTexImage2D(GLenum target, GLint level,
|
|||||||
width, height, border, imageSize, data);
|
width, height, border, imageSize, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void rglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
|
void rglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
|
||||||
{
|
{
|
||||||
#ifdef GLSM_DEBUG
|
#ifdef GLSM_DEBUG
|
||||||
@ -1027,11 +1030,12 @@ void rglBindFragDataLocation(GLuint program, GLuint colorNumber,
|
|||||||
#ifdef GLSM_DEBUG
|
#ifdef GLSM_DEBUG
|
||||||
log_cb(RETRO_LOG_INFO, "glBindFragDataLocation.\n");
|
log_cb(RETRO_LOG_INFO, "glBindFragDataLocation.\n");
|
||||||
#endif
|
#endif
|
||||||
#if !defined(HAVE_OPENGLES2)
|
#if !defined(HAVE_OPENGLES2) && !defined(HAVE_OPENGLES3)
|
||||||
glBindFragDataLocation(program, colorNumber, name);
|
glBindFragDataLocation(program, colorNumber, name);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Category: Shaders
|
* Category: Shaders
|
||||||
*
|
*
|
||||||
@ -1136,6 +1140,7 @@ void rglEndQuery( GLenum target)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Category: UBO
|
* Category: UBO
|
||||||
*
|
*
|
||||||
@ -1500,6 +1505,7 @@ GLboolean rglIsProgram(GLuint program)
|
|||||||
return glIsProgram(program);
|
return glIsProgram(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void rglTexCoord2f(GLfloat s, GLfloat t)
|
void rglTexCoord2f(GLfloat s, GLfloat t)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LEGACY_GL
|
#ifdef HAVE_LEGACY_GL
|
||||||
@ -1967,6 +1973,7 @@ void rglUniform4fv(GLint location, GLsizei count, const GLfloat *value)
|
|||||||
glUniform4fv(location, count, value);
|
glUniform4fv(location, count, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Core in:
|
* Core in:
|
||||||
@ -2201,6 +2208,7 @@ void rglTexImage2DMultisample( GLenum target,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void rglTexImage3D( GLenum target,
|
void rglTexImage3D( GLenum target,
|
||||||
GLint level,
|
GLint level,
|
||||||
GLint internalFormat,
|
GLint internalFormat,
|
||||||
|
@ -323,10 +323,10 @@ size_t fill_dated_filename(char *out_filename,
|
|||||||
* Hidden non-leaf function cost:
|
* Hidden non-leaf function cost:
|
||||||
* - Calls time
|
* - Calls time
|
||||||
* - Calls rtime_localtime()
|
* - Calls rtime_localtime()
|
||||||
* - Calls strlcpy 2x
|
* - Calls strlcpy
|
||||||
* - Calls string_is_empty()
|
* - Calls string_is_empty()
|
||||||
* - Calls strftime
|
* - Calls strftime
|
||||||
* - Calls strlcat
|
* - Calls strlcat at least 2x
|
||||||
*
|
*
|
||||||
* @return Length of the string copied into @out_path
|
* @return Length of the string copied into @out_path
|
||||||
**/
|
**/
|
||||||
@ -369,7 +369,7 @@ char *find_last_slash(const char *str);
|
|||||||
* Hidden non-leaf function cost:
|
* Hidden non-leaf function cost:
|
||||||
* - Calls fill_pathname_slash()
|
* - Calls fill_pathname_slash()
|
||||||
* - Calls path_basename()
|
* - Calls path_basename()
|
||||||
* - Calls strlcpy 2x
|
* - Calls strlcat 2x
|
||||||
**/
|
**/
|
||||||
size_t 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);
|
||||||
@ -470,8 +470,9 @@ void fill_pathname_resolve_relative(char *out_path, const char *in_refpath,
|
|||||||
* between directory and path.
|
* between directory and path.
|
||||||
*
|
*
|
||||||
* Hidden non-leaf function cost:
|
* Hidden non-leaf function cost:
|
||||||
* - calls strlcpy at least once
|
* - calls strlcpy
|
||||||
* - calls fill_pathname_slash()
|
* - calls fill_pathname_slash()
|
||||||
|
* - calls strlcat
|
||||||
*
|
*
|
||||||
* Deprecated. Use fill_pathname_join_special() instead
|
* Deprecated. Use fill_pathname_join_special() instead
|
||||||
* if you can ensure @dir != @out_path
|
* if you can ensure @dir != @out_path
|
||||||
@ -498,8 +499,9 @@ size_t fill_pathname_join(char *out_path, const char *dir,
|
|||||||
* between directory and path.
|
* between directory and path.
|
||||||
*
|
*
|
||||||
* Hidden non-leaf function cost:
|
* Hidden non-leaf function cost:
|
||||||
* - calls strlcpy 2x
|
* - calls strlcpy
|
||||||
* - calls find_last_slash()
|
* - calls find_last_slash()
|
||||||
|
* - calls strlcat
|
||||||
*
|
*
|
||||||
* @return Length of the string copied into @out_path
|
* @return Length of the string copied into @out_path
|
||||||
**/
|
**/
|
||||||
@ -625,7 +627,7 @@ void path_basedir_wrapper(char *path);
|
|||||||
* - can call strlcat once if it returns false
|
* - can call strlcat once if it returns false
|
||||||
* - calls strlen
|
* - calls strlen
|
||||||
**/
|
**/
|
||||||
size_t fill_pathname_slash(char *path, size_t size);
|
void fill_pathname_slash(char *path, size_t size);
|
||||||
|
|
||||||
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
|
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
|
||||||
void fill_pathname_application_path(char *buf, size_t size);
|
void fill_pathname_application_path(char *buf, size_t size);
|
||||||
@ -662,11 +664,6 @@ bool path_mkdir(const char *dir);
|
|||||||
*/
|
*/
|
||||||
bool path_is_directory(const char *path);
|
bool path_is_directory(const char *path);
|
||||||
|
|
||||||
/* Time format strings with AM-PM designation require special
|
|
||||||
* handling due to platform dependence */
|
|
||||||
void strftime_am_pm(char *s, size_t len, const char* format,
|
|
||||||
const void* timeptr);
|
|
||||||
|
|
||||||
bool path_is_character_special(const char *path);
|
bool path_is_character_special(const char *path);
|
||||||
|
|
||||||
int path_stat(const char *path);
|
int path_stat(const char *path);
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
RETRO_BEGIN_DECLS
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
#ifdef HAVE_OPENGLES2
|
#if defined(HAVE_OPENGLES2) || defined(HAVE_OPENGLES3)
|
||||||
typedef double GLdouble;
|
typedef double GLdouble;
|
||||||
typedef double GLclampd;
|
typedef double GLclampd;
|
||||||
#endif
|
#endif
|
||||||
|
@ -291,7 +291,6 @@ enum retro_language
|
|||||||
RETRO_LANGUAGE_CATALAN = 29,
|
RETRO_LANGUAGE_CATALAN = 29,
|
||||||
RETRO_LANGUAGE_BRITISH_ENGLISH = 30,
|
RETRO_LANGUAGE_BRITISH_ENGLISH = 30,
|
||||||
RETRO_LANGUAGE_HUNGARIAN = 31,
|
RETRO_LANGUAGE_HUNGARIAN = 31,
|
||||||
RETRO_LANGUAGE_BELARUSIAN = 32,
|
|
||||||
RETRO_LANGUAGE_LAST,
|
RETRO_LANGUAGE_LAST,
|
||||||
|
|
||||||
/* Ensure sizeof(enum) == sizeof(int) */
|
/* Ensure sizeof(enum) == sizeof(int) */
|
||||||
@ -929,6 +928,8 @@ enum retro_mod
|
|||||||
* anything else.
|
* anything else.
|
||||||
* It is recommended to expose all relevant pointers through
|
* It is recommended to expose all relevant pointers through
|
||||||
* retro_get_memory_* as well.
|
* retro_get_memory_* as well.
|
||||||
|
*
|
||||||
|
* Can be called from retro_init and retro_load_game.
|
||||||
*/
|
*/
|
||||||
#define RETRO_ENVIRONMENT_SET_GEOMETRY 37
|
#define RETRO_ENVIRONMENT_SET_GEOMETRY 37
|
||||||
/* const struct retro_game_geometry * --
|
/* const struct retro_game_geometry * --
|
||||||
@ -1792,63 +1793,6 @@ enum retro_mod
|
|||||||
* this environment call to query support.
|
* this environment call to query support.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define RETRO_ENVIRONMENT_GET_JIT_CAPABLE 74
|
|
||||||
/* bool * --
|
|
||||||
* Result is set to true if the frontend has already verified JIT can be
|
|
||||||
* used, mainly for use iOS/tvOS. On other platforms the result is true.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define RETRO_ENVIRONMENT_GET_MICROPHONE_INTERFACE (75 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
|
||||||
/* struct retro_microphone_interface * --
|
|
||||||
* Returns an interface that can be used to receive input from the microphone driver.
|
|
||||||
*
|
|
||||||
* Returns true if microphone support is available,
|
|
||||||
* even if no microphones are plugged in.
|
|
||||||
* Returns false if mic support is disabled or unavailable.
|
|
||||||
*
|
|
||||||
* This callback can be invoked at any time,
|
|
||||||
* even before the microphone driver is ready.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE 76
|
|
||||||
/* const struct retro_netpacket_callback * --
|
|
||||||
* When set, a core gains control over network packets sent and
|
|
||||||
* received during a multiplayer session. This can be used to
|
|
||||||
* emulate multiplayer games that were originally played on two
|
|
||||||
* or more separate consoles or computers connected together.
|
|
||||||
*
|
|
||||||
* The frontend will take care of connecting players together,
|
|
||||||
* and the core only needs to send the actual data as needed for
|
|
||||||
* the emulation, while handshake and connection management happen
|
|
||||||
* in the background.
|
|
||||||
*
|
|
||||||
* When two or more players are connected and this interface has
|
|
||||||
* been set, time manipulation features (such as pausing, slow motion,
|
|
||||||
* fast forward, rewinding, save state loading, etc.) are disabled to
|
|
||||||
* avoid interrupting communication.
|
|
||||||
*
|
|
||||||
* Should be set in either retro_init or retro_load_game, but not both.
|
|
||||||
*
|
|
||||||
* When not set, a frontend may use state serialization-based
|
|
||||||
* multiplayer, where a deterministic core supporting multiple
|
|
||||||
* input devices does not need to take any action on its own.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define RETRO_ENVIRONMENT_GET_DEVICE_POWER (77 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
|
||||||
/* struct retro_device_power * --
|
|
||||||
* Returns the device's current power state as reported by the frontend.
|
|
||||||
* This is useful for emulating the battery level in handheld consoles,
|
|
||||||
* or for reducing power consumption when on battery power.
|
|
||||||
*
|
|
||||||
* The return value indicates whether the frontend can provide this information,
|
|
||||||
* even if the parameter is NULL.
|
|
||||||
*
|
|
||||||
* If the frontend does not support this functionality,
|
|
||||||
* then the provided argument will remain unchanged.
|
|
||||||
*
|
|
||||||
* Note that this environment call describes the power state for the entire device,
|
|
||||||
* not for individual peripherals like controllers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* VFS functionality */
|
/* VFS functionality */
|
||||||
|
|
||||||
@ -2806,17 +2750,9 @@ enum retro_hw_context_type
|
|||||||
/* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */
|
/* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */
|
||||||
RETRO_HW_CONTEXT_VULKAN = 6,
|
RETRO_HW_CONTEXT_VULKAN = 6,
|
||||||
|
|
||||||
/* Direct3D11, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */
|
/* Direct3D, set version_major to select the type of interface
|
||||||
RETRO_HW_CONTEXT_D3D11 = 7,
|
* returned by RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */
|
||||||
|
RETRO_HW_CONTEXT_DIRECT3D = 7,
|
||||||
/* Direct3D10, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */
|
|
||||||
RETRO_HW_CONTEXT_D3D10 = 8,
|
|
||||||
|
|
||||||
/* Direct3D12, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */
|
|
||||||
RETRO_HW_CONTEXT_D3D12 = 9,
|
|
||||||
|
|
||||||
/* Direct3D9, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */
|
|
||||||
RETRO_HW_CONTEXT_D3D9 = 10,
|
|
||||||
|
|
||||||
RETRO_HW_CONTEXT_DUMMY = INT_MAX
|
RETRO_HW_CONTEXT_DUMMY = INT_MAX
|
||||||
};
|
};
|
||||||
@ -3071,100 +3007,6 @@ struct retro_disk_control_ext_callback
|
|||||||
retro_get_image_label_t get_image_label; /* Optional - may be NULL */
|
retro_get_image_label_t get_image_label; /* Optional - may be NULL */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Definitions for RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE.
|
|
||||||
* A core can set it if sending and receiving custom network packets
|
|
||||||
* during a multiplayer session is desired.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Netpacket flags for retro_netpacket_send_t */
|
|
||||||
#define RETRO_NETPACKET_UNRELIABLE 0 /* Packet to be sent unreliable, depending on network quality it might not arrive. */
|
|
||||||
#define RETRO_NETPACKET_RELIABLE (1 << 0) /* Reliable packets are guaranteed to arrive at the target in the order they were send. */
|
|
||||||
#define RETRO_NETPACKET_UNSEQUENCED (1 << 1) /* Packet will not be sequenced with other packets and may arrive out of order. Cannot be set on reliable packets. */
|
|
||||||
|
|
||||||
/* Used by the core to send a packet to one or more connected players.
|
|
||||||
* A single packet sent via this interface can contain up to 64 KB of data.
|
|
||||||
*
|
|
||||||
* The broadcast flag can be set to true to send to multiple connected clients.
|
|
||||||
* In a broadcast, the client_id argument indicates 1 client NOT to send the
|
|
||||||
* packet to (pass 0xFFFF to send to everyone). Otherwise, the client_id
|
|
||||||
* argument indicates a single client to send the packet to.
|
|
||||||
*
|
|
||||||
* A frontend must support sending reliable packets (RETRO_NETPACKET_RELIABLE).
|
|
||||||
* Unreliable packets might not be supported by the frontend, but the flags can
|
|
||||||
* still be specified. Reliable transmission will be used instead.
|
|
||||||
*
|
|
||||||
* If this function is called passing NULL for buf, it will instead flush all
|
|
||||||
* previously buffered outgoing packets and instantly read any incoming packets.
|
|
||||||
* During such a call, retro_netpacket_receive_t and retro_netpacket_stop_t can
|
|
||||||
* be called. The core can perform this in a loop to do a blocking read, i.e.,
|
|
||||||
* wait for incoming data, but needs to handle stop getting called and also
|
|
||||||
* give up after a short while to avoid freezing on a connection problem.
|
|
||||||
*
|
|
||||||
* This function is not guaranteed to be thread-safe and must be called during
|
|
||||||
* retro_run or any of the netpacket callbacks passed with this interface.
|
|
||||||
*/
|
|
||||||
typedef void (RETRO_CALLCONV *retro_netpacket_send_t)(int flags, const void* buf, size_t len, uint16_t client_id, bool broadcast);
|
|
||||||
|
|
||||||
/* Called by the frontend to signify that a multiplayer session has started.
|
|
||||||
* If client_id is 0 the local player is the host of the session and at this
|
|
||||||
* point no other player has connected yet.
|
|
||||||
*
|
|
||||||
* If client_id is > 0 the local player is a client connected to a host and
|
|
||||||
* at this point is already fully connected to the host.
|
|
||||||
*
|
|
||||||
* The core must store the retro_netpacket_send_t function pointer provided
|
|
||||||
* here and use it whenever it wants to send a packet. This function pointer
|
|
||||||
* remains valid until the frontend calls retro_netpacket_stop_t.
|
|
||||||
*/
|
|
||||||
typedef void (RETRO_CALLCONV *retro_netpacket_start_t)(uint16_t client_id, retro_netpacket_send_t send_fn);
|
|
||||||
|
|
||||||
/* Called by the frontend when a new packet arrives which has been sent from
|
|
||||||
* another player with retro_netpacket_send_t. The client_id argument indicates
|
|
||||||
* who has sent the packet.
|
|
||||||
*/
|
|
||||||
typedef void (RETRO_CALLCONV *retro_netpacket_receive_t)(const void* buf, size_t len, uint16_t client_id);
|
|
||||||
|
|
||||||
/* Called by the frontend when the multiplayer session has ended.
|
|
||||||
* Once this gets called the retro_netpacket_send_t function pointer passed
|
|
||||||
* to retro_netpacket_start_t will not be valid anymore.
|
|
||||||
*/
|
|
||||||
typedef void (RETRO_CALLCONV *retro_netpacket_stop_t)(void);
|
|
||||||
|
|
||||||
/* Called by the frontend every frame (between calls to retro_run while
|
|
||||||
* updating the state of the multiplayer session.
|
|
||||||
* This is a good place for the core to call retro_netpacket_send_t from.
|
|
||||||
*/
|
|
||||||
typedef void (RETRO_CALLCONV *retro_netpacket_poll_t)(void);
|
|
||||||
|
|
||||||
/* Called by the frontend when a new player connects to the hosted session.
|
|
||||||
* This is only called on the host side, not for clients connected to the host.
|
|
||||||
* If this function returns false, the newly connected player gets dropped.
|
|
||||||
* This can be used for example to limit the number of players.
|
|
||||||
*/
|
|
||||||
typedef bool (RETRO_CALLCONV *retro_netpacket_connected_t)(uint16_t client_id);
|
|
||||||
|
|
||||||
/* Called by the frontend when a player leaves or disconnects from the hosted session.
|
|
||||||
* This is only called on the host side, not for clients connected to the host.
|
|
||||||
*/
|
|
||||||
typedef void (RETRO_CALLCONV *retro_netpacket_disconnected_t)(uint16_t client_id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A callback interface for giving a core the ability to send and receive custom
|
|
||||||
* network packets during a multiplayer session between two or more instances
|
|
||||||
* of a libretro frontend.
|
|
||||||
*
|
|
||||||
* @see RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE
|
|
||||||
*/
|
|
||||||
struct retro_netpacket_callback
|
|
||||||
{
|
|
||||||
retro_netpacket_start_t start;
|
|
||||||
retro_netpacket_receive_t receive;
|
|
||||||
retro_netpacket_stop_t stop; /* Optional - may be NULL */
|
|
||||||
retro_netpacket_poll_t poll; /* Optional - may be NULL */
|
|
||||||
retro_netpacket_connected_t connected; /* Optional - may be NULL */
|
|
||||||
retro_netpacket_disconnected_t disconnected; /* Optional - may be NULL */
|
|
||||||
};
|
|
||||||
|
|
||||||
enum retro_pixel_format
|
enum retro_pixel_format
|
||||||
{
|
{
|
||||||
/* 0RGB1555, native endian.
|
/* 0RGB1555, native endian.
|
||||||
@ -3967,289 +3809,6 @@ struct retro_throttle_state
|
|||||||
float rate;
|
float rate;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Opaque handle to a microphone that's been opened for use.
|
|
||||||
* The underlying object is accessed or created with \c retro_microphone_interface_t.
|
|
||||||
*/
|
|
||||||
typedef struct retro_microphone retro_microphone_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parameters for configuring a microphone.
|
|
||||||
* Some of these might not be honored,
|
|
||||||
* depending on the available hardware and driver configuration.
|
|
||||||
*/
|
|
||||||
typedef struct retro_microphone_params
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The desired sample rate of the microphone's input, in Hz.
|
|
||||||
* The microphone's input will be resampled,
|
|
||||||
* so cores can ask for whichever frequency they need.
|
|
||||||
*
|
|
||||||
* If zero, some reasonable default will be provided by the frontend
|
|
||||||
* (usually from its config file).
|
|
||||||
*
|
|
||||||
* @see retro_get_mic_rate_t
|
|
||||||
*/
|
|
||||||
unsigned rate;
|
|
||||||
} retro_microphone_params_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @copydoc retro_microphone_interface::open_mic
|
|
||||||
*/
|
|
||||||
typedef retro_microphone_t *(RETRO_CALLCONV *retro_open_mic_t)(const retro_microphone_params_t *params);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @copydoc retro_microphone_interface::close_mic
|
|
||||||
*/
|
|
||||||
typedef void (RETRO_CALLCONV *retro_close_mic_t)(retro_microphone_t *microphone);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @copydoc retro_microphone_interface::get_params
|
|
||||||
*/
|
|
||||||
typedef bool (RETRO_CALLCONV *retro_get_mic_params_t)(const retro_microphone_t *microphone, retro_microphone_params_t *params);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @copydoc retro_microphone_interface::set_mic_state
|
|
||||||
*/
|
|
||||||
typedef bool (RETRO_CALLCONV *retro_set_mic_state_t)(retro_microphone_t *microphone, bool state);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @copydoc retro_microphone_interface::get_mic_state
|
|
||||||
*/
|
|
||||||
typedef bool (RETRO_CALLCONV *retro_get_mic_state_t)(const retro_microphone_t *microphone);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @copydoc retro_microphone_interface::read_mic
|
|
||||||
*/
|
|
||||||
typedef int (RETRO_CALLCONV *retro_read_mic_t)(retro_microphone_t *microphone, int16_t* samples, size_t num_samples);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current version of the microphone interface.
|
|
||||||
* Will be incremented whenever \c retro_microphone_interface or \c retro_microphone_params_t
|
|
||||||
* receive new fields.
|
|
||||||
*
|
|
||||||
* Frontends using cores built against older mic interface versions
|
|
||||||
* should not access fields introduced in newer versions.
|
|
||||||
*/
|
|
||||||
#define RETRO_MICROPHONE_INTERFACE_VERSION 1
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface for querying the microphone and accessing data read from it.
|
|
||||||
*
|
|
||||||
* @see RETRO_ENVIRONMENT_GET_MICROPHONE_INTERFACE
|
|
||||||
*/
|
|
||||||
struct retro_microphone_interface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The version of this microphone interface.
|
|
||||||
* Set by the core to request a particular version,
|
|
||||||
* and set by the frontend to indicate the returned version.
|
|
||||||
* 0 indicates that the interface is invalid or uninitialized.
|
|
||||||
*/
|
|
||||||
unsigned interface_version;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a new microphone.
|
|
||||||
* Assuming that microphone support is enabled and provided by the frontend,
|
|
||||||
* cores may call this function whenever necessary.
|
|
||||||
* A microphone could be opened throughout a core's lifetime,
|
|
||||||
* or it could wait until a microphone is plugged in to the emulated device.
|
|
||||||
*
|
|
||||||
* The returned handle will be valid until it's freed,
|
|
||||||
* even if the audio driver is reinitialized.
|
|
||||||
*
|
|
||||||
* This function is not guaranteed to be thread-safe.
|
|
||||||
*
|
|
||||||
* @param args[in] Parameters used to create the microphone.
|
|
||||||
* May be \c NULL, in which case the default value of each parameter will be used.
|
|
||||||
*
|
|
||||||
* @returns Pointer to the newly-opened microphone,
|
|
||||||
* or \c NULL if one couldn't be opened.
|
|
||||||
* This likely means that no microphone is plugged in and recognized,
|
|
||||||
* or the maximum number of supported microphones has been reached.
|
|
||||||
*
|
|
||||||
* @note Microphones are \em inactive by default;
|
|
||||||
* to begin capturing audio, call \c set_mic_state.
|
|
||||||
* @see retro_microphone_params_t
|
|
||||||
*/
|
|
||||||
retro_open_mic_t open_mic;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes a microphone that was initialized with \c open_mic.
|
|
||||||
* Calling this function will stop all microphone activity
|
|
||||||
* and free up the resources that it allocated.
|
|
||||||
* Afterwards, the handle is invalid and must not be used.
|
|
||||||
*
|
|
||||||
* A frontend may close opened microphones when unloading content,
|
|
||||||
* but this behavior is not guaranteed.
|
|
||||||
* Cores should close their microphones when exiting, just to be safe.
|
|
||||||
*
|
|
||||||
* @param microphone Pointer to the microphone that was allocated by \c open_mic.
|
|
||||||
* If \c NULL, this function does nothing.
|
|
||||||
*
|
|
||||||
* @note The handle might be reused if another microphone is opened later.
|
|
||||||
*/
|
|
||||||
retro_close_mic_t close_mic;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the configured parameters of this microphone.
|
|
||||||
* These may differ from what was requested depending on
|
|
||||||
* the driver and device configuration.
|
|
||||||
*
|
|
||||||
* Cores should check these values before they start fetching samples.
|
|
||||||
*
|
|
||||||
* Will not change after the mic was opened.
|
|
||||||
*
|
|
||||||
* @param microphone[in] Opaque handle to the microphone
|
|
||||||
* whose parameters will be retrieved.
|
|
||||||
* @param params[out] The parameters object that the
|
|
||||||
* microphone's parameters will be copied to.
|
|
||||||
*
|
|
||||||
* @return \c true if the parameters were retrieved,
|
|
||||||
* \c false if there was an error.
|
|
||||||
*/
|
|
||||||
retro_get_mic_params_t get_params;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables or disables the given microphone.
|
|
||||||
* Microphones are disabled by default
|
|
||||||
* and must be explicitly enabled before they can be used.
|
|
||||||
* Disabled microphones will not process incoming audio samples,
|
|
||||||
* and will therefore have minimal impact on overall performance.
|
|
||||||
* Cores may enable microphones throughout their lifetime,
|
|
||||||
* or only for periods where they're needed.
|
|
||||||
*
|
|
||||||
* Cores that accept microphone input should be able to operate without it;
|
|
||||||
* we suggest substituting silence in this case.
|
|
||||||
*
|
|
||||||
* @param microphone Opaque handle to the microphone
|
|
||||||
* whose state will be adjusted.
|
|
||||||
* This will have been provided by \c open_mic.
|
|
||||||
* @param state \c true if the microphone should receive audio input,
|
|
||||||
* \c false if it should be idle.
|
|
||||||
* @returns \c true if the microphone's state was successfully set,
|
|
||||||
* \c false if \c microphone is invalid
|
|
||||||
* or if there was an error.
|
|
||||||
*/
|
|
||||||
retro_set_mic_state_t set_mic_state;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Queries the active state of a microphone at the given index.
|
|
||||||
* Will return whether the microphone is enabled,
|
|
||||||
* even if the driver is paused.
|
|
||||||
*
|
|
||||||
* @param microphone Opaque handle to the microphone
|
|
||||||
* whose state will be queried.
|
|
||||||
* @return \c true if the provided \c microphone is valid and active,
|
|
||||||
* \c false if not or if there was an error.
|
|
||||||
*/
|
|
||||||
retro_get_mic_state_t get_mic_state;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the input processed by the microphone since the last call.
|
|
||||||
* \em Must be called every frame unless \c microphone is disabled,
|
|
||||||
* similar to how \c retro_audio_sample_batch_t works.
|
|
||||||
*
|
|
||||||
* @param[in] microphone Opaque handle to the microphone
|
|
||||||
* whose recent input will be retrieved.
|
|
||||||
* @param[out] samples The buffer that will be used to store the microphone's data.
|
|
||||||
* Microphone input is in mono (i.e. one number per sample).
|
|
||||||
* Should be large enough to accommodate the expected number of samples per frame;
|
|
||||||
* for example, a 44.1kHz sample rate at 60 FPS would require space for 735 samples.
|
|
||||||
* @param[in] num_samples The size of the data buffer in samples (\em not bytes).
|
|
||||||
* Microphone input is in mono, so a "frame" and a "sample" are equivalent in length here.
|
|
||||||
*
|
|
||||||
* @return The number of samples that were copied into \c samples.
|
|
||||||
* If \c microphone is pending driver initialization,
|
|
||||||
* this function will copy silence of the requested length into \c samples.
|
|
||||||
*
|
|
||||||
* Will return -1 if the microphone is disabled,
|
|
||||||
* the audio driver is paused,
|
|
||||||
* or there was an error.
|
|
||||||
*/
|
|
||||||
retro_read_mic_t read_mic;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Describes how a device is being powered.
|
|
||||||
* @see RETRO_ENVIRONMENT_GET_DEVICE_POWER
|
|
||||||
*/
|
|
||||||
enum retro_power_state
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Indicates that the frontend cannot report its power state at this time,
|
|
||||||
* most likely due to a lack of support.
|
|
||||||
*
|
|
||||||
* \c RETRO_ENVIRONMENT_GET_DEVICE_POWER will not return this value;
|
|
||||||
* instead, the environment callback will return \c false.
|
|
||||||
*/
|
|
||||||
RETRO_POWERSTATE_UNKNOWN = 0,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that the device is running on its battery.
|
|
||||||
* Usually applies to portable devices such as handhelds, laptops, and smartphones.
|
|
||||||
*/
|
|
||||||
RETRO_POWERSTATE_DISCHARGING,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that the device's battery is currently charging.
|
|
||||||
*/
|
|
||||||
RETRO_POWERSTATE_CHARGING,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that the device is connected to a power source
|
|
||||||
* and that its battery has finished charging.
|
|
||||||
*/
|
|
||||||
RETRO_POWERSTATE_CHARGED,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that the device is connected to a power source
|
|
||||||
* and that it does not have a battery.
|
|
||||||
* This usually suggests a desktop computer or a non-portable game console.
|
|
||||||
*/
|
|
||||||
RETRO_POWERSTATE_PLUGGED_IN
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates that an estimate is not available for the battery level or time remaining,
|
|
||||||
* even if the actual power state is known.
|
|
||||||
*/
|
|
||||||
#define RETRO_POWERSTATE_NO_ESTIMATE (-1)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Describes the power state of the device running the frontend.
|
|
||||||
* @see RETRO_ENVIRONMENT_GET_DEVICE_POWER
|
|
||||||
*/
|
|
||||||
struct retro_device_power
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The current state of the frontend's power usage.
|
|
||||||
*/
|
|
||||||
enum retro_power_state state;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A rough estimate of the amount of time remaining (in seconds)
|
|
||||||
* before the device powers off.
|
|
||||||
* This value depends on a variety of factors,
|
|
||||||
* so it is not guaranteed to be accurate.
|
|
||||||
*
|
|
||||||
* Will be set to \c RETRO_POWERSTATE_NO_ESTIMATE if \c state does not equal \c RETRO_POWERSTATE_DISCHARGING.
|
|
||||||
* May still be set to \c RETRO_POWERSTATE_NO_ESTIMATE if the frontend is unable to provide an estimate.
|
|
||||||
*/
|
|
||||||
int seconds;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The approximate percentage of battery charge,
|
|
||||||
* ranging from 0 to 100 (inclusive).
|
|
||||||
* The device may power off before this reaches 0.
|
|
||||||
*
|
|
||||||
* The user might have configured their device
|
|
||||||
* to stop charging before the battery is full,
|
|
||||||
* so do not assume that this will be 100 in the \c RETRO_POWERSTATE_CHARGED state.
|
|
||||||
*/
|
|
||||||
int8_t percent;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Callbacks */
|
/* Callbacks */
|
||||||
|
|
||||||
/* Environment callback. Gives implementations a way of performing
|
/* Environment callback. Gives implementations a way of performing
|
||||||
|
@ -85,15 +85,6 @@ bool dir_list_initialize(struct string_list *list,
|
|||||||
**/
|
**/
|
||||||
void dir_list_sort(struct string_list *list, bool dir_first);
|
void dir_list_sort(struct string_list *list, bool dir_first);
|
||||||
|
|
||||||
/**
|
|
||||||
* dir_list_sort_ignore_ext:
|
|
||||||
* @list : pointer to the directory listing.
|
|
||||||
* @dir_first : move the directories in the listing to the top?
|
|
||||||
*
|
|
||||||
* Sorts a directory listing. File extensions are ignored.
|
|
||||||
**/
|
|
||||||
void dir_list_sort_ignore_ext(struct string_list *list, bool dir_first);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dir_list_free:
|
* dir_list_free:
|
||||||
* @list : pointer to the directory listing
|
* @list : pointer to the directory listing
|
||||||
|
@ -101,26 +101,6 @@ typedef int ssize_t;
|
|||||||
#define STRING_REP_UINT64 "%" PRIu64
|
#define STRING_REP_UINT64 "%" PRIu64
|
||||||
#define STRING_REP_USIZE "%" PRIuPTR
|
#define STRING_REP_USIZE "%" PRIuPTR
|
||||||
|
|
||||||
/* Wrap a declaration in RETRO_DEPRECATED() to produce a compiler warning when
|
|
||||||
it's used. This is intended for developer machines, so it won't work on ancient
|
|
||||||
or obscure compilers */
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#if _MSC_VER >= 1400 /* Visual C 2005 or later */
|
|
||||||
#define RETRO_DEPRECATED(decl) __declspec(deprecated) decl
|
|
||||||
#endif
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
#if __GNUC__ >= 3 /* GCC 3 or later */
|
|
||||||
#define RETRO_DEPRECATED(decl) decl __attribute__((deprecated))
|
|
||||||
#endif
|
|
||||||
#elif defined(__clang__)
|
|
||||||
#if __clang_major__ >= 3 /* clang 3 or later */
|
|
||||||
#define RETRO_DEPRECATED(decl) decl __attribute__((deprecated))
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifndef RETRO_DEPRECATED /* Unsupported compilers */
|
|
||||||
#define RETRO_DEPRECATED(decl) decl
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
I would like to see retro_inline.h moved in here; possibly boolean too.
|
I would like to see retro_inline.h moved in here; possibly boolean too.
|
||||||
|
|
||||||
|
@ -49,10 +49,6 @@
|
|||||||
#include <compat/msvc.h>
|
#include <compat/msvc.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IOS
|
|
||||||
#include <sys/param.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static INLINE void bits_or_bits(uint32_t *a, uint32_t *b, uint32_t count)
|
static INLINE void bits_or_bits(uint32_t *a, uint32_t *b, uint32_t count)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
@ -39,8 +39,6 @@
|
|||||||
#include <psp2/kernel/threadmgr.h>
|
#include <psp2/kernel/threadmgr.h>
|
||||||
#elif defined(_3DS)
|
#elif defined(_3DS)
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
#elif defined(EMSCRIPTEN)
|
|
||||||
#include <emscripten/emscripten.h>
|
|
||||||
#else
|
#else
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#endif
|
#endif
|
||||||
@ -101,8 +99,6 @@ static int nanosleepDOS(const struct timespec *rqtp, struct timespec *rmtp)
|
|||||||
#define retro_sleep(msec) (usleep(1000 * (msec)))
|
#define retro_sleep(msec) (usleep(1000 * (msec)))
|
||||||
#elif defined(WIIU)
|
#elif defined(WIIU)
|
||||||
#define retro_sleep(msec) (OSSleepTicks(ms_to_ticks((msec))))
|
#define retro_sleep(msec) (OSSleepTicks(ms_to_ticks((msec))))
|
||||||
#elif defined(EMSCRIPTEN)
|
|
||||||
#define retro_sleep(msec) (emscripten_sleep(msec))
|
|
||||||
#else
|
#else
|
||||||
static INLINE void retro_sleep(unsigned msec)
|
static INLINE void retro_sleep(unsigned msec)
|
||||||
{
|
{
|
||||||
|
@ -204,7 +204,7 @@ char *string_trim_whitespace(char *const s);
|
|||||||
* correctly any text containing so-called 'wide' Unicode
|
* correctly any text containing so-called 'wide' Unicode
|
||||||
* characters (e.g. CJK languages, emojis, etc.).
|
* characters (e.g. CJK languages, emojis, etc.).
|
||||||
**/
|
**/
|
||||||
size_t word_wrap(char *dst, size_t dst_size, const char *src, size_t src_len,
|
void word_wrap(char *dst, size_t dst_size, const char *src, size_t src_len,
|
||||||
int line_width, int wideglyph_width, unsigned max_lines);
|
int line_width, int wideglyph_width, unsigned max_lines);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -241,7 +241,7 @@ size_t word_wrap(char *dst, size_t dst_size, const char *src, size_t src_len,
|
|||||||
* on-screen pixel width deviates greatly from the set
|
* on-screen pixel width deviates greatly from the set
|
||||||
* @wideglyph_width value.
|
* @wideglyph_width value.
|
||||||
**/
|
**/
|
||||||
size_t word_wrap_wideglyph(
|
void word_wrap_wideglyph(
|
||||||
char *dst, size_t dst_size,
|
char *dst, size_t dst_size,
|
||||||
const char *src, size_t src_len,
|
const char *src, size_t src_len,
|
||||||
int line_width, int wideglyph_width,
|
int line_width, int wideglyph_width,
|
||||||
|
@ -46,22 +46,6 @@ static int qstrcmp_plain(const void *a_, const void *b_)
|
|||||||
return strcasecmp(a->data, b->data);
|
return strcasecmp(a->data, b->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qstrcmp_plain_noext(const void *a_, const void *b_)
|
|
||||||
{
|
|
||||||
const struct string_list_elem *a = (const struct string_list_elem*)a_;
|
|
||||||
const struct string_list_elem *b = (const struct string_list_elem*)b_;
|
|
||||||
|
|
||||||
const char *ext_a = path_get_extension(a->data);
|
|
||||||
size_t l_a = string_is_empty(ext_a) ? strlen(a->data) : (ext_a - a->data - 1);
|
|
||||||
const char *ext_b = path_get_extension(b->data);
|
|
||||||
size_t l_b = string_is_empty(ext_b) ? strlen(b->data) : (ext_b - b->data - 1);
|
|
||||||
|
|
||||||
int rv = strncasecmp(a->data, b->data, MIN(l_a, l_b));
|
|
||||||
if (rv == 0 && l_a != l_b)
|
|
||||||
return (int)(l_a - l_b);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int qstrcmp_dir(const void *a_, const void *b_)
|
static int qstrcmp_dir(const void *a_, const void *b_)
|
||||||
{
|
{
|
||||||
const struct string_list_elem *a = (const struct string_list_elem*)a_;
|
const struct string_list_elem *a = (const struct string_list_elem*)a_;
|
||||||
@ -75,19 +59,6 @@ static int qstrcmp_dir(const void *a_, const void *b_)
|
|||||||
return strcasecmp(a->data, b->data);
|
return strcasecmp(a->data, b->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qstrcmp_dir_noext(const void *a_, const void *b_)
|
|
||||||
{
|
|
||||||
const struct string_list_elem *a = (const struct string_list_elem*)a_;
|
|
||||||
const struct string_list_elem *b = (const struct string_list_elem*)b_;
|
|
||||||
int a_type = a->attr.i;
|
|
||||||
int b_type = b->attr.i;
|
|
||||||
|
|
||||||
/* Sort directories before files. */
|
|
||||||
if (a_type != b_type)
|
|
||||||
return b_type - a_type;
|
|
||||||
return qstrcmp_plain_noext(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dir_list_sort:
|
* dir_list_sort:
|
||||||
* @list : pointer to the directory listing.
|
* @list : pointer to the directory listing.
|
||||||
@ -102,20 +73,6 @@ void dir_list_sort(struct string_list *list, bool dir_first)
|
|||||||
dir_first ? qstrcmp_dir : qstrcmp_plain);
|
dir_first ? qstrcmp_dir : qstrcmp_plain);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* dir_list_sort_ignore_ext:
|
|
||||||
* @list : pointer to the directory listing.
|
|
||||||
* @dir_first : move the directories in the listing to the top?
|
|
||||||
*
|
|
||||||
* Sorts a directory listing. File extensions are ignored.
|
|
||||||
**/
|
|
||||||
void dir_list_sort_ignore_ext(struct string_list *list, bool dir_first)
|
|
||||||
{
|
|
||||||
if (list)
|
|
||||||
qsort(list->elems, list->size, sizeof(struct string_list_elem),
|
|
||||||
dir_first ? qstrcmp_dir_noext : qstrcmp_plain_noext);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dir_list_free:
|
* dir_list_free:
|
||||||
* @list : pointer to the directory listing
|
* @list : pointer to the directory listing
|
||||||
@ -184,11 +141,6 @@ static int dir_list_read(const char *dir,
|
|||||||
|
|
||||||
if (retro_dirent_is_dir(entry, NULL))
|
if (retro_dirent_is_dir(entry, NULL))
|
||||||
{
|
{
|
||||||
/* Exclude this frequent hidden dir on platforms which can not handle hidden attribute */
|
|
||||||
#ifndef _WIN32
|
|
||||||
if (!include_hidden && strcmp(name, "System Volume Information") == 0)
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
if (recursive)
|
if (recursive)
|
||||||
dir_list_read(file_path, list, ext_list, include_dirs,
|
dir_list_read(file_path, list, ext_list, include_dirs,
|
||||||
include_hidden, include_compressed, recursive);
|
include_hidden, include_compressed, recursive);
|
||||||
|
@ -475,28 +475,29 @@ int string_list_find_elem(const struct string_list *list, const char *elem)
|
|||||||
*/
|
*/
|
||||||
bool string_list_find_elem_prefix(const struct string_list *list,
|
bool string_list_find_elem_prefix(const struct string_list *list,
|
||||||
const char *prefix, const char *elem)
|
const char *prefix, const char *elem)
|
||||||
{
|
|
||||||
if (list)
|
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
char prefixed[255];
|
char prefixed[255];
|
||||||
size_t _len = strlcpy(prefixed, prefix, sizeof(prefixed));
|
if (!list)
|
||||||
strlcpy(prefixed + _len, elem, sizeof(prefixed) - _len);
|
return false;
|
||||||
|
strlcpy(prefixed, prefix, sizeof(prefixed));
|
||||||
|
strlcat(prefixed, elem, sizeof(prefixed));
|
||||||
for (i = 0; i < list->size; i++)
|
for (i = 0; i < list->size; i++)
|
||||||
{
|
{
|
||||||
if ( string_is_equal_noncase(list->elems[i].data, elem)
|
if ( string_is_equal_noncase(list->elems[i].data, elem)
|
||||||
|| string_is_equal_noncase(list->elems[i].data, prefixed))
|
|| string_is_equal_noncase(list->elems[i].data, prefixed))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string_list *string_list_clone(const struct string_list *src)
|
struct string_list *string_list_clone(const struct string_list *src)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
struct string_list_elem *elems = NULL;
|
struct string_list_elem
|
||||||
struct string_list *dest = (struct string_list*)
|
*elems = NULL;
|
||||||
|
struct string_list
|
||||||
|
*dest = (struct string_list*)
|
||||||
malloc(sizeof(struct string_list));
|
malloc(sizeof(struct string_list));
|
||||||
|
|
||||||
if (!dest)
|
if (!dest)
|
||||||
|
@ -203,12 +203,14 @@ sthread_t *sthread_create_with_priority(void (*thread_func)(void*), void *userda
|
|||||||
data->func = thread_func;
|
data->func = thread_func;
|
||||||
data->userdata = userdata;
|
data->userdata = userdata;
|
||||||
|
|
||||||
thread->id = 0;
|
|
||||||
#ifdef USE_WIN32_THREADS
|
#ifdef USE_WIN32_THREADS
|
||||||
|
thread->id = 0;
|
||||||
thread->thread = CreateThread(NULL, 0, thread_wrap,
|
thread->thread = CreateThread(NULL, 0, thread_wrap,
|
||||||
data, 0, &thread->id);
|
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);
|
||||||
|
|
||||||
@ -222,27 +224,23 @@ sthread_t *sthread_create_with_priority(void (*thread_func)(void*), void *userda
|
|||||||
|
|
||||||
thread_attr_needed = true;
|
thread_attr_needed = true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(VITA)
|
#if defined(VITA)
|
||||||
pthread_attr_setstacksize(&thread_attr , 0x10000 );
|
pthread_attr_setstacksize(&thread_attr , 0x10000 );
|
||||||
thread_attr_needed = true;
|
thread_attr_needed = true;
|
||||||
#elif defined(__APPLE__)
|
|
||||||
/* Default stack size on Apple is 512Kb;
|
|
||||||
* for PS2 disc scanning and other reasons, we'd like 2MB. */
|
|
||||||
pthread_attr_setstacksize(&thread_attr , 0x200000 );
|
|
||||||
thread_attr_needed = true;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_THREAD_ATTR
|
||||||
if (thread_attr_needed)
|
if (thread_attr_needed)
|
||||||
thread_created = pthread_create(&thread->id, &thread_attr, thread_wrap, data) == 0;
|
thread_created = pthread_create(&thread->id, &thread_attr, thread_wrap, data) == 0;
|
||||||
else
|
else
|
||||||
thread_created = pthread_create(&thread->id, NULL, thread_wrap, data) == 0;
|
|
||||||
|
|
||||||
pthread_attr_destroy(&thread_attr);
|
|
||||||
#else
|
|
||||||
thread_created = pthread_create(&thread->id, NULL, thread_wrap, data) == 0;
|
|
||||||
#endif
|
#endif
|
||||||
|
thread_created = pthread_create(&thread->id, NULL, thread_wrap, data) == 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_THREAD_ATTR
|
||||||
|
pthread_attr_destroy(&thread_attr);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (thread_created)
|
if (thread_created)
|
||||||
|
@ -217,24 +217,27 @@ char *string_trim_whitespace(char *const s)
|
|||||||
* correctly any text containing so-called 'wide' Unicode
|
* correctly any text containing so-called 'wide' Unicode
|
||||||
* characters (e.g. CJK languages, emojis, etc.).
|
* characters (e.g. CJK languages, emojis, etc.).
|
||||||
**/
|
**/
|
||||||
size_t word_wrap(
|
void word_wrap(
|
||||||
char *dst, size_t dst_size,
|
char *dst, size_t dst_size,
|
||||||
const char *src, size_t src_len,
|
const char *src, size_t src_len,
|
||||||
int line_width, int wideglyph_width, unsigned max_lines)
|
int line_width, int wideglyph_width, unsigned max_lines)
|
||||||
{
|
{
|
||||||
char *last_space = NULL;
|
char *lastspace = NULL;
|
||||||
unsigned counter = 0;
|
unsigned counter = 0;
|
||||||
unsigned lines = 1;
|
unsigned lines = 1;
|
||||||
const char *src_end = src + src_len;
|
const char *src_end = src + src_len;
|
||||||
|
|
||||||
/* Prevent buffer overflow */
|
/* Prevent buffer overflow */
|
||||||
if (dst_size < src_len + 1)
|
if (dst_size < src_len + 1)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
/* Early return if src string length is less
|
/* Early return if src string length is less
|
||||||
* than line width */
|
* than line width */
|
||||||
if (src_len < (size_t)line_width)
|
if (src_len < (size_t)line_width)
|
||||||
return strlcpy(dst, src, dst_size);
|
{
|
||||||
|
strlcpy(dst, src, dst_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (*src != '\0')
|
while (*src != '\0')
|
||||||
{
|
{
|
||||||
@ -242,7 +245,7 @@ size_t word_wrap(
|
|||||||
counter++;
|
counter++;
|
||||||
|
|
||||||
if (*src == ' ')
|
if (*src == ' ')
|
||||||
last_space = dst; /* Remember the location of the whitespace */
|
lastspace = dst; /* Remember the location of the whitespace */
|
||||||
else if (*src == '\n')
|
else if (*src == '\n')
|
||||||
{
|
{
|
||||||
/* If newlines embedded in the input,
|
/* If newlines embedded in the input,
|
||||||
@ -253,7 +256,10 @@ size_t word_wrap(
|
|||||||
/* Early return if remaining src string
|
/* Early return if remaining src string
|
||||||
* length is less than line width */
|
* length is less than line width */
|
||||||
if (src_end - src <= line_width)
|
if (src_end - src <= line_width)
|
||||||
return strlcpy(dst, src, dst_size);
|
{
|
||||||
|
strlcpy(dst, src, dst_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (char_len--)
|
while (char_len--)
|
||||||
@ -263,27 +269,29 @@ size_t word_wrap(
|
|||||||
{
|
{
|
||||||
counter = 0;
|
counter = 0;
|
||||||
|
|
||||||
if (last_space && (max_lines == 0 || lines < max_lines))
|
if (lastspace && (max_lines == 0 || lines < max_lines))
|
||||||
{
|
{
|
||||||
/* Replace nearest (previous) whitespace
|
/* Replace nearest (previous) whitespace
|
||||||
* with newline character */
|
* with newline character */
|
||||||
*last_space = '\n';
|
*lastspace = '\n';
|
||||||
lines++;
|
lines++;
|
||||||
|
|
||||||
src -= dst - last_space - 1;
|
src -= dst - lastspace - 1;
|
||||||
dst = last_space + 1;
|
dst = lastspace + 1;
|
||||||
last_space = NULL;
|
lastspace = NULL;
|
||||||
|
|
||||||
/* Early return if remaining src string
|
/* Early return if remaining src string
|
||||||
* length is less than line width */
|
* length is less than line width */
|
||||||
if (src_end - src < line_width)
|
if (src_end - src < line_width)
|
||||||
return strlcpy(dst, src, dst_size);
|
{
|
||||||
|
strlcpy(dst, src, dst_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*dst = '\0';
|
*dst = '\0';
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -319,7 +327,7 @@ size_t word_wrap(
|
|||||||
* on-screen pixel width deviates greatly from the set
|
* on-screen pixel width deviates greatly from the set
|
||||||
* @wideglyph_width value.
|
* @wideglyph_width value.
|
||||||
**/
|
**/
|
||||||
size_t word_wrap_wideglyph(char *dst, size_t dst_size,
|
void word_wrap_wideglyph(char *dst, size_t dst_size,
|
||||||
const char *src, size_t src_len, int line_width,
|
const char *src, size_t src_len, int line_width,
|
||||||
int wideglyph_width, unsigned max_lines)
|
int wideglyph_width, unsigned max_lines)
|
||||||
{
|
{
|
||||||
@ -355,7 +363,10 @@ size_t word_wrap_wideglyph(char *dst, size_t dst_size,
|
|||||||
/* Early return if src string length is less
|
/* Early return if src string length is less
|
||||||
* than line width */
|
* than line width */
|
||||||
if (src_end - src < line_width)
|
if (src_end - src < line_width)
|
||||||
return strlcpy(dst, src, dst_size);
|
{
|
||||||
|
strlcpy(dst, src, dst_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (*src != '\0')
|
while (*src != '\0')
|
||||||
{
|
{
|
||||||
@ -378,7 +389,10 @@ size_t word_wrap_wideglyph(char *dst, size_t dst_size,
|
|||||||
/* Early return if remaining src string
|
/* Early return if remaining src string
|
||||||
* length is less than line width */
|
* length is less than line width */
|
||||||
if (src_end - src <= line_width)
|
if (src_end - src <= line_width)
|
||||||
return strlcpy(dst, src, dst_size);
|
{
|
||||||
|
strlcpy(dst, src, dst_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (char_len >= 3)
|
else if (char_len >= 3)
|
||||||
{
|
{
|
||||||
@ -410,7 +424,10 @@ size_t word_wrap_wideglyph(char *dst, size_t dst_size,
|
|||||||
/* Early return if remaining src string
|
/* Early return if remaining src string
|
||||||
* length is less than line width */
|
* length is less than line width */
|
||||||
if (src_end - src <= line_width)
|
if (src_end - src <= line_width)
|
||||||
return strlcpy(dst, src, dst_size);
|
{
|
||||||
|
strlcpy(dst, src, dst_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (lastspace)
|
else if (lastspace)
|
||||||
{
|
{
|
||||||
@ -425,13 +442,15 @@ size_t word_wrap_wideglyph(char *dst, size_t dst_size,
|
|||||||
/* Early return if remaining src string
|
/* Early return if remaining src string
|
||||||
* length is less than line width */
|
* length is less than line width */
|
||||||
if (src_end - src < line_width)
|
if (src_end - src < line_width)
|
||||||
return strlcpy(dst, src, dst_size);
|
{
|
||||||
|
strlcpy(dst, src, dst_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*dst = '\0';
|
*dst = '\0';
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -700,7 +700,7 @@ int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file *stream,
|
|||||||
int64_t retro_vfs_file_write_impl(libretro_vfs_implementation_file *stream, const void *s, uint64_t len)
|
int64_t retro_vfs_file_write_impl(libretro_vfs_implementation_file *stream, const void *s, uint64_t len)
|
||||||
{
|
{
|
||||||
int64_t pos = 0;
|
int64_t pos = 0;
|
||||||
ssize_t result = -1;
|
size_t result = -1;
|
||||||
|
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return -1;
|
return -1;
|
||||||
@ -738,40 +738,39 @@ int retro_vfs_file_flush_impl(libretro_vfs_implementation_file *stream)
|
|||||||
|
|
||||||
int retro_vfs_file_remove_impl(const char *path)
|
int retro_vfs_file_remove_impl(const char *path)
|
||||||
{
|
{
|
||||||
if (path && *path)
|
|
||||||
{
|
|
||||||
int ret = -1;
|
|
||||||
#if defined(_WIN32) && !defined(_XBOX)
|
#if defined(_WIN32) && !defined(_XBOX)
|
||||||
/* Win32 (no Xbox) */
|
/* Win32 (no Xbox) */
|
||||||
|
|
||||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500
|
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500
|
||||||
char *path_local = NULL;
|
char *path_local = NULL;
|
||||||
if ((path_local = utf8_to_local_string_alloc(path)))
|
|
||||||
{
|
|
||||||
/* We need to check if path is a directory */
|
|
||||||
if ((retro_vfs_stat_impl(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0)
|
|
||||||
ret = _rmdir(path_local);
|
|
||||||
else
|
|
||||||
ret = remove(path_local);
|
|
||||||
free(path_local);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
wchar_t *path_wide = NULL;
|
wchar_t *path_wide = NULL;
|
||||||
if ((path_wide = utf8_to_utf16_string_alloc(path)))
|
#endif
|
||||||
|
if (!path || !*path)
|
||||||
|
return -1;
|
||||||
|
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500
|
||||||
|
if ((path_local = utf8_to_local_string_alloc(path)))
|
||||||
{
|
{
|
||||||
/* We need to check if path is a directory */
|
int ret = remove(path_local);
|
||||||
if ((retro_vfs_stat_impl(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0)
|
free(path_local);
|
||||||
ret = _wrmdir(path_wide);
|
|
||||||
else
|
|
||||||
ret = _wremove(path_wide);
|
|
||||||
free(path_wide);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
ret = remove(path);
|
|
||||||
#endif
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if ((path_wide = utf8_to_utf16_string_alloc(path)))
|
||||||
|
{
|
||||||
|
int ret = _wremove(path_wide);
|
||||||
|
free(path_wide);
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
if (remove(path) == 0)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -843,78 +842,96 @@ 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)
|
||||||
{
|
{
|
||||||
int ret = RETRO_VFS_STAT_IS_VALID;
|
bool is_dir = false;
|
||||||
|
bool is_character_special = false;
|
||||||
|
#if defined(VITA)
|
||||||
|
/* Vita / PSP */
|
||||||
|
SceIoStat buf;
|
||||||
|
int dir_ret;
|
||||||
|
char *tmp = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
if (!path || !*path)
|
if (!path || !*path)
|
||||||
return 0;
|
return 0;
|
||||||
{
|
|
||||||
#if defined(VITA)
|
tmp = strdup(path);
|
||||||
/* Vita / PSP */
|
len = strlen(tmp);
|
||||||
SceIoStat stat_buf;
|
|
||||||
int dir_ret;
|
|
||||||
char *tmp = strdup(path);
|
|
||||||
size_t len = strlen(tmp);
|
|
||||||
if (tmp[len-1] == '/')
|
if (tmp[len-1] == '/')
|
||||||
tmp[len-1] = '\0';
|
tmp[len-1] = '\0';
|
||||||
|
|
||||||
dir_ret = sceIoGetstat(tmp, &stat_buf);
|
dir_ret = sceIoGetstat(tmp, &buf);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
if (dir_ret < 0)
|
if (dir_ret < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (size)
|
if (size)
|
||||||
*size = (int32_t)stat_buf.st_size;
|
*size = (int32_t)buf.st_size;
|
||||||
|
|
||||||
if (FIO_S_ISDIR(stat_buf.st_mode))
|
is_dir = FIO_S_ISDIR(buf.st_mode);
|
||||||
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
|
|
||||||
#elif defined(__PSL1GHT__) || defined(__PS3__)
|
#elif defined(__PSL1GHT__) || defined(__PS3__)
|
||||||
/* Lowlevel Lv2 */
|
/* Lowlevel Lv2 */
|
||||||
sysFSStat stat_buf;
|
sysFSStat buf;
|
||||||
|
|
||||||
if (sysFsStat(path, &stat_buf) < 0)
|
if (!path || !*path)
|
||||||
|
return 0;
|
||||||
|
if (sysFsStat(path, &buf) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (size)
|
if (size)
|
||||||
*size = (int32_t)stat_buf.st_size;
|
*size = (int32_t)buf.st_size;
|
||||||
|
|
||||||
if ((stat_buf.st_mode & S_IFMT) == S_IFDIR)
|
is_dir = ((buf.st_mode & S_IFMT) == S_IFDIR);
|
||||||
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
|
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
/* Windows */
|
/* Windows */
|
||||||
struct _stat stat_buf;
|
DWORD file_info;
|
||||||
|
struct _stat buf;
|
||||||
#if defined(LEGACY_WIN32)
|
#if defined(LEGACY_WIN32)
|
||||||
char *path_local = utf8_to_local_string_alloc(path);
|
char *path_local = NULL;
|
||||||
DWORD file_info = GetFileAttributes(path_local);
|
#else
|
||||||
|
wchar_t *path_wide = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!path || !*path)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#if defined(LEGACY_WIN32)
|
||||||
|
path_local = utf8_to_local_string_alloc(path);
|
||||||
|
file_info = GetFileAttributes(path_local);
|
||||||
|
|
||||||
if (!string_is_empty(path_local))
|
if (!string_is_empty(path_local))
|
||||||
_stat(path_local, &stat_buf);
|
_stat(path_local, &buf);
|
||||||
|
|
||||||
if (path_local)
|
if (path_local)
|
||||||
free(path_local);
|
free(path_local);
|
||||||
#else
|
#else
|
||||||
wchar_t *path_wide = utf8_to_utf16_string_alloc(path);
|
path_wide = utf8_to_utf16_string_alloc(path);
|
||||||
DWORD file_info = GetFileAttributesW(path_wide);
|
file_info = GetFileAttributesW(path_wide);
|
||||||
|
|
||||||
_wstat(path_wide, &stat_buf);
|
_wstat(path_wide, &buf);
|
||||||
|
|
||||||
if (path_wide)
|
if (path_wide)
|
||||||
free(path_wide);
|
free(path_wide);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (file_info == INVALID_FILE_ATTRIBUTES)
|
if (file_info == INVALID_FILE_ATTRIBUTES)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (size)
|
if (size)
|
||||||
*size = (int32_t)stat_buf.st_size;
|
*size = (int32_t)buf.st_size;
|
||||||
|
|
||||||
|
is_dir = (file_info & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
|
||||||
if (file_info & FILE_ATTRIBUTE_DIRECTORY)
|
|
||||||
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
|
|
||||||
#elif defined(GEKKO)
|
#elif defined(GEKKO)
|
||||||
/* On GEKKO platforms, paths cannot have
|
/* On GEKKO platforms, paths cannot have
|
||||||
* trailing slashes - we must therefore
|
* trailing slashes - we must therefore
|
||||||
* remove them */
|
* remove them */
|
||||||
size_t len;
|
|
||||||
char *path_buf = NULL;
|
char *path_buf = NULL;
|
||||||
|
int stat_ret = -1;
|
||||||
struct stat stat_buf;
|
struct stat stat_buf;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (string_is_empty(path))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!(path_buf = strdup(path)))
|
if (!(path_buf = strdup(path)))
|
||||||
return 0;
|
return 0;
|
||||||
@ -923,38 +940,34 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
|
|||||||
if (path_buf[len - 1] == '/')
|
if (path_buf[len - 1] == '/')
|
||||||
path_buf[len - 1] = '\0';
|
path_buf[len - 1] = '\0';
|
||||||
|
|
||||||
if (stat(path_buf, &stat_buf) < 0)
|
stat_ret = stat(path_buf, &stat_buf);
|
||||||
{
|
|
||||||
free(path_buf);
|
free(path_buf);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(path_buf);
|
if (stat_ret < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (size)
|
if (size)
|
||||||
*size = (int32_t)stat_buf.st_size;
|
*size = (int32_t)stat_buf.st_size;
|
||||||
|
|
||||||
if (S_ISDIR(stat_buf.st_mode))
|
is_dir = S_ISDIR(stat_buf.st_mode);
|
||||||
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
|
is_character_special = S_ISCHR(stat_buf.st_mode);
|
||||||
if (S_ISCHR(stat_buf.st_mode))
|
|
||||||
ret |= RETRO_VFS_STAT_IS_CHARACTER_SPECIAL;
|
|
||||||
#else
|
#else
|
||||||
/* Every other platform */
|
/* Every other platform */
|
||||||
struct stat stat_buf;
|
struct stat buf;
|
||||||
|
|
||||||
if (stat(path, &stat_buf) < 0)
|
if (!path || !*path)
|
||||||
|
return 0;
|
||||||
|
if (stat(path, &buf) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (size)
|
if (size)
|
||||||
*size = (int32_t)stat_buf.st_size;
|
*size = (int32_t)buf.st_size;
|
||||||
|
|
||||||
if (S_ISDIR(stat_buf.st_mode))
|
is_dir = S_ISDIR(buf.st_mode);
|
||||||
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
|
is_character_special = S_ISCHR(buf.st_mode);
|
||||||
if (S_ISCHR(stat_buf.st_mode))
|
|
||||||
ret |= RETRO_VFS_STAT_IS_CHARACTER_SPECIAL;
|
|
||||||
#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);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(VITA)
|
#if defined(VITA)
|
||||||
|
Loading…
Reference in New Issue
Block a user