mirror of
https://github.com/libretro/beetle-pce-fast-libretro.git
synced 2024-11-23 07:50:03 +00:00
Merge pull request #119 from bparker06/cdrom_fast
initial cdrom support (master branch)
This commit is contained in:
commit
49001078e8
26
Makefile
26
Makefile
@ -14,15 +14,15 @@ unixcygpath = /$(subst :,,$(call unixpath,$1))
|
|||||||
|
|
||||||
ifeq ($(platform),)
|
ifeq ($(platform),)
|
||||||
platform = unix
|
platform = unix
|
||||||
ifeq ($(shell uname -a),)
|
ifeq ($(shell uname -s),)
|
||||||
platform = win
|
platform = win
|
||||||
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
else ifneq ($(findstring Darwin,$(shell uname -s)),)
|
||||||
platform = osx
|
platform = osx
|
||||||
arch = intel
|
arch = intel
|
||||||
ifeq ($(shell uname -p),powerpc)
|
ifeq ($(shell uname -p),powerpc)
|
||||||
arch = ppc
|
arch = ppc
|
||||||
endif
|
endif
|
||||||
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
else ifneq ($(findstring MINGW,$(shell uname -s)),)
|
||||||
platform = win
|
platform = win
|
||||||
endif
|
endif
|
||||||
else ifneq (,$(findstring armv,$(platform)))
|
else ifneq (,$(findstring armv,$(platform)))
|
||||||
@ -46,6 +46,7 @@ NEED_CRC32 = 1
|
|||||||
WANT_NEW_API = 1
|
WANT_NEW_API = 1
|
||||||
CORE_DEFINE := -DWANT_PCE_FAST_EMU -DWANT_STEREO_SOUND
|
CORE_DEFINE := -DWANT_PCE_FAST_EMU -DWANT_STEREO_SOUND
|
||||||
HAVE_CHD = 1
|
HAVE_CHD = 1
|
||||||
|
HAVE_CDROM = 0
|
||||||
|
|
||||||
prefix := /usr
|
prefix := /usr
|
||||||
libdir := $(prefix)/lib
|
libdir := $(prefix)/lib
|
||||||
@ -76,6 +77,10 @@ ifneq (,$(findstring unix,$(platform)))
|
|||||||
LDFLAGS += -lrt
|
LDFLAGS += -lrt
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq ($(findstring Linux,$(shell uname -s)),)
|
||||||
|
HAVE_CDROM = 1
|
||||||
|
endif
|
||||||
|
|
||||||
# Raspberry Pi
|
# Raspberry Pi
|
||||||
ifneq (,$(findstring rpi,$(platform)))
|
ifneq (,$(findstring rpi,$(platform)))
|
||||||
FLAGS += -fomit-frame-pointer -ffast-math
|
FLAGS += -fomit-frame-pointer -ffast-math
|
||||||
@ -357,6 +362,8 @@ else ifneq (,$(findstring windows_msvc2017,$(platform)))
|
|||||||
VCCompilerToolsBinDir := $(VcCompilerToolsDir)\bin\HostX86
|
VCCompilerToolsBinDir := $(VcCompilerToolsDir)\bin\HostX86
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
HAVE_CDROM = 1
|
||||||
|
|
||||||
PATH := $(shell IFS=$$'\n'; cygpath "$(VCCompilerToolsBinDir)/$(TargetArchMoniker)"):$(PATH)
|
PATH := $(shell IFS=$$'\n'; cygpath "$(VCCompilerToolsBinDir)/$(TargetArchMoniker)"):$(PATH)
|
||||||
PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VsInstallRoot)/Common7/IDE")
|
PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VsInstallRoot)/Common7/IDE")
|
||||||
INCLUDE := $(shell IFS=$$'\n'; cygpath -w "$(VcCompilerToolsDir)/include")
|
INCLUDE := $(shell IFS=$$'\n'; cygpath -w "$(VcCompilerToolsDir)/include")
|
||||||
@ -388,6 +395,7 @@ WindowsSdkDir ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windo
|
|||||||
WindowsSdkDirInc := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include
|
WindowsSdkDirInc := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include
|
||||||
WindowsSdkDirInc ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include
|
WindowsSdkDirInc ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include
|
||||||
|
|
||||||
|
HAVE_CDROM = 1
|
||||||
|
|
||||||
INCFLAGS_PLATFORM = -I"$(WindowsSdkDirInc)"
|
INCFLAGS_PLATFORM = -I"$(WindowsSdkDirInc)"
|
||||||
export INCLUDE := $(INCLUDE)
|
export INCLUDE := $(INCLUDE)
|
||||||
@ -413,6 +421,7 @@ WindowsSdkDir ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windo
|
|||||||
WindowsSdkDirInc := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include
|
WindowsSdkDirInc := $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include
|
||||||
WindowsSdkDirInc ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include
|
WindowsSdkDirInc ?= $(shell reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include
|
||||||
|
|
||||||
|
HAVE_CDROM = 1
|
||||||
|
|
||||||
INCFLAGS_PLATFORM = -I"$(WindowsSdkDirInc)"
|
INCFLAGS_PLATFORM = -I"$(WindowsSdkDirInc)"
|
||||||
export INCLUDE := $(INCLUDE)
|
export INCLUDE := $(INCLUDE)
|
||||||
@ -435,6 +444,8 @@ BIN := $(shell IFS=$$'\n'; cygpath "$(VS80COMNTOOLS)../../VC/bin")
|
|||||||
|
|
||||||
WindowsSdkDir := $(INETSDK)
|
WindowsSdkDir := $(INETSDK)
|
||||||
|
|
||||||
|
HAVE_CDROM = 1
|
||||||
|
|
||||||
export INCLUDE := $(INCLUDE);$(INETSDK)/Include;libretro-common/include/compat/msvc
|
export INCLUDE := $(INCLUDE);$(INETSDK)/Include;libretro-common/include/compat/msvc
|
||||||
export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib
|
export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib
|
||||||
TARGET := $(TARGET_NAME)_libretro.dll
|
TARGET := $(TARGET_NAME)_libretro.dll
|
||||||
@ -465,6 +476,7 @@ else ifeq ($(platform), windows_msvc2003_x86)
|
|||||||
CC = cl.exe
|
CC = cl.exe
|
||||||
CXX = cl.exe
|
CXX = cl.exe
|
||||||
|
|
||||||
|
HAVE_CDROM = 1
|
||||||
PATH := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/bin"):$(PATH)
|
PATH := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/bin"):$(PATH)
|
||||||
PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../IDE")
|
PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../IDE")
|
||||||
INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/include")
|
INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/include")
|
||||||
@ -488,6 +500,7 @@ else
|
|||||||
CXX = g++
|
CXX = g++
|
||||||
SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T
|
SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T
|
||||||
LDFLAGS += -static-libgcc -static-libstdc++ -lwinmm
|
LDFLAGS += -static-libgcc -static-libstdc++ -lwinmm
|
||||||
|
HAVE_CDROM = 1
|
||||||
WINDOWS_VERSION=1
|
WINDOWS_VERSION=1
|
||||||
|
|
||||||
endif
|
endif
|
||||||
@ -550,6 +563,13 @@ ifeq ($(WANT_NEW_API), 1)
|
|||||||
FLAGS += -DWANT_NEW_API
|
FLAGS += -DWANT_NEW_API
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(HAVE_CDROM), 1)
|
||||||
|
FLAGS += -DHAVE_CDROM
|
||||||
|
ifeq ($(CDROM_DEBUG), 1)
|
||||||
|
FLAGS += -DCDROM_DEBUG
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
CXXFLAGS += $(FLAGS)
|
CXXFLAGS += $(FLAGS)
|
||||||
CFLAGS += $(FLAGS)
|
CFLAGS += $(FLAGS)
|
||||||
|
|
||||||
|
@ -20,6 +20,12 @@ ifneq (,$(findstring msvc2003,$(platform)))
|
|||||||
INCFLAGS += -I$(LIBRETRO_COMM_DIR)/include/compat/msvc
|
INCFLAGS += -I$(LIBRETRO_COMM_DIR)/include/compat/msvc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(HAVE_CDROM), 1)
|
||||||
|
SOURCES_C += \
|
||||||
|
$(LIBRETRO_COMM_DIR)/cdrom/cdrom.c \
|
||||||
|
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation_cdrom.c
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq ($(HAVE_GRIFFIN),1)
|
ifneq ($(HAVE_GRIFFIN),1)
|
||||||
SOURCES_CXX += \
|
SOURCES_CXX += \
|
||||||
$(CORE_EMU_DIR)/huc6280.cpp \
|
$(CORE_EMU_DIR)/huc6280.cpp \
|
||||||
@ -196,6 +202,10 @@ endif
|
|||||||
ifneq ($(STATIC_LINKING), 1)
|
ifneq ($(STATIC_LINKING), 1)
|
||||||
SOURCES_C += $(LIBRETRO_COMM_DIR)/streams/file_stream.c \
|
SOURCES_C += $(LIBRETRO_COMM_DIR)/streams/file_stream.c \
|
||||||
$(LIBRETRO_COMM_DIR)/streams/file_stream_transforms.c \
|
$(LIBRETRO_COMM_DIR)/streams/file_stream_transforms.c \
|
||||||
|
$(LIBRETRO_COMM_DIR)/file/file_path.c \
|
||||||
|
$(LIBRETRO_COMM_DIR)/file/retro_dirent.c \
|
||||||
|
$(LIBRETRO_COMM_DIR)/lists/string_list.c \
|
||||||
|
$(LIBRETRO_COMM_DIR)/lists/dir_list.c \
|
||||||
$(LIBRETRO_COMM_DIR)/compat/compat_strl.c \
|
$(LIBRETRO_COMM_DIR)/compat/compat_strl.c \
|
||||||
$(LIBRETRO_COMM_DIR)/compat/compat_snprintf.c \
|
$(LIBRETRO_COMM_DIR)/compat/compat_snprintf.c \
|
||||||
$(LIBRETRO_COMM_DIR)/compat/compat_posix_string.c \
|
$(LIBRETRO_COMM_DIR)/compat/compat_posix_string.c \
|
||||||
@ -204,5 +214,6 @@ SOURCES_C += $(LIBRETRO_COMM_DIR)/streams/file_stream.c \
|
|||||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \
|
$(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \
|
||||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_crc32.c \
|
$(LIBRETRO_COMM_DIR)/encodings/encoding_crc32.c \
|
||||||
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c \
|
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c \
|
||||||
|
$(LIBRETRO_COMM_DIR)/memmap/memalign.c \
|
||||||
$(LIBRETRO_COMM_DIR)/string/stdstring.c
|
$(LIBRETRO_COMM_DIR)/string/stdstring.c
|
||||||
endif
|
endif
|
||||||
|
1720
libretro-common/cdrom/cdrom.c
Normal file
1720
libretro-common/cdrom/cdrom.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -23,10 +23,7 @@
|
|||||||
/* THIS FILE HAS NOT BEEN VALIDATED ON PLATFORMS BESIDES MSVC */
|
/* THIS FILE HAS NOT BEEN VALIDATED ON PLATFORMS BESIDES MSVC */
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
#include <retro_common.h>
|
#include <stdio.h>
|
||||||
#if _MSC_VER >= 1800
|
|
||||||
#include <stdio.h> /* added for _vsnprintf_s and _vscprintf on VS2015 and VS2017 */
|
|
||||||
#endif
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#if _MSC_VER < 1800
|
#if _MSC_VER < 1800
|
||||||
@ -54,11 +51,14 @@ int c99_vsnprintf_retro__(char *outBuf, size_t size, const char *format, va_list
|
|||||||
int count = -1;
|
int count = -1;
|
||||||
|
|
||||||
if (size != 0)
|
if (size != 0)
|
||||||
|
{
|
||||||
#if (_MSC_VER <= 1310)
|
#if (_MSC_VER <= 1310)
|
||||||
count = _vsnprintf(outBuf, size - 1, format, ap);
|
count = _vsnprintf(outBuf, size - 1, format, ap);
|
||||||
#else
|
#else
|
||||||
count = _vsnprintf_s(outBuf, size, size - 1, format, ap);
|
count = _vsnprintf_s(outBuf, size, size - 1, format, ap);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if (count == -1)
|
if (count == -1)
|
||||||
count = _vscprintf(format, ap);
|
count = _vscprintf(format, ap);
|
||||||
|
|
||||||
|
@ -36,9 +36,7 @@
|
|||||||
|
|
||||||
void *fopen_utf8(const char * filename, const char * mode)
|
void *fopen_utf8(const char * filename, const char * mode)
|
||||||
{
|
{
|
||||||
#if defined(_XBOX)
|
#if defined(LEGACY_WIN32)
|
||||||
return fopen(filename, mode);
|
|
||||||
#elif defined(LEGACY_WIN32)
|
|
||||||
FILE *ret = NULL;
|
FILE *ret = NULL;
|
||||||
char * filename_local = utf8_to_local_string_alloc(filename);
|
char * filename_local = utf8_to_local_string_alloc(filename);
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <encodings/crc32.h>
|
#include <encodings/crc32.h>
|
||||||
|
#include <streams/file_stream.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
static const uint32_t crc32_table[256] = {
|
static const uint32_t crc32_table[256] = {
|
||||||
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
|
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
|
||||||
@ -88,3 +90,51 @@ uint32_t encoding_crc32(uint32_t crc, const uint8_t *buf, size_t len)
|
|||||||
|
|
||||||
return crc ^ 0xffffffff;
|
return crc ^ 0xffffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CRC32_BUFFER_SIZE 1048576
|
||||||
|
#define CRC32_MAX_MB 64
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate a CRC32 from the first part of the given file.
|
||||||
|
* "first part" being the first (CRC32_BUFFER_SIZE * CRC32_MAX_MB)
|
||||||
|
* bytes.
|
||||||
|
*
|
||||||
|
* Returns: the crc32, or 0 if there was an error.
|
||||||
|
*/
|
||||||
|
uint32_t file_crc32(uint32_t crc, const char *path)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
RFILE *file = NULL;
|
||||||
|
unsigned char *buf = NULL;
|
||||||
|
if (!path)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
file = filestream_open(path, RETRO_VFS_FILE_ACCESS_READ, 0);
|
||||||
|
if (!file)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
buf = (unsigned char*)malloc(CRC32_BUFFER_SIZE);
|
||||||
|
if (!buf)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for(i = 0; i < CRC32_MAX_MB; i++)
|
||||||
|
{
|
||||||
|
int64_t nread = filestream_read(file, buf, CRC32_BUFFER_SIZE);
|
||||||
|
if (nread < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
crc = encoding_crc32(crc, buf, (size_t)nread);
|
||||||
|
if (filestream_eof(file))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
filestream_close(file);
|
||||||
|
return crc;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (buf)
|
||||||
|
free(buf);
|
||||||
|
if (file)
|
||||||
|
filestream_close(file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -211,10 +211,7 @@ size_t utf8len(const char *string)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t utf8_walkbyte(const char **string)
|
#define utf8_walkbyte(string) (*((*(string))++))
|
||||||
{
|
|
||||||
return *((*string)++);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Does not validate the input, returns garbage if it's not UTF-8. */
|
/* Does not validate the input, returns garbage if it's not UTF-8. */
|
||||||
uint32_t utf8_walk(const char **string)
|
uint32_t utf8_walk(const char **string)
|
||||||
@ -227,14 +224,16 @@ uint32_t utf8_walk(const char **string)
|
|||||||
|
|
||||||
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
||||||
if (first >= 0xE0)
|
if (first >= 0xE0)
|
||||||
|
{
|
||||||
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
||||||
if (first >= 0xF0)
|
if (first >= 0xF0)
|
||||||
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
{
|
||||||
|
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
||||||
if (first >= 0xF0)
|
return ret | (first & 7) << 18;
|
||||||
return ret | (first & 7) << 18;
|
}
|
||||||
if (first >= 0xE0)
|
|
||||||
return ret | (first & 15) << 12;
|
return ret | (first & 15) << 12;
|
||||||
|
}
|
||||||
|
|
||||||
return ret | (first & 31) << 6;
|
return ret | (first & 31) << 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,37 +272,25 @@ bool utf16_to_char_string(const uint16_t *in, char *s, size_t len)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
|
||||||
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||||
static char* mb_to_mb_string_alloc(const char *str,
|
static char *mb_to_mb_string_alloc(const char *str,
|
||||||
enum CodePage cp_in, enum CodePage cp_out)
|
enum CodePage cp_in, enum CodePage cp_out)
|
||||||
{
|
{
|
||||||
char *path_buf = NULL;
|
char *path_buf = NULL;
|
||||||
wchar_t *path_buf_wide = NULL;
|
wchar_t *path_buf_wide = NULL;
|
||||||
int path_buf_len = 0;
|
int path_buf_len = 0;
|
||||||
int path_buf_wide_len = 0;
|
int path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
|
||||||
|
|
||||||
if (!str || !*str)
|
/* Windows 95 will return 0 from these functions with
|
||||||
return NULL;
|
* a UTF8 codepage set without MSLU.
|
||||||
|
*
|
||||||
(void)path_buf;
|
* From an unknown MSDN version (others omit this info):
|
||||||
(void)path_buf_wide;
|
* - CP_UTF8 Windows 98/Me, Windows NT 4.0 and later:
|
||||||
(void)path_buf_len;
|
* Translate using UTF-8. When this is set, dwFlags must be zero.
|
||||||
(void)path_buf_wide_len;
|
* - Windows 95: Under the Microsoft Layer for Unicode,
|
||||||
|
* MultiByteToWideChar also supports CP_UTF7 and CP_UTF8.
|
||||||
#if !defined(_WIN32) || defined(_XBOX)
|
|
||||||
/* assume string needs no modification if not on Windows */
|
|
||||||
return strdup(str);
|
|
||||||
#else
|
|
||||||
#ifdef UNICODE
|
|
||||||
/* TODO/FIXME: Not implemented. */
|
|
||||||
return strdup(str);
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* Windows 95 will return 0 from these functions with a UTF8 codepage set without MSLU. From an unknown MSDN version (others omit this info):
|
|
||||||
* - CP_UTF8 Windows 98/Me, Windows NT 4.0 and later: Translate using UTF-8. When this is set, dwFlags must be zero.
|
|
||||||
* - Windows 95: Under the Microsoft Layer for Unicode, MultiByteToWideChar also supports CP_UTF7 and CP_UTF8.
|
|
||||||
*/
|
*/
|
||||||
path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
|
|
||||||
|
|
||||||
if (path_buf_wide_len)
|
if (path_buf_wide_len)
|
||||||
{
|
{
|
||||||
@ -355,20 +342,37 @@ static char* mb_to_mb_string_alloc(const char *str,
|
|||||||
free(path_buf_wide);
|
free(path_buf_wide);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||||
char* utf8_to_local_string_alloc(const char *str)
|
char* utf8_to_local_string_alloc(const char *str)
|
||||||
{
|
{
|
||||||
return mb_to_mb_string_alloc(str, CODEPAGE_UTF8, CODEPAGE_LOCAL);
|
if (str && *str)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
|
||||||
|
return mb_to_mb_string_alloc(str, CODEPAGE_UTF8, CODEPAGE_LOCAL);
|
||||||
|
#else
|
||||||
|
/* assume string needs no modification if not on Windows */
|
||||||
|
return strdup(str);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||||
char* local_to_utf8_string_alloc(const char *str)
|
char* local_to_utf8_string_alloc(const char *str)
|
||||||
{
|
{
|
||||||
return mb_to_mb_string_alloc(str, CODEPAGE_LOCAL, CODEPAGE_UTF8);
|
if (str && *str)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
|
||||||
|
return mb_to_mb_string_alloc(str, CODEPAGE_LOCAL, CODEPAGE_UTF8);
|
||||||
|
#else
|
||||||
|
/* assume string needs no modification if not on Windows */
|
||||||
|
return strdup(str);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||||
@ -447,52 +451,44 @@ wchar_t* utf8_to_utf16_string_alloc(const char *str)
|
|||||||
char* utf16_to_utf8_string_alloc(const wchar_t *str)
|
char* utf16_to_utf8_string_alloc(const wchar_t *str)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int out_len = 0;
|
|
||||||
#else
|
#else
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
size_t out_len = 0;
|
|
||||||
#endif
|
#endif
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
|
|
||||||
if (!str || !*str)
|
if (!str || !*str)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
len = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
|
|
||||||
|
|
||||||
if (len)
|
|
||||||
{
|
{
|
||||||
|
UINT code_page = CP_UTF8;
|
||||||
|
len = WideCharToMultiByte(code_page,
|
||||||
|
0, str, -1, NULL, 0, NULL, NULL);
|
||||||
|
|
||||||
|
/* fallback to ANSI codepage instead */
|
||||||
|
if (!len)
|
||||||
|
{
|
||||||
|
code_page = CP_ACP;
|
||||||
|
len = WideCharToMultiByte(code_page,
|
||||||
|
0, str, -1, NULL, 0, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
buf = (char*)calloc(len, sizeof(char));
|
buf = (char*)calloc(len, sizeof(char));
|
||||||
|
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
out_len = WideCharToMultiByte(CP_UTF8, 0, str, -1, buf, len, NULL, NULL);
|
if (WideCharToMultiByte(code_page,
|
||||||
}
|
0, str, -1, buf, len, NULL, NULL) < 0)
|
||||||
else
|
|
||||||
{
|
|
||||||
/* fallback to ANSI codepage instead */
|
|
||||||
len = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
|
|
||||||
|
|
||||||
if (len)
|
|
||||||
{
|
{
|
||||||
buf = (char*)calloc(len, sizeof(char));
|
free(buf);
|
||||||
|
return NULL;
|
||||||
if (!buf)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
out_len = WideCharToMultiByte(CP_ACP, 0, str, -1, buf, len, NULL, NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out_len < 0)
|
|
||||||
{
|
|
||||||
free(buf);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
/* NOTE: For now, assume non-Windows platforms' locale is already UTF-8. */
|
/* NOTE: For now, assume non-Windows platforms'
|
||||||
|
* locale is already UTF-8. */
|
||||||
len = wcstombs(NULL, str, 0) + 1;
|
len = wcstombs(NULL, str, 0) + 1;
|
||||||
|
|
||||||
if (len)
|
if (len)
|
||||||
@ -502,13 +498,11 @@ char* utf16_to_utf8_string_alloc(const wchar_t *str)
|
|||||||
if (!buf)
|
if (!buf)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
out_len = wcstombs(buf, str, len);
|
if (wcstombs(buf, str, len) == (size_t)-1)
|
||||||
}
|
{
|
||||||
|
free(buf);
|
||||||
if (out_len == (size_t)-1)
|
return NULL;
|
||||||
{
|
}
|
||||||
free(buf);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
1402
libretro-common/file/file_path.c
Normal file
1402
libretro-common/file/file_path.c
Normal file
File diff suppressed because it is too large
Load Diff
118
libretro-common/file/retro_dirent.c
Normal file
118
libretro-common/file/retro_dirent.c
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/* Copyright (C) 2010-2019 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (retro_dirent.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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <retro_common.h>
|
||||||
|
|
||||||
|
#include <boolean.h>
|
||||||
|
#include <retro_dirent.h>
|
||||||
|
#define VFS_FRONTEND
|
||||||
|
#include <vfs/vfs_implementation.h>
|
||||||
|
|
||||||
|
static retro_vfs_opendir_t dirent_opendir_cb = NULL;
|
||||||
|
static retro_vfs_readdir_t dirent_readdir_cb = NULL;
|
||||||
|
static retro_vfs_dirent_get_name_t dirent_dirent_get_name_cb = NULL;
|
||||||
|
static retro_vfs_dirent_is_dir_t dirent_dirent_is_dir_cb = NULL;
|
||||||
|
static retro_vfs_closedir_t dirent_closedir_cb = NULL;
|
||||||
|
|
||||||
|
void dirent_vfs_init(const struct retro_vfs_interface_info* vfs_info)
|
||||||
|
{
|
||||||
|
const struct retro_vfs_interface* vfs_iface;
|
||||||
|
|
||||||
|
dirent_opendir_cb = NULL;
|
||||||
|
dirent_readdir_cb = NULL;
|
||||||
|
dirent_dirent_get_name_cb = NULL;
|
||||||
|
dirent_dirent_is_dir_cb = NULL;
|
||||||
|
dirent_closedir_cb = NULL;
|
||||||
|
|
||||||
|
vfs_iface = vfs_info->iface;
|
||||||
|
|
||||||
|
if (vfs_info->required_interface_version < DIRENT_REQUIRED_VFS_VERSION || !vfs_iface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dirent_opendir_cb = vfs_iface->opendir;
|
||||||
|
dirent_readdir_cb = vfs_iface->readdir;
|
||||||
|
dirent_dirent_get_name_cb = vfs_iface->dirent_get_name;
|
||||||
|
dirent_dirent_is_dir_cb = vfs_iface->dirent_is_dir;
|
||||||
|
dirent_closedir_cb = vfs_iface->closedir;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RDIR *retro_opendir_include_hidden(const char *name, bool include_hidden)
|
||||||
|
{
|
||||||
|
if (dirent_opendir_cb != NULL)
|
||||||
|
return (struct RDIR *)dirent_opendir_cb(name, include_hidden);
|
||||||
|
return (struct RDIR *)retro_vfs_opendir_impl(name, include_hidden);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RDIR *retro_opendir(const char *name)
|
||||||
|
{
|
||||||
|
return retro_opendir_include_hidden(name, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool retro_dirent_error(struct RDIR *rdir)
|
||||||
|
{
|
||||||
|
/* Left for compatibility */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int retro_readdir(struct RDIR *rdir)
|
||||||
|
{
|
||||||
|
if (dirent_readdir_cb != NULL)
|
||||||
|
return dirent_readdir_cb((struct retro_vfs_dir_handle *)rdir);
|
||||||
|
return retro_vfs_readdir_impl((struct retro_vfs_dir_handle *)rdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *retro_dirent_get_name(struct RDIR *rdir)
|
||||||
|
{
|
||||||
|
if (dirent_dirent_get_name_cb != NULL)
|
||||||
|
return dirent_dirent_get_name_cb((struct retro_vfs_dir_handle *)rdir);
|
||||||
|
return retro_vfs_dirent_get_name_impl((struct retro_vfs_dir_handle *)rdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* retro_dirent_is_dir:
|
||||||
|
* @rdir : pointer to the directory entry.
|
||||||
|
* @unused : deprecated, included for compatibility reasons, pass NULL
|
||||||
|
*
|
||||||
|
* Is the directory listing entry a directory?
|
||||||
|
*
|
||||||
|
* Returns: true if directory listing entry is
|
||||||
|
* a directory, false if not.
|
||||||
|
*/
|
||||||
|
bool retro_dirent_is_dir(struct RDIR *rdir, const char *unused)
|
||||||
|
{
|
||||||
|
if (dirent_dirent_is_dir_cb != NULL)
|
||||||
|
return dirent_dirent_is_dir_cb((struct retro_vfs_dir_handle *)rdir);
|
||||||
|
return retro_vfs_dirent_is_dir_impl((struct retro_vfs_dir_handle *)rdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void retro_closedir(struct RDIR *rdir)
|
||||||
|
{
|
||||||
|
if (dirent_closedir_cb != NULL)
|
||||||
|
dirent_closedir_cb((struct retro_vfs_dir_handle *)rdir);
|
||||||
|
else
|
||||||
|
retro_vfs_closedir_impl((struct retro_vfs_dir_handle *)rdir);
|
||||||
|
}
|
125
libretro-common/include/cdrom/cdrom.h
Normal file
125
libretro-common/include/cdrom/cdrom.h
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/* Copyright (C) 2010-2019 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (cdrom.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBRETRO_SDK_CDROM_H
|
||||||
|
#define __LIBRETRO_SDK_CDROM_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <vfs/vfs.h>
|
||||||
|
#include <libretro.h>
|
||||||
|
#include <retro_common_api.h>
|
||||||
|
#include <retro_inline.h>
|
||||||
|
|
||||||
|
#include <boolean.h>
|
||||||
|
|
||||||
|
struct string_list;
|
||||||
|
|
||||||
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned short g1_timeout;
|
||||||
|
unsigned short g2_timeout;
|
||||||
|
unsigned short g3_timeout;
|
||||||
|
} cdrom_group_timeouts_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned lba_start; /* start of pregap */
|
||||||
|
unsigned lba; /* start of data */
|
||||||
|
unsigned track_size; /* in LBAs */
|
||||||
|
unsigned track_bytes;
|
||||||
|
unsigned char track_num;
|
||||||
|
unsigned char min; /* start of data */
|
||||||
|
unsigned char sec;
|
||||||
|
unsigned char frame;
|
||||||
|
unsigned char mode;
|
||||||
|
bool audio;
|
||||||
|
} cdrom_track_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char drive;
|
||||||
|
unsigned char num_tracks;
|
||||||
|
cdrom_group_timeouts_t timeouts;
|
||||||
|
cdrom_track_t track[99];
|
||||||
|
} cdrom_toc_t;
|
||||||
|
|
||||||
|
void cdrom_lba_to_msf(unsigned lba, unsigned char *min, unsigned char *sec, unsigned char *frame);
|
||||||
|
|
||||||
|
unsigned cdrom_msf_to_lba(unsigned char min, unsigned char sec, unsigned char frame);
|
||||||
|
|
||||||
|
void increment_msf(unsigned char *min, unsigned char *sec, unsigned char *frame);
|
||||||
|
|
||||||
|
int cdrom_read_subq(libretro_vfs_implementation_file *stream, unsigned char *buf, size_t len);
|
||||||
|
|
||||||
|
int cdrom_write_cue(libretro_vfs_implementation_file *stream, char **out_buf, size_t *out_len, char cdrom_drive, unsigned char *num_tracks, cdrom_toc_t *toc);
|
||||||
|
|
||||||
|
/* needs 32 bytes for full vendor, product and version */
|
||||||
|
int cdrom_get_inquiry(libretro_vfs_implementation_file *stream, char *model, int len, bool *is_cdrom);
|
||||||
|
|
||||||
|
int cdrom_read(libretro_vfs_implementation_file *stream, cdrom_group_timeouts_t *timeouts, unsigned char min, unsigned char sec, unsigned char frame, void *s, size_t len, size_t skip);
|
||||||
|
|
||||||
|
int cdrom_set_read_speed(libretro_vfs_implementation_file *stream, unsigned speed);
|
||||||
|
|
||||||
|
int cdrom_stop(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
int cdrom_unlock(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
int cdrom_open_tray(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
int cdrom_close_tray(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
/* must be freed by the caller */
|
||||||
|
struct string_list* cdrom_get_available_drives(void);
|
||||||
|
|
||||||
|
bool cdrom_is_media_inserted(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
bool cdrom_drive_has_media(const char drive);
|
||||||
|
|
||||||
|
void cdrom_get_current_config_core(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
void cdrom_get_current_config_profiles(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
void cdrom_get_current_config_cdread(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
void cdrom_get_current_config_multiread(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
void cdrom_get_current_config_random_readable(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
int cdrom_get_sense(libretro_vfs_implementation_file *stream, unsigned char *sense, size_t len);
|
||||||
|
|
||||||
|
bool cdrom_set_read_cache(libretro_vfs_implementation_file *stream, bool enabled);
|
||||||
|
|
||||||
|
bool cdrom_get_timeouts(libretro_vfs_implementation_file *stream, cdrom_group_timeouts_t *timeouts);
|
||||||
|
|
||||||
|
bool cdrom_has_atip(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char track, bool is_cue);
|
||||||
|
|
||||||
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
@ -72,4 +72,3 @@ RETRO_END_DECLS
|
|||||||
|
|
||||||
/* pragma once */
|
/* pragma once */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ RETRO_BEGIN_DECLS
|
|||||||
/* Count Leading Zero, unsigned 16bit input value */
|
/* Count Leading Zero, unsigned 16bit input value */
|
||||||
static INLINE unsigned compat_clz_u16(uint16_t val)
|
static INLINE unsigned compat_clz_u16(uint16_t val)
|
||||||
{
|
{
|
||||||
#ifdef __GNUC__
|
#if defined(__GNUC__) && !defined(PS2)
|
||||||
return __builtin_clz(val << 16 | 0x8000);
|
return __builtin_clz(val << 16 | 0x8000);
|
||||||
#else
|
#else
|
||||||
unsigned ret = 0;
|
unsigned ret = 0;
|
||||||
@ -61,7 +61,7 @@ static INLINE int compat_ctz(unsigned x)
|
|||||||
{
|
{
|
||||||
#if defined(__GNUC__) && !defined(RARCH_CONSOLE)
|
#if defined(__GNUC__) && !defined(RARCH_CONSOLE)
|
||||||
return __builtin_ctz(x);
|
return __builtin_ctz(x);
|
||||||
#elif _MSC_VER >= 1400 && !defined(_XBOX)
|
#elif _MSC_VER >= 1400 && !defined(_XBOX) && !defined(__WINRT__)
|
||||||
unsigned long r = 0;
|
unsigned long r = 0;
|
||||||
_BitScanReverse((unsigned long*)&r, x);
|
_BitScanReverse((unsigned long*)&r, x);
|
||||||
return (int)r;
|
return (int)r;
|
||||||
|
@ -39,8 +39,8 @@ extern "C" {
|
|||||||
int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...);
|
int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Pre-MSVC 2010 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
|
/* Pre-MSVC 2008 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
|
||||||
#if _MSC_VER < 1600
|
#if _MSC_VER < 1500
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#ifndef vsnprintf
|
#ifndef vsnprintf
|
||||||
@ -56,6 +56,8 @@ extern "C" {
|
|||||||
#undef UNICODE /* Do not bother with UNICODE at this time. */
|
#undef UNICODE /* Do not bother with UNICODE at this time. */
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
/* Python headers defines ssize_t and sets HAVE_SSIZE_T.
|
/* Python headers defines ssize_t and sets HAVE_SSIZE_T.
|
||||||
@ -125,4 +127,3 @@ typedef int ssize_t;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -67,7 +67,6 @@ extern "C" {
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* 7.18.1 Integer types. */
|
/* 7.18.1 Integer types. */
|
||||||
|
|
||||||
/* 7.18.1.1 Exact-width integer types. */
|
/* 7.18.1.1 Exact-width integer types. */
|
||||||
@ -94,7 +93,6 @@ extern "C" {
|
|||||||
typedef signed __int64 int64_t;
|
typedef signed __int64 int64_t;
|
||||||
typedef unsigned __int64 uint64_t;
|
typedef unsigned __int64 uint64_t;
|
||||||
|
|
||||||
|
|
||||||
/* 7.18.1.2 Minimum-width integer types. */
|
/* 7.18.1.2 Minimum-width integer types. */
|
||||||
typedef int8_t int_least8_t;
|
typedef int8_t int_least8_t;
|
||||||
typedef int16_t int_least16_t;
|
typedef int16_t int_least16_t;
|
||||||
@ -255,4 +253,3 @@ typedef uint64_t uintmax_t;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -29,6 +29,10 @@
|
|||||||
#include <compat/msvc.h>
|
#include <compat/msvc.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(PS2)
|
||||||
|
#include <compat_ctype.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
RETRO_BEGIN_DECLS
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -55,7 +59,6 @@ int isblank(int c);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
RETRO_END_DECLS
|
RETRO_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined(PS2)
|
||||||
|
#include <compat_ctype.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
|
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
|
||||||
#include "../../../config.h"
|
#include "../../../config.h"
|
||||||
#endif
|
#endif
|
||||||
@ -46,4 +50,3 @@ RETRO_END_DECLS
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -57,4 +57,3 @@ char *strldup(const char *s, size_t n);
|
|||||||
RETRO_END_DECLS
|
RETRO_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
RETRO_BEGIN_DECLS
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
uint32_t encoding_crc32(uint32_t crc, const uint8_t *buf, size_t len);
|
uint32_t encoding_crc32(uint32_t crc, const uint8_t *buf, size_t len);
|
||||||
|
uint32_t file_crc32(uint32_t crc, const char *path);
|
||||||
|
|
||||||
RETRO_END_DECLS
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
531
libretro-common/include/file/file_path.h
Normal file
531
libretro-common/include/file/file_path.h
Normal file
@ -0,0 +1,531 @@
|
|||||||
|
/* Copyright (C) 2010-2019 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (file_path.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBRETRO_SDK_FILE_PATH_H
|
||||||
|
#define __LIBRETRO_SDK_FILE_PATH_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <libretro.h>
|
||||||
|
#include <retro_common_api.h>
|
||||||
|
|
||||||
|
#include <boolean.h>
|
||||||
|
|
||||||
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define PATH_REQUIRED_VFS_VERSION 3
|
||||||
|
|
||||||
|
void path_vfs_init(const struct retro_vfs_interface_info* vfs_info);
|
||||||
|
|
||||||
|
/* Order in this enum is equivalent to negative sort order in filelist
|
||||||
|
* (i.e. DIRECTORY is on top of PLAIN_FILE) */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RARCH_FILETYPE_UNSET,
|
||||||
|
RARCH_PLAIN_FILE,
|
||||||
|
RARCH_COMPRESSED_FILE_IN_ARCHIVE,
|
||||||
|
RARCH_COMPRESSED_ARCHIVE,
|
||||||
|
RARCH_DIRECTORY,
|
||||||
|
RARCH_FILE_UNSUPPORTED
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_is_compressed_file:
|
||||||
|
* @path : path
|
||||||
|
*
|
||||||
|
* Checks if path is a compressed file.
|
||||||
|
*
|
||||||
|
* Returns: true (1) if path is a compressed file, otherwise false (0).
|
||||||
|
**/
|
||||||
|
bool path_is_compressed_file(const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_contains_compressed_file:
|
||||||
|
* @path : path
|
||||||
|
*
|
||||||
|
* Checks if path contains a compressed file.
|
||||||
|
*
|
||||||
|
* Currently we only check for hash symbol (#) inside the pathname.
|
||||||
|
* If path is ever expanded to a general URI, we should check for that here.
|
||||||
|
*
|
||||||
|
* Example: Somewhere in the path there might be a compressed file
|
||||||
|
* E.g.: /path/to/file.7z#mygame.img
|
||||||
|
*
|
||||||
|
* Returns: true (1) if path contains compressed file, otherwise false (0).
|
||||||
|
**/
|
||||||
|
#define path_contains_compressed_file(path) (path_get_archive_delim((path)) != NULL)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_get_archive_delim:
|
||||||
|
* @path : path
|
||||||
|
*
|
||||||
|
* Gets delimiter of an archive file. Only the first '#'
|
||||||
|
* after a compression extension is considered.
|
||||||
|
*
|
||||||
|
* Returns: pointer to the delimiter in the path if it contains
|
||||||
|
* a compressed file, otherwise NULL.
|
||||||
|
*/
|
||||||
|
const char *path_get_archive_delim(const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_get_extension:
|
||||||
|
* @path : path
|
||||||
|
*
|
||||||
|
* Gets extension of file. Only '.'s
|
||||||
|
* after the last slash are considered.
|
||||||
|
*
|
||||||
|
* Returns: extension part from the path.
|
||||||
|
*/
|
||||||
|
const char *path_get_extension(const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_remove_extension:
|
||||||
|
* @path : path
|
||||||
|
*
|
||||||
|
* Mutates path by removing its extension. Removes all
|
||||||
|
* text after and including the last '.'.
|
||||||
|
* Only '.'s after the last slash are considered.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 1) If path has an extension, returns path with the
|
||||||
|
* extension removed.
|
||||||
|
* 2) If there is no extension, returns NULL.
|
||||||
|
* 3) If path is empty or NULL, returns NULL
|
||||||
|
*/
|
||||||
|
char *path_remove_extension(char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_basename:
|
||||||
|
* @path : path
|
||||||
|
*
|
||||||
|
* Get basename from @path.
|
||||||
|
*
|
||||||
|
* Returns: basename from path.
|
||||||
|
**/
|
||||||
|
const char *path_basename(const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_basedir:
|
||||||
|
* @path : path
|
||||||
|
*
|
||||||
|
* Extracts base directory by mutating path.
|
||||||
|
* Keeps trailing '/'.
|
||||||
|
**/
|
||||||
|
void path_basedir(char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_parent_dir:
|
||||||
|
* @path : path
|
||||||
|
*
|
||||||
|
* Extracts parent directory by mutating path.
|
||||||
|
* Assumes that path is a directory. Keeps trailing '/'.
|
||||||
|
* If the path was already at the root directory, returns empty string
|
||||||
|
**/
|
||||||
|
void path_parent_dir(char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_resolve_realpath:
|
||||||
|
* @buf : input and output buffer for path
|
||||||
|
* @size : size of buffer
|
||||||
|
* @resolve_symlinks : whether to resolve symlinks or not
|
||||||
|
*
|
||||||
|
* Resolves use of ".", "..", multiple slashes etc in absolute paths.
|
||||||
|
*
|
||||||
|
* Relative paths are rebased on the current working dir.
|
||||||
|
*
|
||||||
|
* Returns: @buf if successful, NULL otherwise.
|
||||||
|
* Note: Not implemented on consoles
|
||||||
|
* Note: Symlinks are only resolved on Unix-likes
|
||||||
|
* Note: The current working dir might not be what you expect,
|
||||||
|
* e.g. on Android it is "/"
|
||||||
|
* Use of fill_pathname_resolve_relative() should be prefered
|
||||||
|
**/
|
||||||
|
char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_relative_to:
|
||||||
|
* @out : buffer to write the relative path to
|
||||||
|
* @path : path to be expressed relatively
|
||||||
|
* @base : relative to this
|
||||||
|
* @size : size of output buffer
|
||||||
|
*
|
||||||
|
* Turns @path into a path relative to @base and writes it to @out.
|
||||||
|
*
|
||||||
|
* @base is assumed to be a base directory, i.e. a path ending with '/' or '\'.
|
||||||
|
* Both @path and @base are assumed to be absolute paths without "." or "..".
|
||||||
|
*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_is_absolute:
|
||||||
|
* @path : path
|
||||||
|
*
|
||||||
|
* Checks if @path is an absolute path or a relative path.
|
||||||
|
*
|
||||||
|
* Returns: true if path is absolute, false if path is relative.
|
||||||
|
**/
|
||||||
|
bool path_is_absolute(const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_pathname:
|
||||||
|
* @out_path : output path
|
||||||
|
* @in_path : input path
|
||||||
|
* @replace : what to replace
|
||||||
|
* @size : buffer size of output path
|
||||||
|
*
|
||||||
|
* FIXME: Verify
|
||||||
|
*
|
||||||
|
* Replaces filename extension with 'replace' and outputs result to out_path.
|
||||||
|
* The extension here is considered to be the string from the last '.'
|
||||||
|
* to the end.
|
||||||
|
*
|
||||||
|
* Only '.'s after the last slash are considered as extensions.
|
||||||
|
* If no '.' is present, in_path and replace will simply be concatenated.
|
||||||
|
* 'size' is buffer size of 'out_path'.
|
||||||
|
* E.g.: in_path = "/foo/bar/baz/boo.c", replace = ".asm" =>
|
||||||
|
* out_path = "/foo/bar/baz/boo.asm"
|
||||||
|
* E.g.: in_path = "/foo/bar/baz/boo.c", replace = "" =>
|
||||||
|
* out_path = "/foo/bar/baz/boo"
|
||||||
|
*/
|
||||||
|
void fill_pathname(char *out_path, const char *in_path,
|
||||||
|
const char *replace, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_dated_filename:
|
||||||
|
* @out_filename : output filename
|
||||||
|
* @ext : extension of output filename
|
||||||
|
* @size : buffer size of output filename
|
||||||
|
*
|
||||||
|
* Creates a 'dated' filename prefixed by 'RetroArch', and
|
||||||
|
* concatenates extension (@ext) to it.
|
||||||
|
*
|
||||||
|
* E.g.:
|
||||||
|
* out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
|
||||||
|
**/
|
||||||
|
void fill_dated_filename(char *out_filename,
|
||||||
|
const char *ext, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_str_dated_filename:
|
||||||
|
* @out_filename : output filename
|
||||||
|
* @in_str : input string
|
||||||
|
* @ext : extension of output filename
|
||||||
|
* @size : buffer size of output filename
|
||||||
|
*
|
||||||
|
* Creates a 'dated' filename prefixed by the string @in_str, and
|
||||||
|
* concatenates extension (@ext) to it.
|
||||||
|
*
|
||||||
|
* E.g.:
|
||||||
|
* out_filename = "RetroArch-{year}{month}{day}-{Hour}{Minute}{Second}.{@ext}"
|
||||||
|
**/
|
||||||
|
void fill_str_dated_filename(char *out_filename,
|
||||||
|
const char *in_str, const char *ext, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_pathname_noext:
|
||||||
|
* @out_path : output path
|
||||||
|
* @in_path : input path
|
||||||
|
* @replace : what to replace
|
||||||
|
* @size : buffer size of output path
|
||||||
|
*
|
||||||
|
* Appends a filename extension 'replace' to 'in_path', and outputs
|
||||||
|
* result in 'out_path'.
|
||||||
|
*
|
||||||
|
* Assumes in_path has no extension. If an extension is still
|
||||||
|
* present in 'in_path', it will be ignored.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void fill_pathname_noext(char *out_path, const char *in_path,
|
||||||
|
const char *replace, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_last_slash:
|
||||||
|
* @str : input path
|
||||||
|
*
|
||||||
|
* Gets a pointer to the last slash in the input path.
|
||||||
|
*
|
||||||
|
* Returns: a pointer to the last slash in the input path.
|
||||||
|
**/
|
||||||
|
char *find_last_slash(const char *str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_pathname_dir:
|
||||||
|
* @in_dir : input directory path
|
||||||
|
* @in_basename : input basename to be appended to @in_dir
|
||||||
|
* @replace : replacement to be appended to @in_basename
|
||||||
|
* @size : size of buffer
|
||||||
|
*
|
||||||
|
* Appends basename of 'in_basename', to 'in_dir', along with 'replace'.
|
||||||
|
* Basename of in_basename is the string after the last '/' or '\\',
|
||||||
|
* i.e the filename without directories.
|
||||||
|
*
|
||||||
|
* If in_basename has no '/' or '\\', the whole 'in_basename' will be used.
|
||||||
|
* 'size' is buffer size of 'in_dir'.
|
||||||
|
*
|
||||||
|
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
|
||||||
|
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
|
||||||
|
**/
|
||||||
|
void fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||||
|
const char *replace, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_pathname_base:
|
||||||
|
* @out : output path
|
||||||
|
* @in_path : input path
|
||||||
|
* @size : size of output path
|
||||||
|
*
|
||||||
|
* Copies basename of @in_path into @out_path.
|
||||||
|
**/
|
||||||
|
void fill_pathname_base(char *out_path, const char *in_path, size_t size);
|
||||||
|
|
||||||
|
void fill_pathname_base_noext(char *out_dir,
|
||||||
|
const char *in_path, size_t size);
|
||||||
|
|
||||||
|
void fill_pathname_base_ext(char *out,
|
||||||
|
const char *in_path, const char *ext,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_pathname_basedir:
|
||||||
|
* @out_dir : output directory
|
||||||
|
* @in_path : input path
|
||||||
|
* @size : size of output directory
|
||||||
|
*
|
||||||
|
* Copies base directory of @in_path into @out_path.
|
||||||
|
* If in_path is a path without any slashes (relative current directory),
|
||||||
|
* @out_path will get path "./".
|
||||||
|
**/
|
||||||
|
void fill_pathname_basedir(char *out_path, const char *in_path, size_t size);
|
||||||
|
|
||||||
|
void fill_pathname_basedir_noext(char *out_dir,
|
||||||
|
const char *in_path, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_pathname_parent_dir_name:
|
||||||
|
* @out_dir : output directory
|
||||||
|
* @in_dir : input directory
|
||||||
|
* @size : size of output directory
|
||||||
|
*
|
||||||
|
* Copies only the parent directory name of @in_dir into @out_dir.
|
||||||
|
* The two buffers must not overlap. Removes trailing '/'.
|
||||||
|
* Returns true on success, false if a slash was not found in the path.
|
||||||
|
**/
|
||||||
|
bool fill_pathname_parent_dir_name(char *out_dir,
|
||||||
|
const char *in_dir, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_pathname_parent_dir:
|
||||||
|
* @out_dir : output directory
|
||||||
|
* @in_dir : input directory
|
||||||
|
* @size : size of output directory
|
||||||
|
*
|
||||||
|
* Copies parent directory of @in_dir into @out_dir.
|
||||||
|
* Assumes @in_dir is a directory. Keeps trailing '/'.
|
||||||
|
* If the path was already at the root directory, @out_dir will be an empty string.
|
||||||
|
**/
|
||||||
|
void fill_pathname_parent_dir(char *out_dir,
|
||||||
|
const char *in_dir, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_pathname_resolve_relative:
|
||||||
|
* @out_path : output path
|
||||||
|
* @in_refpath : input reference path
|
||||||
|
* @in_path : input path
|
||||||
|
* @size : size of @out_path
|
||||||
|
*
|
||||||
|
* Joins basedir of @in_refpath together with @in_path.
|
||||||
|
* If @in_path is an absolute path, out_path = in_path.
|
||||||
|
* E.g.: in_refpath = "/foo/bar/baz.a", in_path = "foobar.cg",
|
||||||
|
* out_path = "/foo/bar/foobar.cg".
|
||||||
|
**/
|
||||||
|
void fill_pathname_resolve_relative(char *out_path, const char *in_refpath,
|
||||||
|
const char *in_path, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_pathname_join:
|
||||||
|
* @out_path : output path
|
||||||
|
* @dir : directory
|
||||||
|
* @path : path
|
||||||
|
* @size : size of output path
|
||||||
|
*
|
||||||
|
* Joins a directory (@dir) and path (@path) together.
|
||||||
|
* Makes sure not to get two consecutive slashes
|
||||||
|
* between directory and path.
|
||||||
|
**/
|
||||||
|
void fill_pathname_join(char *out_path, const char *dir,
|
||||||
|
const char *path, size_t size);
|
||||||
|
|
||||||
|
void 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,
|
||||||
|
const char *dir, const char *path,
|
||||||
|
const char *concat,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
|
void fill_pathname_join_concat(char *out_path,
|
||||||
|
const char *dir, const char *path,
|
||||||
|
const char *concat,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
|
void fill_pathname_join_noext(char *out_path,
|
||||||
|
const char *dir, const char *path, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_pathname_join_delim:
|
||||||
|
* @out_path : output path
|
||||||
|
* @dir : directory
|
||||||
|
* @path : path
|
||||||
|
* @delim : delimiter
|
||||||
|
* @size : size of output 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,
|
||||||
|
const char *path, const char delim, size_t size);
|
||||||
|
|
||||||
|
void fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
||||||
|
const char *path, const char delim, const char *concat,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_short_pathname_representation:
|
||||||
|
* @out_rep : output representation
|
||||||
|
* @in_path : input path
|
||||||
|
* @size : size of output representation
|
||||||
|
*
|
||||||
|
* Generates a short representation of path. It should only
|
||||||
|
* be used for displaying the result; the output representation is not
|
||||||
|
* binding in any meaningful way (for a normal path, this is the same as basename)
|
||||||
|
* In case of more complex URLs, this should cut everything except for
|
||||||
|
* the main image file.
|
||||||
|
*
|
||||||
|
* 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,
|
||||||
|
const char *in_path, size_t size);
|
||||||
|
|
||||||
|
void fill_short_pathname_representation_noext(char* out_rep,
|
||||||
|
const char *in_path, size_t size);
|
||||||
|
|
||||||
|
void fill_pathname_expand_special(char *out_path,
|
||||||
|
const char *in_path, size_t size);
|
||||||
|
|
||||||
|
void fill_pathname_abbreviate_special(char *out_path,
|
||||||
|
const char *in_path, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_basedir:
|
||||||
|
* @path : path
|
||||||
|
*
|
||||||
|
* Extracts base directory by mutating path.
|
||||||
|
* Keeps trailing '/'.
|
||||||
|
**/
|
||||||
|
void path_basedir_wrapper(char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_char_is_slash:
|
||||||
|
* @c : character
|
||||||
|
*
|
||||||
|
* Checks if character (@c) is a slash.
|
||||||
|
*
|
||||||
|
* Returns: true (1) if character is a slash, otherwise false (0).
|
||||||
|
*/
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define path_char_is_slash(c) (((c) == '/') || ((c) == '\\'))
|
||||||
|
#else
|
||||||
|
#define path_char_is_slash(c) ((c) == '/')
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_default_slash and path_default_slash_c:
|
||||||
|
*
|
||||||
|
* Gets the default slash separator.
|
||||||
|
*
|
||||||
|
* Returns: default slash separator.
|
||||||
|
*/
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define path_default_slash() "\\"
|
||||||
|
#define path_default_slash_c() '\\'
|
||||||
|
#else
|
||||||
|
#define path_default_slash() "/"
|
||||||
|
#define path_default_slash_c() '/'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill_pathname_slash:
|
||||||
|
* @path : path
|
||||||
|
* @size : size of path
|
||||||
|
*
|
||||||
|
* Assumes path is a directory. Appends a slash
|
||||||
|
* if not already there.
|
||||||
|
**/
|
||||||
|
void fill_pathname_slash(char *path, size_t size);
|
||||||
|
|
||||||
|
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
|
||||||
|
void fill_pathname_application_path(char *buf, size_t size);
|
||||||
|
void fill_pathname_application_dir(char *buf, size_t size);
|
||||||
|
void fill_pathname_home_dir(char *buf, size_t size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_mkdir:
|
||||||
|
* @dir : directory
|
||||||
|
*
|
||||||
|
* Create directory on filesystem.
|
||||||
|
*
|
||||||
|
* Returns: true (1) if directory could be created, otherwise false (0).
|
||||||
|
**/
|
||||||
|
bool path_mkdir(const char *dir);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path_is_directory:
|
||||||
|
* @path : path
|
||||||
|
*
|
||||||
|
* Checks if path is a directory.
|
||||||
|
*
|
||||||
|
* Returns: true (1) if path is a directory, otherwise false (0).
|
||||||
|
*/
|
||||||
|
bool path_is_directory(const char *path);
|
||||||
|
|
||||||
|
bool path_is_character_special(const char *path);
|
||||||
|
|
||||||
|
int path_stat(const char *path);
|
||||||
|
|
||||||
|
bool path_is_valid(const char *path);
|
||||||
|
|
||||||
|
int32_t path_get_size(const char *path);
|
||||||
|
|
||||||
|
bool is_path_accessible_using_standard_io(const char *path);
|
||||||
|
|
||||||
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
@ -128,7 +128,8 @@ extern "C" {
|
|||||||
|
|
||||||
/* LIGHTGUN device is similar to Guncon-2 for PlayStation 2.
|
/* LIGHTGUN device is similar to Guncon-2 for PlayStation 2.
|
||||||
* It reports X/Y coordinates in screen space (similar to the pointer)
|
* It reports X/Y coordinates in screen space (similar to the pointer)
|
||||||
* in the range [-0x8000, 0x7fff] in both axes, with zero being center.
|
* in the range [-0x8000, 0x7fff] in both axes, with zero being center and
|
||||||
|
* -0x8000 being out of bounds.
|
||||||
* As well as reporting on/off screen state. It features a trigger,
|
* As well as reporting on/off screen state. It features a trigger,
|
||||||
* start/select buttons, auxiliary action buttons and a
|
* start/select buttons, auxiliary action buttons and a
|
||||||
* directional pad. A forced off-screen shot can be requested for
|
* directional pad. A forced off-screen shot can be requested for
|
||||||
@ -139,7 +140,8 @@ extern "C" {
|
|||||||
/* The ANALOG device is an extension to JOYPAD (RetroPad).
|
/* The ANALOG device is an extension to JOYPAD (RetroPad).
|
||||||
* Similar to DualShock2 it adds two analog sticks and all buttons can
|
* Similar to DualShock2 it adds two analog sticks and all buttons can
|
||||||
* be analog. This is treated as a separate device type as it returns
|
* be analog. This is treated as a separate device type as it returns
|
||||||
* axis values in the full analog range of [-0x8000, 0x7fff].
|
* axis values in the full analog range of [-0x7fff, 0x7fff],
|
||||||
|
* although some devices may return -0x8000.
|
||||||
* Positive X axis is right. Positive Y axis is down.
|
* Positive X axis is right. Positive Y axis is down.
|
||||||
* Buttons are returned in the range [0, 0x7fff].
|
* Buttons are returned in the range [0, 0x7fff].
|
||||||
* Only use ANALOG type when polling for analog values.
|
* Only use ANALOG type when polling for analog values.
|
||||||
@ -200,6 +202,8 @@ extern "C" {
|
|||||||
#define RETRO_DEVICE_ID_JOYPAD_L3 14
|
#define RETRO_DEVICE_ID_JOYPAD_L3 14
|
||||||
#define RETRO_DEVICE_ID_JOYPAD_R3 15
|
#define RETRO_DEVICE_ID_JOYPAD_R3 15
|
||||||
|
|
||||||
|
#define RETRO_DEVICE_ID_JOYPAD_MASK 256
|
||||||
|
|
||||||
/* Index / Id values for ANALOG device. */
|
/* Index / Id values for ANALOG device. */
|
||||||
#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0
|
#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0
|
||||||
#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1
|
#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1
|
||||||
@ -246,6 +250,7 @@ extern "C" {
|
|||||||
#define RETRO_DEVICE_ID_POINTER_X 0
|
#define RETRO_DEVICE_ID_POINTER_X 0
|
||||||
#define RETRO_DEVICE_ID_POINTER_Y 1
|
#define RETRO_DEVICE_ID_POINTER_Y 1
|
||||||
#define RETRO_DEVICE_ID_POINTER_PRESSED 2
|
#define RETRO_DEVICE_ID_POINTER_PRESSED 2
|
||||||
|
#define RETRO_DEVICE_ID_POINTER_COUNT 3
|
||||||
|
|
||||||
/* Returned from retro_get_region(). */
|
/* Returned from retro_get_region(). */
|
||||||
#define RETRO_REGION_NTSC 0
|
#define RETRO_REGION_NTSC 0
|
||||||
@ -271,6 +276,8 @@ enum retro_language
|
|||||||
RETRO_LANGUAGE_POLISH = 14,
|
RETRO_LANGUAGE_POLISH = 14,
|
||||||
RETRO_LANGUAGE_VIETNAMESE = 15,
|
RETRO_LANGUAGE_VIETNAMESE = 15,
|
||||||
RETRO_LANGUAGE_ARABIC = 16,
|
RETRO_LANGUAGE_ARABIC = 16,
|
||||||
|
RETRO_LANGUAGE_GREEK = 17,
|
||||||
|
RETRO_LANGUAGE_TURKISH = 18,
|
||||||
RETRO_LANGUAGE_LAST,
|
RETRO_LANGUAGE_LAST,
|
||||||
|
|
||||||
/* Ensure sizeof(enum) == sizeof(int) */
|
/* Ensure sizeof(enum) == sizeof(int) */
|
||||||
@ -450,6 +457,7 @@ enum retro_key
|
|||||||
RETROK_POWER = 320,
|
RETROK_POWER = 320,
|
||||||
RETROK_EURO = 321,
|
RETROK_EURO = 321,
|
||||||
RETROK_UNDO = 322,
|
RETROK_UNDO = 322,
|
||||||
|
RETROK_OEM_102 = 323,
|
||||||
|
|
||||||
RETROK_LAST,
|
RETROK_LAST,
|
||||||
|
|
||||||
@ -481,11 +489,13 @@ enum retro_mod
|
|||||||
/* Environment commands. */
|
/* Environment commands. */
|
||||||
#define RETRO_ENVIRONMENT_SET_ROTATION 1 /* const unsigned * --
|
#define RETRO_ENVIRONMENT_SET_ROTATION 1 /* const unsigned * --
|
||||||
* Sets screen rotation of graphics.
|
* Sets screen rotation of graphics.
|
||||||
* Is only implemented if rotation can be accelerated by hardware.
|
|
||||||
* Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180,
|
* Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180,
|
||||||
* 270 degrees counter-clockwise respectively.
|
* 270 degrees counter-clockwise respectively.
|
||||||
*/
|
*/
|
||||||
#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 /* bool * --
|
#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 /* bool * --
|
||||||
|
* NOTE: As of 2019 this callback is considered deprecated in favor of
|
||||||
|
* using core options to manage overscan in a more nuanced, core-specific way.
|
||||||
|
*
|
||||||
* Boolean value whether or not the implementation should use overscan,
|
* Boolean value whether or not the implementation should use overscan,
|
||||||
* or crop away overscan.
|
* or crop away overscan.
|
||||||
*/
|
*/
|
||||||
@ -604,7 +614,7 @@ enum retro_mod
|
|||||||
* Afterward it may be called again for the core to communicate
|
* Afterward it may be called again for the core to communicate
|
||||||
* updated options to the frontend, but the number of core
|
* updated options to the frontend, but the number of core
|
||||||
* options must not change from the number in the initial call.
|
* options must not change from the number in the initial call.
|
||||||
*
|
*
|
||||||
* 'data' points to an array of retro_variable structs
|
* 'data' points to an array of retro_variable structs
|
||||||
* terminated by a { NULL, NULL } element.
|
* terminated by a { NULL, NULL } element.
|
||||||
* retro_variable::key should be namespaced to not collide
|
* retro_variable::key should be namespaced to not collide
|
||||||
@ -657,6 +667,15 @@ enum retro_mod
|
|||||||
/* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK.
|
/* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK.
|
||||||
* It was not used by any known core at the time,
|
* It was not used by any known core at the time,
|
||||||
* and was removed from the API. */
|
* and was removed from the API. */
|
||||||
|
#define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21
|
||||||
|
/* const struct retro_frame_time_callback * --
|
||||||
|
* Lets the core know how much time has passed since last
|
||||||
|
* invocation of retro_run().
|
||||||
|
* The frontend can tamper with the timing to fake fast-forward,
|
||||||
|
* slow-motion, frame stepping, etc.
|
||||||
|
* In this case the delta time will use the reference value
|
||||||
|
* in frame_time_callback..
|
||||||
|
*/
|
||||||
#define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22
|
#define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22
|
||||||
/* const struct retro_audio_callback * --
|
/* const struct retro_audio_callback * --
|
||||||
* Sets an interface which is used to notify a libretro core about audio
|
* Sets an interface which is used to notify a libretro core about audio
|
||||||
@ -683,15 +702,6 @@ enum retro_mod
|
|||||||
* A libretro core using SET_AUDIO_CALLBACK should also make use of
|
* A libretro core using SET_AUDIO_CALLBACK should also make use of
|
||||||
* SET_FRAME_TIME_CALLBACK.
|
* SET_FRAME_TIME_CALLBACK.
|
||||||
*/
|
*/
|
||||||
#define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21
|
|
||||||
/* const struct retro_frame_time_callback * --
|
|
||||||
* Lets the core know how much time has passed since last
|
|
||||||
* invocation of retro_run().
|
|
||||||
* The frontend can tamper with the timing to fake fast-forward,
|
|
||||||
* slow-motion, frame stepping, etc.
|
|
||||||
* In this case the delta time will use the reference value
|
|
||||||
* in frame_time_callback..
|
|
||||||
*/
|
|
||||||
#define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23
|
#define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23
|
||||||
/* struct retro_rumble_interface * --
|
/* struct retro_rumble_interface * --
|
||||||
* Gets an interface which is used by a libretro core to set
|
* Gets an interface which is used by a libretro core to set
|
||||||
@ -871,12 +881,12 @@ enum retro_mod
|
|||||||
* types already defined in the libretro API.
|
* types already defined in the libretro API.
|
||||||
*
|
*
|
||||||
* The core must pass an array of const struct retro_controller_info which
|
* The core must pass an array of const struct retro_controller_info which
|
||||||
* is terminated with a blanked out struct. Each element of the
|
* is terminated with a blanked out struct. Each element of the
|
||||||
* retro_controller_info struct corresponds to the ascending port index
|
* retro_controller_info struct corresponds to the ascending port index
|
||||||
* that is passed to retro_set_controller_port_device() when that function
|
* that is passed to retro_set_controller_port_device() when that function
|
||||||
* is called to indicate to the core that the frontend has changed the
|
* is called to indicate to the core that the frontend has changed the
|
||||||
* active device subclass. SEE ALSO: retro_set_controller_port_device()
|
* active device subclass. SEE ALSO: retro_set_controller_port_device()
|
||||||
*
|
*
|
||||||
* The ascending input port indexes provided by the core in the struct
|
* The ascending input port indexes provided by the core in the struct
|
||||||
* are generally presented by frontends as ascending User # or Player #,
|
* are generally presented by frontends as ascending User # or Player #,
|
||||||
* such as Player 1, Player 2, Player 3, etc. Which device subclasses are
|
* such as Player 1, Player 2, Player 3, etc. Which device subclasses are
|
||||||
@ -888,7 +898,7 @@ enum retro_mod
|
|||||||
* User or Player, beginning with the generic Libretro device that the
|
* User or Player, beginning with the generic Libretro device that the
|
||||||
* subclasses are derived from. The second inner element of each entry is the
|
* subclasses are derived from. The second inner element of each entry is the
|
||||||
* total number of subclasses that are listed in the retro_controller_description.
|
* total number of subclasses that are listed in the retro_controller_description.
|
||||||
*
|
*
|
||||||
* NOTE: Even if special device types are set in the libretro core,
|
* NOTE: Even if special device types are set in the libretro core,
|
||||||
* libretro should only poll input based on the base input device types.
|
* libretro should only poll input based on the base input device types.
|
||||||
*/
|
*/
|
||||||
@ -968,7 +978,37 @@ enum retro_mod
|
|||||||
* A frontend must make sure that the pointer obtained from this function is
|
* A frontend must make sure that the pointer obtained from this function is
|
||||||
* writeable (and readable).
|
* writeable (and readable).
|
||||||
*/
|
*/
|
||||||
|
#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||||
|
/* const struct retro_hw_render_interface ** --
|
||||||
|
* Returns an API specific rendering interface for accessing API specific data.
|
||||||
|
* Not all HW rendering APIs support or need this.
|
||||||
|
* The contents of the returned pointer is specific to the rendering API
|
||||||
|
* being used. See the various headers like libretro_vulkan.h, etc.
|
||||||
|
*
|
||||||
|
* GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called.
|
||||||
|
* Similarly, after context_destroyed callback returns,
|
||||||
|
* the contents of the HW_RENDER_INTERFACE are invalidated.
|
||||||
|
*/
|
||||||
|
#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||||
|
/* const bool * --
|
||||||
|
* If true, the libretro implementation supports achievements
|
||||||
|
* either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS
|
||||||
|
* or via retro_get_memory_data/retro_get_memory_size.
|
||||||
|
*
|
||||||
|
* This must be called before the first call to retro_run.
|
||||||
|
*/
|
||||||
|
#define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||||
|
/* const struct retro_hw_render_context_negotiation_interface * --
|
||||||
|
* Sets an interface which lets the libretro core negotiate with frontend how a context is created.
|
||||||
|
* The semantics of this interface depends on which API is used in SET_HW_RENDER earlier.
|
||||||
|
* This interface will be used when the frontend is trying to create a HW rendering context,
|
||||||
|
* so it will be used after SET_HW_RENDER, but before the context_reset callback.
|
||||||
|
*/
|
||||||
|
#define RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS 44
|
||||||
|
/* uint64_t * --
|
||||||
|
* Sets quirk flags associated with serialization. The frontend will zero any flags it doesn't
|
||||||
|
* recognize or support. Should be set in either retro_init or retro_load_game, but not both.
|
||||||
|
*/
|
||||||
#define RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT (44 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
#define RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT (44 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||||
/* N/A (null) * --
|
/* N/A (null) * --
|
||||||
* The frontend will try to use a 'shared' hardware context (mostly applicable
|
* The frontend will try to use a 'shared' hardware context (mostly applicable
|
||||||
@ -980,160 +1020,19 @@ enum retro_mod
|
|||||||
* This will do nothing on its own until SET_HW_RENDER env callbacks are
|
* This will do nothing on its own until SET_HW_RENDER env callbacks are
|
||||||
* being used.
|
* being used.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define RETRO_ENVIRONMENT_GET_VFS_INTERFACE (45 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
#define RETRO_ENVIRONMENT_GET_VFS_INTERFACE (45 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||||
/* struct retro_vfs_interface_info * --
|
/* struct retro_vfs_interface_info * --
|
||||||
* Gets access to the VFS interface.
|
* Gets access to the VFS interface.
|
||||||
* VFS presence needs to be queried prior to load_game or any
|
* VFS presence needs to be queried prior to load_game or any
|
||||||
* get_system/save/other_directory being called to let front end know
|
* get_system/save/other_directory being called to let front end know
|
||||||
* core supports VFS before it starts handing out paths.
|
* core supports VFS before it starts handing out paths.
|
||||||
* It is recomended to do so in retro_set_environment */
|
* It is recomended to do so in retro_set_environment
|
||||||
|
*/
|
||||||
/* VFS functionality */
|
|
||||||
|
|
||||||
/* File paths:
|
|
||||||
* File paths passed as parameters when using this api shall be well formed unix-style,
|
|
||||||
* using "/" (unquoted forward slash) as directory separator regardless of the platform's native separator.
|
|
||||||
* Paths shall also include at least one forward slash ("game.bin" is an invalid path, use "./game.bin" instead).
|
|
||||||
* Other than the directory separator, cores shall not make assumptions about path format:
|
|
||||||
* "C:/path/game.bin", "http://example.com/game.bin", "#game/game.bin", "./game.bin" (without quotes) are all valid paths.
|
|
||||||
* Cores may replace the basename or remove path components from the end, and/or add new components;
|
|
||||||
* however, cores shall not append "./", "../" or multiple consecutive forward slashes ("//") to paths they request to front end.
|
|
||||||
* The frontend is encouraged to make such paths work as well as it can, but is allowed to give up if the core alters paths too much.
|
|
||||||
* Frontends are encouraged, but not required, to support native file system paths (modulo replacing the directory separator, if applicable).
|
|
||||||
* Cores are allowed to try using them, but must remain functional if the front rejects such requests.
|
|
||||||
* Cores are encouraged to use the libretro-common filestream functions for file I/O,
|
|
||||||
* as they seamlessly integrate with VFS, deal with directory separator replacement as appropriate
|
|
||||||
* and provide platform-specific fallbacks in cases where front ends do not support VFS. */
|
|
||||||
|
|
||||||
/* Opaque file handle
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
struct retro_vfs_file_handle;
|
|
||||||
|
|
||||||
/* File open flags
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
#define RETRO_VFS_FILE_ACCESS_READ (1 << 0) /* Read only mode */
|
|
||||||
#define RETRO_VFS_FILE_ACCESS_WRITE (1 << 1) /* Write only mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified */
|
|
||||||
#define RETRO_VFS_FILE_ACCESS_READ_WRITE (RETRO_VFS_FILE_ACCESS_READ | RETRO_VFS_FILE_ACCESS_WRITE) /* Read-write mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified*/
|
|
||||||
#define RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING (1 << 2) /* Prevents discarding content of existing files opened for writing */
|
|
||||||
|
|
||||||
/* These are only hints. The frontend may choose to ignore them. Other than RAM/CPU/etc use,
|
|
||||||
and how they react to unlikely external interference (for example someone else writing to that file,
|
|
||||||
or the file's server going down), behavior will not change. */
|
|
||||||
#define RETRO_VFS_FILE_ACCESS_HINT_NONE (0)
|
|
||||||
/* Indicate that the file will be accessed many times. The frontend should aggressively cache everything. */
|
|
||||||
#define RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS (1 << 0)
|
|
||||||
|
|
||||||
/* Seek positions */
|
|
||||||
#define RETRO_VFS_SEEK_POSITION_START 0
|
|
||||||
#define RETRO_VFS_SEEK_POSITION_CURRENT 1
|
|
||||||
#define RETRO_VFS_SEEK_POSITION_END 2
|
|
||||||
|
|
||||||
/* Get path from opaque handle. Returns the exact same path passed to file_open when getting the handle
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
typedef const char *(RETRO_CALLCONV *retro_vfs_get_path_t)(struct retro_vfs_file_handle *stream);
|
|
||||||
|
|
||||||
/* Open a file for reading or writing. If path points to a directory, this will
|
|
||||||
* fail. Returns the opaque file handle, or NULL for error.
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
typedef struct retro_vfs_file_handle *(RETRO_CALLCONV *retro_vfs_open_t)(const char *path, unsigned mode, unsigned hints);
|
|
||||||
|
|
||||||
/* Close the file and release its resources. Must be called if open_file returns non-NULL. Returns 0 on succes, -1 on failure.
|
|
||||||
* Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used.
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
typedef int (RETRO_CALLCONV *retro_vfs_close_t)(struct retro_vfs_file_handle *stream);
|
|
||||||
|
|
||||||
/* Return the size of the file in bytes, or -1 for error.
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
typedef int64_t (RETRO_CALLCONV *retro_vfs_size_t)(struct retro_vfs_file_handle *stream);
|
|
||||||
|
|
||||||
/* Get the current read / write position for the file. Returns - 1 for error.
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
typedef int64_t (RETRO_CALLCONV *retro_vfs_tell_t)(struct retro_vfs_file_handle *stream);
|
|
||||||
|
|
||||||
/* Set the current read/write position for the file. Returns the new position, -1 for error.
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
typedef int64_t (RETRO_CALLCONV *retro_vfs_seek_t)(struct retro_vfs_file_handle *stream, int64_t offset, int seek_position);
|
|
||||||
|
|
||||||
/* Read data from a file. Returns the number of bytes read, or -1 for error.
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
typedef int64_t (RETRO_CALLCONV *retro_vfs_read_t)(struct retro_vfs_file_handle *stream, void *s, uint64_t len);
|
|
||||||
|
|
||||||
/* Write data to a file. Returns the number of bytes written, or -1 for error.
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
typedef int64_t (RETRO_CALLCONV *retro_vfs_write_t)(struct retro_vfs_file_handle *stream, const void *s, uint64_t len);
|
|
||||||
|
|
||||||
/* Flush pending writes to file, if using buffered IO. Returns 0 on sucess, or -1 on failure.
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
typedef int (RETRO_CALLCONV *retro_vfs_flush_t)(struct retro_vfs_file_handle *stream);
|
|
||||||
|
|
||||||
/* Delete the specified file. Returns 0 on success, -1 on failure
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
typedef int (RETRO_CALLCONV *retro_vfs_remove_t)(const char *path);
|
|
||||||
|
|
||||||
/* Rename the specified file. Returns 0 on success, -1 on failure
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const char *new_path);
|
|
||||||
|
|
||||||
struct retro_vfs_interface
|
|
||||||
{
|
|
||||||
retro_vfs_get_path_t get_path;
|
|
||||||
retro_vfs_open_t open;
|
|
||||||
retro_vfs_close_t close;
|
|
||||||
retro_vfs_size_t size;
|
|
||||||
retro_vfs_tell_t tell;
|
|
||||||
retro_vfs_seek_t seek;
|
|
||||||
retro_vfs_read_t read;
|
|
||||||
retro_vfs_write_t write;
|
|
||||||
retro_vfs_flush_t flush;
|
|
||||||
retro_vfs_remove_t remove;
|
|
||||||
retro_vfs_rename_t rename;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct retro_vfs_interface_info
|
|
||||||
{
|
|
||||||
/* Set by core: should this be higher than the version the front end supports,
|
|
||||||
* front end will return false in the RETRO_ENVIRONMENT_GET_VFS_INTERFACE call
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
uint32_t required_interface_version;
|
|
||||||
|
|
||||||
/* Frontend writes interface pointer here. The frontend also sets the actual
|
|
||||||
* version, must be at least required_interface_version.
|
|
||||||
* Introduced in VFS API v1 */
|
|
||||||
struct retro_vfs_interface *iface;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum retro_hw_render_interface_type
|
|
||||||
{
|
|
||||||
RETRO_HW_RENDER_INTERFACE_VULKAN = 0,
|
|
||||||
RETRO_HW_RENDER_INTERFACE_D3D9 = 1,
|
|
||||||
RETRO_HW_RENDER_INTERFACE_D3D10 = 2,
|
|
||||||
RETRO_HW_RENDER_INTERFACE_D3D11 = 3,
|
|
||||||
RETRO_HW_RENDER_INTERFACE_D3D12 = 4,
|
|
||||||
RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Base struct. All retro_hw_render_interface_* types
|
|
||||||
* contain at least these fields. */
|
|
||||||
struct retro_hw_render_interface
|
|
||||||
{
|
|
||||||
enum retro_hw_render_interface_type interface_type;
|
|
||||||
unsigned interface_version;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define RETRO_ENVIRONMENT_GET_LED_INTERFACE (46 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
#define RETRO_ENVIRONMENT_GET_LED_INTERFACE (46 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||||
/* struct retro_led_interface * --
|
/* struct retro_led_interface * --
|
||||||
* Gets an interface which is used by a libretro core to set
|
* Gets an interface which is used by a libretro core to set
|
||||||
* state of LEDs.
|
* state of LEDs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef void (RETRO_CALLCONV *retro_set_led_state_t)(int led, int state);
|
|
||||||
struct retro_led_interface
|
|
||||||
{
|
|
||||||
retro_set_led_state_t set_led_state;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
#define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||||
/* int * --
|
/* int * --
|
||||||
* Tells the core if the frontend wants audio or video.
|
* Tells the core if the frontend wants audio or video.
|
||||||
@ -1175,12 +1074,377 @@ struct retro_led_interface
|
|||||||
* never need an accurate audio state in the future.
|
* never need an accurate audio state in the future.
|
||||||
* * State will never be saved when using Hard Disable Audio.
|
* * State will never be saved when using Hard Disable Audio.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define RETRO_ENVIRONMENT_GET_MIDI_INTERFACE (48 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
#define RETRO_ENVIRONMENT_GET_MIDI_INTERFACE (48 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||||
/* struct retro_midi_interface ** --
|
/* struct retro_midi_interface ** --
|
||||||
* Returns a MIDI interface that can be used for raw data I/O.
|
* Returns a MIDI interface that can be used for raw data I/O.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_GET_FASTFORWARDING (49 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||||
|
/* bool * --
|
||||||
|
* Boolean value that indicates whether or not the frontend is in
|
||||||
|
* fastforwarding mode.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE (50 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||||
|
/* float * --
|
||||||
|
* Float value that lets us know what target refresh rate
|
||||||
|
* is curently in use by the frontend.
|
||||||
|
*
|
||||||
|
* The core can use the returned value to set an ideal
|
||||||
|
* refresh rate/framerate.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_GET_INPUT_BITMASKS (51 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||||
|
/* bool * --
|
||||||
|
* Boolean value that indicates whether or not the frontend supports
|
||||||
|
* input bitmasks being returned by retro_input_state_t. The advantage
|
||||||
|
* of this is that retro_input_state_t has to be only called once to
|
||||||
|
* grab all button states instead of multiple times.
|
||||||
|
*
|
||||||
|
* If it returns true, you can pass RETRO_DEVICE_ID_JOYPAD_MASK as 'id'
|
||||||
|
* to retro_input_state_t (make sure 'device' is set to RETRO_DEVICE_JOYPAD).
|
||||||
|
* It will return a bitmask of all the digital buttons.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION 52
|
||||||
|
/* unsigned * --
|
||||||
|
* Unsigned value is the API version number of the core options
|
||||||
|
* interface supported by the frontend. If callback return false,
|
||||||
|
* API version is assumed to be 0.
|
||||||
|
*
|
||||||
|
* In legacy code, core options are set by passing an array of
|
||||||
|
* retro_variable structs to RETRO_ENVIRONMENT_SET_VARIABLES.
|
||||||
|
* This may be still be done regardless of the core options
|
||||||
|
* interface version.
|
||||||
|
*
|
||||||
|
* If version is 1 however, core options may instead be set by
|
||||||
|
* passing an array of retro_core_option_definition structs to
|
||||||
|
* RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of
|
||||||
|
* retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL.
|
||||||
|
* This allows the core to additionally set option sublabel information
|
||||||
|
* and/or provide localisation support.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS 53
|
||||||
|
/* const struct retro_core_option_definition ** --
|
||||||
|
* Allows an implementation to signal the environment
|
||||||
|
* which variables it might want to check for later using
|
||||||
|
* GET_VARIABLE.
|
||||||
|
* This allows the frontend to present these variables to
|
||||||
|
* a user dynamically.
|
||||||
|
* This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
|
||||||
|
* returns an API version of 1.
|
||||||
|
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
|
||||||
|
* This should be called the first time as early as
|
||||||
|
* possible (ideally in retro_set_environment).
|
||||||
|
* Afterwards it may be called again for the core to communicate
|
||||||
|
* updated options to the frontend, but the number of core
|
||||||
|
* options must not change from the number in the initial call.
|
||||||
|
*
|
||||||
|
* 'data' points to an array of retro_core_option_definition structs
|
||||||
|
* terminated by a { NULL, NULL, NULL, {{0}}, NULL } element.
|
||||||
|
* retro_core_option_definition::key should be namespaced to not collide
|
||||||
|
* with other implementations' keys. e.g. A core called
|
||||||
|
* 'foo' should use keys named as 'foo_option'.
|
||||||
|
* retro_core_option_definition::desc should contain a human readable
|
||||||
|
* description of the key.
|
||||||
|
* retro_core_option_definition::info should contain any additional human
|
||||||
|
* readable information text that a typical user may need to
|
||||||
|
* understand the functionality of the option.
|
||||||
|
* retro_core_option_definition::values is an array of retro_core_option_value
|
||||||
|
* structs terminated by a { NULL, NULL } element.
|
||||||
|
* > retro_core_option_definition::values[index].value is an expected option
|
||||||
|
* value.
|
||||||
|
* > retro_core_option_definition::values[index].label is a human readable
|
||||||
|
* label used when displaying the value on screen. If NULL,
|
||||||
|
* the value itself is used.
|
||||||
|
* retro_core_option_definition::default_value is the default core option
|
||||||
|
* setting. It must match one of the expected option values in the
|
||||||
|
* retro_core_option_definition::values array. If it does not, or the
|
||||||
|
* default value is NULL, the first entry in the
|
||||||
|
* retro_core_option_definition::values array is treated as the default.
|
||||||
|
*
|
||||||
|
* The number of possible options should be very limited,
|
||||||
|
* and must be less than RETRO_NUM_CORE_OPTION_VALUES_MAX.
|
||||||
|
* i.e. it should be feasible to cycle through options
|
||||||
|
* without a keyboard.
|
||||||
|
*
|
||||||
|
* First entry should be treated as a default.
|
||||||
|
*
|
||||||
|
* Example entry:
|
||||||
|
* {
|
||||||
|
* "foo_option",
|
||||||
|
* "Speed hack coprocessor X",
|
||||||
|
* "Provides increased performance at the expense of reduced accuracy",
|
||||||
|
* {
|
||||||
|
* { "false", NULL },
|
||||||
|
* { "true", NULL },
|
||||||
|
* { "unstable", "Turbo (Unstable)" },
|
||||||
|
* { NULL, NULL },
|
||||||
|
* },
|
||||||
|
* "false"
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Only strings are operated on. The possible values will
|
||||||
|
* generally be displayed and stored as-is by the frontend.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL 54
|
||||||
|
/* const struct retro_core_options_intl * --
|
||||||
|
* Allows an implementation to signal the environment
|
||||||
|
* which variables it might want to check for later using
|
||||||
|
* GET_VARIABLE.
|
||||||
|
* This allows the frontend to present these variables to
|
||||||
|
* a user dynamically.
|
||||||
|
* This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
|
||||||
|
* returns an API version of 1.
|
||||||
|
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
|
||||||
|
* This should be called the first time as early as
|
||||||
|
* possible (ideally in retro_set_environment).
|
||||||
|
* Afterwards it may be called again for the core to communicate
|
||||||
|
* updated options to the frontend, but the number of core
|
||||||
|
* options must not change from the number in the initial call.
|
||||||
|
*
|
||||||
|
* This is fundamentally the same as RETRO_ENVIRONMENT_SET_CORE_OPTIONS,
|
||||||
|
* with the addition of localisation support. The description of the
|
||||||
|
* RETRO_ENVIRONMENT_SET_CORE_OPTIONS callback should be consulted
|
||||||
|
* for further details.
|
||||||
|
*
|
||||||
|
* 'data' points to a retro_core_options_intl struct.
|
||||||
|
*
|
||||||
|
* retro_core_options_intl::us is a pointer to an array of
|
||||||
|
* retro_core_option_definition structs defining the US English
|
||||||
|
* core options implementation. It must point to a valid array.
|
||||||
|
*
|
||||||
|
* retro_core_options_intl::local is a pointer to an array of
|
||||||
|
* retro_core_option_definition structs defining core options for
|
||||||
|
* the current frontend language. It may be NULL (in which case
|
||||||
|
* retro_core_options_intl::us is used by the frontend). Any items
|
||||||
|
* missing from this array will be read from retro_core_options_intl::us
|
||||||
|
* instead.
|
||||||
|
*
|
||||||
|
* NOTE: Default core option values are always taken from the
|
||||||
|
* retro_core_options_intl::us array. Any default values in
|
||||||
|
* retro_core_options_intl::local array will be ignored.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY 55
|
||||||
|
/* struct retro_core_option_display * --
|
||||||
|
*
|
||||||
|
* Allows an implementation to signal the environment to show
|
||||||
|
* or hide a variable when displaying core options. This is
|
||||||
|
* considered a *suggestion*. The frontend is free to ignore
|
||||||
|
* this callback, and its implementation not considered mandatory.
|
||||||
|
*
|
||||||
|
* 'data' points to a retro_core_option_display struct
|
||||||
|
*
|
||||||
|
* retro_core_option_display::key is a variable identifier
|
||||||
|
* which has already been set by SET_VARIABLES/SET_CORE_OPTIONS.
|
||||||
|
*
|
||||||
|
* retro_core_option_display::visible is a boolean, specifying
|
||||||
|
* whether variable should be displayed
|
||||||
|
*
|
||||||
|
* Note that all core option variables will be set visible by
|
||||||
|
* default when calling SET_VARIABLES/SET_CORE_OPTIONS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* VFS functionality */
|
||||||
|
|
||||||
|
/* File paths:
|
||||||
|
* File paths passed as parameters when using this API shall be well formed UNIX-style,
|
||||||
|
* using "/" (unquoted forward slash) as directory separator regardless of the platform's native separator.
|
||||||
|
* Paths shall also include at least one forward slash ("game.bin" is an invalid path, use "./game.bin" instead).
|
||||||
|
* Other than the directory separator, cores shall not make assumptions about path format:
|
||||||
|
* "C:/path/game.bin", "http://example.com/game.bin", "#game/game.bin", "./game.bin" (without quotes) are all valid paths.
|
||||||
|
* Cores may replace the basename or remove path components from the end, and/or add new components;
|
||||||
|
* however, cores shall not append "./", "../" or multiple consecutive forward slashes ("//") to paths they request to front end.
|
||||||
|
* The frontend is encouraged to make such paths work as well as it can, but is allowed to give up if the core alters paths too much.
|
||||||
|
* Frontends are encouraged, but not required, to support native file system paths (modulo replacing the directory separator, if applicable).
|
||||||
|
* Cores are allowed to try using them, but must remain functional if the front rejects such requests.
|
||||||
|
* Cores are encouraged to use the libretro-common filestream functions for file I/O,
|
||||||
|
* as they seamlessly integrate with VFS, deal with directory separator replacement as appropriate
|
||||||
|
* and provide platform-specific fallbacks in cases where front ends do not support VFS. */
|
||||||
|
|
||||||
|
/* Opaque file handle
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
struct retro_vfs_file_handle;
|
||||||
|
|
||||||
|
/* Opaque directory handle
|
||||||
|
* Introduced in VFS API v3 */
|
||||||
|
struct retro_vfs_dir_handle;
|
||||||
|
|
||||||
|
/* File open flags
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
#define RETRO_VFS_FILE_ACCESS_READ (1 << 0) /* Read only mode */
|
||||||
|
#define RETRO_VFS_FILE_ACCESS_WRITE (1 << 1) /* Write only mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified */
|
||||||
|
#define RETRO_VFS_FILE_ACCESS_READ_WRITE (RETRO_VFS_FILE_ACCESS_READ | RETRO_VFS_FILE_ACCESS_WRITE) /* Read-write mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified*/
|
||||||
|
#define RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING (1 << 2) /* Prevents discarding content of existing files opened for writing */
|
||||||
|
|
||||||
|
/* These are only hints. The frontend may choose to ignore them. Other than RAM/CPU/etc use,
|
||||||
|
and how they react to unlikely external interference (for example someone else writing to that file,
|
||||||
|
or the file's server going down), behavior will not change. */
|
||||||
|
#define RETRO_VFS_FILE_ACCESS_HINT_NONE (0)
|
||||||
|
/* Indicate that the file will be accessed many times. The frontend should aggressively cache everything. */
|
||||||
|
#define RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS (1 << 0)
|
||||||
|
|
||||||
|
/* Seek positions */
|
||||||
|
#define RETRO_VFS_SEEK_POSITION_START 0
|
||||||
|
#define RETRO_VFS_SEEK_POSITION_CURRENT 1
|
||||||
|
#define RETRO_VFS_SEEK_POSITION_END 2
|
||||||
|
|
||||||
|
/* stat() result flags
|
||||||
|
* Introduced in VFS API v3 */
|
||||||
|
#define RETRO_VFS_STAT_IS_VALID (1 << 0)
|
||||||
|
#define RETRO_VFS_STAT_IS_DIRECTORY (1 << 1)
|
||||||
|
#define RETRO_VFS_STAT_IS_CHARACTER_SPECIAL (1 << 2)
|
||||||
|
|
||||||
|
/* Get path from opaque handle. Returns the exact same path passed to file_open when getting the handle
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
typedef const char *(RETRO_CALLCONV *retro_vfs_get_path_t)(struct retro_vfs_file_handle *stream);
|
||||||
|
|
||||||
|
/* Open a file for reading or writing. If path points to a directory, this will
|
||||||
|
* fail. Returns the opaque file handle, or NULL for error.
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
typedef struct retro_vfs_file_handle *(RETRO_CALLCONV *retro_vfs_open_t)(const char *path, unsigned mode, unsigned hints);
|
||||||
|
|
||||||
|
/* Close the file and release its resources. Must be called if open_file returns non-NULL. Returns 0 on success, -1 on failure.
|
||||||
|
* Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used.
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
typedef int (RETRO_CALLCONV *retro_vfs_close_t)(struct retro_vfs_file_handle *stream);
|
||||||
|
|
||||||
|
/* Return the size of the file in bytes, or -1 for error.
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
typedef int64_t (RETRO_CALLCONV *retro_vfs_size_t)(struct retro_vfs_file_handle *stream);
|
||||||
|
|
||||||
|
/* Truncate file to specified size. Returns 0 on success or -1 on error
|
||||||
|
* Introduced in VFS API v2 */
|
||||||
|
typedef int64_t (RETRO_CALLCONV *retro_vfs_truncate_t)(struct retro_vfs_file_handle *stream, int64_t length);
|
||||||
|
|
||||||
|
/* Get the current read / write position for the file. Returns -1 for error.
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
typedef int64_t (RETRO_CALLCONV *retro_vfs_tell_t)(struct retro_vfs_file_handle *stream);
|
||||||
|
|
||||||
|
/* Set the current read/write position for the file. Returns the new position, -1 for error.
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
typedef int64_t (RETRO_CALLCONV *retro_vfs_seek_t)(struct retro_vfs_file_handle *stream, int64_t offset, int seek_position);
|
||||||
|
|
||||||
|
/* Read data from a file. Returns the number of bytes read, or -1 for error.
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
typedef int64_t (RETRO_CALLCONV *retro_vfs_read_t)(struct retro_vfs_file_handle *stream, void *s, uint64_t len);
|
||||||
|
|
||||||
|
/* Write data to a file. Returns the number of bytes written, or -1 for error.
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
typedef int64_t (RETRO_CALLCONV *retro_vfs_write_t)(struct retro_vfs_file_handle *stream, const void *s, uint64_t len);
|
||||||
|
|
||||||
|
/* Flush pending writes to file, if using buffered IO. Returns 0 on sucess, or -1 on failure.
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
typedef int (RETRO_CALLCONV *retro_vfs_flush_t)(struct retro_vfs_file_handle *stream);
|
||||||
|
|
||||||
|
/* Delete the specified file. Returns 0 on success, -1 on failure
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
typedef int (RETRO_CALLCONV *retro_vfs_remove_t)(const char *path);
|
||||||
|
|
||||||
|
/* Rename the specified file. Returns 0 on success, -1 on failure
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const char *new_path);
|
||||||
|
|
||||||
|
/* Stat the specified file. Retruns a bitmask of RETRO_VFS_STAT_* flags, none are set if path was not valid.
|
||||||
|
* Additionally stores file size in given variable, unless NULL is given.
|
||||||
|
* Introduced in VFS API v3 */
|
||||||
|
typedef int (RETRO_CALLCONV *retro_vfs_stat_t)(const char *path, int32_t *size);
|
||||||
|
|
||||||
|
/* Create the specified directory. Returns 0 on success, -1 on unknown failure, -2 if already exists.
|
||||||
|
* Introduced in VFS API v3 */
|
||||||
|
typedef int (RETRO_CALLCONV *retro_vfs_mkdir_t)(const char *dir);
|
||||||
|
|
||||||
|
/* Open the specified directory for listing. Returns the opaque dir handle, or NULL for error.
|
||||||
|
* Support for the include_hidden argument may vary depending on the platform.
|
||||||
|
* Introduced in VFS API v3 */
|
||||||
|
typedef struct retro_vfs_dir_handle *(RETRO_CALLCONV *retro_vfs_opendir_t)(const char *dir, bool include_hidden);
|
||||||
|
|
||||||
|
/* Read the directory entry at the current position, and move the read pointer to the next position.
|
||||||
|
* Returns true on success, false if already on the last entry.
|
||||||
|
* Introduced in VFS API v3 */
|
||||||
|
typedef bool (RETRO_CALLCONV *retro_vfs_readdir_t)(struct retro_vfs_dir_handle *dirstream);
|
||||||
|
|
||||||
|
/* Get the name of the last entry read. Returns a string on success, or NULL for error.
|
||||||
|
* The returned string pointer is valid until the next call to readdir or closedir.
|
||||||
|
* Introduced in VFS API v3 */
|
||||||
|
typedef const char *(RETRO_CALLCONV *retro_vfs_dirent_get_name_t)(struct retro_vfs_dir_handle *dirstream);
|
||||||
|
|
||||||
|
/* Check if the last entry read was a directory. Returns true if it was, false otherwise (or on error).
|
||||||
|
* Introduced in VFS API v3 */
|
||||||
|
typedef bool (RETRO_CALLCONV *retro_vfs_dirent_is_dir_t)(struct retro_vfs_dir_handle *dirstream);
|
||||||
|
|
||||||
|
/* Close the directory and release its resources. Must be called if opendir returns non-NULL. Returns 0 on success, -1 on failure.
|
||||||
|
* Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used.
|
||||||
|
* Introduced in VFS API v3 */
|
||||||
|
typedef int (RETRO_CALLCONV *retro_vfs_closedir_t)(struct retro_vfs_dir_handle *dirstream);
|
||||||
|
|
||||||
|
struct retro_vfs_interface
|
||||||
|
{
|
||||||
|
/* VFS API v1 */
|
||||||
|
retro_vfs_get_path_t get_path;
|
||||||
|
retro_vfs_open_t open;
|
||||||
|
retro_vfs_close_t close;
|
||||||
|
retro_vfs_size_t size;
|
||||||
|
retro_vfs_tell_t tell;
|
||||||
|
retro_vfs_seek_t seek;
|
||||||
|
retro_vfs_read_t read;
|
||||||
|
retro_vfs_write_t write;
|
||||||
|
retro_vfs_flush_t flush;
|
||||||
|
retro_vfs_remove_t remove;
|
||||||
|
retro_vfs_rename_t rename;
|
||||||
|
/* VFS API v2 */
|
||||||
|
retro_vfs_truncate_t truncate;
|
||||||
|
/* VFS API v3 */
|
||||||
|
retro_vfs_stat_t stat;
|
||||||
|
retro_vfs_mkdir_t mkdir;
|
||||||
|
retro_vfs_opendir_t opendir;
|
||||||
|
retro_vfs_readdir_t readdir;
|
||||||
|
retro_vfs_dirent_get_name_t dirent_get_name;
|
||||||
|
retro_vfs_dirent_is_dir_t dirent_is_dir;
|
||||||
|
retro_vfs_closedir_t closedir;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct retro_vfs_interface_info
|
||||||
|
{
|
||||||
|
/* Set by core: should this be higher than the version the front end supports,
|
||||||
|
* front end will return false in the RETRO_ENVIRONMENT_GET_VFS_INTERFACE call
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
uint32_t required_interface_version;
|
||||||
|
|
||||||
|
/* Frontend writes interface pointer here. The frontend also sets the actual
|
||||||
|
* version, must be at least required_interface_version.
|
||||||
|
* Introduced in VFS API v1 */
|
||||||
|
struct retro_vfs_interface *iface;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum retro_hw_render_interface_type
|
||||||
|
{
|
||||||
|
RETRO_HW_RENDER_INTERFACE_VULKAN = 0,
|
||||||
|
RETRO_HW_RENDER_INTERFACE_D3D9 = 1,
|
||||||
|
RETRO_HW_RENDER_INTERFACE_D3D10 = 2,
|
||||||
|
RETRO_HW_RENDER_INTERFACE_D3D11 = 3,
|
||||||
|
RETRO_HW_RENDER_INTERFACE_D3D12 = 4,
|
||||||
|
RETRO_HW_RENDER_INTERFACE_GSKIT_PS2 = 5,
|
||||||
|
RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Base struct. All retro_hw_render_interface_* types
|
||||||
|
* contain at least these fields. */
|
||||||
|
struct retro_hw_render_interface
|
||||||
|
{
|
||||||
|
enum retro_hw_render_interface_type interface_type;
|
||||||
|
unsigned interface_version;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (RETRO_CALLCONV *retro_set_led_state_t)(int led, int state);
|
||||||
|
struct retro_led_interface
|
||||||
|
{
|
||||||
|
retro_set_led_state_t set_led_state;
|
||||||
|
};
|
||||||
|
|
||||||
/* Retrieves the current state of the MIDI input.
|
/* Retrieves the current state of the MIDI input.
|
||||||
* Returns true if it's enabled, false otherwise. */
|
* Returns true if it's enabled, false otherwise. */
|
||||||
typedef bool (RETRO_CALLCONV *retro_midi_input_enabled_t)(void);
|
typedef bool (RETRO_CALLCONV *retro_midi_input_enabled_t)(void);
|
||||||
@ -1211,27 +1475,6 @@ struct retro_midi_interface
|
|||||||
retro_midi_flush_t flush;
|
retro_midi_flush_t flush;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
|
||||||
/* const struct retro_hw_render_interface ** --
|
|
||||||
* Returns an API specific rendering interface for accessing API specific data.
|
|
||||||
* Not all HW rendering APIs support or need this.
|
|
||||||
* The contents of the returned pointer is specific to the rendering API
|
|
||||||
* being used. See the various headers like libretro_vulkan.h, etc.
|
|
||||||
*
|
|
||||||
* GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called.
|
|
||||||
* Similarly, after context_destroyed callback returns,
|
|
||||||
* the contents of the HW_RENDER_INTERFACE are invalidated.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
|
||||||
/* const bool * --
|
|
||||||
* If true, the libretro implementation supports achievements
|
|
||||||
* either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS
|
|
||||||
* or via retro_get_memory_data/retro_get_memory_size.
|
|
||||||
*
|
|
||||||
* This must be called before the first call to retro_run.
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum retro_hw_render_context_negotiation_interface_type
|
enum retro_hw_render_context_negotiation_interface_type
|
||||||
{
|
{
|
||||||
RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN = 0,
|
RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN = 0,
|
||||||
@ -1245,13 +1488,6 @@ struct retro_hw_render_context_negotiation_interface
|
|||||||
enum retro_hw_render_context_negotiation_interface_type interface_type;
|
enum retro_hw_render_context_negotiation_interface_type interface_type;
|
||||||
unsigned interface_version;
|
unsigned interface_version;
|
||||||
};
|
};
|
||||||
#define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
|
||||||
/* const struct retro_hw_render_context_negotiation_interface * --
|
|
||||||
* Sets an interface which lets the libretro core negotiate with frontend how a context is created.
|
|
||||||
* The semantics of this interface depends on which API is used in SET_HW_RENDER earlier.
|
|
||||||
* This interface will be used when the frontend is trying to create a HW rendering context,
|
|
||||||
* so it will be used after SET_HW_RENDER, but before the context_reset callback.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Serialized state is incomplete in some way. Set if serialization is
|
/* Serialized state is incomplete in some way. Set if serialization is
|
||||||
* usable in typical end-user cases but should not be relied upon to
|
* usable in typical end-user cases but should not be relied upon to
|
||||||
@ -1277,20 +1513,17 @@ struct retro_hw_render_context_negotiation_interface
|
|||||||
* dependence */
|
* dependence */
|
||||||
#define RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT (1 << 6)
|
#define RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT (1 << 6)
|
||||||
|
|
||||||
#define RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS 44
|
#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */
|
||||||
/* uint64_t * --
|
#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */
|
||||||
* Sets quirk flags associated with serialization. The frontend will zero any flags it doesn't
|
#define RETRO_MEMDESC_SYSTEM_RAM (1 << 2) /* The memory area is system RAM. This is main RAM of the gaming system. */
|
||||||
* recognize or support. Should be set in either retro_init or retro_load_game, but not both.
|
#define RETRO_MEMDESC_SAVE_RAM (1 << 3) /* The memory area is save RAM. This RAM is usually found on a game cartridge, backed up by a battery. */
|
||||||
*/
|
#define RETRO_MEMDESC_VIDEO_RAM (1 << 4) /* The memory area is video RAM (VRAM) */
|
||||||
|
#define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */
|
||||||
#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */
|
#define RETRO_MEMDESC_ALIGN_4 (2 << 16)
|
||||||
#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */
|
#define RETRO_MEMDESC_ALIGN_8 (3 << 16)
|
||||||
#define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */
|
#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) /* All memory in this region is accessed at least 2 bytes at the time. */
|
||||||
#define RETRO_MEMDESC_ALIGN_4 (2 << 16)
|
#define RETRO_MEMDESC_MINSIZE_4 (2 << 24)
|
||||||
#define RETRO_MEMDESC_ALIGN_8 (3 << 16)
|
#define RETRO_MEMDESC_MINSIZE_8 (3 << 24)
|
||||||
#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) /* All memory in this region is accessed at least 2 bytes at the time. */
|
|
||||||
#define RETRO_MEMDESC_MINSIZE_4 (2 << 24)
|
|
||||||
#define RETRO_MEMDESC_MINSIZE_8 (3 << 24)
|
|
||||||
struct retro_memory_descriptor
|
struct retro_memory_descriptor
|
||||||
{
|
{
|
||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
@ -2190,17 +2423,26 @@ struct retro_system_info
|
|||||||
* Typically used for a GUI to filter
|
* Typically used for a GUI to filter
|
||||||
* out extensions. */
|
* out extensions. */
|
||||||
|
|
||||||
/* If true, retro_load_game() is guaranteed to provide a valid pathname
|
/* Libretro cores that need to have direct access to their content
|
||||||
* in retro_game_info::path.
|
* files, including cores which use the path of the content files to
|
||||||
* ::data and ::size are both invalid.
|
* determine the paths of other files, should set need_fullpath to true.
|
||||||
*
|
*
|
||||||
* If false, ::data and ::size are guaranteed to be valid, but ::path
|
* Cores should strive for setting need_fullpath to false,
|
||||||
* might not be valid.
|
* as it allows the frontend to perform patching, etc.
|
||||||
*
|
*
|
||||||
* This is typically set to true for libretro implementations that must
|
* If need_fullpath is true and retro_load_game() is called:
|
||||||
* load from file.
|
* - retro_game_info::path is guaranteed to have a valid path
|
||||||
* Implementations should strive for setting this to false, as it allows
|
* - retro_game_info::data and retro_game_info::size are invalid
|
||||||
* the frontend to perform patching, etc. */
|
*
|
||||||
|
* If need_fullpath is false and retro_load_game() is called:
|
||||||
|
* - retro_game_info::path may be NULL
|
||||||
|
* - retro_game_info::data and retro_game_info::size are guaranteed
|
||||||
|
* to be valid
|
||||||
|
*
|
||||||
|
* See also:
|
||||||
|
* - RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY
|
||||||
|
* - RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY
|
||||||
|
*/
|
||||||
bool need_fullpath;
|
bool need_fullpath;
|
||||||
|
|
||||||
/* If true, the frontend is not allowed to extract any archives before
|
/* If true, the frontend is not allowed to extract any archives before
|
||||||
@ -2251,6 +2493,64 @@ struct retro_variable
|
|||||||
const char *value;
|
const char *value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct retro_core_option_display
|
||||||
|
{
|
||||||
|
/* Variable to configure in RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY */
|
||||||
|
const char *key;
|
||||||
|
|
||||||
|
/* Specifies whether variable should be displayed
|
||||||
|
* when presenting core options to the user */
|
||||||
|
bool visible;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Maximum number of values permitted for a core option
|
||||||
|
* NOTE: This may be increased on a core-by-core basis
|
||||||
|
* if required (doing so has no effect on the frontend) */
|
||||||
|
#define RETRO_NUM_CORE_OPTION_VALUES_MAX 128
|
||||||
|
|
||||||
|
struct retro_core_option_value
|
||||||
|
{
|
||||||
|
/* Expected option value */
|
||||||
|
const char *value;
|
||||||
|
|
||||||
|
/* Human-readable value label. If NULL, value itself
|
||||||
|
* will be displayed by the frontend */
|
||||||
|
const char *label;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct retro_core_option_definition
|
||||||
|
{
|
||||||
|
/* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. */
|
||||||
|
const char *key;
|
||||||
|
|
||||||
|
/* Human-readable core option description (used as menu label) */
|
||||||
|
const char *desc;
|
||||||
|
|
||||||
|
/* Human-readable core option information (used as menu sublabel) */
|
||||||
|
const char *info;
|
||||||
|
|
||||||
|
/* Array of retro_core_option_value structs, terminated by NULL */
|
||||||
|
struct retro_core_option_value values[RETRO_NUM_CORE_OPTION_VALUES_MAX];
|
||||||
|
|
||||||
|
/* Default core option value. Must match one of the values
|
||||||
|
* in the retro_core_option_value array, otherwise will be
|
||||||
|
* ignored */
|
||||||
|
const char *default_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct retro_core_options_intl
|
||||||
|
{
|
||||||
|
/* Pointer to an array of retro_core_option_definition structs
|
||||||
|
* - US English implementation
|
||||||
|
* - Must point to a valid array */
|
||||||
|
struct retro_core_option_definition *us;
|
||||||
|
|
||||||
|
/* Pointer to an array of retro_core_option_definition structs
|
||||||
|
* - Implementation for current frontend language
|
||||||
|
* - May be NULL */
|
||||||
|
struct retro_core_option_definition *local;
|
||||||
|
};
|
||||||
|
|
||||||
struct retro_game_info
|
struct retro_game_info
|
||||||
{
|
{
|
||||||
const char *path; /* Path to game, UTF-8 encoded.
|
const char *path; /* Path to game, UTF-8 encoded.
|
||||||
@ -2423,7 +2723,7 @@ RETRO_API bool retro_unserialize(const void *data, size_t size);
|
|||||||
RETRO_API void retro_cheat_reset(void);
|
RETRO_API void retro_cheat_reset(void);
|
||||||
RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code);
|
RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code);
|
||||||
|
|
||||||
/* Loads a game.
|
/* Loads a game.
|
||||||
* Return true to indicate successful loading and false to indicate load failure.
|
* Return true to indicate successful loading and false to indicate load failure.
|
||||||
*/
|
*/
|
||||||
RETRO_API bool retro_load_game(const struct retro_game_info *game);
|
RETRO_API bool retro_load_game(const struct retro_game_info *game);
|
||||||
|
87
libretro-common/include/lists/dir_list.h
Normal file
87
libretro-common/include/lists/dir_list.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (dir_list.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBRETRO_SDK_DIR_LIST_H
|
||||||
|
#define __LIBRETRO_SDK_DIR_LIST_H
|
||||||
|
|
||||||
|
#include <retro_common_api.h>
|
||||||
|
|
||||||
|
#include <lists/string_list.h>
|
||||||
|
|
||||||
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dir_list_append:
|
||||||
|
* @list : existing list to append to.
|
||||||
|
* @dir : directory path.
|
||||||
|
* @ext : allowed extensions of file directory entries to include.
|
||||||
|
* @include_dirs : include directories as part of the finished directory listing?
|
||||||
|
* @include_hidden : include hidden files and directories as part of the finished directory listing?
|
||||||
|
* @include_compressed : Only include files which match ext. Do not try to match compressed files, etc.
|
||||||
|
* @recursive : list directory contents recursively
|
||||||
|
*
|
||||||
|
* Create a directory listing, appending to an existing list
|
||||||
|
*
|
||||||
|
* Returns: true success, false in case of error.
|
||||||
|
**/
|
||||||
|
bool dir_list_append(struct string_list *list, const char *dir, const char *ext,
|
||||||
|
bool include_dirs, bool include_hidden, bool include_compressed, bool recursive);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dir_list_new:
|
||||||
|
* @dir : directory path.
|
||||||
|
* @ext : allowed extensions of file directory entries to include.
|
||||||
|
* @include_dirs : include directories as part of the finished directory listing?
|
||||||
|
* @include_hidden : include hidden files and directories as part of the finished directory listing?
|
||||||
|
* @include_compressed : include compressed files, even when not part of ext.
|
||||||
|
* @recursive : list directory contents recursively
|
||||||
|
*
|
||||||
|
* Create a directory listing.
|
||||||
|
*
|
||||||
|
* Returns: pointer to a directory listing of type 'struct string_list *' on success,
|
||||||
|
* NULL in case of error. Has to be freed manually.
|
||||||
|
**/
|
||||||
|
struct string_list *dir_list_new(const char *dir, const char *ext,
|
||||||
|
bool include_dirs, bool include_hidden, bool include_compressed, bool recursive);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dir_list_sort:
|
||||||
|
* @list : pointer to the directory listing.
|
||||||
|
* @dir_first : move the directories in the listing to the top?
|
||||||
|
*
|
||||||
|
* Sorts a directory listing.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
void dir_list_sort(struct string_list *list, bool dir_first);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dir_list_free:
|
||||||
|
* @list : pointer to the directory listing
|
||||||
|
*
|
||||||
|
* Frees a directory listing.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
void dir_list_free(struct string_list *list);
|
||||||
|
|
||||||
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
162
libretro-common/include/lists/string_list.h
Normal file
162
libretro-common/include/lists/string_list.h
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (string_list.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBRETRO_SDK_STRING_LIST_H
|
||||||
|
#define __LIBRETRO_SDK_STRING_LIST_H
|
||||||
|
|
||||||
|
#include <retro_common_api.h>
|
||||||
|
|
||||||
|
#include <boolean.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
|
union string_list_elem_attr
|
||||||
|
{
|
||||||
|
bool b;
|
||||||
|
int i;
|
||||||
|
void *p;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct string_list_elem
|
||||||
|
{
|
||||||
|
char *data;
|
||||||
|
union string_list_elem_attr attr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct string_list
|
||||||
|
{
|
||||||
|
struct string_list_elem *elems;
|
||||||
|
size_t size;
|
||||||
|
size_t cap;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_find_elem:
|
||||||
|
* @list : pointer to string list
|
||||||
|
* @elem : element to find inside the string list.
|
||||||
|
*
|
||||||
|
* Searches for an element (@elem) inside the string list.
|
||||||
|
*
|
||||||
|
* Returns: true (1) if element could be found, otherwise false (0).
|
||||||
|
*/
|
||||||
|
int string_list_find_elem(const struct string_list *list, const char *elem);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_find_elem_prefix:
|
||||||
|
* @list : pointer to string list
|
||||||
|
* @prefix : prefix to append to @elem
|
||||||
|
* @elem : element to find inside the string list.
|
||||||
|
*
|
||||||
|
* Searches for an element (@elem) inside the string list. Will
|
||||||
|
* also search for the same element prefixed by @prefix.
|
||||||
|
*
|
||||||
|
* Returns: true (1) if element could be found, otherwise false (0).
|
||||||
|
*/
|
||||||
|
bool string_list_find_elem_prefix(const struct string_list *list,
|
||||||
|
const char *prefix, const char *elem);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_split:
|
||||||
|
* @str : string to turn into a string list
|
||||||
|
* @delim : delimiter character to use for splitting the string.
|
||||||
|
*
|
||||||
|
* Creates a new string list based on string @str, delimited by @delim.
|
||||||
|
*
|
||||||
|
* Returns: new string list if successful, otherwise NULL.
|
||||||
|
*/
|
||||||
|
struct string_list *string_split(const char *str, const char *delim);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_new:
|
||||||
|
*
|
||||||
|
* Creates a new string list. Has to be freed manually.
|
||||||
|
*
|
||||||
|
* Returns: new string list if successful, otherwise NULL.
|
||||||
|
*/
|
||||||
|
struct string_list *string_list_new(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_append:
|
||||||
|
* @list : pointer to string list
|
||||||
|
* @elem : element to add to the string list
|
||||||
|
* @attr : attributes of new element.
|
||||||
|
*
|
||||||
|
* Appends a new element to the string list.
|
||||||
|
*
|
||||||
|
* Returns: true (1) if successful, otherwise false (0).
|
||||||
|
**/
|
||||||
|
bool string_list_append(struct string_list *list, const char *elem,
|
||||||
|
union string_list_elem_attr attr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_append_n:
|
||||||
|
* @list : pointer to string list
|
||||||
|
* @elem : element to add to the string list
|
||||||
|
* @length : read at most this many bytes from elem
|
||||||
|
* @attr : attributes of new element.
|
||||||
|
*
|
||||||
|
* Appends a new element to the string list.
|
||||||
|
*
|
||||||
|
* Returns: true (1) if successful, otherwise false (0).
|
||||||
|
**/
|
||||||
|
bool string_list_append_n(struct string_list *list, const char *elem,
|
||||||
|
unsigned length, union string_list_elem_attr attr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_free
|
||||||
|
* @list : pointer to string list object
|
||||||
|
*
|
||||||
|
* Frees a string list.
|
||||||
|
*/
|
||||||
|
void string_list_free(struct string_list *list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_join_concat:
|
||||||
|
* @buffer : buffer that @list will be joined to.
|
||||||
|
* @size : length of @buffer.
|
||||||
|
* @list : pointer to string list.
|
||||||
|
* @delim : delimiter character for @list.
|
||||||
|
*
|
||||||
|
* A string list will be joined/concatenated as a
|
||||||
|
* string to @buffer, delimited by @delim.
|
||||||
|
*/
|
||||||
|
void string_list_join_concat(char *buffer, size_t size,
|
||||||
|
const struct string_list *list, const char *sep);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_set:
|
||||||
|
* @list : pointer to string list
|
||||||
|
* @idx : index of element in string list
|
||||||
|
* @str : value for the element.
|
||||||
|
*
|
||||||
|
* Set value of element inside string list.
|
||||||
|
**/
|
||||||
|
void string_list_set(struct string_list *list, unsigned idx,
|
||||||
|
const char *str);
|
||||||
|
|
||||||
|
struct string_list *string_list_clone(const struct string_list *src);
|
||||||
|
|
||||||
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
40
libretro-common/include/memalign.h
Normal file
40
libretro-common/include/memalign.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (memalign.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBRETRO_MEMALIGN_H
|
||||||
|
#define _LIBRETRO_MEMALIGN_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <retro_common_api.h>
|
||||||
|
|
||||||
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
|
void *memalign_alloc(size_t boundary, size_t size);
|
||||||
|
|
||||||
|
void *memalign_alloc_aligned(size_t size);
|
||||||
|
|
||||||
|
void memalign_free(void *ptr);
|
||||||
|
|
||||||
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
@ -26,7 +26,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#if defined(__CELLOS_LV2__) || defined(PSP) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH)
|
#if defined(__CELLOS_LV2__) || defined(PSP) || defined(PS2) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH)
|
||||||
/* No mman available */
|
/* No mman available */
|
||||||
#elif defined(_WIN32) && !defined(_XBOX)
|
#elif defined(_WIN32) && !defined(_XBOX)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
37
libretro-common/include/retro_assert.h
Normal file
37
libretro-common/include/retro_assert.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (retro_assert.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RETRO_ASSERT_H
|
||||||
|
#define __RETRO_ASSERT_H
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifdef RARCH_INTERNAL
|
||||||
|
#include <stdio.h>
|
||||||
|
#define retro_assert(cond) do { \
|
||||||
|
if (!(cond)) { printf("Assertion failed at %s:%d.\n", __FILE__, __LINE__); abort(); } \
|
||||||
|
} while(0)
|
||||||
|
#else
|
||||||
|
#define retro_assert(cond) assert(cond)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -34,4 +34,3 @@ in a public API, you may need this.
|
|||||||
#include <compat/msvc.h>
|
#include <compat/msvc.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -113,6 +113,5 @@ Of course, another school of thought is that you should do as little damage as p
|
|||||||
in as few places as possible...
|
in as few places as possible...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* _LIBRETRO_COMMON_RETRO_COMMON_API_H */
|
/* _LIBRETRO_COMMON_RETRO_COMMON_API_H */
|
||||||
#endif
|
#endif
|
||||||
|
78
libretro-common/include/retro_dirent.h
Normal file
78
libretro-common/include/retro_dirent.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* Copyright (C) 2010-2019 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (retro_dirent.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RETRO_DIRENT_H
|
||||||
|
#define __RETRO_DIRENT_H
|
||||||
|
|
||||||
|
#include <libretro.h>
|
||||||
|
#include <retro_common_api.h>
|
||||||
|
#include <retro_miscellaneous.h>
|
||||||
|
|
||||||
|
#include <boolean.h>
|
||||||
|
|
||||||
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define DIRENT_REQUIRED_VFS_VERSION 3
|
||||||
|
|
||||||
|
void dirent_vfs_init(const struct retro_vfs_interface_info* vfs_info);
|
||||||
|
|
||||||
|
typedef struct RDIR RDIR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* retro_opendir:
|
||||||
|
* @name : path to the directory to open.
|
||||||
|
*
|
||||||
|
* Opens a directory for reading. Tidy up with retro_closedir.
|
||||||
|
*
|
||||||
|
* Returns: RDIR pointer on success, NULL if name is not a
|
||||||
|
* valid directory, null itself or the empty string.
|
||||||
|
*/
|
||||||
|
struct RDIR *retro_opendir(const char *name);
|
||||||
|
|
||||||
|
struct RDIR *retro_opendir_include_hidden(const char *name, bool include_hidden);
|
||||||
|
|
||||||
|
int retro_readdir(struct RDIR *rdir);
|
||||||
|
|
||||||
|
/* Deprecated, returns false, left for compatibility */
|
||||||
|
bool retro_dirent_error(struct RDIR *rdir);
|
||||||
|
|
||||||
|
const char *retro_dirent_get_name(struct RDIR *rdir);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* retro_dirent_is_dir:
|
||||||
|
* @rdir : pointer to the directory entry.
|
||||||
|
* @unused : deprecated, included for compatibility reasons, pass NULL
|
||||||
|
*
|
||||||
|
* Is the directory listing entry a directory?
|
||||||
|
*
|
||||||
|
* Returns: true if directory listing entry is
|
||||||
|
* a directory, false if not.
|
||||||
|
*/
|
||||||
|
bool retro_dirent_is_dir(struct RDIR *rdir, const char *unused);
|
||||||
|
|
||||||
|
void retro_closedir(struct RDIR *rdir);
|
||||||
|
|
||||||
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
258
libretro-common/include/retro_endianness.h
Normal file
258
libretro-common/include/retro_endianness.h
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (retro_endianness.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBRETRO_SDK_ENDIANNESS_H
|
||||||
|
#define __LIBRETRO_SDK_ENDIANNESS_H
|
||||||
|
|
||||||
|
#include <retro_inline.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||||
|
#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) \
|
||||||
|
))
|
||||||
|
#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))
|
||||||
|
#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))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is_little_endian:
|
||||||
|
*
|
||||||
|
* Checks if the system is little endian or big-endian.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* swap_if_big64:
|
||||||
|
* @val : unsigned 64-bit value
|
||||||
|
*
|
||||||
|
* Byteswap unsigned 64-bit value if system is big-endian.
|
||||||
|
*
|
||||||
|
* Returns: Byteswapped value in case system is big-endian,
|
||||||
|
* otherwise returns same value.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#if defined(MSB_FIRST)
|
||||||
|
#define swap_if_big64(val) (SWAP64(val))
|
||||||
|
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
|
||||||
|
#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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* swap_if_big32:
|
||||||
|
* @val : unsigned 32-bit value
|
||||||
|
*
|
||||||
|
* Byteswap unsigned 32-bit value if system is big-endian.
|
||||||
|
*
|
||||||
|
* Returns: Byteswapped value in case system is big-endian,
|
||||||
|
* otherwise returns same value.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#if defined(MSB_FIRST)
|
||||||
|
#define swap_if_big32(val) (SWAP32(val))
|
||||||
|
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
|
||||||
|
#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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* swap_if_little64:
|
||||||
|
* @val : unsigned 64-bit value
|
||||||
|
*
|
||||||
|
* Byteswap unsigned 64-bit value if system is little-endian.
|
||||||
|
*
|
||||||
|
* Returns: Byteswapped value in case system is little-endian,
|
||||||
|
* otherwise returns same value.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#if defined(MSB_FIRST)
|
||||||
|
#define swap_if_little64(val) (val)
|
||||||
|
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
|
||||||
|
#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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* swap_if_little32:
|
||||||
|
* @val : unsigned 32-bit value
|
||||||
|
*
|
||||||
|
* Byteswap unsigned 32-bit value if system is little-endian.
|
||||||
|
*
|
||||||
|
* Returns: Byteswapped value in case system is little-endian,
|
||||||
|
* otherwise returns same value.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#if defined(MSB_FIRST)
|
||||||
|
#define swap_if_little32(val) (val)
|
||||||
|
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
|
||||||
|
#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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* swap_if_big16:
|
||||||
|
* @val : unsigned 16-bit value
|
||||||
|
*
|
||||||
|
* Byteswap unsigned 16-bit value if system is big-endian.
|
||||||
|
*
|
||||||
|
* Returns: Byteswapped value in case system is big-endian,
|
||||||
|
* otherwise returns same value.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#if defined(MSB_FIRST)
|
||||||
|
#define swap_if_big16(val) (SWAP16(val))
|
||||||
|
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
|
||||||
|
#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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* swap_if_little16:
|
||||||
|
* @val : unsigned 16-bit value
|
||||||
|
*
|
||||||
|
* Byteswap unsigned 16-bit value if system is little-endian.
|
||||||
|
*
|
||||||
|
* Returns: Byteswapped value in case system is little-endian,
|
||||||
|
* otherwise returns same value.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#if defined(MSB_FIRST)
|
||||||
|
#define swap_if_little16(val) (val)
|
||||||
|
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
|
||||||
|
#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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* store32be:
|
||||||
|
* @addr : pointer to unsigned 32-bit buffer
|
||||||
|
* @data : unsigned 32-bit value to write
|
||||||
|
*
|
||||||
|
* Write data to address. Endian-safe. Byteswaps the data
|
||||||
|
* first if necessary before storing it.
|
||||||
|
**/
|
||||||
|
static INLINE void store32be(uint32_t *addr, uint32_t data)
|
||||||
|
{
|
||||||
|
*addr = swap_if_little32(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load32be:
|
||||||
|
* @addr : pointer to unsigned 32-bit buffer
|
||||||
|
*
|
||||||
|
* Load value from address. Endian-safe.
|
||||||
|
*
|
||||||
|
* Returns: value from address, byte-swapped if necessary.
|
||||||
|
**/
|
||||||
|
static INLINE uint32_t load32be(const uint32_t *addr)
|
||||||
|
{
|
||||||
|
return swap_if_little32(*addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -101,6 +101,14 @@ printf("This is C++, version %d.\n", __cplusplus);
|
|||||||
#define __WINRT__ 1
|
#define __WINRT__ 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* MSVC obviously has to have some non-standard constants... */
|
||||||
|
#if _M_IX86_FP == 1
|
||||||
|
#define __SSE__ 1
|
||||||
|
#elif _M_IX86_FP == 2 || (defined(_M_AMD64) || defined(_M_X64))
|
||||||
|
#define __SSE__ 1
|
||||||
|
#define __SSE2__ 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
94
libretro-common/include/retro_math.h
Normal file
94
libretro-common/include/retro_math.h
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (retro_math.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBRETRO_COMMON_MATH_H
|
||||||
|
#define _LIBRETRO_COMMON_MATH_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(_XBOX)
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#elif defined(_WIN32) && defined(_XBOX)
|
||||||
|
#include <Xtl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include <compat/msvc.h>
|
||||||
|
#endif
|
||||||
|
#include <retro_inline.h>
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
#if !defined(USE_MATH_DEFINES)
|
||||||
|
#define M_PI 3.14159265358979323846264338327
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* next_pow2:
|
||||||
|
* @v : initial value
|
||||||
|
*
|
||||||
|
* Get next power of 2 value based on initial value.
|
||||||
|
*
|
||||||
|
* Returns: next power of 2 value (derived from @v).
|
||||||
|
**/
|
||||||
|
static INLINE uint32_t next_pow2(uint32_t v)
|
||||||
|
{
|
||||||
|
v--;
|
||||||
|
v |= v >> 1;
|
||||||
|
v |= v >> 2;
|
||||||
|
v |= v >> 4;
|
||||||
|
v |= v >> 8;
|
||||||
|
v |= v >> 16;
|
||||||
|
v++;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prev_pow2:
|
||||||
|
* @v : initial value
|
||||||
|
*
|
||||||
|
* Get previous power of 2 value based on initial value.
|
||||||
|
*
|
||||||
|
* Returns: previous power of 2 value (derived from @v).
|
||||||
|
**/
|
||||||
|
static INLINE uint32_t prev_pow2(uint32_t v)
|
||||||
|
{
|
||||||
|
v |= v >> 1;
|
||||||
|
v |= v >> 2;
|
||||||
|
v |= v >> 4;
|
||||||
|
v |= v >> 8;
|
||||||
|
v |= v >> 16;
|
||||||
|
return v - (v >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -77,7 +77,7 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
|
|||||||
#ifndef PATH_MAX_LENGTH
|
#ifndef PATH_MAX_LENGTH
|
||||||
#if defined(__CELLOS_LV2__)
|
#if defined(__CELLOS_LV2__)
|
||||||
#define PATH_MAX_LENGTH CELL_FS_MAX_FS_PATH_LENGTH
|
#define PATH_MAX_LENGTH CELL_FS_MAX_FS_PATH_LENGTH
|
||||||
#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(GEKKO)|| defined(WIIU)
|
#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(ORBIS)
|
||||||
#define PATH_MAX_LENGTH 512
|
#define PATH_MAX_LENGTH 512
|
||||||
#else
|
#else
|
||||||
#define PATH_MAX_LENGTH 4096
|
#define PATH_MAX_LENGTH 4096
|
||||||
@ -159,14 +159,24 @@ typedef struct
|
|||||||
# ifdef _WIN64
|
# ifdef _WIN64
|
||||||
# define PRI_SIZET PRIu64
|
# define PRI_SIZET PRIu64
|
||||||
# else
|
# else
|
||||||
#if _MSC_VER == 1800
|
# if _MSC_VER == 1800
|
||||||
# define PRI_SIZET PRIu32
|
# define PRI_SIZET PRIu32
|
||||||
#else
|
# else
|
||||||
# define PRI_SIZET "u"
|
# define PRI_SIZET "u"
|
||||||
#endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
#elif PS2
|
||||||
|
# define PRI_SIZET "u"
|
||||||
#else
|
#else
|
||||||
# define PRI_SIZET "zu"
|
# if (SIZE_MAX == 0xFFFF)
|
||||||
|
# define PRI_SIZET "hu"
|
||||||
|
# elif (SIZE_MAX == 0xFFFFFFFF)
|
||||||
|
# define PRI_SIZET "u"
|
||||||
|
# elif (SIZE_MAX == 0xFFFFFFFFFFFFFFFF)
|
||||||
|
# define PRI_SIZET "lu"
|
||||||
|
# else
|
||||||
|
# error PRI_SIZET: unknown SIZE_MAX
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,6 +37,8 @@
|
|||||||
#include <pspthreadman.h>
|
#include <pspthreadman.h>
|
||||||
#elif defined(VITA)
|
#elif defined(VITA)
|
||||||
#include <psp2/kernel/threadmgr.h>
|
#include <psp2/kernel/threadmgr.h>
|
||||||
|
#elif defined(PS2)
|
||||||
|
#include <SDL/SDL_timer.h>
|
||||||
#elif defined(_3DS)
|
#elif defined(_3DS)
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
#else
|
#else
|
||||||
@ -89,10 +91,12 @@ static INLINE void retro_sleep(unsigned msec)
|
|||||||
sys_timer_usleep(1000 * msec);
|
sys_timer_usleep(1000 * msec);
|
||||||
#elif defined(PSP) || defined(VITA)
|
#elif defined(PSP) || defined(VITA)
|
||||||
sceKernelDelayThread(1000 * msec);
|
sceKernelDelayThread(1000 * msec);
|
||||||
|
#elif defined(PS2)
|
||||||
|
SDL_Delay(msec);
|
||||||
#elif defined(_3DS)
|
#elif defined(_3DS)
|
||||||
svcSleepThread(1000000 * (s64)msec);
|
svcSleepThread(1000000 * (s64)msec);
|
||||||
#elif defined(__WINRT__)
|
#elif defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||||
/* TODO/FIXME */
|
SleepEx(msec, FALSE);
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
Sleep(msec);
|
Sleep(msec);
|
||||||
#elif defined(XENON)
|
#elif defined(XENON)
|
||||||
|
@ -36,19 +36,22 @@
|
|||||||
#include <boolean.h>
|
#include <boolean.h>
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <vfs/vfs_implementation.h>
|
||||||
|
|
||||||
#define FILESTREAM_REQUIRED_VFS_VERSION 1
|
#define FILESTREAM_REQUIRED_VFS_VERSION 2
|
||||||
|
|
||||||
RETRO_BEGIN_DECLS
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
typedef struct RFILE RFILE;
|
typedef struct RFILE RFILE;
|
||||||
|
|
||||||
#define FILESTREAM_REQUIRED_VFS_VERSION 1
|
#define FILESTREAM_REQUIRED_VFS_VERSION 2
|
||||||
|
|
||||||
void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info);
|
void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info);
|
||||||
|
|
||||||
int64_t filestream_get_size(RFILE *stream);
|
int64_t filestream_get_size(RFILE *stream);
|
||||||
|
|
||||||
|
int64_t filestream_truncate(RFILE *stream, int64_t length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* filestream_open:
|
* filestream_open:
|
||||||
* @path : path to file
|
* @path : path to file
|
||||||
@ -104,6 +107,8 @@ bool filestream_exists(const char *path);
|
|||||||
|
|
||||||
char *filestream_getline(RFILE *stream);
|
char *filestream_getline(RFILE *stream);
|
||||||
|
|
||||||
|
libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream);
|
||||||
|
|
||||||
RETRO_END_DECLS
|
RETRO_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
RETRO_BEGIN_DECLS
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
|
#ifndef SKIP_STDIO_REDEFINES
|
||||||
|
|
||||||
#define FILE RFILE
|
#define FILE RFILE
|
||||||
|
|
||||||
#undef fopen
|
#undef fopen
|
||||||
@ -41,9 +43,11 @@ RETRO_BEGIN_DECLS
|
|||||||
#undef fgetc
|
#undef fgetc
|
||||||
#undef fwrite
|
#undef fwrite
|
||||||
#undef fputc
|
#undef fputc
|
||||||
|
#undef fflush
|
||||||
#undef fprintf
|
#undef fprintf
|
||||||
#undef ferror
|
#undef ferror
|
||||||
#undef feof
|
#undef feof
|
||||||
|
#undef fscanf
|
||||||
|
|
||||||
#define fopen rfopen
|
#define fopen rfopen
|
||||||
#define fclose rfclose
|
#define fclose rfclose
|
||||||
@ -54,9 +58,13 @@ RETRO_BEGIN_DECLS
|
|||||||
#define fgetc rfgetc
|
#define fgetc rfgetc
|
||||||
#define fwrite rfwrite
|
#define fwrite rfwrite
|
||||||
#define fputc rfputc
|
#define fputc rfputc
|
||||||
|
#define fflush rfflush
|
||||||
#define fprintf rfprintf
|
#define fprintf rfprintf
|
||||||
#define ferror rferror
|
#define ferror rferror
|
||||||
#define feof rfeof
|
#define feof rfeof
|
||||||
|
#define fscanf rfscanf
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
RFILE* rfopen(const char *path, const char *mode);
|
RFILE* rfopen(const char *path, const char *mode);
|
||||||
|
|
||||||
@ -78,12 +86,16 @@ int64_t rfwrite(void const* buffer,
|
|||||||
|
|
||||||
int rfputc(int character, RFILE * stream);
|
int rfputc(int character, RFILE * stream);
|
||||||
|
|
||||||
|
int64_t rfflush(RFILE * stream);
|
||||||
|
|
||||||
int rfprintf(RFILE * stream, const char * format, ...);
|
int rfprintf(RFILE * stream, const char * format, ...);
|
||||||
|
|
||||||
int rferror(RFILE* stream);
|
int rferror(RFILE* stream);
|
||||||
|
|
||||||
int rfeof(RFILE* stream);
|
int rfeof(RFILE* stream);
|
||||||
|
|
||||||
|
int rfscanf(RFILE * stream, const char * format, ...);
|
||||||
|
|
||||||
RETRO_END_DECLS
|
RETRO_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2019 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (stdstring.h).
|
* The following license statement only applies to this file (stdstring.h).
|
||||||
@ -37,35 +37,30 @@ RETRO_BEGIN_DECLS
|
|||||||
|
|
||||||
static INLINE bool string_is_empty(const char *data)
|
static INLINE bool string_is_empty(const char *data)
|
||||||
{
|
{
|
||||||
return (data == NULL) || (*data == '\0');
|
return !data || (*data == '\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE bool string_is_equal(const char *a, const char *b)
|
static INLINE bool string_is_equal(const char *a, const char *b)
|
||||||
{
|
{
|
||||||
if (!a || !b)
|
return (a && b) ? !strcmp(a, b) : false;
|
||||||
return false;
|
|
||||||
while(*a && (*a == *b))
|
|
||||||
{
|
|
||||||
a++;
|
|
||||||
b++;
|
|
||||||
}
|
|
||||||
return (*(const unsigned char*)a - *(const unsigned char*)b) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE bool string_is_not_equal(const char *a, const char *b)
|
#define STRLEN_CONST(x) ((sizeof((x))-1))
|
||||||
{
|
|
||||||
return !string_is_equal(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define string_add_pair_open(s, size) strlcat((s), " (", (size))
|
#define string_is_not_equal(a, b) !string_is_equal((a), (b))
|
||||||
#define string_add_pair_close(s, size) strlcat((s), ")", (size))
|
|
||||||
#define string_add_bracket_open(s, size) strlcat((s), "{", (size))
|
#define string_add_pair_open(s, size) strlcat((s), " (", (size))
|
||||||
|
#define string_add_pair_close(s, size) strlcat((s), ")", (size))
|
||||||
|
#define string_add_bracket_open(s, size) strlcat((s), "{", (size))
|
||||||
#define string_add_bracket_close(s, size) strlcat((s), "}", (size))
|
#define string_add_bracket_close(s, size) strlcat((s), "}", (size))
|
||||||
#define string_add_single_quote(s, size) strlcat((s), "'", (size))
|
#define string_add_single_quote(s, size) strlcat((s), "'", (size))
|
||||||
#define string_add_quote(s, size) strlcat((s), "\"", (size))
|
#define string_add_quote(s, size) strlcat((s), "\"", (size))
|
||||||
#define string_add_colon(s, size) strlcat((s), ":", (size))
|
#define string_add_colon(s, size) strlcat((s), ":", (size))
|
||||||
#define string_add_glob_open(s, size) strlcat((s), "glob('*", (size))
|
#define string_add_glob_open(s, size) strlcat((s), "glob('*", (size))
|
||||||
#define string_add_glob_close(s, size) strlcat((s), "*')", (size))
|
#define string_add_glob_close(s, size) strlcat((s), "*')", (size))
|
||||||
|
|
||||||
|
#define string_is_not_equal_fast(a, b, size) (memcmp(a, b, size) != 0)
|
||||||
|
#define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0)
|
||||||
|
|
||||||
static INLINE void string_add_between_pairs(char *s, const char *str,
|
static INLINE void string_add_between_pairs(char *s, const char *str,
|
||||||
size_t size)
|
size_t size)
|
||||||
@ -75,9 +70,6 @@ static INLINE void string_add_between_pairs(char *s, const char *str,
|
|||||||
string_add_pair_close(s, size);
|
string_add_pair_close(s, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define string_is_not_equal_fast(a, b, size) (memcmp(a, b, size) != 0)
|
|
||||||
#define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0)
|
|
||||||
|
|
||||||
static INLINE bool string_is_equal_case_insensitive(const char *a,
|
static INLINE bool string_is_equal_case_insensitive(const char *a,
|
||||||
const char *b)
|
const char *b)
|
||||||
{
|
{
|
||||||
@ -119,7 +111,7 @@ char *string_to_upper(char *s);
|
|||||||
|
|
||||||
char *string_to_lower(char *s);
|
char *string_to_lower(char *s);
|
||||||
|
|
||||||
char *string_ucwords(char* s);
|
char *string_ucwords(char *s);
|
||||||
|
|
||||||
char *string_replace_substring(const char *in, const char *pattern,
|
char *string_replace_substring(const char *in, const char *pattern,
|
||||||
const char *by);
|
const char *by);
|
||||||
@ -133,7 +125,9 @@ char *string_trim_whitespace_right(char *const s);
|
|||||||
/* Remove leading and trailing whitespaces */
|
/* Remove leading and trailing whitespaces */
|
||||||
char *string_trim_whitespace(char *const s);
|
char *string_trim_whitespace(char *const s);
|
||||||
|
|
||||||
char *word_wrap(char* buffer, const char *string, int line_width, bool unicode);
|
/* max_lines == 0 means no limit */
|
||||||
|
char *word_wrap(char *buffer, const char *string,
|
||||||
|
int line_width, bool unicode, unsigned max_lines);
|
||||||
|
|
||||||
RETRO_END_DECLS
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
111
libretro-common/include/vfs/vfs.h
Normal file
111
libretro-common/include/vfs/vfs.h
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/* Copyright (C) 2010-2019 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (vfs_implementation.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBRETRO_SDK_VFS_H
|
||||||
|
#define __LIBRETRO_SDK_VFS_H
|
||||||
|
|
||||||
|
#include <retro_common_api.h>
|
||||||
|
#include <boolean.h>
|
||||||
|
|
||||||
|
#ifdef RARCH_INTERNAL
|
||||||
|
#ifndef VFS_FRONTEND
|
||||||
|
#define VFS_FRONTEND
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
typedef void* HANDLE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_CDROM
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *cue_buf;
|
||||||
|
size_t cue_len;
|
||||||
|
int64_t byte_pos;
|
||||||
|
char drive;
|
||||||
|
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];
|
||||||
|
bool last_frame_valid;
|
||||||
|
} vfs_cdrom_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum vfs_scheme
|
||||||
|
{
|
||||||
|
VFS_SCHEME_NONE = 0,
|
||||||
|
VFS_SCHEME_CDROM
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef __WINRT__
|
||||||
|
#ifdef VFS_FRONTEND
|
||||||
|
struct retro_vfs_file_handle
|
||||||
|
#else
|
||||||
|
struct libretro_vfs_implementation_file
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
unsigned hints;
|
||||||
|
int64_t size;
|
||||||
|
char *buf;
|
||||||
|
FILE *fp;
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE fh;
|
||||||
|
#endif
|
||||||
|
char* orig_path;
|
||||||
|
uint64_t mappos;
|
||||||
|
uint64_t mapsize;
|
||||||
|
uint8_t *mapped;
|
||||||
|
enum vfs_scheme scheme;
|
||||||
|
#ifdef HAVE_CDROM
|
||||||
|
vfs_cdrom_t cdrom;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Replace the following symbol with something appropriate
|
||||||
|
* to signify the file is being compiled for a front end instead of a core.
|
||||||
|
* This allows the same code to act as reference implementation
|
||||||
|
* for VFS and as fallbacks for when the front end does not provide VFS functionality.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef VFS_FRONTEND
|
||||||
|
typedef struct retro_vfs_file_handle libretro_vfs_implementation_file;
|
||||||
|
#else
|
||||||
|
typedef struct libretro_vfs_implementation_file libretro_vfs_implementation_file;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef VFS_FRONTEND
|
||||||
|
typedef struct retro_vfs_dir_handle libretro_vfs_implementation_dir;
|
||||||
|
#else
|
||||||
|
typedef struct libretro_vfs_implementation_dir libretro_vfs_implementation_dir;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010-2018 The RetroArch team
|
/* Copyright (C) 2010-2019 The RetroArch team
|
||||||
*
|
*
|
||||||
* ---------------------------------------------------------------------------------------
|
* ---------------------------------------------------------------------------------------
|
||||||
* The following license statement only applies to this file (vfs_implementation.h).
|
* The following license statement only applies to this file (vfs_implementation.h).
|
||||||
@ -23,20 +23,13 @@
|
|||||||
#ifndef __LIBRETRO_SDK_VFS_IMPLEMENTATION_H
|
#ifndef __LIBRETRO_SDK_VFS_IMPLEMENTATION_H
|
||||||
#define __LIBRETRO_SDK_VFS_IMPLEMENTATION_H
|
#define __LIBRETRO_SDK_VFS_IMPLEMENTATION_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <libretro.h>
|
#include <libretro.h>
|
||||||
|
#include <retro_environment.h>
|
||||||
|
#include <vfs/vfs.h>
|
||||||
|
|
||||||
/* Replace the following symbol with something appropriate
|
RETRO_BEGIN_DECLS
|
||||||
* to signify the file is being compiled for a front end instead of a core.
|
|
||||||
* This allows the same code to act as reference implementation
|
|
||||||
* for VFS and as fallbacks for when the front end does not provide VFS functionality.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef VFS_FRONTEND
|
|
||||||
typedef struct retro_vfs_file_handle libretro_vfs_implementation_file;
|
|
||||||
#else
|
|
||||||
typedef struct libretro_vfs_implementation_file libretro_vfs_implementation_file;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints);
|
libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints);
|
||||||
|
|
||||||
@ -46,6 +39,8 @@ int retro_vfs_file_error_impl(libretro_vfs_implementation_file *stream);
|
|||||||
|
|
||||||
int64_t retro_vfs_file_size_impl(libretro_vfs_implementation_file *stream);
|
int64_t retro_vfs_file_size_impl(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
int64_t retro_vfs_file_truncate_impl(libretro_vfs_implementation_file *stream, int64_t length);
|
||||||
|
|
||||||
int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream);
|
int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file *stream, int64_t offset, int seek_position);
|
int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file *stream, int64_t offset, int seek_position);
|
||||||
@ -62,4 +57,20 @@ int retro_vfs_file_rename_impl(const char *old_path, const char *new_path);
|
|||||||
|
|
||||||
const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *stream);
|
const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
int retro_vfs_stat_impl(const char *path, int32_t *size);
|
||||||
|
|
||||||
|
int retro_vfs_mkdir_impl(const char *dir);
|
||||||
|
|
||||||
|
libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *dir, bool include_hidden);
|
||||||
|
|
||||||
|
bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir *dirstream);
|
||||||
|
|
||||||
|
const char *retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir *dirstream);
|
||||||
|
|
||||||
|
bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *dirstream);
|
||||||
|
|
||||||
|
int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *dirstream);
|
||||||
|
|
||||||
|
RETRO_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
52
libretro-common/include/vfs/vfs_implementation_cdrom.h
Normal file
52
libretro-common/include/vfs/vfs_implementation_cdrom.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* Copyright (C) 2010-2019 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (vfs_implementation_cdrom.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBRETRO_SDK_VFS_IMPLEMENTATION_CDROM_H
|
||||||
|
#define __LIBRETRO_SDK_VFS_IMPLEMENTATION_CDROM_H
|
||||||
|
|
||||||
|
#include <vfs/vfs.h>
|
||||||
|
#include <cdrom/cdrom.h>
|
||||||
|
|
||||||
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
|
int64_t retro_vfs_file_seek_cdrom(libretro_vfs_implementation_file *stream, int64_t offset, int whence);
|
||||||
|
|
||||||
|
void retro_vfs_file_open_cdrom(
|
||||||
|
libretro_vfs_implementation_file *stream,
|
||||||
|
const char *path, unsigned mode, unsigned hints);
|
||||||
|
|
||||||
|
int retro_vfs_file_close_cdrom(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
int64_t retro_vfs_file_tell_cdrom(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
|
||||||
|
void *s, uint64_t len);
|
||||||
|
|
||||||
|
int retro_vfs_file_error_cdrom(libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
const cdrom_toc_t* retro_vfs_file_get_cdrom_toc(void);
|
||||||
|
|
||||||
|
const vfs_cdrom_t* retro_vfs_file_get_cdrom_position(const libretro_vfs_implementation_file *stream);
|
||||||
|
|
||||||
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
240
libretro-common/lists/dir_list.c
Normal file
240
libretro-common/lists/dir_list.c
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (dir_list.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 <stdlib.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(_XBOX)
|
||||||
|
#include <xtl.h>
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <lists/dir_list.h>
|
||||||
|
#include <lists/string_list.h>
|
||||||
|
#include <file/file_path.h>
|
||||||
|
|
||||||
|
#include <compat/strl.h>
|
||||||
|
#include <retro_dirent.h>
|
||||||
|
|
||||||
|
#include <string/stdstring.h>
|
||||||
|
#include <retro_miscellaneous.h>
|
||||||
|
|
||||||
|
static int qstrcmp_plain(const void *a_, const void *b_)
|
||||||
|
{
|
||||||
|
const struct string_list_elem *a = (const struct string_list_elem*)a_;
|
||||||
|
const struct string_list_elem *b = (const struct string_list_elem*)b_;
|
||||||
|
|
||||||
|
return strcasecmp(a->data, b->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qstrcmp_dir(const void *a_, const void *b_)
|
||||||
|
{
|
||||||
|
const struct string_list_elem *a = (const struct string_list_elem*)a_;
|
||||||
|
const struct string_list_elem *b = (const struct string_list_elem*)b_;
|
||||||
|
int a_type = a->attr.i;
|
||||||
|
int b_type = b->attr.i;
|
||||||
|
|
||||||
|
/* Sort directories before files. */
|
||||||
|
if (a_type != b_type)
|
||||||
|
return b_type - a_type;
|
||||||
|
return strcasecmp(a->data, b->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dir_list_sort:
|
||||||
|
* @list : pointer to the directory listing.
|
||||||
|
* @dir_first : move the directories in the listing to the top?
|
||||||
|
*
|
||||||
|
* Sorts a directory listing.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
void dir_list_sort(struct string_list *list, bool dir_first)
|
||||||
|
{
|
||||||
|
if (list)
|
||||||
|
qsort(list->elems, list->size, sizeof(struct string_list_elem),
|
||||||
|
dir_first ? qstrcmp_dir : qstrcmp_plain);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dir_list_free:
|
||||||
|
* @list : pointer to the directory listing
|
||||||
|
*
|
||||||
|
* Frees a directory listing.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
void dir_list_free(struct string_list *list)
|
||||||
|
{
|
||||||
|
string_list_free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dir_list_read:
|
||||||
|
* @dir : directory path.
|
||||||
|
* @list : the string list to add files to
|
||||||
|
* @ext_list : the string list of extensions to include
|
||||||
|
* @include_dirs : include directories as part of the finished directory listing?
|
||||||
|
* @include_hidden : include hidden files and directories as part of the finished directory listing?
|
||||||
|
* @include_compressed : Only include files which match ext. Do not try to match compressed files, etc.
|
||||||
|
* @recursive : list directory contents recursively
|
||||||
|
*
|
||||||
|
* Add files within a directory to an existing string list
|
||||||
|
*
|
||||||
|
* Returns: -1 on error, 0 on success.
|
||||||
|
**/
|
||||||
|
static int dir_list_read(const char *dir,
|
||||||
|
struct string_list *list, struct string_list *ext_list,
|
||||||
|
bool include_dirs, bool include_hidden,
|
||||||
|
bool include_compressed, bool recursive)
|
||||||
|
{
|
||||||
|
struct RDIR *entry = retro_opendir_include_hidden(dir, include_hidden);
|
||||||
|
|
||||||
|
if (!entry || retro_dirent_error(entry))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
while (retro_readdir(entry))
|
||||||
|
{
|
||||||
|
union string_list_elem_attr attr;
|
||||||
|
char file_path[PATH_MAX_LENGTH];
|
||||||
|
const char *name = retro_dirent_get_name(entry);
|
||||||
|
|
||||||
|
if (!include_hidden && *name == '.')
|
||||||
|
continue;
|
||||||
|
if (!strcmp(name, ".") || !strcmp(name, ".."))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
file_path[0] = '\0';
|
||||||
|
fill_pathname_join(file_path, dir, name, sizeof(file_path));
|
||||||
|
|
||||||
|
if (retro_dirent_is_dir(entry, NULL))
|
||||||
|
{
|
||||||
|
if (recursive)
|
||||||
|
dir_list_read(file_path, list, ext_list, include_dirs,
|
||||||
|
include_hidden, include_compressed, recursive);
|
||||||
|
|
||||||
|
if (!include_dirs)
|
||||||
|
continue;
|
||||||
|
attr.i = RARCH_DIRECTORY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *file_ext = path_get_extension(name);
|
||||||
|
|
||||||
|
attr.i = RARCH_FILETYPE_UNSET;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the file format is explicitly supported by the libretro-core, we
|
||||||
|
* need to immediately load it and not designate it as a compressed file.
|
||||||
|
*
|
||||||
|
* Example: .zip could be supported as a image by the core and as a
|
||||||
|
* compressed_file. In that case, we have to interpret it as a image.
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
if (string_list_find_elem_prefix(ext_list, ".", file_ext))
|
||||||
|
attr.i = RARCH_PLAIN_FILE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool is_compressed_file;
|
||||||
|
if ((is_compressed_file = path_is_compressed_file(file_path)))
|
||||||
|
attr.i = RARCH_COMPRESSED_ARCHIVE;
|
||||||
|
|
||||||
|
if (ext_list &&
|
||||||
|
(!is_compressed_file || !include_compressed))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string_list_append(list, file_path, attr))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
retro_closedir(entry);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (entry)
|
||||||
|
retro_closedir(entry);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dir_list_append:
|
||||||
|
* @list : existing list to append to.
|
||||||
|
* @dir : directory path.
|
||||||
|
* @ext : allowed extensions of file directory entries to include.
|
||||||
|
* @include_dirs : include directories as part of the finished directory listing?
|
||||||
|
* @include_hidden : include hidden files and directories as part of the finished directory listing?
|
||||||
|
* @include_compressed : Only include files which match ext. Do not try to match compressed files, etc.
|
||||||
|
* @recursive : list directory contents recursively
|
||||||
|
*
|
||||||
|
* Create a directory listing, appending to an existing list
|
||||||
|
*
|
||||||
|
* Returns: true success, false in case of error.
|
||||||
|
**/
|
||||||
|
bool dir_list_append(struct string_list *list,
|
||||||
|
const char *dir,
|
||||||
|
const char *ext, bool include_dirs,
|
||||||
|
bool include_hidden, bool include_compressed,
|
||||||
|
bool recursive)
|
||||||
|
{
|
||||||
|
struct string_list *ext_list = ext ? string_split(ext, "|") : NULL;
|
||||||
|
bool ret = dir_list_read(dir, list, ext_list,
|
||||||
|
include_dirs, include_hidden, include_compressed, recursive) != -1;
|
||||||
|
|
||||||
|
string_list_free(ext_list);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dir_list_new:
|
||||||
|
* @dir : directory path.
|
||||||
|
* @ext : allowed extensions of file directory entries to include.
|
||||||
|
* @include_dirs : include directories as part of the finished directory listing?
|
||||||
|
* @include_hidden : include hidden files and directories as part of the finished directory listing?
|
||||||
|
* @include_compressed : Only include files which match ext. Do not try to match compressed files, etc.
|
||||||
|
* @recursive : list directory contents recursively
|
||||||
|
*
|
||||||
|
* Create a directory listing.
|
||||||
|
*
|
||||||
|
* Returns: pointer to a directory listing of type 'struct string_list *' on success,
|
||||||
|
* NULL in case of error. Has to be freed manually.
|
||||||
|
**/
|
||||||
|
struct string_list *dir_list_new(const char *dir,
|
||||||
|
const char *ext, bool include_dirs,
|
||||||
|
bool include_hidden, bool include_compressed,
|
||||||
|
bool recursive)
|
||||||
|
{
|
||||||
|
struct string_list *list = NULL;
|
||||||
|
|
||||||
|
if (!(list = string_list_new()))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!dir_list_append(list, dir, ext, include_dirs,
|
||||||
|
include_hidden, include_compressed, recursive))
|
||||||
|
{
|
||||||
|
string_list_free(list);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
363
libretro-common/lists/string_list.c
Normal file
363
libretro-common/lists/string_list.c
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (string_list.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 <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <lists/string_list.h>
|
||||||
|
#include <compat/strl.h>
|
||||||
|
#include <compat/posix_string.h>
|
||||||
|
#include <string/stdstring.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_free
|
||||||
|
* @list : pointer to string list object
|
||||||
|
*
|
||||||
|
* Frees a string list.
|
||||||
|
*/
|
||||||
|
void string_list_free(struct string_list *list)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
if (!list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (list->elems)
|
||||||
|
{
|
||||||
|
for (i = 0; i < list->size; i++)
|
||||||
|
{
|
||||||
|
if (list->elems[i].data)
|
||||||
|
free(list->elems[i].data);
|
||||||
|
list->elems[i].data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(list->elems);
|
||||||
|
}
|
||||||
|
|
||||||
|
list->elems = NULL;
|
||||||
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_capacity:
|
||||||
|
* @list : pointer to string list
|
||||||
|
* @cap : new capacity for string list.
|
||||||
|
*
|
||||||
|
* Change maximum capacity of string list's size.
|
||||||
|
*
|
||||||
|
* Returns: true (1) if successful, otherwise false (0).
|
||||||
|
**/
|
||||||
|
static bool string_list_capacity(struct string_list *list, size_t cap)
|
||||||
|
{
|
||||||
|
struct string_list_elem *new_data = (struct string_list_elem*)
|
||||||
|
realloc(list->elems, cap * sizeof(*new_data));
|
||||||
|
|
||||||
|
if (!new_data)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (cap > list->cap)
|
||||||
|
memset(&new_data[list->cap], 0, sizeof(*new_data) * (cap - list->cap));
|
||||||
|
|
||||||
|
list->elems = new_data;
|
||||||
|
list->cap = cap;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_new:
|
||||||
|
*
|
||||||
|
* Creates a new string list. Has to be freed manually.
|
||||||
|
*
|
||||||
|
* Returns: new string list if successful, otherwise NULL.
|
||||||
|
*/
|
||||||
|
struct string_list *string_list_new(void)
|
||||||
|
{
|
||||||
|
struct string_list *list = (struct string_list*)
|
||||||
|
calloc(1, sizeof(*list));
|
||||||
|
|
||||||
|
if (!list)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!string_list_capacity(list, 32))
|
||||||
|
{
|
||||||
|
string_list_free(list);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_append:
|
||||||
|
* @list : pointer to string list
|
||||||
|
* @elem : element to add to the string list
|
||||||
|
* @attr : attributes of new element.
|
||||||
|
*
|
||||||
|
* Appends a new element to the string list.
|
||||||
|
*
|
||||||
|
* Returns: true (1) if successful, otherwise false (0).
|
||||||
|
**/
|
||||||
|
bool string_list_append(struct string_list *list, const char *elem,
|
||||||
|
union string_list_elem_attr attr)
|
||||||
|
{
|
||||||
|
char *data_dup = NULL;
|
||||||
|
|
||||||
|
if (list->size >= list->cap &&
|
||||||
|
!string_list_capacity(list, list->cap * 2))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
data_dup = strdup(elem);
|
||||||
|
if (!data_dup)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
list->elems[list->size].data = data_dup;
|
||||||
|
list->elems[list->size].attr = attr;
|
||||||
|
|
||||||
|
list->size++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_append_n:
|
||||||
|
* @list : pointer to string list
|
||||||
|
* @elem : element to add to the string list
|
||||||
|
* @length : read at most this many bytes from elem
|
||||||
|
* @attr : attributes of new element.
|
||||||
|
*
|
||||||
|
* Appends a new element to the string list.
|
||||||
|
*
|
||||||
|
* Returns: true (1) if successful, otherwise false (0).
|
||||||
|
**/
|
||||||
|
bool string_list_append_n(struct string_list *list, const char *elem,
|
||||||
|
unsigned length, union string_list_elem_attr attr)
|
||||||
|
{
|
||||||
|
char *data_dup = NULL;
|
||||||
|
|
||||||
|
if (list->size >= list->cap &&
|
||||||
|
!string_list_capacity(list, list->cap * 2))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
data_dup = (char*)malloc(length + 1);
|
||||||
|
|
||||||
|
if (!data_dup)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
strlcpy(data_dup, elem, length + 1);
|
||||||
|
|
||||||
|
list->elems[list->size].data = data_dup;
|
||||||
|
list->elems[list->size].attr = attr;
|
||||||
|
|
||||||
|
list->size++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_set:
|
||||||
|
* @list : pointer to string list
|
||||||
|
* @idx : index of element in string list
|
||||||
|
* @str : value for the element.
|
||||||
|
*
|
||||||
|
* Set value of element inside string list.
|
||||||
|
**/
|
||||||
|
void string_list_set(struct string_list *list,
|
||||||
|
unsigned idx, const char *str)
|
||||||
|
{
|
||||||
|
free(list->elems[idx].data);
|
||||||
|
list->elems[idx].data = strdup(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_join_concat:
|
||||||
|
* @buffer : buffer that @list will be joined to.
|
||||||
|
* @size : length of @buffer.
|
||||||
|
* @list : pointer to string list.
|
||||||
|
* @delim : delimiter character for @list.
|
||||||
|
*
|
||||||
|
* A string list will be joined/concatenated as a
|
||||||
|
* string to @buffer, delimited by @delim.
|
||||||
|
*/
|
||||||
|
void string_list_join_concat(char *buffer, size_t size,
|
||||||
|
const struct string_list *list, const char *delim)
|
||||||
|
{
|
||||||
|
size_t i, len = strlen(buffer);
|
||||||
|
|
||||||
|
buffer += len;
|
||||||
|
size -= len;
|
||||||
|
|
||||||
|
for (i = 0; i < list->size; i++)
|
||||||
|
{
|
||||||
|
strlcat(buffer, list->elems[i].data, size);
|
||||||
|
if ((i + 1) < list->size)
|
||||||
|
strlcat(buffer, delim, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_split:
|
||||||
|
* @str : string to turn into a string list
|
||||||
|
* @delim : delimiter character to use for splitting the string.
|
||||||
|
*
|
||||||
|
* Creates a new string list based on string @str, delimited by @delim.
|
||||||
|
*
|
||||||
|
* Returns: new string list if successful, otherwise NULL.
|
||||||
|
*/
|
||||||
|
struct string_list *string_split(const char *str, const char *delim)
|
||||||
|
{
|
||||||
|
char *save = NULL;
|
||||||
|
char *copy = NULL;
|
||||||
|
const char *tmp = NULL;
|
||||||
|
struct string_list *list = string_list_new();
|
||||||
|
|
||||||
|
if (!list)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
copy = strdup(str);
|
||||||
|
if (!copy)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
tmp = strtok_r(copy, delim, &save);
|
||||||
|
while (tmp)
|
||||||
|
{
|
||||||
|
union string_list_elem_attr attr;
|
||||||
|
|
||||||
|
attr.i = 0;
|
||||||
|
|
||||||
|
if (!string_list_append(list, tmp, attr))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
tmp = strtok_r(NULL, delim, &save);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(copy);
|
||||||
|
return list;
|
||||||
|
|
||||||
|
error:
|
||||||
|
string_list_free(list);
|
||||||
|
free(copy);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_find_elem:
|
||||||
|
* @list : pointer to string list
|
||||||
|
* @elem : element to find inside the string list.
|
||||||
|
*
|
||||||
|
* Searches for an element (@elem) inside the string list.
|
||||||
|
*
|
||||||
|
* Returns: true (1) if element could be found, otherwise false (0).
|
||||||
|
*/
|
||||||
|
int string_list_find_elem(const struct string_list *list, const char *elem)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!list)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (i = 0; i < list->size; i++)
|
||||||
|
{
|
||||||
|
if (string_is_equal_noncase(list->elems[i].data, elem))
|
||||||
|
return (int)(i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string_list_find_elem_prefix:
|
||||||
|
* @list : pointer to string list
|
||||||
|
* @prefix : prefix to append to @elem
|
||||||
|
* @elem : element to find inside the string list.
|
||||||
|
*
|
||||||
|
* Searches for an element (@elem) inside the string list. Will
|
||||||
|
* also search for the same element prefixed by @prefix.
|
||||||
|
*
|
||||||
|
* Returns: true (1) if element could be found, otherwise false (0).
|
||||||
|
*/
|
||||||
|
bool string_list_find_elem_prefix(const struct string_list *list,
|
||||||
|
const char *prefix, const char *elem)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
char prefixed[255];
|
||||||
|
|
||||||
|
if (!list)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
prefixed[0] = '\0';
|
||||||
|
|
||||||
|
strlcpy(prefixed, prefix, sizeof(prefixed));
|
||||||
|
strlcat(prefixed, elem, sizeof(prefixed));
|
||||||
|
|
||||||
|
for (i = 0; i < list->size; i++)
|
||||||
|
{
|
||||||
|
if (string_is_equal_noncase(list->elems[i].data, elem) ||
|
||||||
|
string_is_equal_noncase(list->elems[i].data, prefixed))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct string_list *string_list_clone(
|
||||||
|
const struct string_list *src)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
struct string_list_elem *elems = NULL;
|
||||||
|
struct string_list *dest = (struct string_list*)
|
||||||
|
calloc(1, sizeof(struct string_list));
|
||||||
|
|
||||||
|
if (!dest)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dest->size = src->size;
|
||||||
|
dest->cap = src->cap;
|
||||||
|
if (dest->cap < dest->size)
|
||||||
|
dest->cap = dest->size;
|
||||||
|
|
||||||
|
elems = (struct string_list_elem*)
|
||||||
|
calloc(dest->cap, sizeof(struct string_list_elem));
|
||||||
|
|
||||||
|
if (!elems)
|
||||||
|
{
|
||||||
|
free(dest);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest->elems = elems;
|
||||||
|
|
||||||
|
for (i = 0; i < src->size; i++)
|
||||||
|
{
|
||||||
|
const char *_src = src->elems[i].data;
|
||||||
|
size_t len = _src ? strlen(_src) : 0;
|
||||||
|
|
||||||
|
dest->elems[i].data = NULL;
|
||||||
|
dest->elems[i].attr = src->elems[i].attr;
|
||||||
|
|
||||||
|
if (len != 0)
|
||||||
|
{
|
||||||
|
char *result = (char*)malloc(len + 1);
|
||||||
|
strcpy(result, _src);
|
||||||
|
dest->elems[i].data = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
63
libretro-common/memmap/memalign.c
Normal file
63
libretro-common/memmap/memalign.c
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (memalign.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 <stdlib.h>
|
||||||
|
|
||||||
|
#include <memalign.h>
|
||||||
|
|
||||||
|
void *memalign_alloc(size_t boundary, size_t size)
|
||||||
|
{
|
||||||
|
void **place = NULL;
|
||||||
|
uintptr_t addr = 0;
|
||||||
|
void *ptr = (void*)malloc(boundary + size + sizeof(uintptr_t));
|
||||||
|
if (!ptr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
addr = ((uintptr_t)ptr + sizeof(uintptr_t) + boundary)
|
||||||
|
& ~(boundary - 1);
|
||||||
|
place = (void**)addr;
|
||||||
|
place[-1] = ptr;
|
||||||
|
|
||||||
|
return (void*)addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void memalign_free(void *ptr)
|
||||||
|
{
|
||||||
|
void **p = NULL;
|
||||||
|
if (!ptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
p = (void**)ptr;
|
||||||
|
free(p[-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memalign_alloc_aligned(size_t size)
|
||||||
|
{
|
||||||
|
#if defined(__x86_64__) || defined(__LP64) || defined(__IA64__) || defined(_M_X64) || defined(_M_X64) || defined(_WIN64)
|
||||||
|
return memalign_alloc(64, size);
|
||||||
|
#elif defined(__i386__) || defined(__i486__) || defined(__i686__) || defined(GEKKO) || defined(_M_IX86)
|
||||||
|
return memalign_alloc(32, size);
|
||||||
|
#else
|
||||||
|
return memalign_alloc(32, size);
|
||||||
|
#endif
|
||||||
|
}
|
@ -41,6 +41,7 @@ static retro_vfs_get_path_t filestream_get_path_cb = NULL;
|
|||||||
static retro_vfs_open_t filestream_open_cb = NULL;
|
static retro_vfs_open_t filestream_open_cb = NULL;
|
||||||
static retro_vfs_close_t filestream_close_cb = NULL;
|
static retro_vfs_close_t filestream_close_cb = NULL;
|
||||||
static retro_vfs_size_t filestream_size_cb = NULL;
|
static retro_vfs_size_t filestream_size_cb = NULL;
|
||||||
|
static retro_vfs_truncate_t filestream_truncate_cb = NULL;
|
||||||
static retro_vfs_tell_t filestream_tell_cb = NULL;
|
static retro_vfs_tell_t filestream_tell_cb = NULL;
|
||||||
static retro_vfs_seek_t filestream_seek_cb = NULL;
|
static retro_vfs_seek_t filestream_seek_cb = NULL;
|
||||||
static retro_vfs_read_t filestream_read_cb = NULL;
|
static retro_vfs_read_t filestream_read_cb = NULL;
|
||||||
@ -67,6 +68,7 @@ void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info)
|
|||||||
filestream_close_cb = NULL;
|
filestream_close_cb = NULL;
|
||||||
filestream_tell_cb = NULL;
|
filestream_tell_cb = NULL;
|
||||||
filestream_size_cb = NULL;
|
filestream_size_cb = NULL;
|
||||||
|
filestream_truncate_cb = NULL;
|
||||||
filestream_seek_cb = NULL;
|
filestream_seek_cb = NULL;
|
||||||
filestream_read_cb = NULL;
|
filestream_read_cb = NULL;
|
||||||
filestream_write_cb = NULL;
|
filestream_write_cb = NULL;
|
||||||
@ -84,6 +86,7 @@ void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info)
|
|||||||
filestream_open_cb = vfs_iface->open;
|
filestream_open_cb = vfs_iface->open;
|
||||||
filestream_close_cb = vfs_iface->close;
|
filestream_close_cb = vfs_iface->close;
|
||||||
filestream_size_cb = vfs_iface->size;
|
filestream_size_cb = vfs_iface->size;
|
||||||
|
filestream_truncate_cb = vfs_iface->truncate;
|
||||||
filestream_tell_cb = vfs_iface->tell;
|
filestream_tell_cb = vfs_iface->tell;
|
||||||
filestream_seek_cb = vfs_iface->seek;
|
filestream_seek_cb = vfs_iface->seek;
|
||||||
filestream_read_cb = vfs_iface->read;
|
filestream_read_cb = vfs_iface->read;
|
||||||
@ -127,6 +130,21 @@ int64_t filestream_get_size(RFILE *stream)
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t filestream_truncate(RFILE *stream, int64_t length)
|
||||||
|
{
|
||||||
|
int64_t output;
|
||||||
|
|
||||||
|
if (filestream_truncate_cb != NULL)
|
||||||
|
output = filestream_truncate_cb(stream->hfile, length);
|
||||||
|
else
|
||||||
|
output = retro_vfs_file_truncate_impl((libretro_vfs_implementation_file*)stream->hfile, length);
|
||||||
|
|
||||||
|
if (output == vfs_error_return_value)
|
||||||
|
stream->error_flag = true;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* filestream_open:
|
* filestream_open:
|
||||||
* @path : path to file
|
* @path : path to file
|
||||||
@ -186,9 +204,9 @@ int filestream_getc(RFILE *stream)
|
|||||||
{
|
{
|
||||||
char c = 0;
|
char c = 0;
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return 0;
|
return EOF;
|
||||||
if(filestream_read(stream, &c, 1) == 1)
|
if (filestream_read(stream, &c, 1) == 1)
|
||||||
return (int)c;
|
return (int)(unsigned char)c;
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,37 +215,40 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
|
|||||||
char buf[4096];
|
char buf[4096];
|
||||||
char subfmt[64];
|
char subfmt[64];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
const char * bufiter = buf;
|
const char * bufiter = buf;
|
||||||
int64_t startpos = filestream_tell(stream);
|
int64_t startpos = filestream_tell(stream);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int64_t maxlen = filestream_read(stream, buf, sizeof(buf)-1);
|
int64_t maxlen = filestream_read(stream, buf, sizeof(buf)-1);
|
||||||
|
|
||||||
|
if (maxlen <= 0)
|
||||||
|
return EOF;
|
||||||
|
|
||||||
buf[maxlen] = '\0';
|
buf[maxlen] = '\0';
|
||||||
|
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
|
|
||||||
while (*format)
|
while (*format)
|
||||||
{
|
{
|
||||||
if (*format == '%')
|
if (*format == '%')
|
||||||
{
|
{
|
||||||
int sublen;
|
int sublen;
|
||||||
|
|
||||||
char* subfmtiter = subfmt;
|
char* subfmtiter = subfmt;
|
||||||
bool asterisk = false;
|
bool asterisk = false;
|
||||||
|
|
||||||
*subfmtiter++ = *format++; /* '%' */
|
*subfmtiter++ = *format++; /* '%' */
|
||||||
|
|
||||||
/* %[*][width][length]specifier */
|
/* %[*][width][length]specifier */
|
||||||
|
|
||||||
if (*format == '*')
|
if (*format == '*')
|
||||||
{
|
{
|
||||||
asterisk = true;
|
asterisk = true;
|
||||||
*subfmtiter++ = *format++;
|
*subfmtiter++ = *format++;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (isdigit(*format)) *subfmtiter++ = *format++; /* width */
|
while (isdigit(*format)) *subfmtiter++ = *format++; /* width */
|
||||||
|
|
||||||
/* length */
|
/* length */
|
||||||
if (*format == 'h' || *format == 'l')
|
if (*format == 'h' || *format == 'l')
|
||||||
{
|
{
|
||||||
@ -238,7 +259,7 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
|
|||||||
{
|
{
|
||||||
*subfmtiter++ = *format++;
|
*subfmtiter++ = *format++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* specifier - always a single character (except ]) */
|
/* specifier - always a single character (except ]) */
|
||||||
if (*format == '[')
|
if (*format == '[')
|
||||||
{
|
{
|
||||||
@ -246,11 +267,11 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
|
|||||||
*subfmtiter++ = *format++;
|
*subfmtiter++ = *format++;
|
||||||
}
|
}
|
||||||
else *subfmtiter++ = *format++;
|
else *subfmtiter++ = *format++;
|
||||||
|
|
||||||
*subfmtiter++ = '%';
|
*subfmtiter++ = '%';
|
||||||
*subfmtiter++ = 'n';
|
*subfmtiter++ = 'n';
|
||||||
*subfmtiter++ = '\0';
|
*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 (asterisk)
|
||||||
{
|
{
|
||||||
@ -260,7 +281,7 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
|
|||||||
{
|
{
|
||||||
if (sscanf(bufiter, subfmt, va_arg(args, void*), &sublen) != 1) break;
|
if (sscanf(bufiter, subfmt, va_arg(args, void*), &sublen) != 1) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret++;
|
ret++;
|
||||||
bufiter += sublen;
|
bufiter += sublen;
|
||||||
}
|
}
|
||||||
@ -277,10 +298,10 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
|
|||||||
format++;
|
format++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
filestream_seek(stream, startpos+(bufiter-buf), RETRO_VFS_SEEK_POSITION_START);
|
filestream_seek(stream, startpos+(bufiter-buf), RETRO_VFS_SEEK_POSITION_START);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,7 +326,6 @@ int filestream_eof(RFILE *stream)
|
|||||||
return stream->eof_flag;
|
return stream->eof_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int64_t filestream_tell(RFILE *stream)
|
int64_t filestream_tell(RFILE *stream)
|
||||||
{
|
{
|
||||||
int64_t output;
|
int64_t output;
|
||||||
@ -407,7 +427,7 @@ int filestream_putc(RFILE *stream, int c)
|
|||||||
char c_char = (char)c;
|
char c_char = (char)c;
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return EOF;
|
return EOF;
|
||||||
return filestream_write(stream, &c_char, 1)==1 ? 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)
|
int filestream_vprintf(RFILE *stream, const char* format, va_list args)
|
||||||
@ -592,3 +612,8 @@ char *filestream_getline(RFILE *stream)
|
|||||||
newline[idx] = '\0';
|
newline[idx] = '\0';
|
||||||
return newline;
|
return newline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream)
|
||||||
|
{
|
||||||
|
return (libretro_vfs_implementation_file*)stream->hfile;
|
||||||
|
}
|
||||||
|
@ -37,7 +37,7 @@ RFILE* rfopen(const char *path, const char *mode)
|
|||||||
retro_mode = RETRO_VFS_FILE_ACCESS_READ;
|
retro_mode = RETRO_VFS_FILE_ACCESS_READ;
|
||||||
if (strstr(mode, "+"))
|
if (strstr(mode, "+"))
|
||||||
{
|
{
|
||||||
retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE |
|
retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE |
|
||||||
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
|
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,12 +49,12 @@ RFILE* rfopen(const char *path, const char *mode)
|
|||||||
}
|
}
|
||||||
else if (strstr(mode, "a"))
|
else if (strstr(mode, "a"))
|
||||||
{
|
{
|
||||||
retro_mode = RETRO_VFS_FILE_ACCESS_WRITE |
|
retro_mode = RETRO_VFS_FILE_ACCESS_WRITE |
|
||||||
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
|
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
|
||||||
position_to_end = true;
|
position_to_end = true;
|
||||||
if (strstr(mode, "+"))
|
if (strstr(mode, "+"))
|
||||||
{
|
{
|
||||||
retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE |
|
retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE |
|
||||||
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
|
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ int64_t rfseek(RFILE* stream, int64_t offset, int origin)
|
|||||||
int64_t rfread(void* buffer,
|
int64_t rfread(void* buffer,
|
||||||
size_t elem_size, size_t elem_count, RFILE* stream)
|
size_t elem_size, size_t elem_count, RFILE* stream)
|
||||||
{
|
{
|
||||||
return filestream_read(stream, buffer, elem_size * elem_count);
|
return (filestream_read(stream, buffer, elem_size * elem_count) / elem_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *rfgets(char *buffer, int maxCount, RFILE* stream)
|
char *rfgets(char *buffer, int maxCount, RFILE* stream)
|
||||||
@ -109,7 +109,7 @@ char *rfgets(char *buffer, int maxCount, RFILE* stream)
|
|||||||
|
|
||||||
int rfgetc(RFILE* stream)
|
int rfgetc(RFILE* stream)
|
||||||
{
|
{
|
||||||
return filestream_getc(stream);
|
return filestream_getc(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t rfwrite(void const* buffer,
|
int64_t rfwrite(void const* buffer,
|
||||||
@ -123,14 +123,19 @@ int rfputc(int character, RFILE * stream)
|
|||||||
return filestream_putc(stream, character);
|
return filestream_putc(stream, character);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t rfflush(RFILE * stream)
|
||||||
|
{
|
||||||
|
return filestream_flush(stream);
|
||||||
|
}
|
||||||
|
|
||||||
int rfprintf(RFILE * stream, const char * format, ...)
|
int rfprintf(RFILE * stream, const char * format, ...)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
va_list vl;
|
va_list vl;
|
||||||
va_start(vl, format);
|
va_start(vl, format);
|
||||||
result = filestream_vprintf(stream, format, vl);
|
result = filestream_vprintf(stream, format, vl);
|
||||||
va_end(vl);
|
va_end(vl);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rferror(RFILE* stream)
|
int rferror(RFILE* stream)
|
||||||
@ -142,3 +147,13 @@ int rfeof(RFILE* stream)
|
|||||||
{
|
{
|
||||||
return filestream_eof(stream);
|
return filestream_eof(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rfscanf(RFILE * stream, const char * format, ...)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
va_list vl;
|
||||||
|
va_start(vl, format);
|
||||||
|
result = filestream_scanf(stream, format, vl);
|
||||||
|
va_end(vl);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -82,6 +82,10 @@ char *string_replace_substring(const char *in,
|
|||||||
|
|
||||||
outlen = strlen(in) - pattern_len*numhits + replacement_len*numhits;
|
outlen = strlen(in) - pattern_len*numhits + replacement_len*numhits;
|
||||||
out = (char *)malloc(outlen+1);
|
out = (char *)malloc(outlen+1);
|
||||||
|
|
||||||
|
if (!out)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
outat = out;
|
outat = out;
|
||||||
inat = in;
|
inat = in;
|
||||||
inprev = in;
|
inprev = in;
|
||||||
@ -105,18 +109,17 @@ char *string_trim_whitespace_left(char *const s)
|
|||||||
{
|
{
|
||||||
if(s && *s)
|
if(s && *s)
|
||||||
{
|
{
|
||||||
size_t len = strlen(s);
|
size_t len = strlen(s);
|
||||||
char *cur = s;
|
char *current = s;
|
||||||
|
|
||||||
while(*cur && isspace((unsigned char)*cur))
|
while(*current && isspace((unsigned char)*current))
|
||||||
{
|
{
|
||||||
++cur;
|
++current;
|
||||||
--len;
|
--len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(s != cur)
|
if(s != current)
|
||||||
memmove(s, cur, len + 1);
|
memmove(s, current, len + 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
@ -127,16 +130,16 @@ char *string_trim_whitespace_right(char *const s)
|
|||||||
{
|
{
|
||||||
if(s && *s)
|
if(s && *s)
|
||||||
{
|
{
|
||||||
size_t len = strlen(s);
|
size_t len = strlen(s);
|
||||||
char *cur = s + len - 1;
|
char *current = s + len - 1;
|
||||||
|
|
||||||
while(cur != s && isspace((unsigned char)*cur))
|
while(current != s && isspace((unsigned char)*current))
|
||||||
{
|
{
|
||||||
--cur;
|
--current;
|
||||||
--len;
|
--len;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur[isspace((unsigned char)*cur) ? 0 : 1] = '\0';
|
current[isspace((unsigned char)*current) ? 0 : 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
@ -151,14 +154,16 @@ char *string_trim_whitespace(char *const s)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *word_wrap(char* buffer, const char *string, int line_width, bool unicode)
|
char *word_wrap(char* buffer, const char *string, int line_width, bool unicode, unsigned max_lines)
|
||||||
{
|
{
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
unsigned len = (unsigned)strlen(string);
|
unsigned len = (unsigned)strlen(string);
|
||||||
|
unsigned lines = 1;
|
||||||
|
|
||||||
while (i < len)
|
while (i < len)
|
||||||
{
|
{
|
||||||
unsigned counter;
|
unsigned counter;
|
||||||
|
int pos = (int)(&buffer[i] - buffer);
|
||||||
|
|
||||||
/* copy string until the end of the line is reached */
|
/* copy string until the end of the line is reached */
|
||||||
for (counter = 1; counter <= (unsigned)line_width; counter++)
|
for (counter = 1; counter <= (unsigned)line_width; counter++)
|
||||||
@ -190,14 +195,21 @@ char *word_wrap(char* buffer, const char *string, int line_width, bool unicode)
|
|||||||
/* check for newlines embedded in the original input
|
/* check for newlines embedded in the original input
|
||||||
* and reset the index */
|
* and reset the index */
|
||||||
if (buffer[j] == '\n')
|
if (buffer[j] == '\n')
|
||||||
|
{
|
||||||
|
lines++;
|
||||||
counter = 1;
|
counter = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for whitespace */
|
/* check for whitespace */
|
||||||
if (string[i] == ' ')
|
if (string[i] == ' ')
|
||||||
{
|
{
|
||||||
buffer[i] = '\n';
|
if ((max_lines == 0 || lines < max_lines))
|
||||||
i++;
|
{
|
||||||
|
buffer[i] = '\n';
|
||||||
|
i++;
|
||||||
|
lines++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -206,14 +218,18 @@ char *word_wrap(char* buffer, const char *string, int line_width, bool unicode)
|
|||||||
/* check for nearest whitespace back in string */
|
/* check for nearest whitespace back in string */
|
||||||
for (k = i; k > 0; k--)
|
for (k = i; k > 0; k--)
|
||||||
{
|
{
|
||||||
if (string[k] != ' ')
|
if (string[k] != ' ' || (max_lines != 0 && lines >= max_lines))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
buffer[k] = '\n';
|
buffer[k] = '\n';
|
||||||
/* set string index back to character after this one */
|
/* set string index back to character after this one */
|
||||||
i = k + 1;
|
i = k + 1;
|
||||||
|
lines++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (&buffer[i] - buffer == pos)
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
423
libretro-common/vfs/vfs_implementation_cdrom.c
Normal file
423
libretro-common/vfs/vfs_implementation_cdrom.c
Normal file
@ -0,0 +1,423 @@
|
|||||||
|
/* Copyright (C) 2010-2019 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (vfs_implementation_cdrom.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 <vfs/vfs_implementation.h>
|
||||||
|
#include <file/file_path.h>
|
||||||
|
#include <compat/fopen_utf8.h>
|
||||||
|
#include <string/stdstring.h>
|
||||||
|
#include <cdrom/cdrom.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(_XBOX)
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static cdrom_toc_t vfs_cdrom_toc = {0};
|
||||||
|
|
||||||
|
const cdrom_toc_t* retro_vfs_file_get_cdrom_toc(void)
|
||||||
|
{
|
||||||
|
return &vfs_cdrom_toc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t retro_vfs_file_seek_cdrom(libretro_vfs_implementation_file *stream, int64_t offset, int whence)
|
||||||
|
{
|
||||||
|
const char *ext = path_get_extension(stream->orig_path);
|
||||||
|
|
||||||
|
if (string_is_equal_noncase(ext, "cue"))
|
||||||
|
{
|
||||||
|
switch (whence)
|
||||||
|
{
|
||||||
|
case SEEK_SET:
|
||||||
|
stream->cdrom.byte_pos = offset;
|
||||||
|
break;
|
||||||
|
case SEEK_CUR:
|
||||||
|
stream->cdrom.byte_pos += offset;
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
stream->cdrom.byte_pos = (stream->cdrom.cue_len - 1) + offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] Seek: Path %s Offset %" PRIu64 " is now at %" PRIu64 "\n", stream->orig_path, offset, stream->cdrom.byte_pos);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (string_is_equal_noncase(ext, "bin"))
|
||||||
|
{
|
||||||
|
int lba = (offset / 2352);
|
||||||
|
unsigned char min = 0;
|
||||||
|
unsigned char sec = 0;
|
||||||
|
unsigned char frame = 0;
|
||||||
|
const char *seek_type = "SEEK_SET";
|
||||||
|
|
||||||
|
(void)seek_type;
|
||||||
|
|
||||||
|
switch (whence)
|
||||||
|
{
|
||||||
|
case SEEK_CUR:
|
||||||
|
{
|
||||||
|
unsigned new_lba;
|
||||||
|
|
||||||
|
stream->cdrom.byte_pos += offset;
|
||||||
|
new_lba = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352);
|
||||||
|
seek_type = "SEEK_CUR";
|
||||||
|
|
||||||
|
cdrom_lba_to_msf(new_lba, &min, &sec, &frame);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SEEK_END:
|
||||||
|
{
|
||||||
|
ssize_t pregap_lba_len = (vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].audio ? 0 : (vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba_start));
|
||||||
|
ssize_t lba_len = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_size - pregap_lba_len;
|
||||||
|
|
||||||
|
cdrom_lba_to_msf(lba_len + lba, &min, &sec, &frame);
|
||||||
|
|
||||||
|
stream->cdrom.byte_pos = lba_len * 2352;
|
||||||
|
seek_type = "SEEK_END";
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SEEK_SET:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
seek_type = "SEEK_SET";
|
||||||
|
stream->cdrom.byte_pos = offset;
|
||||||
|
cdrom_lba_to_msf(vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352), &min, &sec, &frame);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->cdrom.cur_min = min;
|
||||||
|
stream->cdrom.cur_sec = sec;
|
||||||
|
stream->cdrom.cur_frame = frame;
|
||||||
|
stream->cdrom.cur_lba = cdrom_msf_to_lba(min, sec, frame);
|
||||||
|
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] Seek %s: Path %s Offset %" PRIu64 " is now at %" PRIu64 " (MSF %02u:%02u:%02u) (LBA %u)...\n", seek_type, stream->orig_path, offset, stream->cdrom.byte_pos, (unsigned)stream->cdrom.cur_min, (unsigned)stream->cdrom.cur_sec, (unsigned)stream->cdrom.cur_frame, stream->cdrom.cur_lba);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void retro_vfs_file_open_cdrom(
|
||||||
|
libretro_vfs_implementation_file *stream,
|
||||||
|
const char *path, unsigned mode, unsigned hints)
|
||||||
|
{
|
||||||
|
#if defined(__linux__) && !defined(ANDROID)
|
||||||
|
char cdrom_path[] = "/dev/sg1";
|
||||||
|
size_t path_len = strlen(path);
|
||||||
|
const char *ext = path_get_extension(path);
|
||||||
|
|
||||||
|
stream->cdrom.cur_track = 1;
|
||||||
|
|
||||||
|
if (!string_is_equal_noncase(ext, "cue") && !string_is_equal_noncase(ext, "bin"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (path_len >= strlen("drive1-track01.bin"))
|
||||||
|
{
|
||||||
|
if (!memcmp(path, "drive", strlen("drive")))
|
||||||
|
{
|
||||||
|
if (!memcmp(path + 6, "-track", strlen("-track")))
|
||||||
|
{
|
||||||
|
if (sscanf(path + 12, "%02u", (unsigned*)&stream->cdrom.cur_track))
|
||||||
|
{
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] Opening track %d\n", stream->cdrom.cur_track);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path_len >= strlen("drive1.cue"))
|
||||||
|
{
|
||||||
|
if (!memcmp(path, "drive", strlen("drive")))
|
||||||
|
{
|
||||||
|
if (path[5] >= '0' && path[5] <= '9')
|
||||||
|
{
|
||||||
|
cdrom_path[7] = path[5];
|
||||||
|
stream->cdrom.drive = path[5];
|
||||||
|
vfs_cdrom_toc.drive = stream->cdrom.drive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] Open: Path %s URI %s\n", cdrom_path, path);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
stream->fp = (FILE*)fopen_utf8(cdrom_path, "r+b");
|
||||||
|
|
||||||
|
if (!stream->fp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (string_is_equal_noncase(ext, "cue"))
|
||||||
|
{
|
||||||
|
if (stream->cdrom.cue_buf)
|
||||||
|
{
|
||||||
|
free(stream->cdrom.cue_buf);
|
||||||
|
stream->cdrom.cue_buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cdrom_write_cue(stream, &stream->cdrom.cue_buf, &stream->cdrom.cue_len, stream->cdrom.drive, &vfs_cdrom_toc.num_tracks, &vfs_cdrom_toc);
|
||||||
|
cdrom_get_timeouts(stream, &vfs_cdrom_toc.timeouts);
|
||||||
|
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
if (string_is_empty(stream->cdrom.cue_buf))
|
||||||
|
{
|
||||||
|
printf("[CDROM] Error writing cue sheet.\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("[CDROM] CUE Sheet:\n%s\n", stream->cdrom.cue_buf);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(_WIN32) && !defined(_XBOX)
|
||||||
|
char cdrom_path[] = "\\\\.\\D:";
|
||||||
|
size_t path_len = strlen(path);
|
||||||
|
const char *ext = path_get_extension(path);
|
||||||
|
|
||||||
|
if (!string_is_equal_noncase(ext, "cue") && !string_is_equal_noncase(ext, "bin"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (path_len >= strlen("d:/drive-track01.bin"))
|
||||||
|
{
|
||||||
|
if (!memcmp(path + 1, ":/drive-track", strlen(":/drive-track")))
|
||||||
|
{
|
||||||
|
if (sscanf(path + 14, "%02u", (unsigned*)&stream->cdrom.cur_track))
|
||||||
|
{
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] Opening track %d\n", stream->cdrom.cur_track);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path_len >= strlen("d:/drive.cue"))
|
||||||
|
{
|
||||||
|
if (!memcmp(path + 1, ":/drive", strlen(":/drive")))
|
||||||
|
{
|
||||||
|
if ((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z'))
|
||||||
|
{
|
||||||
|
cdrom_path[4] = path[0];
|
||||||
|
stream->cdrom.drive = path[0];
|
||||||
|
vfs_cdrom_toc.drive = stream->cdrom.drive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] Open: Path %s URI %s\n", cdrom_path, path);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
stream->fh = CreateFile(cdrom_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
|
||||||
|
if (stream->fh == INVALID_HANDLE_VALUE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (string_is_equal_noncase(ext, "cue"))
|
||||||
|
{
|
||||||
|
if (stream->cdrom.cue_buf)
|
||||||
|
{
|
||||||
|
free(stream->cdrom.cue_buf);
|
||||||
|
stream->cdrom.cue_buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cdrom_write_cue(stream, &stream->cdrom.cue_buf, &stream->cdrom.cue_len, stream->cdrom.drive, &vfs_cdrom_toc.num_tracks, &vfs_cdrom_toc);
|
||||||
|
cdrom_get_timeouts(stream, &vfs_cdrom_toc.timeouts);
|
||||||
|
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
if (string_is_empty(stream->cdrom.cue_buf))
|
||||||
|
{
|
||||||
|
printf("[CDROM] Error writing cue sheet.\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("[CDROM] CUE Sheet:\n%s\n", stream->cdrom.cue_buf);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (vfs_cdrom_toc.num_tracks > 1 && stream->cdrom.cur_track)
|
||||||
|
{
|
||||||
|
stream->cdrom.cur_min = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].min;
|
||||||
|
stream->cdrom.cur_sec = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].sec;
|
||||||
|
stream->cdrom.cur_frame = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].frame;
|
||||||
|
stream->cdrom.cur_lba = cdrom_msf_to_lba(stream->cdrom.cur_min, stream->cdrom.cur_sec, stream->cdrom.cur_frame);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stream->cdrom.cur_min = vfs_cdrom_toc.track[0].min;
|
||||||
|
stream->cdrom.cur_sec = vfs_cdrom_toc.track[0].sec;
|
||||||
|
stream->cdrom.cur_frame = vfs_cdrom_toc.track[0].frame;
|
||||||
|
stream->cdrom.cur_lba = cdrom_msf_to_lba(stream->cdrom.cur_min, stream->cdrom.cur_sec, stream->cdrom.cur_frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int retro_vfs_file_close_cdrom(libretro_vfs_implementation_file *stream)
|
||||||
|
{
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] Close: Path %s\n", stream->orig_path);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(_XBOX)
|
||||||
|
if (!stream->fh || !CloseHandle(stream->fh))
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
|
if (!stream->fp || fclose(stream->fp))
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t retro_vfs_file_tell_cdrom(libretro_vfs_implementation_file *stream)
|
||||||
|
{
|
||||||
|
const char *ext = NULL;
|
||||||
|
if (!stream)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ext = path_get_extension(stream->orig_path);
|
||||||
|
|
||||||
|
if (string_is_equal_noncase(ext, "cue"))
|
||||||
|
{
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] (cue) Tell: Path %s Position %" PRIu64 "\n", stream->orig_path, stream->cdrom.byte_pos);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
return stream->cdrom.byte_pos;
|
||||||
|
}
|
||||||
|
else if (string_is_equal_noncase(ext, "bin"))
|
||||||
|
{
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] (bin) Tell: Path %s Position %" PRId64 "\n", stream->orig_path, stream->cdrom.byte_pos);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
return stream->cdrom.byte_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
|
||||||
|
void *s, uint64_t len)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
const char *ext = path_get_extension(stream->orig_path);
|
||||||
|
|
||||||
|
if (string_is_equal_noncase(ext, "cue"))
|
||||||
|
{
|
||||||
|
if ((int64_t)len < (int64_t)stream->cdrom.cue_len - stream->cdrom.byte_pos)
|
||||||
|
{
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] Read: Reading %" PRIu64 " bytes from cuesheet starting at %" PRIu64 "...\n", len, stream->cdrom.byte_pos);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
memcpy(s, stream->cdrom.cue_buf + stream->cdrom.byte_pos, len);
|
||||||
|
stream->cdrom.byte_pos += len;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] Read: Reading %" PRIu64 " bytes from cuesheet starting at %" PRIu64 " failed.\n", len, stream->cdrom.byte_pos);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (string_is_equal_noncase(ext, "bin"))
|
||||||
|
{
|
||||||
|
size_t skip = stream->cdrom.byte_pos % 2352;
|
||||||
|
unsigned char min = 0;
|
||||||
|
unsigned char sec = 0;
|
||||||
|
unsigned char frame = 0;
|
||||||
|
unsigned char rmin = 0;
|
||||||
|
unsigned char rsec = 0;
|
||||||
|
unsigned char rframe = 0;
|
||||||
|
|
||||||
|
if (stream->cdrom.byte_pos >= vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (stream->cdrom.byte_pos + len > vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes)
|
||||||
|
len -= (stream->cdrom.byte_pos + len) - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes;
|
||||||
|
|
||||||
|
cdrom_lba_to_msf(stream->cdrom.cur_lba, &min, &sec, &frame);
|
||||||
|
cdrom_lba_to_msf(stream->cdrom.cur_lba - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba, &rmin, &rsec, &rframe);
|
||||||
|
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] Read: Reading %" PRIu64 " bytes from %s starting at byte offset %" PRIu64 " (rMSF %02u:%02u:%02u aMSF %02u:%02u:%02u) (LBA %u) skip %" PRIu64 "...\n", len, stream->orig_path, stream->cdrom.byte_pos, (unsigned)rmin, (unsigned)rsec, (unsigned)rframe, (unsigned)min, (unsigned)sec, (unsigned)frame, stream->cdrom.cur_lba, skip);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rv = cdrom_read(stream, &vfs_cdrom_toc.timeouts, min, sec, frame, s, (size_t)len, skip);
|
||||||
|
/*rv = cdrom_read_lba(stream, stream->cdrom.cur_lba, s, (size_t)len, skip);*/
|
||||||
|
|
||||||
|
if (rv)
|
||||||
|
{
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] Failed to read %" PRIu64 " bytes from CD.\n", len);
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->cdrom.byte_pos += len;
|
||||||
|
stream->cdrom.cur_lba = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352);
|
||||||
|
|
||||||
|
cdrom_lba_to_msf(stream->cdrom.cur_lba, &stream->cdrom.cur_min, &stream->cdrom.cur_sec, &stream->cdrom.cur_frame);
|
||||||
|
|
||||||
|
#ifdef CDROM_DEBUG
|
||||||
|
printf("[CDROM] read %" PRIu64 " bytes, position is now: %" PRIu64 " (MSF %02u:%02u:%02u) (LBA %u)\n", len, stream->cdrom.byte_pos, (unsigned)stream->cdrom.cur_min, (unsigned)stream->cdrom.cur_sec, (unsigned)stream->cdrom.cur_frame, cdrom_msf_to_lba(stream->cdrom.cur_min, stream->cdrom.cur_sec, stream->cdrom.cur_frame));
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int retro_vfs_file_error_cdrom(libretro_vfs_implementation_file *stream)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vfs_cdrom_t* retro_vfs_file_get_cdrom_position(const libretro_vfs_implementation_file *stream)
|
||||||
|
{
|
||||||
|
return &stream->cdrom;
|
||||||
|
}
|
@ -670,7 +670,13 @@ bool CDAccess_Image::ImageOpen(const std::string& path, bool image_memcache)
|
|||||||
active_track = -1;
|
active_track = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string efn = MDFN_EvalFIP(base_dir, args[0]);
|
std::string efn;
|
||||||
|
|
||||||
|
if(args[0].find("cdrom://") == std::string::npos)
|
||||||
|
efn = MDFN_EvalFIP(base_dir, args[0]);
|
||||||
|
else
|
||||||
|
efn = args[0];
|
||||||
|
|
||||||
TmpTrack.fp = new FileStream(efn.c_str(), MODE_READ);
|
TmpTrack.fp = new FileStream(efn.c_str(), MODE_READ);
|
||||||
TmpTrack.FirstFileInstance = 1;
|
TmpTrack.FirstFileInstance = 1;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user