mirror of
https://github.com/libretro/beetle-pce-fast-libretro.git
synced 2024-11-27 01:50:21 +00:00
Merge pull request #143 from negativeExponent/libretro_updates
libretro-common and general input-related updates
This commit is contained in:
commit
9142408648
@ -931,23 +931,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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
|
||||
printf("[CDROM] First Track Number: %d ", pmin);
|
||||
printf("[CDROM] Disc Type: %d ", psec);
|
||||
printf("First Track Number: %d ", pmin);
|
||||
printf("Disc Type: %d ", psec);
|
||||
}
|
||||
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] Last Track Number: %d ", pmin);
|
||||
printf("Last Track Number: %d ", pmin);
|
||||
}
|
||||
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] 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");
|
||||
@ -1494,9 +1494,7 @@ bool cdrom_is_media_inserted(libretro_vfs_implementation_file *stream)
|
||||
bool cdrom_drive_has_media(const char drive)
|
||||
{
|
||||
RFILE *file;
|
||||
char cdrom_path_bin[256];
|
||||
|
||||
cdrom_path_bin[0] = '\0';
|
||||
char cdrom_path_bin[256] = {0};
|
||||
|
||||
cdrom_device_fillpath(cdrom_path_bin, sizeof(cdrom_path_bin), drive, 1, false);
|
||||
|
||||
@ -1690,8 +1688,11 @@ void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char tra
|
||||
#ifdef __linux__
|
||||
pos = strlcpy(path, "cdrom://drive", len);
|
||||
|
||||
if (len > pos)
|
||||
if (len > pos + 1)
|
||||
{
|
||||
path[pos++] = drive;
|
||||
path[pos] = '\0';
|
||||
}
|
||||
|
||||
pos = strlcat(path, ".cue", len);
|
||||
#endif
|
||||
@ -1702,8 +1703,11 @@ void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char tra
|
||||
#ifdef _WIN32
|
||||
pos = strlcpy(path, "cdrom://", len);
|
||||
|
||||
if (len > pos)
|
||||
if (len > pos + 1)
|
||||
{
|
||||
path[pos++] = drive;
|
||||
path[pos] = '\0';
|
||||
}
|
||||
|
||||
pos += snprintf(path + pos, len - pos, ":/drive-track%02d.bin", track);
|
||||
#else
|
||||
|
@ -114,16 +114,16 @@
|
||||
|
||||
#endif
|
||||
|
||||
static retro_vfs_stat_t path_stat_cb = NULL;
|
||||
static retro_vfs_mkdir_t path_mkdir_cb = NULL;
|
||||
static retro_vfs_stat_t path_stat_cb = retro_vfs_stat_impl;
|
||||
static retro_vfs_mkdir_t path_mkdir_cb = retro_vfs_mkdir_impl;
|
||||
|
||||
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;
|
||||
path_stat_cb = retro_vfs_stat_impl;
|
||||
path_mkdir_cb = retro_vfs_mkdir_impl;
|
||||
|
||||
if (vfs_info->required_interface_version < PATH_REQUIRED_VFS_VERSION || !vfs_iface)
|
||||
return;
|
||||
@ -132,13 +132,9 @@ void path_vfs_init(const struct retro_vfs_interface_info* vfs_info)
|
||||
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);
|
||||
return path_stat_cb(path, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -151,23 +147,23 @@ int path_stat(const char *path)
|
||||
*/
|
||||
bool path_is_directory(const char *path)
|
||||
{
|
||||
return (path_stat_internal(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
|
||||
return (path_stat_cb(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;
|
||||
return (path_stat_cb(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;
|
||||
return (path_stat_cb(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)
|
||||
if (path_stat_cb(path, &filesize) != 0)
|
||||
return filesize;
|
||||
|
||||
return -1;
|
||||
@ -233,7 +229,7 @@ bool path_mkdir(const char *dir)
|
||||
|
||||
if (norecurse)
|
||||
{
|
||||
int ret = path_mkdir_norecurse(dir);
|
||||
int ret = path_mkdir_cb(dir);
|
||||
|
||||
/* Don't treat this as an error. */
|
||||
if (ret == -2 && path_is_directory(dir))
|
||||
@ -393,11 +389,11 @@ void fill_pathname(char *out_path, const char *in_path,
|
||||
* 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)
|
||||
{
|
||||
strlcpy(out_path, in_path, size);
|
||||
strlcat(out_path, replace, size);
|
||||
return strlcat(out_path, replace, size);
|
||||
}
|
||||
|
||||
char *find_last_slash(const char *str)
|
||||
@ -435,12 +431,8 @@ void fill_pathname_slash(char *path, size_t size)
|
||||
/* Try to preserve slash type. */
|
||||
if (last_slash != (path + path_len - 1))
|
||||
{
|
||||
char join_str[2];
|
||||
|
||||
join_str[0] = '\0';
|
||||
|
||||
strlcpy(join_str, last_slash, sizeof(join_str));
|
||||
strlcat(path, join_str, size);
|
||||
path[path_len] = last_slash[0];
|
||||
path[path_len+1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,7 +453,7 @@ void fill_pathname_slash(char *path, size_t size)
|
||||
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
|
||||
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
|
||||
**/
|
||||
void fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
size_t fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
const char *replace, size_t size)
|
||||
{
|
||||
const char *base = NULL;
|
||||
@ -469,7 +461,7 @@ void fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
fill_pathname_slash(in_dir, size);
|
||||
base = path_basename(in_basename);
|
||||
strlcat(in_dir, base, size);
|
||||
strlcat(in_dir, replace, size);
|
||||
return strlcat(in_dir, replace, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -480,14 +472,14 @@ void fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
*
|
||||
* 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);
|
||||
|
||||
if (!ptr)
|
||||
ptr = in_path;
|
||||
|
||||
strlcpy(out, ptr, size);
|
||||
return strlcpy(out, ptr, size);
|
||||
}
|
||||
|
||||
void fill_pathname_base_noext(char *out,
|
||||
@ -497,12 +489,12 @@ void fill_pathname_base_noext(char *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,
|
||||
size_t size)
|
||||
{
|
||||
fill_pathname_base_noext(out, in_path, size);
|
||||
strlcat(out, ext, size);
|
||||
return strlcat(out, ext, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -597,7 +589,7 @@ void fill_pathname_parent_dir(char *out_dir,
|
||||
* E.g.:
|
||||
* 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)
|
||||
{
|
||||
time_t cur_time = time(NULL);
|
||||
@ -605,7 +597,7 @@ void fill_dated_filename(char *out_filename,
|
||||
|
||||
strftime(out_filename, size,
|
||||
"RetroArch-%m%d-%H%M%S", tm_);
|
||||
strlcat(out_filename, ext, size);
|
||||
return strlcat(out_filename, ext, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -655,6 +647,7 @@ void fill_str_dated_filename(char *out_filename,
|
||||
void path_basedir(char *path)
|
||||
{
|
||||
char *last = NULL;
|
||||
|
||||
if (strlen(path) < 2)
|
||||
return;
|
||||
|
||||
@ -858,13 +851,9 @@ char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks)
|
||||
t++;
|
||||
}
|
||||
else if (next - p == 1 && p[0] == '.')
|
||||
{
|
||||
p += 2;
|
||||
}
|
||||
else if (next - p == 0)
|
||||
{
|
||||
p += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fail when truncating */
|
||||
@ -901,7 +890,7 @@ end:
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
size_t i;
|
||||
@ -912,10 +901,7 @@ void path_relative_to(char *out,
|
||||
if (strlen(path) >= 2 && strlen(base) >= 2
|
||||
&& path[1] == ':' && base[1] == ':'
|
||||
&& path[0] != base[0])
|
||||
{
|
||||
strlcpy(out, path, size);
|
||||
return;
|
||||
}
|
||||
return strlcpy(out, path, size);
|
||||
#endif
|
||||
|
||||
/* Trim common beginning */
|
||||
@ -929,7 +915,8 @@ void path_relative_to(char *out,
|
||||
for (i = 0; trimmed_base[i]; i++)
|
||||
if (trimmed_base[i] == path_default_slash_c())
|
||||
strlcat(out, ".." path_default_slash(), size);
|
||||
strlcat(out, trimmed_path, size);
|
||||
|
||||
return strlcat(out, trimmed_path, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -969,7 +956,7 @@ void fill_pathname_resolve_relative(char *out_path,
|
||||
* Makes sure not to get two consecutive slashes
|
||||
* 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)
|
||||
{
|
||||
if (out_path != dir)
|
||||
@ -978,10 +965,10 @@ void fill_pathname_join(char *out_path,
|
||||
if (*out_path)
|
||||
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 *last, const char *ext,
|
||||
size_t size)
|
||||
@ -991,25 +978,25 @@ void fill_pathname_join_special_ext(char *out_path,
|
||||
fill_pathname_slash(out_path, 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 *concat,
|
||||
size_t 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 *concat,
|
||||
size_t 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,
|
||||
@ -1030,7 +1017,7 @@ void fill_pathname_join_noext(char *out_path,
|
||||
* Joins a directory (@dir) and path (@path) together
|
||||
* 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)
|
||||
{
|
||||
size_t copied;
|
||||
@ -1044,15 +1031,16 @@ void fill_pathname_join_delim(char *out_path, const char *dir,
|
||||
out_path[copied+1] = '\0';
|
||||
|
||||
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,
|
||||
size_t size)
|
||||
{
|
||||
fill_pathname_join_delim(out_path, dir, path, delim, size);
|
||||
strlcat(out_path, concat, size);
|
||||
return strlcat(out_path, concat, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1070,7 +1058,7 @@ void fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
||||
* E.g.: "/path/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)
|
||||
{
|
||||
char path_short[PATH_MAX_LENGTH];
|
||||
@ -1080,7 +1068,7 @@ void fill_short_pathname_representation(char* out_rep,
|
||||
fill_pathname(path_short, path_basename(in_path), "",
|
||||
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,
|
||||
@ -1298,20 +1286,24 @@ void fill_pathname_application_path(char *s, size_t len)
|
||||
CFStringRef bundle_path = CFURLCopyPath(bundle_url);
|
||||
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);
|
||||
strlcat(s,"/",len);
|
||||
}
|
||||
{
|
||||
/* 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_url);
|
||||
#ifndef HAVE_COCOATOUCH
|
||||
// Not sure what this does but it breaks stuff for iOS so skipping
|
||||
/* Not sure what this does but it breaks
|
||||
* stuff for iOS, so skipping */
|
||||
retro_assert(strlcat(s, "nobin", len) < len);
|
||||
#endif
|
||||
return;
|
||||
|
@ -26,7 +26,6 @@
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <complex>
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
@ -178,7 +178,7 @@ char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks);
|
||||
*
|
||||
* 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:
|
||||
@ -226,7 +226,7 @@ void fill_pathname(char *out_path, const char *in_path,
|
||||
* E.g.:
|
||||
* 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);
|
||||
|
||||
/**
|
||||
@ -259,7 +259,7 @@ void fill_str_dated_filename(char *out_filename,
|
||||
* 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);
|
||||
|
||||
/**
|
||||
@ -289,7 +289,7 @@ char *find_last_slash(const char *str);
|
||||
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
|
||||
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
|
||||
**/
|
||||
void fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
size_t fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
const char *replace, size_t size);
|
||||
|
||||
/**
|
||||
@ -300,12 +300,12 @@ void fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
*
|
||||
* 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,
|
||||
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,
|
||||
size_t size);
|
||||
|
||||
@ -376,20 +376,20 @@ void fill_pathname_resolve_relative(char *out_path, const char *in_refpath,
|
||||
* Makes sure not to get two consecutive slashes
|
||||
* 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);
|
||||
|
||||
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 *last, const char *ext,
|
||||
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 *concat,
|
||||
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 *concat,
|
||||
size_t size);
|
||||
@ -408,10 +408,10 @@ void fill_pathname_join_noext(char *out_path,
|
||||
* Joins a directory (@dir) and path (@path) together
|
||||
* 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);
|
||||
|
||||
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,
|
||||
size_t size);
|
||||
|
||||
@ -430,7 +430,7 @@ void fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
||||
* E.g.: "/path/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);
|
||||
|
||||
void fill_short_pathname_representation_noext(char* out_rep,
|
||||
|
@ -1248,6 +1248,16 @@ enum retro_mod
|
||||
* default when calling SET_VARIABLES/SET_CORE_OPTIONS.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER 56
|
||||
/* unsigned * --
|
||||
*
|
||||
* Allows an implementation to ask frontend preferred hardware
|
||||
* context to use. Core should use this information to deal
|
||||
* with what specific context to request with SET_HW_RENDER.
|
||||
*
|
||||
* 'data' points to an unsigned variable
|
||||
*/
|
||||
|
||||
/* VFS functionality */
|
||||
|
||||
/* File paths:
|
||||
@ -1924,6 +1934,10 @@ enum retro_sensor_action
|
||||
{
|
||||
RETRO_SENSOR_ACCELEROMETER_ENABLE = 0,
|
||||
RETRO_SENSOR_ACCELEROMETER_DISABLE,
|
||||
RETRO_SENSOR_GYROSCOPE_ENABLE,
|
||||
RETRO_SENSOR_GYROSCOPE_DISABLE,
|
||||
RETRO_SENSOR_ILLUMINANCE_ENABLE,
|
||||
RETRO_SENSOR_ILLUMINANCE_DISABLE,
|
||||
|
||||
RETRO_SENSOR_DUMMY = INT_MAX
|
||||
};
|
||||
@ -1932,6 +1946,10 @@ enum retro_sensor_action
|
||||
#define RETRO_SENSOR_ACCELEROMETER_X 0
|
||||
#define RETRO_SENSOR_ACCELEROMETER_Y 1
|
||||
#define RETRO_SENSOR_ACCELEROMETER_Z 2
|
||||
#define RETRO_SENSOR_GYROSCOPE_X 3
|
||||
#define RETRO_SENSOR_GYROSCOPE_Y 4
|
||||
#define RETRO_SENSOR_GYROSCOPE_Z 5
|
||||
#define RETRO_SENSOR_ILLUMINANCE 6
|
||||
|
||||
typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port,
|
||||
enum retro_sensor_action action, unsigned rate);
|
||||
|
@ -41,6 +41,7 @@ union string_list_elem_attr
|
||||
struct string_list_elem
|
||||
{
|
||||
char *data;
|
||||
void *userdata;
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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:
|
||||
*
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <stdio.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 */
|
||||
#elif defined(_WIN32) && !defined(_XBOX)
|
||||
#include <windows.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 */
|
||||
/* https://stackoverflow.com/questions/8132399/how-to-printf-uint64-t-fails-with-spurious-trailing-in-format */
|
||||
/* https://github.com/libretro/RetroArch/issues/6009 */
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#ifndef __STDC_FORMAT_MACROS
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#ifndef PRId64
|
||||
|
@ -61,7 +61,7 @@ int64_t filestream_truncate(RFILE *stream, int64_t length);
|
||||
* Opens a file for reading or writing, depending on the requested mode.
|
||||
* Returns a pointer to an RFILE if opened successfully, otherwise NULL.
|
||||
**/
|
||||
RFILE *filestream_open(const char *path, unsigned mode, unsigned hints);
|
||||
RFILE* filestream_open(const char *path, unsigned mode, unsigned hints);
|
||||
|
||||
int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position);
|
||||
|
||||
@ -77,7 +77,7 @@ int filestream_close(RFILE *stream);
|
||||
|
||||
int64_t filestream_read_file(const char *path, void **buf, int64_t *len);
|
||||
|
||||
char *filestream_gets(RFILE *stream, char *s, size_t len);
|
||||
char* filestream_gets(RFILE *stream, char *s, size_t len);
|
||||
|
||||
int filestream_getc(RFILE *stream);
|
||||
|
||||
@ -101,11 +101,12 @@ int filestream_delete(const char *path);
|
||||
|
||||
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);
|
||||
|
||||
bool filestream_exists(const char *path);
|
||||
|
||||
char *filestream_getline(RFILE *stream);
|
||||
/* Returned pointer must be freed by the caller. */
|
||||
char* filestream_getline(RFILE *stream);
|
||||
|
||||
libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream);
|
||||
|
||||
|
@ -49,27 +49,9 @@ static INLINE bool string_is_equal(const char *a, const char *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_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,
|
||||
const char *b)
|
||||
{
|
||||
@ -129,6 +111,41 @@ char *string_trim_whitespace(char *const s);
|
||||
char *word_wrap(char *buffer, const char *string,
|
||||
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);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -47,7 +47,10 @@ void string_list_free(struct string_list *list)
|
||||
{
|
||||
if (list->elems[i].data)
|
||||
free(list->elems[i].data);
|
||||
list->elems[i].data = NULL;
|
||||
if (list->elems[i].userdata)
|
||||
free(list->elems[i].userdata);
|
||||
list->elems[i].data = NULL;
|
||||
list->elems[i].userdata = NULL;
|
||||
}
|
||||
|
||||
free(list->elems);
|
||||
@ -256,6 +259,59 @@ error:
|
||||
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:
|
||||
* @list : pointer to string list
|
||||
|
@ -154,7 +154,7 @@ int64_t filestream_truncate(RFILE *stream, int64_t length)
|
||||
* Opens a file for reading or writing, depending on the requested mode.
|
||||
* Returns a pointer to an RFILE if opened successfully, otherwise NULL.
|
||||
**/
|
||||
RFILE *filestream_open(const char *path, unsigned mode, unsigned hints)
|
||||
RFILE* filestream_open(const char *path, unsigned mode, unsigned hints)
|
||||
{
|
||||
struct retro_vfs_file_handle *fp = NULL;
|
||||
RFILE* output = NULL;
|
||||
@ -176,7 +176,7 @@ RFILE *filestream_open(const char *path, unsigned mode, unsigned hints)
|
||||
return output;
|
||||
}
|
||||
|
||||
char *filestream_gets(RFILE *stream, char *s, size_t len)
|
||||
char* filestream_gets(RFILE *stream, char *s, size_t len)
|
||||
{
|
||||
int c = 0;
|
||||
char *p = s;
|
||||
@ -399,7 +399,7 @@ int filestream_rename(const char *old_path, const char *new_path)
|
||||
return retro_vfs_file_rename_impl(old_path, new_path);
|
||||
}
|
||||
|
||||
const char *filestream_get_path(RFILE *stream)
|
||||
const char* filestream_get_path(RFILE *stream)
|
||||
{
|
||||
if (filestream_get_path_cb != NULL)
|
||||
return filestream_get_path_cb(stream->hfile);
|
||||
@ -572,13 +572,14 @@ bool filestream_write_file(const char *path, const void *data, int64_t size)
|
||||
return true;
|
||||
}
|
||||
|
||||
char *filestream_getline(RFILE *stream)
|
||||
/* Returned pointer must be freed by the caller. */
|
||||
char* filestream_getline(RFILE *stream)
|
||||
{
|
||||
char* newline_tmp = NULL;
|
||||
char *newline_tmp = NULL;
|
||||
size_t cur_size = 8;
|
||||
size_t idx = 0;
|
||||
int in = 0;
|
||||
char* newline = (char*)malloc(9);
|
||||
char *newline = (char*)malloc(9);
|
||||
|
||||
if (!stream || !newline)
|
||||
{
|
||||
|
@ -237,3 +237,148 @@ char *word_wrap(char* buffer, const char *string, int line_width, bool unicode,
|
||||
|
||||
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)) != NULL)
|
||||
*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);
|
||||
}
|
||||
|
@ -172,7 +172,7 @@
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
#if defined(_WIN32)
|
||||
#if !defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
#define ATLEAST_VC2005
|
||||
#endif
|
||||
@ -938,7 +938,9 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
|
||||
/* if fileXioGetStat fails */
|
||||
int dir_ret = fileXioDopen(path);
|
||||
is_dir = dir_ret > 0;
|
||||
fileXioDclose(dir_ret);
|
||||
if (is_dir) {
|
||||
fileXioDclose(dir_ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
is_dir = FIO_S_ISDIR(buf.mode);
|
||||
@ -1117,11 +1119,13 @@ static bool dirent_check_error(libretro_vfs_implementation_dir *rdir)
|
||||
#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)
|
||||
unsigned path_len;
|
||||
char path_buf[1024];
|
||||
size_t copied = 0;
|
||||
#if defined(LEGACY_WIN32)
|
||||
char *path_local = NULL;
|
||||
#else
|
||||
@ -1145,21 +1149,24 @@ libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *name, bool i
|
||||
path_buf[0] = '\0';
|
||||
path_len = strlen(name);
|
||||
|
||||
copied = strlcpy(path_buf, name, sizeof(path_buf));
|
||||
|
||||
/* Non-NT platforms don't like extra slashes in the path */
|
||||
if (name[path_len - 1] == '\\')
|
||||
snprintf(path_buf, sizeof(path_buf), "%s*", name);
|
||||
else
|
||||
snprintf(path_buf, sizeof(path_buf), "%s\\*", name);
|
||||
if (name[path_len - 1] != '\\')
|
||||
path_buf[copied++] = '\\';
|
||||
|
||||
path_buf[copied] = '*';
|
||||
path_buf[copied+1] = '\0';
|
||||
|
||||
#if defined(LEGACY_WIN32)
|
||||
path_local = utf8_to_local_string_alloc(path_buf);
|
||||
rdir->directory = FindFirstFile(path_local, &rdir->entry);
|
||||
path_local = utf8_to_local_string_alloc(path_buf);
|
||||
rdir->directory = FindFirstFile(path_local, &rdir->entry);
|
||||
|
||||
if (path_local)
|
||||
free(path_local);
|
||||
#else
|
||||
path_wide = utf8_to_utf16_string_alloc(path_buf);
|
||||
rdir->directory = FindFirstFileW(path_wide, &rdir->entry);
|
||||
path_wide = utf8_to_utf16_string_alloc(path_buf);
|
||||
rdir->directory = FindFirstFileW(path_wide, &rdir->entry);
|
||||
|
||||
if (path_wide)
|
||||
free(path_wide);
|
||||
@ -1229,19 +1236,23 @@ const char *retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir *rdir
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
#if defined(LEGACY_WIN32)
|
||||
char *name_local = 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));
|
||||
{
|
||||
char *name_local = 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);
|
||||
if (name_local)
|
||||
free(name_local);
|
||||
}
|
||||
#else
|
||||
char *name = utf16_to_utf8_string_alloc(rdir->entry.cFileName);
|
||||
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
|
||||
strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName));
|
||||
{
|
||||
char *name = utf16_to_utf8_string_alloc(rdir->entry.cFileName);
|
||||
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
|
||||
strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName));
|
||||
|
||||
if (name)
|
||||
free(name);
|
||||
if (name)
|
||||
free(name);
|
||||
}
|
||||
#endif
|
||||
return (char*)rdir->entry.cFileName;
|
||||
#elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) || defined(ORBIS)
|
||||
@ -1249,7 +1260,8 @@ const char *retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir *rdir
|
||||
#elif defined(PS2)
|
||||
return rdir->entry.name;
|
||||
#else
|
||||
|
||||
if (!rdir || !rdir->entry)
|
||||
return NULL;
|
||||
return rdir->entry->d_name;
|
||||
#endif
|
||||
}
|
||||
|
@ -55,62 +55,10 @@ using namespace Windows::Storage::FileProperties;
|
||||
#include <string/stdstring.h>
|
||||
#include <retro_environment.h>
|
||||
#include <uwp/uwp_func.h>
|
||||
#include <uwp/uwp_async.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
/* Dear Microsoft
|
||||
* I really appreciate all the effort you took to not provide any
|
||||
* synchronous file APIs and block all attempts to synchronously
|
||||
* wait for the results of async tasks for "smooth user experience",
|
||||
* but I'm not going to run and rewrite all RetroArch cores for
|
||||
* async I/O. I hope you like this hack I made instead.
|
||||
*/
|
||||
template<typename T>
|
||||
T RunAsync(std::function<concurrency::task<T>()> func)
|
||||
{
|
||||
volatile bool finished = false;
|
||||
Platform::Exception^ exception = nullptr;
|
||||
T result;
|
||||
|
||||
func().then([&finished, &exception, &result](concurrency::task<T> t) {
|
||||
try
|
||||
{
|
||||
result = t.get();
|
||||
}
|
||||
catch (Platform::Exception^ exception_)
|
||||
{
|
||||
exception = exception_;
|
||||
}
|
||||
finished = true;
|
||||
});
|
||||
|
||||
/* Don't stall the UI thread - prevents a deadlock */
|
||||
Windows::UI::Core::CoreWindow^ corewindow = Windows::UI::Core::CoreWindow::GetForCurrentThread();
|
||||
while (!finished)
|
||||
{
|
||||
if (corewindow) {
|
||||
corewindow->Dispatcher->ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent);
|
||||
}
|
||||
}
|
||||
|
||||
if (exception != nullptr)
|
||||
throw exception;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T RunAsyncAndCatchErrors(std::function<concurrency::task<T>()> func, T valueOnError)
|
||||
{
|
||||
try
|
||||
{
|
||||
return RunAsync<T>(func);
|
||||
}
|
||||
catch (Platform::Exception^ e)
|
||||
{
|
||||
return valueOnError;
|
||||
}
|
||||
}
|
||||
|
||||
void windowsize_path(wchar_t* path)
|
||||
{
|
||||
/* UWP deals with paths containing / instead of \ way worse than normal Windows */
|
||||
|
138
libretro.cpp
138
libretro.cpp
@ -1179,7 +1179,9 @@ static void set_volume (uint32_t *ptr, unsigned number)
|
||||
|
||||
#define MAX_PLAYERS 5
|
||||
#define MAX_BUTTONS 15
|
||||
static uint8_t input_buf[MAX_PLAYERS][2] = {};
|
||||
static uint8_t input_type[MAX_PLAYERS] = {};
|
||||
static uint8_t input_buf[MAX_PLAYERS][5] = {};
|
||||
static float mouse_sensitivity = 1.0f;
|
||||
|
||||
// Array to keep track of whether a given player's button is turbo
|
||||
static int turbo_enable[MAX_PLAYERS][MAX_BUTTONS] = {};
|
||||
@ -1340,6 +1342,13 @@ static void check_variables(void)
|
||||
else
|
||||
turbo_toggle_alt = false;
|
||||
}
|
||||
|
||||
var.key = "pce_mouse_sensitivity";
|
||||
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
{
|
||||
mouse_sensitivity = atof(var.value);
|
||||
}
|
||||
}
|
||||
|
||||
bool retro_load_game(const struct retro_game_info *info)
|
||||
@ -1396,8 +1405,10 @@ bool retro_load_game(const struct retro_game_info *info)
|
||||
}
|
||||
|
||||
// Possible endian bug ...
|
||||
for (unsigned i = 0; i < MAX_PLAYERS; i++)
|
||||
PCEINPUT_SetInput(i, "gamepad", &input_buf[i][0]);
|
||||
for (unsigned i = 0; i < MAX_PLAYERS; i++) {
|
||||
input_type[i] = RETRO_DEVICE_JOYPAD;
|
||||
PCEINPUT_SetInput(i, "gamepad", (uint8_t*)&input_buf[i][0]);
|
||||
}
|
||||
|
||||
VDC_SetPixelFormat();
|
||||
|
||||
@ -1495,53 +1506,93 @@ static void update_input(void)
|
||||
|
||||
for (unsigned j = 0; j < MAX_PLAYERS; j++)
|
||||
{
|
||||
uint16_t input_state = 0;
|
||||
|
||||
// read normal inputs
|
||||
for (unsigned i = 0; i < MAX_BUTTONS; i++)
|
||||
|
||||
switch (input_type[j])
|
||||
{
|
||||
input_state |= input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, map[i]) ? (1 << i) : 0;
|
||||
case RETRO_DEVICE_JOYPAD:
|
||||
{
|
||||
uint16_t input_state = 0;
|
||||
|
||||
// handle turbo buttons
|
||||
if (turbo_enable[j][i] == 1) // Check whether a given button is turbo-capable
|
||||
// read normal inputs
|
||||
for (unsigned i = 0; i < MAX_BUTTONS; i++)
|
||||
{
|
||||
if (input_state & (1 << i))
|
||||
input_state |= input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, map[i]) ? (1 << i) : 0;
|
||||
|
||||
// handle turbo buttons
|
||||
if (turbo_enable[j][i] == 1) // Check whether a given button is turbo-capable
|
||||
{
|
||||
if (turbo_counter[j][i] < 2) // Some PCE games needs 2 frames to react to button presses, so
|
||||
input_state |= 1 << i; // trigger turbo button at counter 0 and 1
|
||||
if (input_state & (1 << i))
|
||||
{
|
||||
if (turbo_counter[j][i] < 2) // Some PCE games needs 2 frames to react to button presses, so
|
||||
input_state |= 1 << i; // trigger turbo button at counter 0 and 1
|
||||
else
|
||||
input_state &= ~(1 << i);
|
||||
turbo_counter[j][i]++; // Counter is incremented by 1
|
||||
if (turbo_counter[j][i] > Turbo_Delay) // When the counter exceeds turbo delay, reset counter to zero
|
||||
turbo_counter[j][i] = 0;
|
||||
}
|
||||
else
|
||||
input_state &= ~(1 << i);
|
||||
turbo_counter[j][i]++; // Counter is incremented by 1
|
||||
if (turbo_counter[j][i] > Turbo_Delay) // When the counter exceeds turbo delay, reset counter to zero
|
||||
turbo_counter[j][i] = 0;
|
||||
turbo_counter[j][i] = 0; // Reset counter if button is not pressed.
|
||||
}
|
||||
else
|
||||
turbo_counter[j][i] = 0; // Reset counter if button is not pressed.
|
||||
}
|
||||
else
|
||||
turbo_counter[j][i] = 0; // Reset counter if button is not pressed.
|
||||
turbo_counter[j][i] = 0; // Reset counter if button is not pressed.
|
||||
|
||||
// handle 2/6 button mode switching
|
||||
if (turbo_map_selected[i] != -1 && Turbo_Toggling && !AVPad6Enabled[j])
|
||||
{
|
||||
if (input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, map[i]))
|
||||
// handle 2/6 button mode switching
|
||||
if (turbo_map_selected[i] != -1 && Turbo_Toggling && !AVPad6Enabled[j])
|
||||
{
|
||||
if (turbo_toggle_down[j][i] == 0)
|
||||
if (input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, map[i]))
|
||||
{
|
||||
turbo_toggle_down[j][i] = 1;
|
||||
turbo_enable[j][turbo_map_selected[i]] = turbo_enable[j][turbo_map_selected[i]] ^ 1;
|
||||
MDFN_DispMessage("Pad %i Button %s Turbo %s", j + 1,
|
||||
i == (!turbo_toggle_alt ? 9 : 14) ? "I" : "II",
|
||||
turbo_enable[j][turbo_map_selected[i]] ? "ON" : "OFF" );
|
||||
if (turbo_toggle_down[j][i] == 0)
|
||||
{
|
||||
turbo_toggle_down[j][i] = 1;
|
||||
turbo_enable[j][turbo_map_selected[i]] = turbo_enable[j][turbo_map_selected[i]] ^ 1;
|
||||
MDFN_DispMessage("Pad %i Button %s Turbo %s", j + 1,
|
||||
i == (!turbo_toggle_alt ? 9 : 14) ? "I" : "II",
|
||||
turbo_enable[j][turbo_map_selected[i]] ? "ON" : "OFF" );
|
||||
}
|
||||
}
|
||||
else turbo_toggle_down[j][i] = 0;
|
||||
}
|
||||
else turbo_toggle_down[j][i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Input data must be little endian.
|
||||
input_buf[j][0] = (input_state >> 0) & 0xff;
|
||||
input_buf[j][1] = (input_state >> 8) & 0xff;
|
||||
// Input data must be little endian.
|
||||
input_buf[j][0] = (input_state >> 0) & 0xff;
|
||||
input_buf[j][1] = (input_state >> 8) & 0xff;
|
||||
} break;
|
||||
|
||||
case RETRO_DEVICE_MOUSE:
|
||||
{
|
||||
int16_t raw_x = input_state_cb(j, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X);
|
||||
int16_t raw_y = input_state_cb(j, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y);
|
||||
|
||||
int16_t x = (int16_t)roundf((float)raw_x * mouse_sensitivity);
|
||||
int16_t y = (int16_t)roundf((float)raw_y * mouse_sensitivity);
|
||||
|
||||
input_buf[j][0] = (x >> 0) & 0xff;
|
||||
input_buf[j][1] = (x >> 8) & 0xff;
|
||||
input_buf[j][2] = (y >> 0) & 0xff;
|
||||
input_buf[j][3] = (y >> 8) & 0xff;
|
||||
|
||||
input_buf[j][4] = 0;
|
||||
|
||||
// left mouse button
|
||||
if (input_state_cb(j, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT))
|
||||
input_buf[j][4] |= (1 << 0);
|
||||
|
||||
// right mouse button
|
||||
if (input_state_cb(j, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT))
|
||||
input_buf[j][4] |= (1 << 1);
|
||||
|
||||
// select
|
||||
if (input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT))
|
||||
input_buf[j][4] |= (1 << 2);
|
||||
|
||||
// start
|
||||
if (input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START) ||
|
||||
input_state_cb(j, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_MIDDLE))
|
||||
input_buf[j][4] |= (1 << 3);
|
||||
} break;
|
||||
} // case
|
||||
}
|
||||
}
|
||||
|
||||
@ -1675,13 +1726,21 @@ unsigned retro_api_version(void)
|
||||
|
||||
void retro_set_controller_port_device(unsigned in_port, unsigned device)
|
||||
{
|
||||
if (in_port > 4)
|
||||
return;
|
||||
|
||||
switch(device)
|
||||
{
|
||||
case RETRO_DEVICE_JOYPAD:
|
||||
PCEINPUT_SetInput(in_port, "gamepad", &input_buf[in_port][0]);
|
||||
input_type[in_port] = RETRO_DEVICE_JOYPAD;
|
||||
PCEINPUT_SetInput(in_port, "gamepad", (uint8_t*)&input_buf[in_port][0]);
|
||||
break;
|
||||
case RETRO_DEVICE_MOUSE:
|
||||
PCEINPUT_SetInput(in_port, "mouse", &input_buf[in_port][0]);
|
||||
input_type[in_port] = RETRO_DEVICE_MOUSE;
|
||||
PCEINPUT_SetInput(in_port, "mouse", (uint8_t*)&input_buf[in_port][0]);
|
||||
break;
|
||||
default:
|
||||
input_type[in_port] = RETRO_DEVICE_NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1697,6 +1756,9 @@ void retro_set_environment(retro_environment_t cb)
|
||||
};
|
||||
|
||||
static const struct retro_controller_info ports[] = {
|
||||
{ pads, 2 },
|
||||
{ pads, 2 },
|
||||
{ pads, 2 },
|
||||
{ pads, 2 },
|
||||
{ pads, 2 },
|
||||
{ 0 },
|
||||
|
@ -320,6 +320,35 @@ struct retro_core_option_definition option_defs_us[] = {
|
||||
},
|
||||
"1"
|
||||
},
|
||||
{
|
||||
"pce_mouse_sensitivity",
|
||||
"Mouse Sensitivity",
|
||||
"Configure the PCE Mouse device type's sensitivity.",
|
||||
{
|
||||
{ "0.25", NULL },
|
||||
{ "0.50", NULL },
|
||||
{ "0.75", NULL },
|
||||
{ "1.00", NULL },
|
||||
{ "1.25", NULL },
|
||||
{ "1.50", NULL },
|
||||
{ "1.75", NULL },
|
||||
{ "2.00", NULL },
|
||||
{ "2.25", NULL },
|
||||
{ "2.50", NULL },
|
||||
{ "2.75", NULL },
|
||||
{ "3.00", NULL },
|
||||
{ "3.25", NULL },
|
||||
{ "3.50", NULL },
|
||||
{ "3.75", NULL },
|
||||
{ "4.00", NULL },
|
||||
{ "4.25", NULL },
|
||||
{ "4.50", NULL },
|
||||
{ "4.75", NULL },
|
||||
{ "5.00", NULL },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"1.25"
|
||||
},
|
||||
{
|
||||
"pce_turbo_delay",
|
||||
"Turbo Delay",
|
||||
|
@ -51,11 +51,11 @@ void PCEINPUT_Init(void)
|
||||
SyncSettings();
|
||||
}
|
||||
|
||||
void PCEINPUT_SetInput(int port, const char *type, void *ptr)
|
||||
void PCEINPUT_SetInput(unsigned port, const char *type, uint8 *ptr)
|
||||
{
|
||||
if(!strcasecmp(type, "gamepad"))
|
||||
if(!strcmp(type, "gamepad"))
|
||||
InputTypes[port] = 1;
|
||||
else if(!strcasecmp(type, "mouse"))
|
||||
else if(!strcmp(type, "mouse"))
|
||||
InputTypes[port] = 2;
|
||||
else
|
||||
InputTypes[port] = 0;
|
||||
@ -82,9 +82,9 @@ void INPUT_Frame(void)
|
||||
}
|
||||
else if(InputTypes[x] == 2)
|
||||
{
|
||||
mouse_x[x] += (int32)MDFN_de32lsb(data_ptr[x] + 0);
|
||||
mouse_y[x] += (int32)MDFN_de32lsb(data_ptr[x] + 4);
|
||||
pce_mouse_button[x] = *(uint8 *)(data_ptr[x] + 8);
|
||||
mouse_x[x] += (int16)MDFN_de16lsb(data_ptr[x] + 0);
|
||||
mouse_y[x] += (int16)MDFN_de16lsb(data_ptr[x] + 2);
|
||||
pce_mouse_button[x] = *(uint8 *)(data_ptr[x] + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -148,11 +148,7 @@ uint8 INPUT_Read(unsigned int A)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pce_mouse_button[tmp_ri] & 1)
|
||||
ret ^= 0x3; //pce_mouse_button[tmp_ri];
|
||||
|
||||
if(pce_mouse_button[tmp_ri] & 0x2)
|
||||
ret ^= 0x8;
|
||||
ret ^= pce_mouse_button[tmp_ri] & 0xF;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
void PCEINPUT_Init(void);
|
||||
void PCEINPUT_SettingChanged(const char *name);
|
||||
void PCEINPUT_SetInput(int port, const char *type, void *ptr);
|
||||
void PCEINPUT_SetInput(unsigned port, const char *type, uint8 *ptr);
|
||||
uint8 INPUT_Read(unsigned int A);
|
||||
void INPUT_Write(unsigned int A, uint8 V);
|
||||
void INPUT_Frame(void);
|
||||
|
Loading…
Reference in New Issue
Block a user