libretro, update libretro-common

This commit is contained in:
kub 2022-02-09 18:42:04 +00:00
parent 8717984c12
commit b4e7cd1b51
39 changed files with 1767 additions and 738 deletions

View file

@ -196,10 +196,13 @@ endif
ifeq "$(PLATFORM)" "libretro"
OBJS += platform/libretro/libretro.o
ifeq "$(USE_LIBRETRO_VFS)" "1"
OBJS += platform/libretro/libretro-common/compat/compat_strcasestr.o
OBJS += platform/libretro/libretro-common/compat/compat_posix_string.o
OBJS += platform/libretro/libretro-common/compat/compat_strl.o
OBJS += platform/libretro/libretro-common/compat/fopen_utf8.o
OBJS += platform/libretro/libretro-common/memmap/memmap.o
OBJS += platform/libretro/libretro-common/encodings/encoding_utf.o
OBJS += platform/libretro/libretro-common/string/stdstring.o
OBJS += platform/libretro/libretro-common/streams/file_stream.o
OBJS += platform/libretro/libretro-common/streams/file_stream_transforms.o
OBJS += platform/libretro/libretro-common/vfs/vfs_implementation.o

View file

@ -160,7 +160,6 @@ else ifeq ($(platform), ps3)
AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe
CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ -DFAMEC_NO_GOTOS
STATIC_LINKING = 1
NO_MMAP = 1
# PS3 has memory mapped in a way not suitable for DRC
use_sh2drc = 0
use_svpdrc = 0
@ -173,7 +172,6 @@ else ifeq ($(platform), sncps3)
AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe
CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ -DFAMEC_NO_GOTOS
STATIC_LINKING = 1
NO_MMAP = 1
# PS3 has memory mapped in a way not suitable for DRC
use_sh2drc = 0
use_svpdrc = 0
@ -185,7 +183,6 @@ else ifeq ($(platform), psl1ght)
AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT)
CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ -DFAMEC_NO_GOTOS
STATIC_LINKING = 1
NO_MMAP = 1
# PS3 has memory mapped in a way not suitable for DRC
use_sh2drc = 0
use_svpdrc = 0
@ -199,7 +196,6 @@ else ifeq ($(platform), psp1)
CFLAGS += -G0 -ftracer
CFLAGS += -DPSP
STATIC_LINKING = 1
NO_MMAP = 1
# PS2
else ifeq ($(platform), ps2)
@ -211,7 +207,6 @@ else ifeq ($(platform), ps2)
CFLAGS += -I$(PS2DEV)/gsKit/include -I$(PS2SDK)/ee/include -I$(PS2SDK)/common/include
CFLAGS += -DHAVE_NO_LANGEXTRA
STATIC_LINKING = 1
NO_MMAP = 1
# CTR (3DS)
else ifeq ($(platform), ctr)
@ -224,7 +219,6 @@ else ifeq ($(platform), ctr)
CFLAGS += -Wall -mword-relocations
CFLAGS += -fomit-frame-pointer -ffast-math
STATIC_LINKING = 1
NO_MMAP = 1
OBJS += platform/libretro/3ds/3ds_utils.o platform/libretro/3ds/utils.o
@ -249,7 +243,6 @@ else ifeq ($(platform), vita)
CFLAGS += -mword-relocations -fno-unwind-tables
CFLAGS += -fno-optimize-sibling-calls
STATIC_LINKING = 1
NO_MMAP = 1
# Xbox 360
else ifeq ($(platform), xenon)
@ -265,7 +258,6 @@ else ifeq ($(platform), ngc)
AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT)
CFLAGS += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST
STATIC_LINKING = 1
NO_MMAP = 1
# Nintendo Wii
else ifeq ($(platform), wii)
@ -274,7 +266,6 @@ else ifeq ($(platform), wii)
AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT)
CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST
STATIC_LINKING = 1
NO_MMAP = 1
# Nintendo Wii U
else ifeq ($(platform), wiiu)
@ -284,14 +275,12 @@ else ifeq ($(platform), wiiu)
AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT)
CFLAGS += -DGEKKO -DWIIU -DHW_RVL -DHW_WUP -mwup -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST
STATIC_LINKING = 1
NO_MMAP = 1
# Nintendo Switch (libtransistor)
else ifeq ($(platform), switch)
TARGET := $(TARGET_NAME)_libretro_$(platform).a
include $(LIBTRANSISTOR_HOME)/libtransistor.mk
STATIC_LINKING=1
NO_MMAP = 1
# Nintendo Switch (libnx)
else ifeq ($(platform), libnx)
@ -548,14 +537,9 @@ endif
CFLAGS += -DNO_ZLIB -D__LIBRETRO__
ifeq ($(USE_LIBRETRO_VFS),1)
NO_MMAP = 1
CFLAGS += -DUSE_LIBRETRO_VFS
endif
ifeq ($(NO_MMAP),1)
CFLAGS += -DNO_MMAP
endif
ifeq ($(NO_ARM_ASM),1)
use_cyclone = 0
use_fame = 1

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_posix_string.c).

View file

@ -0,0 +1,58 @@
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_strcasestr.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <ctype.h>
#include <compat/strcasestr.h>
/* Pretty much strncasecmp. */
static int casencmp(const char *a, const char *b, size_t n)
{
size_t i;
for (i = 0; i < n; i++)
{
int a_lower = tolower(a[i]);
int b_lower = tolower(b[i]);
if (a_lower != b_lower)
return a_lower - b_lower;
}
return 0;
}
char *strcasestr_retro__(const char *haystack, const char *needle)
{
size_t i, search_off;
size_t hay_len = strlen(haystack);
size_t needle_len = strlen(needle);
if (needle_len > hay_len)
return NULL;
search_off = hay_len - needle_len;
for (i = 0; i <= search_off; i++)
if (!casencmp(haystack + i, needle, needle_len))
return (char*)haystack + i;
return NULL;
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_strl.c).

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (fopen_utf8.c).
@ -49,8 +49,13 @@ void *fopen_utf8(const char * filename, const char * mode)
#else
wchar_t * filename_w = utf8_to_utf16_string_alloc(filename);
wchar_t * mode_w = utf8_to_utf16_string_alloc(mode);
FILE* ret = _wfopen(filename_w, mode_w);
FILE* ret = NULL;
if (filename_w && mode_w)
ret = _wfopen(filename_w, mode_w);
if (filename_w)
free(filename_w);
if (mode_w)
free(mode_w);
return ret;
#endif

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (encoding_utf.c).
@ -37,6 +37,8 @@
#include <xtl.h>
#endif
#define UTF8_WALKBYTE(string) (*((*(string))++))
static unsigned leading_ones(uint8_t c)
{
unsigned ones = 0;
@ -89,13 +91,14 @@ size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
const uint16_t *in, size_t in_size)
{
static uint8_t kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
size_t out_pos = 0;
size_t in_pos = 0;
static const
uint8_t utf8_limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
for (;;)
{
unsigned numAdds;
unsigned num_adds;
uint32_t value;
if (in_pos == in_size)
@ -124,21 +127,21 @@ bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
}
for (numAdds = 1; numAdds < 5; numAdds++)
if (value < (((uint32_t)1) << (numAdds * 5 + 6)))
for (num_adds = 1; num_adds < 5; num_adds++)
if (value < (((uint32_t)1) << (num_adds * 5 + 6)))
break;
if (out)
out[out_pos] = (char)(kUtf8Limits[numAdds - 1]
+ (value >> (6 * numAdds)));
out[out_pos] = (char)(utf8_limits[num_adds - 1]
+ (value >> (6 * num_adds)));
out_pos++;
do
{
numAdds--;
num_adds--;
if (out)
out[out_pos] = (char)(0x80
+ ((value >> (6 * numAdds)) & 0x3F));
+ ((value >> (6 * num_adds)) & 0x3F));
out_pos++;
}while (numAdds != 0);
}while (num_adds != 0);
}
*out_chars = out_pos;
@ -166,13 +169,15 @@ size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars)
while (*sb && chars-- > 0)
{
sb++;
while ((*sb & 0xC0) == 0x80) sb++;
while ((*sb & 0xC0) == 0x80)
sb++;
}
if ((size_t)(sb - sb_org) > d_len-1 /* NUL */)
{
sb = sb_org + d_len-1;
while ((*sb & 0xC0) == 0x80) sb--;
while ((*sb & 0xC0) == 0x80)
sb--;
}
memcpy(d, sb_org, sb-sb_org);
@ -184,14 +189,18 @@ size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars)
const char *utf8skip(const char *str, size_t chars)
{
const uint8_t *strb = (const uint8_t*)str;
if (!chars)
return str;
do
{
strb++;
while ((*strb & 0xC0)==0x80) strb++;
while ((*strb & 0xC0)==0x80)
strb++;
chars--;
} while(chars);
}while (chars);
return (const char*)strb;
}
@ -211,24 +220,22 @@ size_t utf8len(const char *string)
return ret;
}
#define utf8_walkbyte(string) (*((*(string))++))
/* Does not validate the input, returns garbage if it's not UTF-8. */
uint32_t utf8_walk(const char **string)
{
uint8_t first = utf8_walkbyte(string);
uint8_t first = UTF8_WALKBYTE(string);
uint32_t ret = 0;
if (first < 128)
return first;
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
ret = (ret << 6) | (UTF8_WALKBYTE(string) & 0x3F);
if (first >= 0xE0)
{
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
ret = (ret << 6) | (UTF8_WALKBYTE(string) & 0x3F);
if (first >= 0xF0)
{
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
ret = (ret << 6) | (UTF8_WALKBYTE(string) & 0x3F);
return ret | (first & 7) << 18;
}
return ret | (first & 15) << 12;
@ -277,9 +284,7 @@ bool utf16_to_char_string(const uint16_t *in, char *s, size_t len)
static char *mb_to_mb_string_alloc(const char *str,
enum CodePage cp_in, enum CodePage cp_out)
{
char *path_buf = NULL;
wchar_t *path_buf_wide = NULL;
int path_buf_len = 0;
int path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
/* Windows 95 will return 0 from these functions with
@ -292,8 +297,9 @@ static char *mb_to_mb_string_alloc(const char *str,
* MultiByteToWideChar also supports CP_UTF7 and CP_UTF8.
*/
if (path_buf_wide_len)
{
if (!path_buf_wide_len)
return strdup(str);
path_buf_wide = (wchar_t*)
calloc(path_buf_wide_len + sizeof(wchar_t), sizeof(wchar_t));
@ -304,12 +310,12 @@ static char *mb_to_mb_string_alloc(const char *str,
if (*path_buf_wide)
{
path_buf_len = WideCharToMultiByte(cp_out, 0,
int path_buf_len = WideCharToMultiByte(cp_out, 0,
path_buf_wide, -1, NULL, 0, NULL, NULL);
if (path_buf_len)
{
path_buf = (char*)
char *path_buf = (char*)
calloc(path_buf_len + sizeof(char), sizeof(char));
if (path_buf)
@ -333,13 +339,9 @@ static char *mb_to_mb_string_alloc(const char *str,
return strdup(str);
}
}
}
}
else
return strdup(str);
if (path_buf_wide)
free(path_buf_wide);
}
return NULL;
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (boolean.h).

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (apple_compat.h).

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (fnmatch.h).

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (fopen_utf8.h).

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (getopt.h).

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (intrinsics.h).
@ -41,7 +41,7 @@ RETRO_BEGIN_DECLS
/* Count Leading Zero, unsigned 16bit input value */
static INLINE unsigned compat_clz_u16(uint16_t val)
{
#if defined(__GNUC__) && !defined(PS2)
#if defined(__GNUC__)
return __builtin_clz(val << 16 | 0x8000);
#else
unsigned ret = 0;
@ -63,20 +63,34 @@ static INLINE int compat_ctz(unsigned x)
return __builtin_ctz(x);
#elif _MSC_VER >= 1400 && !defined(_XBOX) && !defined(__WINRT__)
unsigned long r = 0;
_BitScanReverse((unsigned long*)&r, x);
_BitScanForward((unsigned long*)&r, x);
return (int)r;
#else
/* Only checks at nibble granularity,
* because that's what we need. */
if (x & 0x000f)
return 0;
if (x & 0x00f0)
return 4;
if (x & 0x0f00)
return 8;
if (x & 0xf000)
return 12;
return 16;
int count = 0;
if (!(x & 0xffff))
{
x >>= 16;
count |= 16;
}
if (!(x & 0xff))
{
x >>= 8;
count |= 8;
}
if (!(x & 0xf))
{
x >>= 4;
count |= 4;
}
if (!(x & 0x3))
{
x >>= 2;
count |= 2;
}
if (!(x & 0x1))
count |= 1;
return count;
#endif
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (msvc.h).
@ -29,22 +29,17 @@
extern "C" {
#endif
/* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */
/* Pre-MSVC 2015 compilers don't implement snprintf, vsnprintf in a cross-platform manner. */
#if _MSC_VER < 1900
#include <stdio.h>
#include <stdlib.h>
#ifndef snprintf
#define snprintf c99_snprintf_retro__
#endif
int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...);
#endif
/* Pre-MSVC 2008 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
#if _MSC_VER < 1500
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#ifndef snprintf
#define snprintf c99_snprintf_retro__
#endif
int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...);
#ifndef vsnprintf
#define vsnprintf c99_vsnprintf_retro__
#endif

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (posix_string.h).
@ -29,10 +29,6 @@
#include <compat/msvc.h>
#endif
#if defined(PS2)
#include <compat_ctype.h>
#endif
RETRO_BEGIN_DECLS
#ifdef _WIN32

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (strcasestr.h).
@ -25,10 +25,6 @@
#include <string.h>
#if defined(PS2)
#include <compat_ctype.h>
#endif
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
#include "../../../config.h"
#endif

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (strl.h).

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (utf.h).

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2019 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_path.h).
@ -125,6 +125,7 @@ char *path_remove_extension(char *path);
* Returns: basename from path.
**/
const char *path_basename(const char *path);
const char *path_basename_nocompression(const char *path);
/**
* path_basedir:
@ -178,7 +179,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 +227,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 +260,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 +290,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 +301,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 +377,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 +409,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 +431,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,
@ -442,6 +443,12 @@ void fill_pathname_expand_special(char *out_path,
void fill_pathname_abbreviate_special(char *out_path,
const char *in_path, size_t size);
void fill_pathname_abbreviated_or_relative(char *out_path, const char *in_refpath, const char *in_path, size_t size);
void pathname_conform_slashes_to_os(char *path);
void pathname_make_slashes_portable(char *path);
/**
* path_basedir:
* @path : path
@ -460,9 +467,9 @@ void path_basedir_wrapper(char *path);
* Returns: true (1) if character is a slash, otherwise false (0).
*/
#ifdef _WIN32
#define path_char_is_slash(c) (((c) == '/') || ((c) == '\\'))
#define PATH_CHAR_IS_SLASH(c) (((c) == '/') || ((c) == '\\'))
#else
#define path_char_is_slash(c) ((c) == '/')
#define PATH_CHAR_IS_SLASH(c) ((c) == '/')
#endif
/**
@ -473,11 +480,11 @@ void path_basedir_wrapper(char *path);
* Returns: default slash separator.
*/
#ifdef _WIN32
#define path_default_slash() "\\"
#define path_default_slash_c() '\\'
#define PATH_DEFAULT_SLASH() "\\"
#define PATH_DEFAULT_SLASH_C() '\\'
#else
#define path_default_slash() "/"
#define path_default_slash_c() '/'
#define PATH_DEFAULT_SLASH() "/"
#define PATH_DEFAULT_SLASH_C() '/'
#endif
/**

View file

@ -283,6 +283,9 @@ enum retro_language
RETRO_LANGUAGE_HEBREW = 21,
RETRO_LANGUAGE_ASTURIAN = 22,
RETRO_LANGUAGE_FINNISH = 23,
RETRO_LANGUAGE_INDONESIAN = 24,
RETRO_LANGUAGE_SWEDISH = 25,
RETRO_LANGUAGE_UKRAINIAN = 26,
RETRO_LANGUAGE_LAST,
/* Ensure sizeof(enum) == sizeof(int) */
@ -3461,6 +3464,10 @@ struct retro_core_option_definition
const char *default_value;
};
#ifdef __PS3__
#undef local
#endif
struct retro_core_options_intl
{
/* Pointer to an array of retro_core_option_definition structs

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (memmap.h).
@ -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) || defined(HAVE_LIBNX)
#if defined(PSP) || defined(PS2) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH) || defined(HAVE_LIBNX) || defined(__PS3__) || defined(__PSL1GHT__)
/* No mman available */
#elif defined(_WIN32) && !defined(_XBOX)
#include <windows.h>

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_common.h).

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_common_api.h).

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2019 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_dirent.h).
@ -25,7 +25,6 @@
#include <libretro.h>
#include <retro_common_api.h>
#include <retro_miscellaneous.h>
#include <boolean.h>

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_endianness.h).
@ -31,40 +31,97 @@
#define SWAP16 _byteswap_ushort
#define SWAP32 _byteswap_ulong
#else
#define SWAP16(x) ((uint16_t)( \
(((uint16_t)(x) & 0x00ff) << 8) | \
(((uint16_t)(x) & 0xff00) >> 8) \
))
#define SWAP32(x) ((uint32_t)( \
(((uint32_t)(x) & 0x000000ff) << 24) | \
(((uint32_t)(x) & 0x0000ff00) << 8) | \
(((uint32_t)(x) & 0x00ff0000) >> 8) | \
(((uint32_t)(x) & 0xff000000) >> 24) \
))
static INLINE uint16_t SWAP16(uint16_t x)
{
return ((x & 0x00ff) << 8) |
((x & 0xff00) >> 8);
}
static INLINE uint32_t SWAP32(uint32_t x)
{
return ((x & 0x000000ff) << 24) |
((x & 0x0000ff00) << 8) |
((x & 0x00ff0000) >> 8) |
((x & 0xff000000) >> 24);
}
#endif
#if defined(_MSC_VER) && _MSC_VER <= 1200
#define SWAP64(val) \
((((uint64_t)(val) & 0x00000000000000ff) << 56) \
| (((uint64_t)(val) & 0x000000000000ff00) << 40) \
| (((uint64_t)(val) & 0x0000000000ff0000) << 24) \
| (((uint64_t)(val) & 0x00000000ff000000) << 8) \
| (((uint64_t)(val) & 0x000000ff00000000) >> 8) \
| (((uint64_t)(val) & 0x0000ff0000000000) >> 24) \
| (((uint64_t)(val) & 0x00ff000000000000) >> 40) \
| (((uint64_t)(val) & 0xff00000000000000) >> 56))
static INLINE uint64_t SWAP64(uint64_t val)
{
return
((val & 0x00000000000000ff) << 56)
| ((val & 0x000000000000ff00) << 40)
| ((val & 0x0000000000ff0000) << 24)
| ((val & 0x00000000ff000000) << 8)
| ((val & 0x000000ff00000000) >> 8)
| ((val & 0x0000ff0000000000) >> 24)
| ((val & 0x00ff000000000000) >> 40)
| ((val & 0xff00000000000000) >> 56);
}
#else
#define SWAP64(val) \
((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \
| (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \
| (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \
| (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \
| (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \
| (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \
| (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \
| (((uint64_t)(val) & 0xff00000000000000ULL) >> 56))
static INLINE uint64_t SWAP64(uint64_t val)
{
return ((val & 0x00000000000000ffULL) << 56)
| ((val & 0x000000000000ff00ULL) << 40)
| ((val & 0x0000000000ff0000ULL) << 24)
| ((val & 0x00000000ff000000ULL) << 8)
| ((val & 0x000000ff00000000ULL) >> 8)
| ((val & 0x0000ff0000000000ULL) >> 24)
| ((val & 0x00ff000000000000ULL) >> 40)
| ((val & 0xff00000000000000ULL) >> 56);
}
#endif
#if defined (LSB_FIRST) || defined (MSB_FIRST)
# warning Defining MSB_FIRST and LSB_FIRST in compile options is deprecated
# undef LSB_FIRST
# undef MSB_FIRST
#endif
#ifdef _MSC_VER
/* MSVC pre-defines macros depending on target arch */
#if defined (_M_IX86) || defined (_M_AMD64) || defined (_M_ARM) || defined (_M_ARM64)
#define LSB_FIRST 1
#elif _M_PPC
#define MSB_FIRST 1
#else
/* MSVC can run on _M_ALPHA and _M_IA64 too, but they're both bi-endian; need to find what mode MSVC runs them at */
#error "unknown platform, can't determine endianness"
#endif
#else
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define MSB_FIRST 1
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define LSB_FIRST 1
#else
#error "Invalid endianness macros"
#endif
#endif
#if defined(MSB_FIRST) && defined(LSB_FIRST)
# error "Bug in LSB_FIRST/MSB_FIRST definition"
#endif
#if !defined(MSB_FIRST) && !defined(LSB_FIRST)
# error "Bug in LSB_FIRST/MSB_FIRST definition"
#endif
#ifdef MSB_FIRST
# define RETRO_IS_BIG_ENDIAN 1
# define RETRO_IS_LITTLE_ENDIAN 0
/* For compatibility */
# define WORDS_BIGENDIAN 1
#else
# define RETRO_IS_BIG_ENDIAN 0
# define RETRO_IS_LITTLE_ENDIAN 1
/* For compatibility */
# undef WORDS_BIGENDIAN
#endif
/**
* is_little_endian:
*
@ -73,23 +130,7 @@
* Returns: greater than 0 if little-endian,
* otherwise big-endian.
**/
#if defined(MSB_FIRST)
#define is_little_endian() (0)
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
#define is_little_endian() (1)
#else
static INLINE uint8_t is_little_endian(void)
{
union
{
uint16_t x;
uint8_t y[2];
} u;
u.x = 1;
return u.y[0];
}
#endif
#define is_little_endian() RETRO_IS_LITTLE_ENDIAN
/**
* swap_if_big64:
@ -101,17 +142,10 @@ static INLINE uint8_t is_little_endian(void)
* otherwise returns same value.
**/
#if defined(MSB_FIRST)
#if RETRO_IS_BIG_ENDIAN
#define swap_if_big64(val) (SWAP64(val))
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
#elif RETRO_IS_LITTLE_ENDIAN
#define swap_if_big64(val) (val)
#else
static INLINE uint64_t swap_if_big64(uint64_t val)
{
if (is_little_endian())
return val;
return SWAP64(val);
}
#endif
/**
@ -124,17 +158,10 @@ static INLINE uint64_t swap_if_big64(uint64_t val)
* otherwise returns same value.
**/
#if defined(MSB_FIRST)
#if RETRO_IS_BIG_ENDIAN
#define swap_if_big32(val) (SWAP32(val))
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
#elif RETRO_IS_LITTLE_ENDIAN
#define swap_if_big32(val) (val)
#else
static INLINE uint32_t swap_if_big32(uint32_t val)
{
if (is_little_endian())
return val;
return SWAP32(val);
}
#endif
/**
@ -147,17 +174,10 @@ static INLINE uint32_t swap_if_big32(uint32_t val)
* otherwise returns same value.
**/
#if defined(MSB_FIRST)
#if RETRO_IS_BIG_ENDIAN
#define swap_if_little64(val) (val)
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
#elif RETRO_IS_LITTLE_ENDIAN
#define swap_if_little64(val) (SWAP64(val))
#else
static INLINE uint64_t swap_if_little64(uint64_t val)
{
if (is_little_endian())
return SWAP64(val);
return val;
}
#endif
/**
@ -170,17 +190,10 @@ static INLINE uint64_t swap_if_little64(uint64_t val)
* otherwise returns same value.
**/
#if defined(MSB_FIRST)
#if RETRO_IS_BIG_ENDIAN
#define swap_if_little32(val) (val)
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
#elif RETRO_IS_LITTLE_ENDIAN
#define swap_if_little32(val) (SWAP32(val))
#else
static INLINE uint32_t swap_if_little32(uint32_t val)
{
if (is_little_endian())
return SWAP32(val);
return val;
}
#endif
/**
@ -193,17 +206,10 @@ static INLINE uint32_t swap_if_little32(uint32_t val)
* otherwise returns same value.
**/
#if defined(MSB_FIRST)
#if RETRO_IS_BIG_ENDIAN
#define swap_if_big16(val) (SWAP16(val))
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
#elif RETRO_IS_LITTLE_ENDIAN
#define swap_if_big16(val) (val)
#else
static INLINE uint16_t swap_if_big16(uint16_t val)
{
if (is_little_endian())
return val;
return SWAP16(val);
}
#endif
/**
@ -216,17 +222,10 @@ static INLINE uint16_t swap_if_big16(uint16_t val)
* otherwise returns same value.
**/
#if defined(MSB_FIRST)
#if RETRO_IS_BIG_ENDIAN
#define swap_if_little16(val) (val)
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
#elif RETRO_IS_LITTLE_ENDIAN
#define swap_if_little16(val) (SWAP16(val))
#else
static INLINE uint16_t swap_if_little16(uint16_t val)
{
if (is_little_endian())
return SWAP16(val);
return val;
}
#endif
/**
@ -255,4 +254,326 @@ static INLINE uint32_t load32be(const uint32_t *addr)
return swap_if_little32(*addr);
}
/**
* retro_cpu_to_le16:
* @val : unsigned 16-bit value
*
* Convert unsigned 16-bit value from system to little-endian.
*
* Returns: Little-endian representation of val.
**/
#define retro_cpu_to_le16(val) swap_if_big16(val)
/**
* retro_cpu_to_le32:
* @val : unsigned 32-bit value
*
* Convert unsigned 32-bit value from system to little-endian.
*
* Returns: Little-endian representation of val.
**/
#define retro_cpu_to_le32(val) swap_if_big32(val)
/**
* retro_cpu_to_le64:
* @val : unsigned 64-bit value
*
* Convert unsigned 64-bit value from system to little-endian.
*
* Returns: Little-endian representation of val.
**/
#define retro_cpu_to_le64(val) swap_if_big64(val)
/**
* retro_le_to_cpu16:
* @val : unsigned 16-bit value
*
* Convert unsigned 16-bit value from little-endian to native.
*
* Returns: Native representation of little-endian val.
**/
#define retro_le_to_cpu16(val) swap_if_big16(val)
/**
* retro_le_to_cpu32:
* @val : unsigned 32-bit value
*
* Convert unsigned 32-bit value from little-endian to native.
*
* Returns: Native representation of little-endian val.
**/
#define retro_le_to_cpu32(val) swap_if_big32(val)
/**
* retro_le_to_cpu16:
* @val : unsigned 64-bit value
*
* Convert unsigned 64-bit value from little-endian to native.
*
* Returns: Native representation of little-endian val.
**/
#define retro_le_to_cpu64(val) swap_if_big64(val)
/**
* retro_cpu_to_be16:
* @val : unsigned 16-bit value
*
* Convert unsigned 16-bit value from system to big-endian.
*
* Returns: Big-endian representation of val.
**/
#define retro_cpu_to_be16(val) swap_if_little16(val)
/**
* retro_cpu_to_be32:
* @val : unsigned 32-bit value
*
* Convert unsigned 32-bit value from system to big-endian.
*
* Returns: Big-endian representation of val.
**/
#define retro_cpu_to_be32(val) swap_if_little32(val)
/**
* retro_cpu_to_be64:
* @val : unsigned 64-bit value
*
* Convert unsigned 64-bit value from system to big-endian.
*
* Returns: Big-endian representation of val.
**/
#define retro_cpu_to_be64(val) swap_if_little64(val)
/**
* retro_be_to_cpu16:
* @val : unsigned 16-bit value
*
* Convert unsigned 16-bit value from big-endian to native.
*
* Returns: Native representation of big-endian val.
**/
#define retro_be_to_cpu16(val) swap_if_little16(val)
/**
* retro_be_to_cpu32:
* @val : unsigned 32-bit value
*
* Convert unsigned 32-bit value from big-endian to native.
*
* Returns: Native representation of big-endian val.
**/
#define retro_be_to_cpu32(val) swap_if_little32(val)
/**
* retro_be_to_cpu64:
* @val : unsigned 64-bit value
*
* Convert unsigned 64-bit value from big-endian to native.
*
* Returns: Native representation of big-endian val.
**/
#define retro_be_to_cpu64(val) swap_if_little64(val)
#ifdef __GNUC__
/* This attribute means that the same memory may be referred through
pointers to different size of the object (aliasing). E.g. that u8 *
and u32 * may actually be pointing to the same object. */
#define MAY_ALIAS __attribute__((__may_alias__))
#else
#define MAY_ALIAS
#endif
#pragma pack(push, 1)
struct retro_unaligned_uint16_s
{
uint16_t val;
} MAY_ALIAS;
struct retro_unaligned_uint32_s
{
uint32_t val;
} MAY_ALIAS;
struct retro_unaligned_uint64_s
{
uint64_t val;
} MAY_ALIAS;
#pragma pack(pop)
typedef struct retro_unaligned_uint16_s retro_unaligned_uint16_t;
typedef struct retro_unaligned_uint32_s retro_unaligned_uint32_t;
typedef struct retro_unaligned_uint64_s retro_unaligned_uint64_t;
/* L-value references to unaligned pointers. */
#define retro_unaligned16(p) (((retro_unaligned_uint16_t *)p)->val)
#define retro_unaligned32(p) (((retro_unaligned_uint32_t *)p)->val)
#define retro_unaligned64(p) (((retro_unaligned_uint64_t *)p)->val)
/**
* retro_get_unaligned_16be:
* @addr : pointer to unsigned 16-bit value
*
* Convert unsigned unaligned 16-bit value from big-endian to native.
*
* Returns: Native representation of big-endian val.
**/
static INLINE uint16_t retro_get_unaligned_16be(void *addr) {
return retro_be_to_cpu16(retro_unaligned16(addr));
}
/**
* retro_get_unaligned_32be:
* @addr : pointer to unsigned 32-bit value
*
* Convert unsigned unaligned 32-bit value from big-endian to native.
*
* Returns: Native representation of big-endian val.
**/
static INLINE uint32_t retro_get_unaligned_32be(void *addr) {
return retro_be_to_cpu32(retro_unaligned32(addr));
}
/**
* retro_get_unaligned_64be:
* @addr : pointer to unsigned 64-bit value
*
* Convert unsigned unaligned 64-bit value from big-endian to native.
*
* Returns: Native representation of big-endian val.
**/
static INLINE uint64_t retro_get_unaligned_64be(void *addr) {
return retro_be_to_cpu64(retro_unaligned64(addr));
}
/**
* retro_get_unaligned_16le:
* @addr : pointer to unsigned 16-bit value
*
* Convert unsigned unaligned 16-bit value from little-endian to native.
*
* Returns: Native representation of little-endian val.
**/
static INLINE uint16_t retro_get_unaligned_16le(void *addr) {
return retro_le_to_cpu16(retro_unaligned16(addr));
}
/**
* retro_get_unaligned_32le:
* @addr : pointer to unsigned 32-bit value
*
* Convert unsigned unaligned 32-bit value from little-endian to native.
*
* Returns: Native representation of little-endian val.
**/
static INLINE uint32_t retro_get_unaligned_32le(void *addr) {
return retro_le_to_cpu32(retro_unaligned32(addr));
}
/**
* retro_get_unaligned_64le:
* @addr : pointer to unsigned 64-bit value
*
* Convert unsigned unaligned 64-bit value from little-endian to native.
*
* Returns: Native representation of little-endian val.
**/
static INLINE uint64_t retro_get_unaligned_64le(void *addr) {
return retro_le_to_cpu64(retro_unaligned64(addr));
}
/**
* retro_set_unaligned_16le:
* @addr : pointer to unsigned 16-bit value
* @val : value to store
*
* Convert native value to unsigned unaligned 16-bit little-endian value
*
**/
static INLINE void retro_set_unaligned_16le(void *addr, uint16_t v) {
retro_unaligned16(addr) = retro_cpu_to_le16(v);
}
/**
* retro_set_unaligned_32le:
* @addr : pointer to unsigned 32-bit value
* @val : value to store
*
* Convert native value to unsigned unaligned 32-bit little-endian value
*
**/
static INLINE void retro_set_unaligned_32le(void *addr, uint32_t v) {
retro_unaligned32(addr) = retro_cpu_to_le32(v);
}
/**
* retro_set_unaligned_32le:
* @addr : pointer to unsigned 32-bit value
* @val : value to store
*
* Convert native value to unsigned unaligned 32-bit little-endian value
*
**/
static INLINE void retro_set_unaligned_64le(void *addr, uint64_t v) {
retro_unaligned64(addr) = retro_cpu_to_le64(v);
}
/**
* retro_set_unaligned_16be:
* @addr : pointer to unsigned 16-bit value
* @val : value to store
*
* Convert native value to unsigned unaligned 16-bit big-endian value
*
**/
static INLINE void retro_set_unaligned_16be(void *addr, uint16_t v) {
retro_unaligned16(addr) = retro_cpu_to_be16(v);
}
/**
* retro_set_unaligned_32be:
* @addr : pointer to unsigned 32-bit value
* @val : value to store
*
* Convert native value to unsigned unaligned 32-bit big-endian value
*
**/
static INLINE void retro_set_unaligned_32be(void *addr, uint32_t v) {
retro_unaligned32(addr) = retro_cpu_to_be32(v);
}
/**
* retro_set_unaligned_32be:
* @addr : pointer to unsigned 32-bit value
* @val : value to store
*
* Convert native value to unsigned unaligned 32-bit big-endian value
*
**/
static INLINE void retro_set_unaligned_64be(void *addr, uint64_t v) {
retro_unaligned64(addr) = retro_cpu_to_be64(v);
}
#endif

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_environment.h).

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_inline.h).

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_miscellaneous.h).
@ -30,17 +30,17 @@
#include <boolean.h>
#include <retro_inline.h>
#if defined(_WIN32) && !defined(_XBOX)
#if defined(_WIN32)
#if defined(_XBOX)
#include <Xtl.h>
#else
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#elif defined(_WIN32) && defined(_XBOX)
#include <Xtl.h>
#endif
#if defined(__CELLOS_LV2__)
#include <sys/fs_external.h>
#endif
#include <limits.h>
@ -75,15 +75,17 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
}
#ifndef PATH_MAX_LENGTH
#if defined(__CELLOS_LV2__)
#define PATH_MAX_LENGTH CELL_FS_MAX_FS_PATH_LENGTH
#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(ORBIS)
#if defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(ORBIS) || defined(__PSL1GHT__) || defined(__PS3__)
#define PATH_MAX_LENGTH 512
#else
#define PATH_MAX_LENGTH 4096
#endif
#endif
#ifndef NAME_MAX_LENGTH
#define NAME_MAX_LENGTH 256
#endif
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
@ -106,8 +108,8 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
#define BIT16_GET(a, bit) (((a) >> ((bit) & 15)) & 1)
#define BIT16_CLEAR_ALL(a) ((a) = 0)
#define BIT32_SET(a, bit) ((a) |= (1 << ((bit) & 31)))
#define BIT32_CLEAR(a, bit) ((a) &= ~(1 << ((bit) & 31)))
#define BIT32_SET(a, bit) ((a) |= (UINT32_C(1) << ((bit) & 31)))
#define BIT32_CLEAR(a, bit) ((a) &= ~(UINT32_C(1) << ((bit) & 31)))
#define BIT32_GET(a, bit) (((a) >> ((bit) & 31)) & 1)
#define BIT32_CLEAR_ALL(a) ((a) = 0)
@ -116,8 +118,8 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
#define BIT64_GET(a, bit) (((a) >> ((bit) & 63)) & 1)
#define BIT64_CLEAR_ALL(a) ((a) = 0)
#define BIT128_SET(a, bit) ((a).data[(bit) >> 5] |= (1 << ((bit) & 31)))
#define BIT128_CLEAR(a, bit) ((a).data[(bit) >> 5] &= ~(1 << ((bit) & 31)))
#define BIT128_SET(a, bit) ((a).data[(bit) >> 5] |= (UINT32_C(1) << ((bit) & 31)))
#define BIT128_CLEAR(a, bit) ((a).data[(bit) >> 5] &= ~(UINT32_C(1) << ((bit) & 31)))
#define BIT128_GET(a, bit) (((a).data[(bit) >> 5] >> ((bit) & 31)) & 1)
#define BIT128_CLEAR_ALL(a) memset(&(a), 0, sizeof(a))
@ -136,6 +138,16 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
#define BIT256_GET_PTR(a, bit) BIT256_GET(*a, bit)
#define BIT256_CLEAR_ALL_PTR(a) BIT256_CLEAR_ALL(*a)
#define BIT512_SET(a, bit) BIT256_SET(a, bit)
#define BIT512_CLEAR(a, bit) BIT256_CLEAR(a, bit)
#define BIT512_GET(a, bit) BIT256_GET(a, bit)
#define BIT512_CLEAR_ALL(a) BIT256_CLEAR_ALL(a)
#define BIT512_SET_PTR(a, bit) BIT512_SET(*a, bit)
#define BIT512_CLEAR_PTR(a, bit) BIT512_CLEAR(*a, bit)
#define BIT512_GET_PTR(a, bit) BIT512_GET(*a, bit)
#define BIT512_CLEAR_ALL_PTR(a) BIT512_CLEAR_ALL(*a)
#define BITS_COPY16_PTR(a,bits) \
{ \
BIT128_CLEAR_ALL_PTR(a); \
@ -148,6 +160,13 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
BITS_GET_ELEM_PTR(a, 0) = (bits); \
}
#define BITS_COPY64_PTR(a,bits) \
{ \
BIT128_CLEAR_ALL_PTR(a); \
BITS_GET_ELEM_PTR(a, 0) = (bits); \
BITS_GET_ELEM_PTR(a, 1) = (bits >> 32); \
}
/* Helper macros and struct to keep track of many booleans. */
/* This struct has 256 bits. */
typedef struct
@ -155,6 +174,12 @@ typedef struct
uint32_t data[8];
} retro_bits_t;
/* This struct has 512 bits. */
typedef struct
{
uint32_t data[16];
} retro_bits_512_t;
#ifdef _WIN32
# ifdef _WIN64
# define PRI_SIZET PRIu64
@ -165,7 +190,7 @@ typedef struct
# define PRI_SIZET "u"
# endif
# endif
#elif PS2
#elif defined(PS2)
# define PRI_SIZET "u"
#else
# if (SIZE_MAX == 0xFFFF)

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream.h).
@ -81,6 +81,8 @@ char* filestream_gets(RFILE *stream, char *s, size_t len);
int filestream_getc(RFILE *stream);
int filestream_vscanf(RFILE *stream, const char* format, va_list *args);
int filestream_scanf(RFILE *stream, const char* format, ...);
int filestream_eof(RFILE *stream);

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream_transforms.h).

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2019 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (stdstring.h).
@ -35,6 +35,33 @@
RETRO_BEGIN_DECLS
#define STRLEN_CONST(x) ((sizeof((x))-1))
#define strcpy_literal(a, b) strcpy(a, b)
#define string_is_not_equal(a, b) !string_is_equal((a), (b))
#define string_is_not_equal_fast(a, b, size) (memcmp(a, b, size) != 0)
#define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0)
#define TOLOWER(c) ((c) | (lr_char_props[(unsigned char)(c)] & 0x20))
#define TOUPPER(c) ((c) & ~(lr_char_props[(unsigned char)(c)] & 0x20))
/* C standard says \f \v are space, but this one disagrees */
#define ISSPACE(c) (lr_char_props[(unsigned char)(c)] & 0x80)
#define ISDIGIT(c) (lr_char_props[(unsigned char)(c)] & 0x40)
#define ISALPHA(c) (lr_char_props[(unsigned char)(c)] & 0x20)
#define ISLOWER(c) (lr_char_props[(unsigned char)(c)] & 0x04)
#define ISUPPER(c) (lr_char_props[(unsigned char)(c)] & 0x02)
#define ISALNUM(c) (lr_char_props[(unsigned char)(c)] & 0x60)
#define ISUALPHA(c) (lr_char_props[(unsigned char)(c)] & 0x28)
#define ISUALNUM(c) (lr_char_props[(unsigned char)(c)] & 0x68)
#define IS_XDIGIT(c) (lr_char_props[(unsigned char)(c)] & 0x01)
/* Deprecated alias, all callers should use string_is_equal_case_insensitive instead */
#define string_is_equal_noncase string_is_equal_case_insensitive
static INLINE bool string_is_empty(const char *data)
{
return !data || (*data == '\0');
@ -45,12 +72,44 @@ static INLINE bool string_is_equal(const char *a, const char *b)
return (a && b) ? !strcmp(a, b) : false;
}
#define STRLEN_CONST(x) ((sizeof((x))-1))
static INLINE bool string_starts_with_size(const char *str, const char *prefix,
size_t size)
{
return (str && prefix) ? !strncmp(prefix, str, size) : false;
}
#define string_is_not_equal(a, b) !string_is_equal((a), (b))
static INLINE bool string_starts_with(const char *str, const char *prefix)
{
return (str && prefix) ? !strncmp(prefix, str, strlen(prefix)) : false;
}
static INLINE bool string_ends_with_size(const char *str, const char *suffix,
size_t str_len, size_t suffix_len)
{
return (str_len < suffix_len) ? false :
!memcmp(suffix, str + (str_len - suffix_len), suffix_len);
}
static INLINE bool string_ends_with(const char *str, const char *suffix)
{
if (!str || !suffix)
return false;
return string_ends_with_size(str, suffix, strlen(str), strlen(suffix));
}
/* Returns the length of 'str' (c.f. strlen()), but only
* checks the first 'size' characters
* - If 'str' is NULL, returns 0
* - If 'str' is not NULL and no '\0' character is found
* in the first 'size' characters, returns 'size' */
static INLINE size_t strlen_size(const char *str, size_t size)
{
size_t i = 0;
if (str)
while (i < size && str[i]) i++;
return i;
}
#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 bool string_is_equal_case_insensitive(const char *a,
const char *b)
@ -71,22 +130,23 @@ static INLINE bool string_is_equal_case_insensitive(const char *a,
return (result == 0);
}
static INLINE bool string_is_equal_noncase(const char *a, const char *b)
static INLINE bool string_starts_with_case_insensitive(const char *str,
const char *prefix)
{
int result = 0;
const unsigned char *p1 = (const unsigned char*)a;
const unsigned char *p2 = (const unsigned char*)b;
const unsigned char *p1 = (const unsigned char*)str;
const unsigned char *p2 = (const unsigned char*)prefix;
if (!a || !b)
if (!str || !prefix)
return false;
if (p1 == p2)
return false;
return true;
while ((result = tolower (*p1) - tolower (*p2++)) == 0)
if (*p1++ == '\0')
while ((result = tolower (*p1++) - tolower (*p2)) == 0)
if (*p2++ == '\0')
break;
return (result == 0);
return (result == 0 || *p2 == '\0');
}
char *string_to_upper(char *s);
@ -107,9 +167,61 @@ char *string_trim_whitespace_right(char *const s);
/* Remove leading and trailing whitespaces */
char *string_trim_whitespace(char *const s);
/* max_lines == 0 means no limit */
char *word_wrap(char *buffer, const char *string,
int line_width, bool unicode, unsigned max_lines);
/*
* Wraps string specified by 'src' to destination buffer
* specified by 'dst' and 'dst_size'.
* This function assumes that all glyphs in the string
* have an on-screen pixel width similar to that of
* regular Latin characters - i.e. it will not wrap
* correctly any text containing so-called 'wide' Unicode
* characters (e.g. CJK languages, emojis, etc.).
*
* @param dst pointer to destination buffer.
* @param dst_size size of destination buffer.
* @param src pointer to input string.
* @param line_width max number of characters per line.
* @param wideglyph_width not used, but is necessary to keep
* compatibility with word_wrap_wideglyph().
* @param max_lines max lines of destination string.
* 0 means no limit.
*/
void word_wrap(char *dst, size_t dst_size, const char *src,
int line_width, int wideglyph_width, unsigned max_lines);
/*
* Wraps string specified by 'src' to destination buffer
* specified by 'dst' and 'dst_size'.
* This function assumes that all glyphs in the string
* are:
* - EITHER 'non-wide' Unicode glyphs, with an on-screen
* pixel width similar to that of regular Latin characters
* - OR 'wide' Unicode glyphs (e.g. CJK languages, emojis, etc.)
* with an on-screen pixel width defined by 'wideglyph_width'
* Note that wrapping may occur in inappropriate locations
* if 'src' string contains 'wide' Unicode characters whose
* on-screen pixel width deviates greatly from the set
* 'wideglyph_width' value.
*
* @param dst pointer to destination buffer.
* @param dst_size size of destination buffer.
* @param src pointer to input string.
* @param line_width max number of characters per line.
* @param wideglyph_width effective width of 'wide' Unicode glyphs.
* the value here is normalised relative to the
* typical on-screen pixel width of a regular
* Latin character:
* - a regular Latin character is defined to
* have an effective width of 100
* - wideglyph_width = 100 * (wide_character_pixel_width / latin_character_pixel_width)
* - e.g. if 'wide' Unicode characters in 'src'
* have an on-screen pixel width twice that of
* regular Latin characters, wideglyph_width
* would be 200
* @param max_lines max lines of destination string.
* 0 means no limit.
*/
void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src,
int line_width, int wideglyph_width, unsigned max_lines);
/* Splits string into tokens seperated by 'delim'
* > Returned token string must be free()'d
@ -121,7 +233,7 @@ char *word_wrap(char *buffer, const char *string,
* char *str = "1,2,3,4,5,6,7,,,10,";
* char **str_ptr = &str;
* char *token = NULL;
* while((token = string_tokenize(str_ptr, ",")))
* while ((token = string_tokenize(str_ptr, ",")))
* {
* printf("%s\n", token);
* free(token);
@ -146,6 +258,30 @@ unsigned string_to_unsigned(const char *str);
* Returns 0 if string is invalid */
unsigned string_hex_to_unsigned(const char *str);
char *string_init(const char *src);
void string_set(char **string, const char *src);
extern const unsigned char lr_char_props[256];
/* Get the total number of occurrences of a character in the given string. */
int string_count_occurrences_single_character(char *str, char t);
/* Replaces all spaces with the given character. */
void string_replace_whitespace_with_single_character(char *str, char t);
/* Replaces multiple spaces with a single space in a string. */
void string_replace_multi_space_with_single_space(char *str);
/* Remove all spaces from the given string. */
void string_remove_all_whitespace(char* str_trimmed, const char* str_untrimmed);
/* Retrieve the last occurance of the given character in a string. */
int string_index_last_occurance(char str[], char t);
/* Find the position of a substring in a string. */
int string_find_index_substring_string(const char* str1, const char* str2);
RETRO_END_DECLS
#endif

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2019 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (vfs_implementation.h).
@ -41,17 +41,17 @@ typedef void* HANDLE;
#ifdef HAVE_CDROM
typedef struct
{
int64_t byte_pos;
char *cue_buf;
size_t cue_len;
int64_t byte_pos;
char drive;
unsigned cur_lba;
unsigned last_frame_lba;
unsigned char cur_min;
unsigned char cur_sec;
unsigned char cur_frame;
unsigned char cur_track;
unsigned cur_lba;
unsigned last_frame_lba;
unsigned char last_frame[2352];
char drive;
bool last_frame_valid;
} vfs_cdrom_t;
#endif
@ -62,29 +62,29 @@ enum vfs_scheme
VFS_SCHEME_CDROM
};
#ifndef __WINRT__
#if !(defined(__WINRT__) && defined(__cplusplus_winrt))
#ifdef VFS_FRONTEND
struct retro_vfs_file_handle
#else
struct libretro_vfs_implementation_file
#endif
{
int fd;
unsigned hints;
#ifdef HAVE_CDROM
vfs_cdrom_t cdrom; /* int64_t alignment */
#endif
int64_t size;
char *buf;
uint64_t mappos;
uint64_t mapsize;
FILE *fp;
#ifdef _WIN32
HANDLE fh;
#endif
char *buf;
char* orig_path;
uint64_t mappos;
uint64_t mapsize;
uint8_t *mapped;
int fd;
unsigned hints;
enum vfs_scheme scheme;
#ifdef HAVE_CDROM
vfs_cdrom_t cdrom;
#endif
};
#endif

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2019 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (vfs_implementation.h).
@ -71,6 +71,12 @@ bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *dirstream);
int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *dirstream);
#ifdef __WINRT__
void uwp_set_acl(const wchar_t* path, const wchar_t* AccessString);
#endif
RETRO_END_DECLS
#endif

View file

@ -0,0 +1,163 @@
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (memmap.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdint.h>
#include <memmap.h>
#ifndef PROT_READ
#define PROT_READ 0x1 /* Page can be read */
#endif
#ifndef PROT_WRITE
#define PROT_WRITE 0x2 /* Page can be written. */
#endif
#ifndef PROT_READWRITE
#define PROT_READWRITE 0x3 /* Page can be written to and read from. */
#endif
#ifndef PROT_EXEC
#define PROT_EXEC 0x4 /* Page can be executed. */
#endif
#ifndef PROT_NONE
#define PROT_NONE 0x0 /* Page can not be accessed. */
#endif
#ifndef MAP_FAILED
#define MAP_FAILED ((void *) -1)
#endif
#ifdef _WIN32
void* mmap(void *addr, size_t len, int prot, int flags,
int fildes, size_t offset)
{
void *map = (void*)NULL;
HANDLE handle = INVALID_HANDLE_VALUE;
switch (prot)
{
case PROT_READ:
default:
handle = CreateFileMapping((HANDLE)
_get_osfhandle(fildes), 0, PAGE_READONLY, 0,
len, 0);
if (!handle)
break;
map = (void*)MapViewOfFile(handle, FILE_MAP_READ, 0, 0, len);
CloseHandle(handle);
break;
case PROT_WRITE:
handle = CreateFileMapping((HANDLE)
_get_osfhandle(fildes),0,PAGE_READWRITE,0,
len, 0);
if (!handle)
break;
map = (void*)MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, len);
CloseHandle(handle);
break;
case PROT_READWRITE:
handle = CreateFileMapping((HANDLE)
_get_osfhandle(fildes),0,PAGE_READWRITE,0,
len, 0);
if (!handle)
break;
map = (void*)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, len);
CloseHandle(handle);
break;
}
if (map == (void*)NULL)
return((void*)MAP_FAILED);
return((void*) ((int8_t*)map + offset));
}
int munmap(void *addr, size_t length)
{
if (!UnmapViewOfFile(addr))
return -1;
return 0;
}
int mprotect(void *addr, size_t len, int prot)
{
/* Incomplete, just assumes PAGE_EXECUTE_READWRITE right now
* instead of correctly handling prot */
prot = 0;
if (prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
prot = PAGE_EXECUTE_READWRITE;
return VirtualProtect(addr, len, prot, 0);
}
#elif !defined(HAVE_MMAN)
void* mmap(void *addr, size_t len, int prot, int flags,
int fildes, size_t offset)
{
return malloc(len);
}
int munmap(void *addr, size_t len)
{
free(addr);
return 0;
}
int mprotect(void *addr, size_t len, int prot)
{
/* stub - not really needed at this point
* since this codepath has no dynarecs. */
return 0;
}
#endif
#if defined(__MACH__) && defined(__arm__)
#include <libkern/OSCacheControl.h>
#endif
int memsync(void *start, void *end)
{
size_t len = (char*)end - (char*)start;
#if defined(__MACH__) && defined(__arm__)
sys_dcache_flush(start ,len);
sys_icache_invalidate(start, len);
return 0;
#elif defined(__arm__) && !defined(__QNX__)
(void)len;
__clear_cache(start, end);
return 0;
#elif defined(HAVE_MMAN)
return msync(start, len, MS_SYNC | MS_INVALIDATE
#ifdef __QNX__
MS_CACHE_ONLY
#endif
);
#else
(void)len;
return 0;
#endif
}
int memprotect(void *addr, size_t len)
{
return mprotect(addr, len, PROT_READ | PROT_WRITE | PROT_EXEC);
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream.c).
@ -31,11 +31,23 @@
#include "config.h"
#endif
#ifdef _MSC_VER
#include <compat/msvc.h>
#endif
#include <string/stdstring.h>
#include <streams/file_stream.h>
#define VFS_FRONTEND
#include <vfs/vfs_implementation.h>
static const int64_t vfs_error_return_value = -1;
#define VFS_ERROR_RETURN_VALUE -1
struct RFILE
{
struct retro_vfs_file_handle *hfile;
bool error_flag;
bool eof_flag;
};
static retro_vfs_get_path_t filestream_get_path_cb = NULL;
static retro_vfs_open_t filestream_open_cb = NULL;
@ -50,18 +62,12 @@ static retro_vfs_flush_t filestream_flush_cb = NULL;
static retro_vfs_remove_t filestream_remove_cb = NULL;
static retro_vfs_rename_t filestream_rename_cb = NULL;
struct RFILE
{
struct retro_vfs_file_handle *hfile;
bool error_flag;
bool eof_flag;
};
/* VFS Initialization */
void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info)
{
const struct retro_vfs_interface* vfs_iface;
const struct retro_vfs_interface *
vfs_iface = vfs_info->iface;
filestream_get_path_cb = NULL;
filestream_open_cb = NULL;
@ -76,9 +82,9 @@ void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info)
filestream_remove_cb = NULL;
filestream_rename_cb = NULL;
vfs_iface = vfs_info->iface;
if (vfs_info->required_interface_version < FILESTREAM_REQUIRED_VFS_VERSION
if (
(vfs_info->required_interface_version <
FILESTREAM_REQUIRED_VFS_VERSION)
|| !vfs_iface)
return;
@ -104,14 +110,19 @@ bool filestream_exists(const char *path)
if (!path || !*path)
return false;
dummy = filestream_open(path,
dummy = filestream_open(
path,
RETRO_VFS_FILE_ACCESS_READ,
RETRO_VFS_FILE_ACCESS_HINT_NONE);
if (!dummy)
return false;
filestream_close(dummy);
if (filestream_close(dummy) != 0)
if (dummy)
free(dummy);
dummy = NULL;
return true;
}
@ -119,12 +130,13 @@ int64_t filestream_get_size(RFILE *stream)
{
int64_t output;
if (filestream_size_cb != NULL)
if (filestream_size_cb)
output = filestream_size_cb(stream->hfile);
else
output = retro_vfs_file_size_impl((libretro_vfs_implementation_file*)stream->hfile);
output = retro_vfs_file_size_impl(
(libretro_vfs_implementation_file*)stream->hfile);
if (output == vfs_error_return_value)
if (output == VFS_ERROR_RETURN_VALUE)
stream->error_flag = true;
return output;
@ -134,12 +146,13 @@ int64_t filestream_truncate(RFILE *stream, int64_t length)
{
int64_t output;
if (filestream_truncate_cb != NULL)
if (filestream_truncate_cb)
output = filestream_truncate_cb(stream->hfile, length);
else
output = retro_vfs_file_truncate_impl((libretro_vfs_implementation_file*)stream->hfile, length);
output = retro_vfs_file_truncate_impl(
(libretro_vfs_implementation_file*)stream->hfile, length);
if (output == vfs_error_return_value)
if (output == VFS_ERROR_RETURN_VALUE)
stream->error_flag = true;
return output;
@ -159,7 +172,7 @@ RFILE* filestream_open(const char *path, unsigned mode, unsigned hints)
struct retro_vfs_file_handle *fp = NULL;
RFILE* output = NULL;
if (filestream_open_cb != NULL)
if (filestream_open_cb)
fp = (struct retro_vfs_file_handle*)
filestream_open_cb(path, mode, hints);
else
@ -203,22 +216,19 @@ char* filestream_gets(RFILE *stream, char *s, size_t len)
int filestream_getc(RFILE *stream)
{
char c = 0;
if (!stream)
return EOF;
if (filestream_read(stream, &c, 1) == 1)
if (stream && filestream_read(stream, &c, 1) == 1)
return (int)(unsigned char)c;
return EOF;
}
int filestream_scanf(RFILE *stream, const char* format, ...)
int filestream_vscanf(RFILE *stream, const char* format, va_list *args)
{
char buf[4096];
char subfmt[64];
va_list args;
va_list args_copy;
const char * bufiter = buf;
int64_t startpos = filestream_tell(stream);
int ret = 0;
int64_t startpos = filestream_tell(stream);
int64_t maxlen = filestream_read(stream, buf, sizeof(buf)-1);
if (maxlen <= 0)
@ -226,14 +236,22 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
buf[maxlen] = '\0';
va_start(args, format);
/* Have to copy the input va_list here
* > Calling va_arg() on 'args' directly would
* cause the va_list to have an indeterminate value
* in the function calling filestream_vscanf(),
* leading to unexpected behaviour */
#ifdef __va_copy
__va_copy(args_copy, *args);
#else
va_copy(args_copy, *args);
#endif
while (*format)
{
if (*format == '%')
{
int sublen;
char* subfmtiter = subfmt;
bool asterisk = false;
@ -247,15 +265,21 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
*subfmtiter++ = *format++;
}
while (isdigit(*format)) *subfmtiter++ = *format++; /* width */
while (ISDIGIT((unsigned char)*format))
*subfmtiter++ = *format++; /* width */
/* length */
if (*format == 'h' || *format == 'l')
{
if (format[1] == format[0]) *subfmtiter++ = *format++;
if (format[1] == format[0])
*subfmtiter++ = *format++;
*subfmtiter++ = *format++;
}
else if (*format == 'j' || *format == 'z' || *format == 't' || *format == 'L')
else if (
*format == 'j' ||
*format == 'z' ||
*format == 't' ||
*format == 'L')
{
*subfmtiter++ = *format++;
}
@ -263,31 +287,44 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
/* specifier - always a single character (except ]) */
if (*format == '[')
{
while (*format != ']') *subfmtiter++ = *format++;
while (*format != ']')
*subfmtiter++ = *format++;
*subfmtiter++ = *format++;
}
else *subfmtiter++ = *format++;
else
*subfmtiter++ = *format++;
*subfmtiter++ = '%';
*subfmtiter++ = 'n';
*subfmtiter++ = '\0';
if (sizeof(void*) != sizeof(long*)) abort(); /* all pointers must have the same size */
if (sizeof(void*) != sizeof(long*))
abort(); /* all pointers must have the same size */
if (asterisk)
{
if (sscanf(bufiter, subfmt, &sublen) != 0) break;
int v = sscanf(bufiter, subfmt, &sublen);
if (v == EOF)
return EOF;
if (v != 0)
break;
}
else
{
if (sscanf(bufiter, subfmt, va_arg(args, void*), &sublen) != 1) break;
int v = sscanf(bufiter, subfmt, va_arg(args_copy, void*), &sublen);
if (v == EOF)
return EOF;
if (v != 1)
break;
}
ret++;
bufiter += sublen;
}
else if (isspace(*format))
else if (isspace((unsigned char)*format))
{
while (isspace(*bufiter)) bufiter++;
while (isspace((unsigned char)*bufiter))
bufiter++;
format++;
}
else
@ -299,23 +336,37 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
}
}
va_end(args);
filestream_seek(stream, startpos+(bufiter-buf), RETRO_VFS_SEEK_POSITION_START);
va_end(args_copy);
filestream_seek(stream, startpos+(bufiter-buf),
RETRO_VFS_SEEK_POSITION_START);
return ret;
}
int filestream_scanf(RFILE *stream, const char* format, ...)
{
int result;
va_list vl;
va_start(vl, format);
result = filestream_vscanf(stream, format, &vl);
va_end(vl);
return result;
}
int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position)
{
int64_t output;
if (filestream_seek_cb != NULL)
if (filestream_seek_cb)
output = filestream_seek_cb(stream->hfile, offset, seek_position);
else
output = retro_vfs_file_seek_impl((libretro_vfs_implementation_file*)stream->hfile, offset, seek_position);
output = retro_vfs_file_seek_impl(
(libretro_vfs_implementation_file*)stream->hfile,
offset, seek_position);
if (output == vfs_error_return_value)
if (output == VFS_ERROR_RETURN_VALUE)
stream->error_flag = true;
stream->eof_flag = false;
return output;
@ -330,12 +381,13 @@ int64_t filestream_tell(RFILE *stream)
{
int64_t output;
if (filestream_size_cb != NULL)
if (filestream_size_cb)
output = filestream_tell_cb(stream->hfile);
else
output = retro_vfs_file_tell_impl((libretro_vfs_implementation_file*)stream->hfile);
output = retro_vfs_file_tell_impl(
(libretro_vfs_implementation_file*)stream->hfile);
if (output == vfs_error_return_value)
if (output == VFS_ERROR_RETURN_VALUE)
stream->error_flag = true;
return output;
@ -354,13 +406,13 @@ int64_t filestream_read(RFILE *stream, void *s, int64_t len)
{
int64_t output;
if (filestream_read_cb != NULL)
if (filestream_read_cb)
output = filestream_read_cb(stream->hfile, s, len);
else
output = retro_vfs_file_read_impl(
(libretro_vfs_implementation_file*)stream->hfile, s, len);
if (output == vfs_error_return_value)
if (output == VFS_ERROR_RETURN_VALUE)
stream->error_flag = true;
if (output < len)
stream->eof_flag = true;
@ -372,12 +424,13 @@ int filestream_flush(RFILE *stream)
{
int output;
if (filestream_flush_cb != NULL)
if (filestream_flush_cb)
output = filestream_flush_cb(stream->hfile);
else
output = retro_vfs_file_flush_impl((libretro_vfs_implementation_file*)stream->hfile);
output = retro_vfs_file_flush_impl(
(libretro_vfs_implementation_file*)stream->hfile);
if (output == vfs_error_return_value)
if (output == VFS_ERROR_RETURN_VALUE)
stream->error_flag = true;
return output;
@ -385,7 +438,7 @@ int filestream_flush(RFILE *stream)
int filestream_delete(const char *path)
{
if (filestream_remove_cb != NULL)
if (filestream_remove_cb)
return filestream_remove_cb(path);
return retro_vfs_file_remove_impl(path);
@ -393,7 +446,7 @@ int filestream_delete(const char *path)
int filestream_rename(const char *old_path, const char *new_path)
{
if (filestream_rename_cb != NULL)
if (filestream_rename_cb)
return filestream_rename_cb(old_path, new_path);
return retro_vfs_file_rename_impl(old_path, new_path);
@ -401,22 +454,24 @@ int filestream_rename(const char *old_path, const char *new_path)
const char* filestream_get_path(RFILE *stream)
{
if (filestream_get_path_cb != NULL)
if (filestream_get_path_cb)
return filestream_get_path_cb(stream->hfile);
return retro_vfs_file_get_path_impl((libretro_vfs_implementation_file*)stream->hfile);
return retro_vfs_file_get_path_impl(
(libretro_vfs_implementation_file*)stream->hfile);
}
int64_t filestream_write(RFILE *stream, const void *s, int64_t len)
{
int64_t output;
if (filestream_write_cb != NULL)
if (filestream_write_cb)
output = filestream_write_cb(stream->hfile, s, len);
else
output = retro_vfs_file_write_impl((libretro_vfs_implementation_file*)stream->hfile, s, len);
output = retro_vfs_file_write_impl(
(libretro_vfs_implementation_file*)stream->hfile, s, len);
if (output == vfs_error_return_value)
if (output == VFS_ERROR_RETURN_VALUE)
stream->error_flag = true;
return output;
@ -427,13 +482,16 @@ int filestream_putc(RFILE *stream, int c)
char c_char = (char)c;
if (!stream)
return EOF;
return filestream_write(stream, &c_char, 1)==1 ? (int)(unsigned char)c : EOF;
return filestream_write(stream, &c_char, 1) == 1
? (int)(unsigned char)c
: EOF;
}
int filestream_vprintf(RFILE *stream, const char* format, va_list args)
{
static char buffer[8 * 1024];
int64_t num_chars = vsprintf(buffer, format, args);
int64_t num_chars = vsnprintf(buffer, sizeof(buffer),
format, args);
if (num_chars < 0)
return -1;
@ -465,10 +523,11 @@ int filestream_close(RFILE *stream)
int output;
struct retro_vfs_file_handle* fp = stream->hfile;
if (filestream_close_cb != NULL)
if (filestream_close_cb)
output = filestream_close_cb(fp);
else
output = retro_vfs_file_close_impl((libretro_vfs_implementation_file*)fp);
output = retro_vfs_file_close_impl(
(libretro_vfs_implementation_file*)fp);
if (output == 0)
free(stream);
@ -481,10 +540,11 @@ int filestream_close(RFILE *stream)
* @path : path to file.
* @buf : buffer to allocate and read the contents of the
* file into. Needs to be freed manually.
* @len : optional output integer containing bytes read.
*
* Read the contents of a file into @buf.
*
* Returns: number of items read, -1 on error.
* Returns: non zero on success.
*/
int64_t filestream_read_file(const char *path, void **buf, int64_t *len)
{
@ -497,8 +557,8 @@ int64_t filestream_read_file(const char *path, void **buf, int64_t *len)
if (!file)
{
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
goto error;
*buf = NULL;
return 0;
}
content_buf_size = filestream_get_size(file);
@ -515,12 +575,11 @@ int64_t filestream_read_file(const char *path, void **buf, int64_t *len)
ret = filestream_read(file, content_buf, (int64_t)content_buf_size);
if (ret < 0)
{
fprintf(stderr, "Failed to read %s: %s\n", path, strerror(errno));
goto error;
}
filestream_close(file);
if (filestream_close(file) != 0)
if (file)
free(file);
*buf = content_buf;
@ -535,7 +594,8 @@ int64_t filestream_read_file(const char *path, void **buf, int64_t *len)
error:
if (file)
filestream_close(file);
if (filestream_close(file) != 0)
free(file);
if (content_buf)
free(content_buf);
if (len)
@ -564,7 +624,9 @@ bool filestream_write_file(const char *path, const void *data, int64_t size)
return false;
ret = filestream_write(file, data, size);
filestream_close(file);
if (filestream_close(file) != 0)
if (file)
free(file);
if (ret != size)
return false;

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream_transforms.c).
@ -69,17 +69,27 @@ RFILE* rfopen(const char *path, const char *mode)
int rfclose(RFILE* stream)
{
if (!stream)
return EOF;
return filestream_close(stream);
}
int64_t rftell(RFILE* stream)
{
if (!stream)
return -1;
return filestream_tell(stream);
}
int64_t rfseek(RFILE* stream, int64_t offset, int origin)
{
int seek_position = -1;
if (!stream)
return -1;
switch (origin)
{
case SEEK_SET:
@ -99,32 +109,50 @@ int64_t rfseek(RFILE* stream, int64_t offset, int origin)
int64_t rfread(void* buffer,
size_t elem_size, size_t elem_count, RFILE* stream)
{
if (!stream || (elem_size == 0) || (elem_count == 0))
return 0;
return (filestream_read(stream, buffer, elem_size * elem_count) / elem_size);
}
char *rfgets(char *buffer, int maxCount, RFILE* stream)
{
if (!stream)
return NULL;
return filestream_gets(stream, buffer, maxCount);
}
int rfgetc(RFILE* stream)
{
if (!stream)
return EOF;
return filestream_getc(stream);
}
int64_t rfwrite(void const* buffer,
size_t elem_size, size_t elem_count, RFILE* stream)
{
return filestream_write(stream, buffer, elem_size * elem_count);
if (!stream || (elem_size == 0) || (elem_count == 0))
return 0;
return (filestream_write(stream, buffer, elem_size * elem_count) / elem_size);
}
int rfputc(int character, RFILE * stream)
{
if (!stream)
return EOF;
return filestream_putc(stream, character);
}
int64_t rfflush(RFILE * stream)
{
if (!stream)
return EOF;
return filestream_flush(stream);
}
@ -132,6 +160,10 @@ int rfprintf(RFILE * stream, const char * format, ...)
{
int result;
va_list vl;
if (!stream)
return -1;
va_start(vl, format);
result = filestream_vprintf(stream, format, vl);
va_end(vl);
@ -152,8 +184,12 @@ int rfscanf(RFILE * stream, const char * format, ...)
{
int result;
va_list vl;
if (!stream)
return 0;
va_start(vl, format);
result = filestream_scanf(stream, format, vl);
result = filestream_vscanf(stream, format, &vl);
va_end(vl);
return result;
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (stdstring.c).
@ -22,10 +22,43 @@
#include <stdint.h>
#include <ctype.h>
#include <string.h>
#include <string/stdstring.h>
#include <encodings/utf.h>
const uint8_t lr_char_props[256] = {
/*x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x00,0x00, /* 0x */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 1x */
0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 2x !"#$%&'()*+,-./ */
0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x00,0x00,0x00,0x00,0x00,0x00, /* 3x 0123456789:;<=>? */
0x00,0x23,0x23,0x23,0x23,0x23,0x23,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, /* 4x @ABCDEFGHIJKLMNO */
0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x00,0x00,0x00,0x00,0x08, /* 5x PQRSTUVWXYZ[\]^_ */
0x00,0x25,0x25,0x25,0x25,0x25,0x25,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, /* 6x `abcdefghijklmno */
0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x00,0x00,0x00,0x00,0x00, /* 7x pqrstuvwxyz{|}~ */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8x */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 9x */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Ax */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Bx */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Cx */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Dx */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Ex */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Fx */
};
char *string_init(const char *src)
{
return src ? strdup(src) : NULL;
}
void string_set(char **string, const char *src)
{
free(*string);
*string = string_init(src);
}
char *string_to_upper(char *s)
{
char *cs = (char *)s;
@ -107,18 +140,18 @@ char *string_replace_substring(const char *in,
/* Remove leading whitespaces */
char *string_trim_whitespace_left(char *const s)
{
if(s && *s)
if (s && *s)
{
size_t len = strlen(s);
char *current = s;
while(*current && isspace((unsigned char)*current))
while (*current && ISSPACE((unsigned char)*current))
{
++current;
--len;
}
if(s != current)
if (s != current)
memmove(s, current, len + 1);
}
@ -128,18 +161,18 @@ char *string_trim_whitespace_left(char *const s)
/* Remove trailing whitespaces */
char *string_trim_whitespace_right(char *const s)
{
if(s && *s)
if (s && *s)
{
size_t len = strlen(s);
char *current = s + len - 1;
while(current != s && isspace((unsigned char)*current))
while (current != s && ISSPACE((unsigned char)*current))
{
--current;
--len;
}
current[isspace((unsigned char)*current) ? 0 : 1] = '\0';
current[ISSPACE((unsigned char)*current) ? 0 : 1] = '\0';
}
return s;
@ -154,88 +187,207 @@ char *string_trim_whitespace(char *const s)
return s;
}
char *word_wrap(char* buffer, const char *string, int line_width, bool unicode, unsigned max_lines)
void word_wrap(char *dst, size_t dst_size, const char *src, int line_width, int wideglyph_width, unsigned max_lines)
{
unsigned i = 0;
unsigned len = (unsigned)strlen(string);
char *lastspace = NULL;
unsigned counter = 0;
unsigned lines = 1;
size_t src_len = strlen(src);
const char *src_end = src + src_len;
while (i < len)
{
unsigned counter;
int pos = (int)(&buffer[i] - buffer);
/* Prevent buffer overflow */
if (dst_size < src_len + 1)
return;
/* copy string until the end of the line is reached */
for (counter = 1; counter <= (unsigned)line_width; counter++)
/* Early return if src string length is less
* than line width */
if (src_len < line_width)
{
strcpy(dst, src);
return;
}
while (*src != '\0')
{
const char *character;
unsigned char_len;
unsigned j = i;
/* check if end of string reached */
if (i == len)
{
buffer[i] = 0;
return buffer;
}
character = utf8skip(&string[i], 1);
char_len = (unsigned)(character - &string[i]);
if (!unicode)
counter += char_len - 1;
do
{
buffer[i] = string[i];
char_len--;
i++;
} while(char_len);
/* check for newlines embedded in the original input
* and reset the index */
if (buffer[j] == '\n')
char_len = (unsigned)(utf8skip(src, 1) - src);
counter++;
if (*src == ' ')
lastspace = dst; /* Remember the location of the whitespace */
else if (*src == '\n')
{
/* If newlines embedded in the input,
* reset the index */
lines++;
counter = 1;
counter = 0;
/* Early return if remaining src string
* length is less than line width */
if (src_end - src <= line_width)
{
strcpy(dst, src);
return;
}
}
/* check for whitespace */
if (string[i] == ' ')
while (char_len--)
*dst++ = *src++;
if (counter >= (unsigned)line_width)
{
if ((max_lines == 0 || lines < max_lines))
counter = 0;
if (lastspace && (max_lines == 0 || lines < max_lines))
{
buffer[i] = '\n';
i++;
/* Replace nearest (previous) whitespace
* with newline character */
*lastspace = '\n';
lines++;
src -= dst - lastspace - 1;
dst = lastspace + 1;
lastspace = NULL;
/* Early return if remaining src string
* length is less than line width */
if (src_end - src < line_width)
{
strcpy(dst, src);
return;
}
}
}
}
else
{
int k;
/* check for nearest whitespace back in string */
for (k = i; k > 0; k--)
{
if (string[k] != ' ' || (max_lines != 0 && lines >= max_lines))
continue;
*dst = '\0';
}
buffer[k] = '\n';
/* set string index back to character after this one */
i = k + 1;
lines++;
void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src, int line_width, int wideglyph_width, unsigned max_lines)
{
char *lastspace = NULL;
char *lastwideglyph = NULL;
const char *src_end = src + strlen(src);
unsigned lines = 1;
/* 'line_width' means max numbers of characters per line,
* but this metric is only meaningful when dealing with
* 'regular' glyphs that have an on-screen pixel width
* similar to that of regular Latin characters.
* When handing so-called 'wide' Unicode glyphs, it is
* necessary to consider the actual on-screen pixel width
* of each character.
* In order to do this, we create a distinction between
* regular Latin 'non-wide' glyphs and 'wide' glyphs, and
* normalise all values relative to the on-screen pixel
* width of regular Latin characters:
* - Regular 'non-wide' glyphs have a normalised width of 100
* - 'line_width' is therefore normalised to 100 * (width_in_characters)
* - 'wide' glyphs have a normalised width of
* 100 * (wide_character_pixel_width / latin_character_pixel_width)
* - When a character is detected, the position in the current
* line is incremented by the regular normalised width of 100
* - If that character is then determined to be a 'wide'
* glyph, the position in the current line is further incremented
* by the difference between the normalised 'wide' and 'non-wide'
* width values */
unsigned counter_normalized = 0;
int line_width_normalized = line_width * 100;
int additional_counter_normalized = wideglyph_width - 100;
/* Early return if src string length is less
* than line width */
if (src_end - src < line_width)
{
strlcpy(dst, src, dst_size);
return;
}
while (*src != '\0')
{
unsigned char_len;
char_len = (unsigned)(utf8skip(src, 1) - src);
counter_normalized += 100;
/* Prevent buffer overflow */
if (char_len >= dst_size)
break;
if (*src == ' ')
lastspace = dst; /* Remember the location of the whitespace */
else if (*src == '\n')
{
/* If newlines embedded in the input,
* reset the index */
lines++;
counter_normalized = 0;
/* Early return if remaining src string
* length is less than line width */
if (src_end - src <= line_width)
{
strlcpy(dst, src, dst_size);
return;
}
}
else if (char_len >= 3)
{
/* Remember the location of the first byte
* whose length as UTF-8 >= 3*/
lastwideglyph = dst;
counter_normalized += additional_counter_normalized;
}
if (&buffer[i] - buffer == pos)
return buffer;
dst_size -= char_len;
while (char_len--)
*dst++ = *src++;
if (counter_normalized >= (unsigned)line_width_normalized)
{
counter_normalized = 0;
if (max_lines != 0 && lines >= max_lines)
continue;
else if (lastwideglyph && (!lastspace || lastwideglyph > lastspace))
{
/* Insert newline character */
*lastwideglyph = '\n';
lines++;
src -= dst - lastwideglyph;
dst = lastwideglyph + 1;
lastwideglyph = NULL;
/* Early return if remaining src string
* length is less than line width */
if (src_end - src <= line_width)
{
strlcpy(dst, src, dst_size);
return;
}
}
else if (lastspace)
{
/* Replace nearest (previous) whitespace
* with newline character */
*lastspace = '\n';
lines++;
src -= dst - lastspace - 1;
dst = lastspace + 1;
lastspace = NULL;
/* Early return if remaining src string
* length is less than line width */
if (src_end - src < line_width)
{
strlcpy(dst, src, dst_size);
return;
}
}
}
}
buffer[i] = 0;
return buffer;
*dst = '\0';
}
/* Splits string into tokens seperated by 'delim'
@ -248,7 +400,7 @@ char *word_wrap(char* buffer, const char *string, int line_width, bool unicode,
* char *str = "1,2,3,4,5,6,7,,,10,";
* char **str_ptr = &str;
* char *token = NULL;
* while((token = string_tokenize(str_ptr, ",")))
* while ((token = string_tokenize(str_ptr, ",")))
* {
* printf("%s\n", token);
* free(token);
@ -328,7 +480,7 @@ void string_replace_all_chars(char *str, char find, char replace)
if (string_is_empty(str))
return;
while((str_ptr = strchr(str_ptr, find)) != NULL)
while ((str_ptr = strchr(str_ptr, find)))
*str_ptr++ = replace;
}
@ -343,7 +495,7 @@ unsigned string_to_unsigned(const char *str)
for (ptr = str; *ptr != '\0'; ptr++)
{
if (!isdigit(*ptr))
if (!ISDIGIT((unsigned char)*ptr))
return 0;
}
@ -376,9 +528,105 @@ unsigned string_hex_to_unsigned(const char *str)
/* Check for valid characters */
for (ptr = hex_str; *ptr != '\0'; ptr++)
{
if (!isxdigit(*ptr))
if (!isxdigit((unsigned char)*ptr))
return 0;
}
return (unsigned)strtoul(hex_str, NULL, 16);
}
/**
* Get the total number of occurrences of a character in the given string.
*/
int string_count_occurrences_single_character(char *str, char t)
{
int ctr = 0;
int i;
for (i = 0; str[i] != '\0'; ++i) {
if (t == str[i])
++ctr;
}
return ctr;
}
/**
* Replaces all spaces with the given character.
*/
void string_replace_whitespace_with_single_character(char *str, char t)
{
while (*str) {
if (isspace(*str))
*str = t;
str++;
}
}
/**
* Replaces multiple spaces with a single space in a string.
*/
void string_replace_multi_space_with_single_space(char *str)
{
char *dest = str;
while (*str != '\0')
{
while (*str == ' ' && *(str + 1) == ' ')
str++;
*dest++ = *str++;
}
*dest = '\0';
}
/**
* Remove all spaces from the given string.
*/
void string_remove_all_whitespace(char* str_trimmed, const char* str_untrimmed)
{
while (*str_untrimmed != '\0')
{
if(!isspace(*str_untrimmed))
{
*str_trimmed = *str_untrimmed;
str_trimmed++;
}
str_untrimmed++;
}
*str_trimmed = '\0';
}
/**
* Retrieve the last occurance of the given character in a string.
*/
int string_index_last_occurance(char *str, char t)
{
const char * ret = strrchr(str, t);
if (ret)
return ret-str;
return -1;
}
/**
* Find the position of a substring in a string.
*/
int string_find_index_substring_string(const char* str1, const char* str2)
{
int index;
if (str1[0] != '\0')
{
const char *pfound = strstr(str1, str2);
if (pfound != NULL)
{
index = (pfound - str1);
return index;
}
}
return -1;
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2019 The RetroArch team
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (vfs_implementation.c).
@ -51,10 +51,6 @@
# if defined(PSP)
# include <pspiofilemgr.h>
# endif
# if defined(PS2)
# include <fileXio_rpc.h>
# include <fileXio_cdvd.h>
# endif
# include <sys/types.h>
# include <sys/stat.h>
# if !defined(VITA)
@ -66,18 +62,12 @@
# include <sys/dirent.h>
# include <orbisFile.h>
# endif
# if defined(WIIU)
# include <malloc.h>
# endif
#endif
#ifdef __CELLOS_LV2__
#include <cell/cell_fs.h>
#define O_RDONLY CELL_FS_O_RDONLY
#define O_WRONLY CELL_FS_O_WRONLY
#define O_CREAT CELL_FS_O_CREAT
#define O_TRUNC CELL_FS_O_TRUNC
#define O_RDWR CELL_FS_O_RDWR
#else
#include <fcntl.h>
#endif
/* TODO: Some things are duplicated but I'm really afraid of breaking other platforms by touching this */
#if defined(VITA)
@ -93,16 +83,13 @@
# if defined(PSP)
# include <pspiofilemgr.h>
# endif
# if defined(PS2)
# include <fileXio_rpc.h>
# endif
# include <sys/types.h>
# include <sys/stat.h>
# include <dirent.h>
# include <unistd.h>
#endif
#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP) || defined(PS2)
#if defined(__QNX__) || defined(PSP)
#include <unistd.h> /* stat() is defined here */
#endif
@ -146,20 +133,18 @@
#include <pspkernel.h>
#endif
#if defined(PS2)
#include <fileXio_rpc.h>
#include <fileXio.h>
#if defined(__PS3__) || defined(__PSL1GHT__)
#include <defines/ps3_defines.h>
#if defined(__PSL1GHT__)
#include <lv2/sysfs.h>
#endif
#if defined(__CELLOS_LV2__)
#include <cell/cell_fs.h>
#endif
#if defined(VITA)
#define FIO_S_ISDIR SCE_S_ISDIR
#endif
#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP)
#if defined(__QNX__) || defined(PSP)
#include <unistd.h> /* stat() is defined here */
#endif
@ -173,14 +158,16 @@
#endif
#if defined(_WIN32)
#if !defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER >= 1400)
#if defined(_MSC_VER) && _MSC_VER >= 1400
#define ATLEAST_VC2005
#endif
#endif
#include <vfs/vfs_implementation.h>
#include <libretro.h>
#if defined(HAVE_MMAP)
#include <memmap.h>
#endif
#include <encodings/utf.h>
#include <compat/fopen_utf8.h>
#include <file/file_path.h>
@ -189,9 +176,17 @@
#include <vfs/vfs_implementation_cdrom.h>
#endif
#if (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE - 0) >= 200112) || (defined(__POSIX_VISIBLE) && __POSIX_VISIBLE >= 200112) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112) || __USE_LARGEFILE || (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64)
#ifndef HAVE_64BIT_OFFSETS
#define HAVE_64BIT_OFFSETS
#endif
#endif
#define RFILE_HINT_UNBUFFERED (1 << 8)
int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, int64_t offset, int whence)
int64_t retro_vfs_file_seek_internal(
libretro_vfs_implementation_file *stream,
int64_t offset, int whence)
{
if (!stream)
return -1;
@ -202,19 +197,9 @@ int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, i
if (stream->scheme == VFS_SCHEME_CDROM)
return retro_vfs_file_seek_cdrom(stream, offset, whence);
#endif
/* VC2005 and up have a special 64-bit fseek */
#ifdef ATLEAST_VC2005
/* VC2005 and up have a special 64-bit fseek */
return _fseeki64(stream->fp, offset, whence);
#elif defined(__CELLOS_LV2__) || defined(_MSC_VER) && _MSC_VER <= 1310
return fseek(stream->fp, (long)offset, whence);
#elif defined(PS2)
{
int64_t ret = fileXioLseek(fileno(stream->fp), (off_t)offset, whence);
/* fileXioLseek could return positive numbers */
if (ret > 0)
return 0;
return ret;
}
#elif defined(ORBIS)
{
int ret = orbisLseek(stream->fd, offset, whence);
@ -222,8 +207,10 @@ int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, i
return -1;
return 0;
}
#else
#elif defined(HAVE_64BIT_OFFSETS)
return fseeko(stream->fp, (off_t)offset, whence);
#else
return fseek(stream->fp, (long)offset, whence);
#endif
}
#ifdef HAVE_MMAP
@ -263,7 +250,7 @@ int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, i
}
#endif
if (lseek(stream->fd, offset, whence) < 0)
if (lseek(stream->fd, (off_t)offset, whence) < 0)
return -1;
return 0;
@ -282,31 +269,61 @@ int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, i
libretro_vfs_implementation_file *retro_vfs_file_open_impl(
const char *path, unsigned mode, unsigned hints)
{
int flags = 0;
const char *mode_str = NULL;
libretro_vfs_implementation_file *stream = (libretro_vfs_implementation_file*)
calloc(1, sizeof(*stream));
#if defined(VFS_FRONTEND) || defined(HAVE_CDROM)
int path_len = (int)strlen(path);
#endif
#ifdef VFS_FRONTEND
const char *dumb_prefix = "vfsonly://";
size_t dumb_prefix_siz = strlen(dumb_prefix);
size_t dumb_prefix_siz = STRLEN_CONST("vfsonly://");
int dumb_prefix_len = (int)dumb_prefix_siz;
#endif
#ifdef HAVE_CDROM
const char *cdrom_prefix = "cdrom://";
size_t cdrom_prefix_siz = STRLEN_CONST("cdrom://");
int cdrom_prefix_len = (int)cdrom_prefix_siz;
#endif
int flags = 0;
const char *mode_str = NULL;
libretro_vfs_implementation_file *stream =
(libretro_vfs_implementation_file*)
malloc(sizeof(*stream));
if (!stream)
return NULL;
stream->fd = 0;
stream->hints = hints;
stream->size = 0;
stream->buf = NULL;
stream->fp = NULL;
#ifdef _WIN32
stream->fh = 0;
#endif
stream->orig_path = NULL;
stream->mappos = 0;
stream->mapsize = 0;
stream->mapped = NULL;
stream->scheme = VFS_SCHEME_NONE;
#ifdef VFS_FRONTEND
if (path_len >= dumb_prefix_len)
{
if (!memcmp(path, dumb_prefix, dumb_prefix_len))
path += dumb_prefix_siz;
}
#endif
#ifdef HAVE_CDROM
{
const char *cdrom_prefix = "cdrom://";
size_t cdrom_prefix_siz = strlen(cdrom_prefix);
int cdrom_prefix_len = (int)cdrom_prefix_siz;
stream->cdrom.cue_buf = NULL;
stream->cdrom.cue_len = 0;
stream->cdrom.byte_pos = 0;
stream->cdrom.drive = 0;
stream->cdrom.cur_min = 0;
stream->cdrom.cur_sec = 0;
stream->cdrom.cur_frame = 0;
stream->cdrom.cur_track = 0;
stream->cdrom.cur_lba = 0;
stream->cdrom.last_frame_lba = 0;
stream->cdrom.last_frame[0] = '\0';
stream->cdrom.last_frame_valid = false;
if (path_len > cdrom_prefix_len)
{
@ -316,15 +333,8 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
stream->scheme = VFS_SCHEME_CDROM;
}
}
}
#endif
if (!stream)
return NULL;
(void)flags;
stream->hints = hints;
stream->orig_path = strdup(path);
#ifdef HAVE_MMAP
@ -350,9 +360,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
flags = O_WRONLY | O_CREAT | O_TRUNC;
#if !defined(ORBIS)
#if defined(PS2)
flags |= FIO_S_IRUSR | FIO_S_IWUSR;
#elif !defined(_WIN32)
#if !defined(_WIN32)
flags |= S_IRUSR | S_IWUSR;
#else
flags |= O_BINARY;
@ -364,9 +372,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
mode_str = "w+b";
flags = O_RDWR | O_CREAT | O_TRUNC;
#if !defined(ORBIS)
#if defined(PS2)
flags |= FIO_S_IRUSR | FIO_S_IWUSR;
#elif !defined(_WIN32)
#if !defined(_WIN32)
flags |= S_IRUSR | S_IWUSR;
#else
flags |= O_BINARY;
@ -380,9 +386,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
flags = O_RDWR;
#if !defined(ORBIS)
#if defined(PS2)
flags |= FIO_S_IRUSR | FIO_S_IWUSR;
#elif !defined(_WIN32)
#if !defined(_WIN32)
flags |= S_IRUSR | S_IWUSR;
#else
flags |= O_BINARY;
@ -432,13 +436,30 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
*
* https://www.freebsd.org/cgi/man.cgi?query=setvbuf&apropos=0&sektion=0&manpath=FreeBSD+11.1-RELEASE&arch=default&format=html
*
* If the size argument is not zero but buf is NULL, a buffer of the given size will be allocated immediately, and
* If the size argument is not zero but buf is NULL,
* a buffer of the given size will be allocated immediately, and
* released on close. This is an extension to ANSI C.
*
* Since C89 does not support specifying a null buffer with a non-zero size, we create and track our own buffer for it.
* Since C89 does not support specifying a NULL buffer
* with a non-zero size, we create and track our own buffer for it.
*/
/* TODO: this is only useful for a few platforms, find which and add ifdef */
#if !defined(PS2) && !defined(PSP)
/* TODO: this is only useful for a few platforms,
* find which and add ifdef */
#if defined(_3DS)
if (stream->scheme != VFS_SCHEME_CDROM)
{
stream->buf = (char*)calloc(1, 0x10000);
if (stream->fp)
setvbuf(stream->fp, stream->buf, _IOFBF, 0x10000);
}
#elif defined(WIIU)
if (stream->scheme != VFS_SCHEME_CDROM)
{
const int bufsize = 128*1024;
stream->buf = (char*)memalign(0x40, bufsize);
if (stream->fp)
setvbuf(stream->fp, stream->buf, _IOFBF, bufsize);
}
if (stream->scheme != VFS_SCHEME_CDROM)
{
stream->buf = (char*)calloc(1, 0x4000);
@ -537,10 +558,8 @@ int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
{
if (stream->fp)
{
fclose(stream->fp);
}
}
else
{
#ifdef HAVE_MMAP
@ -604,7 +623,7 @@ int64_t retro_vfs_file_truncate_impl(libretro_vfs_implementation_file *stream, i
if (_chsize(_fileno(stream->fp), length) != 0)
return -1;
#elif !defined(VITA) && !defined(PSP) && !defined(PS2) && !defined(ORBIS) && (!defined(SWITCH) || defined(HAVE_LIBNX))
if (ftruncate(fileno(stream->fp), length) != 0)
if (ftruncate(fileno(stream->fp), (off_t)length) != 0)
return -1;
#endif
@ -630,9 +649,11 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream)
return ret;
}
#else
/* VC2005 and up have a special 64-bit ftell */
#ifdef ATLEAST_VC2005
/* VC2005 and up have a special 64-bit ftell */
return _ftelli64(stream->fp);
#elif defined(HAVE_64BIT_OFFSETS)
return ftello(stream->fp);
#else
return ftell(stream->fp);
#endif
@ -641,7 +662,8 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream)
#ifdef HAVE_MMAP
/* Need to check stream->mapped because this function
* is called in filestream_open() */
if (stream->mapped && stream->hints & RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS)
if (stream->mapped && stream->hints &
RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS)
return stream->mappos;
#endif
if (lseek(stream->fd, 0, SEEK_CUR) < 0)
@ -865,12 +887,12 @@ const char *retro_vfs_file_get_path_impl(
int retro_vfs_stat_impl(const char *path, int32_t *size)
{
#if defined(VITA) || defined(PSP)
/* Vita / PSP */
SceIoStat buf;
int stat_ret;
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;
@ -882,22 +904,18 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
if (tmp[len-1] == '/')
tmp[len-1] = '\0';
stat_ret = sceIoGetstat(tmp, &buf);
dir_ret = sceIoGetstat(tmp, &buf);
free(tmp);
if (stat_ret < 0)
if (dir_ret < 0)
return 0;
if (size)
*size = (int32_t)buf.st_size;
is_dir = FIO_S_ISDIR(buf.st_mode);
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
#elif defined(ORBIS)
/* Orbis */
bool is_dir, is_character_special;
int dir_ret;
int dir_ret = 0;
if (!path || !*path)
return 0;
@ -910,69 +928,23 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
orbisDclose(dir_ret);
is_character_special = S_ISCHR(buf.st_mode);
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
#elif defined(PS2)
/* PS2 */
iox_stat_t buf;
bool is_dir;
bool is_character_special = false;
char *tmp = NULL;
size_t len = 0;
#elif defined(__PSL1GHT__) || defined(__PS3__)
/* Lowlevel Lv2 */
sysFSStat buf;
if (!path || !*path)
return 0;
tmp = strdup(path);
len = strlen(tmp);
if (tmp[len-1] == '/')
tmp[len-1] = '\0';
fileXioGetStat(tmp, &buf);
free(tmp);
if (size)
*size = (int32_t)buf.size;
if (!buf.mode)
{
/* if fileXioGetStat fails */
int dir_ret = fileXioDopen(path);
is_dir = dir_ret > 0;
if (is_dir) {
fileXioDclose(dir_ret);
}
}
else
is_dir = FIO_S_ISDIR(buf.mode);
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
#elif defined(__CELLOS_LV2__)
/* CellOS Lv2 */
bool is_dir;
bool is_character_special = false;
CellFsStat buf;
if (!path || !*path)
return 0;
if (cellFsStat(path, &buf) < 0)
if (sysFsStat(path, &buf) < 0)
return 0;
if (size)
*size = (int32_t)buf.st_size;
is_dir = ((buf.st_mode & S_IFMT) == S_IFDIR);
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
#elif defined(_WIN32)
/* Windows */
bool is_dir;
DWORD file_info;
struct _stat buf;
bool is_character_special = false;
#if defined(LEGACY_WIN32)
char *path_local = NULL;
#else
@ -1009,11 +981,41 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
is_dir = (file_info & FILE_ATTRIBUTE_DIRECTORY);
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
#elif defined(GEKKO)
/* On GEKKO platforms, paths cannot have
* trailing slashes - we must therefore
* remove them */
char *path_buf = NULL;
int stat_ret = -1;
struct stat stat_buf;
size_t len;
if (string_is_empty(path))
return 0;
path_buf = strdup(path);
if (!path_buf)
return 0;
len = strlen(path_buf);
if (len > 0)
if (path_buf[len - 1] == '/')
path_buf[len - 1] = '\0';
stat_ret = stat(path_buf, &stat_buf);
free(path_buf);
if (stat_ret < 0)
return 0;
if (size)
*size = (int32_t)stat_buf.st_size;
is_dir = S_ISDIR(stat_buf.st_mode);
is_character_special = S_ISCHR(stat_buf.st_mode);
#else
/* Every other platform */
bool is_dir, is_character_special;
struct stat buf;
if (!path || !*path)
@ -1026,9 +1028,8 @@ int retro_vfs_stat_impl(const char *path, int32_t *size)
is_dir = S_ISDIR(buf.st_mode);
is_character_special = S_ISCHR(buf.st_mode);
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
#endif
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
}
#if defined(VITA)
@ -1045,25 +1046,45 @@ int retro_vfs_mkdir_impl(const char *dir)
#ifdef LEGACY_WIN32
int ret = _mkdir(dir);
#else
wchar_t *dirW = utf8_to_utf16_string_alloc(dir);
wchar_t *dir_w = utf8_to_utf16_string_alloc(dir);
int ret = -1;
if (dirW)
if (dir_w)
{
ret = _wmkdir(dirW);
free(dirW);
ret = _wmkdir(dir_w);
free(dir_w);
}
#endif
#elif defined(IOS)
int ret = mkdir(dir, 0755);
#elif defined(VITA) || defined(PSP)
#elif defined(VITA)
int ret = sceIoMkdir(dir, 0777);
#elif defined(PS2)
int ret = fileXioMkdir(dir, 0777);
#elif defined(ORBIS)
int ret = orbisMkdir(dir, 0755);
#elif defined(__QNX__)
int ret = mkdir(dir, 0777);
#elif defined(GEKKO)
/* On GEKKO platforms, mkdir() fails if
* the path has a trailing slash. We must
* therefore remove it. */
int ret = -1;
if (!string_is_empty(dir))
{
char *dir_buf = strdup(dir);
if (dir_buf)
{
size_t len = strlen(dir_buf);
if (len > 0)
if (dir_buf[len - 1] == '/')
dir_buf[len - 1] = '\0';
ret = mkdir(dir_buf, 0750);
free(dir_buf);
}
}
#else
int ret = mkdir(dir, 0750);
#endif
@ -1089,16 +1110,13 @@ struct libretro_vfs_implementation_dir
HANDLE directory;
bool next;
char path[PATH_MAX_LENGTH];
#elif defined(VITA) || defined(PSP)
#elif defined(VITA)
SceUID directory;
SceIoDirent entry;
#elif defined(PS2)
#elif defined(__PSL1GHT__) || defined(__PS3__)
int error;
int directory;
iox_dirent_t entry;
#elif defined(__CELLOS_LV2__)
CellFsErrno error;
int directory;
CellFsDirent entry;
sysFSDirent entry;
#elif defined(ORBIS)
int directory;
struct dirent entry;
@ -1112,10 +1130,10 @@ static bool dirent_check_error(libretro_vfs_implementation_dir *rdir)
{
#if defined(_WIN32)
return (rdir->directory == INVALID_HANDLE_VALUE);
#elif defined(VITA) || defined(PSP) || defined(PS2) || defined(ORBIS)
#elif defined(VITA) || defined(ORBIS)
return (rdir->directory < 0);
#elif defined(__CELLOS_LV2__)
return (rdir->error != CELL_FS_SUCCEEDED);
#elif defined(__PSL1GHT__) || defined(__PS3__)
return (rdir->error != FS_SUCCEEDED);
#else
return !(rdir->directory);
#endif
@ -1174,15 +1192,13 @@ libretro_vfs_implementation_dir *retro_vfs_opendir_impl(
free(path_wide);
#endif
#elif defined(VITA) || defined(PSP)
#elif defined(VITA)
rdir->directory = sceIoDopen(name);
#elif defined(PS2)
rdir->directory = ps2fileXioDopen(name);
#elif defined(_3DS)
rdir->directory = !string_is_empty(name) ? opendir(name) : NULL;
rdir->entry = NULL;
#elif defined(__CELLOS_LV2__)
rdir->error = cellFsOpendir(name, &rdir->directory);
#elif defined(__PSL1GHT__) || defined(__PS3__)
rdir->error = sysFsOpendir(name, &rdir->directory);
#elif defined(ORBIS)
rdir->directory = orbisDopen(name);
#else
@ -1216,16 +1232,11 @@ bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir *rdir)
rdir->next = true;
return (rdir->directory != INVALID_HANDLE_VALUE);
#elif defined(VITA) || defined(PSP)
#elif defined(VITA)
return (sceIoDread(rdir->directory, &rdir->entry) > 0);
#elif defined(PS2)
iox_dirent_t record;
int ret = ps2fileXioDread(rdir->directory, &record);
rdir->entry = record;
return ( ret > 0);
#elif defined(__CELLOS_LV2__)
#elif defined(__PSL1GHT__) || defined(__PS3__)
uint64_t nread;
rdir->error = cellFsReaddir(rdir->directory, &rdir->entry, &nread);
rdir->error = sysFsReaddir(rdir->directory, &rdir->entry, &nread);
return (nread != 0);
#elif defined(ORBIS)
return (orbisDread(rdir->directory, &rdir->entry) > 0);
@ -1238,29 +1249,17 @@ 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));
if (name_local)
free(name_local);
}
char *name = local_to_utf8_string_alloc(rdir->entry.cFileName);
#else
{
char *name = utf16_to_utf8_string_alloc(rdir->entry.cFileName);
#endif
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName));
if (name)
free(name);
}
#endif
return (char*)rdir->entry.cFileName;
#elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) || defined(ORBIS)
#elif defined(VITA) || defined(ORBIS) || defined(__PSL1GHT__) || defined(__PS3__)
return rdir->entry.d_name;
#elif defined(PS2)
return rdir->entry.name;
#else
if (!rdir || !rdir->entry)
return NULL;
@ -1273,19 +1272,12 @@ bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *rdir)
#if defined(_WIN32)
const WIN32_FIND_DATA *entry = (const WIN32_FIND_DATA*)&rdir->entry;
return entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
#elif defined(PSP) || defined(VITA)
const SceIoDirent *entry = (const SceIoDirent*)&rdir->entry;
#if defined(PSP)
return (entry->d_stat.st_attr & FIO_SO_IFDIR) == FIO_SO_IFDIR;
#elif defined(VITA)
const SceIoDirent *entry = (const SceIoDirent*)&rdir->entry;
return SCE_S_ISDIR(entry->d_stat.st_mode);
#endif
#elif defined(PS2)
const iox_dirent_t *entry = (const iox_dirent_t*)&rdir->entry;
return FIO_S_ISDIR(entry->stat.mode);
#elif defined(__CELLOS_LV2__)
CellFsDirent *entry = (CellFsDirent*)&rdir->entry;
return (entry->d_type == CELL_FS_TYPE_DIRECTORY);
#elif defined(__PSL1GHT__) || defined(__PS3__)
sysFSDirent *entry = (sysFSDirent*)&rdir->entry;
return (entry->d_type == FS_TYPE_DIR);
#elif defined(ORBIS)
const struct dirent *entry = &rdir->entry;
if (entry->d_type == DT_DIR)
@ -1320,12 +1312,10 @@ int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *rdir)
#if defined(_WIN32)
if (rdir->directory != INVALID_HANDLE_VALUE)
FindClose(rdir->directory);
#elif defined(VITA) || defined(PSP)
#elif defined(VITA)
sceIoDclose(rdir->directory);
#elif defined(PS2)
ps2fileXioDclose(rdir->directory);
#elif defined(__CELLOS_LV2__)
rdir->error = cellFsClosedir(rdir->directory);
#elif defined(__PSL1GHT__) || defined(__PS3__)
rdir->error = sysFsClosedir(rdir->directory);
#elif defined(ORBIS)
orbisDclose(rdir->directory);
#else

View file

@ -15,13 +15,11 @@
#include <stdarg.h>
#include <string.h>
#ifndef _WIN32
#ifndef NO_MMAP
#ifdef __SWITCH__
#include "switch/mman.h"
#else
#include <sys/mman.h>
#endif
#endif
#else
#include <io.h>
#include <windows.h>
@ -340,30 +338,6 @@ static void munmap(void *addr, size_t length)
UnmapViewOfFile(addr);
/* ruh-ro, we leaked handle from CreateFileMapping() ... */
}
#elif defined(NO_MMAP)
#define PROT_EXEC 0x04
#define MAP_FAILED 0
#define PROT_READ 0
#define PROT_WRITE 0
#define MAP_PRIVATE 0
#define MAP_ANONYMOUS 0
void* mmap(void *desired_addr, size_t len, int mmap_prot, int mmap_flags, int fildes, size_t off)
{
return calloc(1, len);
}
void munmap(void *base_addr, size_t len)
{
free(base_addr);
}
int mprotect(void *addr, size_t len, int prot)
{
/* stub - not really needed at this point since this codepath has no dynarecs */
return 0;
}
#endif
#ifndef MAP_ANONYMOUS