mirror of
https://github.com/libretro/beetle-pce-libretro.git
synced 2024-11-23 08:09:43 +00:00
initial cdrom support
This commit is contained in:
parent
ef3ecc7612
commit
2d050ee501
26
Makefile
26
Makefile
@ -14,15 +14,15 @@ unixcygpath = /$(subst :,,$(call unixpath,$1))
|
||||
|
||||
ifeq ($(platform),)
|
||||
platform = unix
|
||||
ifeq ($(shell uname -a),)
|
||||
ifeq ($(shell uname -s),)
|
||||
platform = win
|
||||
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
||||
else ifneq ($(findstring Darwin,$(shell uname -s)),)
|
||||
platform = osx
|
||||
arch = intel
|
||||
ifeq ($(shell uname -p),powerpc)
|
||||
arch = ppc
|
||||
endif
|
||||
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
||||
else ifneq ($(findstring MINGW,$(shell uname -s)),)
|
||||
platform = win
|
||||
endif
|
||||
else ifneq (,$(findstring armv,$(platform)))
|
||||
@ -46,6 +46,7 @@ NEED_CRC32 = 1
|
||||
WANT_NEW_API = 1
|
||||
CORE_DEFINE := -DWANT_PCE_EMU -DWANT_STEREO_SOUND
|
||||
HAVE_CHD = 1
|
||||
HAVE_CDROM = 0
|
||||
|
||||
prefix := /usr
|
||||
libdir := $(prefix)/lib
|
||||
@ -75,6 +76,10 @@ ifneq (,$(findstring unix,$(platform)))
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
ifneq ($(findstring Linux,$(shell uname -s)),)
|
||||
HAVE_CDROM = 1
|
||||
endif
|
||||
|
||||
# Raspberry Pi
|
||||
ifneq (,$(findstring rpi,$(platform)))
|
||||
FLAGS += -fomit-frame-pointer -ffast-math
|
||||
@ -356,6 +361,8 @@ else ifneq (,$(findstring windows_msvc2017,$(platform)))
|
||||
VCCompilerToolsBinDir := $(VcCompilerToolsDir)\bin\HostX86
|
||||
endif
|
||||
|
||||
HAVE_CDROM = 1
|
||||
|
||||
PATH := $(shell IFS=$$'\n'; cygpath "$(VCCompilerToolsBinDir)/$(TargetArchMoniker)"):$(PATH)
|
||||
PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VsInstallRoot)/Common7/IDE")
|
||||
INCLUDE := $(shell IFS=$$'\n'; cygpath -w "$(VcCompilerToolsDir)/include")
|
||||
@ -387,6 +394,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.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include
|
||||
|
||||
HAVE_CDROM = 1
|
||||
|
||||
INCFLAGS_PLATFORM = -I"$(WindowsSdkDirInc)"
|
||||
export INCLUDE := $(INCLUDE)
|
||||
@ -412,6 +420,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.1A" -v "InstallationFolder" | grep -o '[A-Z]:\\.*')Include
|
||||
|
||||
HAVE_CDROM = 1
|
||||
|
||||
INCFLAGS_PLATFORM = -I"$(WindowsSdkDirInc)"
|
||||
export INCLUDE := $(INCLUDE)
|
||||
@ -434,6 +443,8 @@ BIN := $(shell IFS=$$'\n'; cygpath "$(VS80COMNTOOLS)../../VC/bin")
|
||||
|
||||
WindowsSdkDir := $(INETSDK)
|
||||
|
||||
HAVE_CDROM = 1
|
||||
|
||||
export INCLUDE := $(INCLUDE);$(INETSDK)/Include;libretro-common/include/compat/msvc
|
||||
export LIB := $(LIB);$(WindowsSdkDir);$(INETSDK)/Lib
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
@ -464,6 +475,7 @@ else ifeq ($(platform), windows_msvc2003_x86)
|
||||
CC = cl.exe
|
||||
CXX = cl.exe
|
||||
|
||||
HAVE_CDROM = 1
|
||||
PATH := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/bin"):$(PATH)
|
||||
PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../IDE")
|
||||
INCLUDE := $(shell IFS=$$'\n'; cygpath "$(VS71COMNTOOLS)../../Vc7/include")
|
||||
@ -487,6 +499,7 @@ else
|
||||
CXX = g++
|
||||
SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T
|
||||
LDFLAGS += -static-libgcc -static-libstdc++ -lwinmm
|
||||
HAVE_CDROM = 1
|
||||
WINDOWS_VERSION=1
|
||||
|
||||
endif
|
||||
@ -549,6 +562,13 @@ ifeq ($(WANT_NEW_API), 1)
|
||||
FLAGS += -DWANT_NEW_API
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_CDROM), 1)
|
||||
FLAGS += -DHAVE_CDROM
|
||||
ifeq ($(CDROM_DEBUG), 1)
|
||||
FLAGS += -DCDROM_DEBUG
|
||||
endif
|
||||
endif
|
||||
|
||||
CXXFLAGS += $(FLAGS)
|
||||
CFLAGS += $(FLAGS)
|
||||
|
||||
|
@ -20,6 +20,12 @@ ifneq (,$(findstring msvc2003,$(platform)))
|
||||
INCFLAGS += -I$(LIBRETRO_COMM_DIR)/include/compat/msvc
|
||||
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)
|
||||
SOURCES_CXX += \
|
||||
$(CORE_DIR)/libretro.cpp \
|
||||
@ -209,6 +215,10 @@ ifneq ($(STATIC_LINKING), 1)
|
||||
SOURCES_C += \
|
||||
$(LIBRETRO_COMM_DIR)/streams/file_stream.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_snprintf.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/compat_posix_string.c \
|
||||
@ -217,5 +227,6 @@ SOURCES_C += \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_crc32.c \
|
||||
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c \
|
||||
$(LIBRETRO_COMM_DIR)/memmap/memalign.c \
|
||||
$(LIBRETRO_COMM_DIR)/string/stdstring.c
|
||||
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 */
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#include <retro_common.h>
|
||||
#if _MSC_VER >= 1800
|
||||
#include <stdio.h> /* added for _vsnprintf_s and _vscprintf on VS2015 and VS2017 */
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#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;
|
||||
|
||||
if (size != 0)
|
||||
{
|
||||
#if (_MSC_VER <= 1310)
|
||||
count = _vsnprintf(outBuf, size - 1, format, ap);
|
||||
count = _vsnprintf(outBuf, size - 1, format, ap);
|
||||
#else
|
||||
count = _vsnprintf_s(outBuf, size, size - 1, format, ap);
|
||||
count = _vsnprintf_s(outBuf, size, size - 1, format, ap);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (count == -1)
|
||||
count = _vscprintf(format, ap);
|
||||
|
||||
|
@ -36,9 +36,7 @@
|
||||
|
||||
void *fopen_utf8(const char * filename, const char * mode)
|
||||
{
|
||||
#if defined(_XBOX)
|
||||
return fopen(filename, mode);
|
||||
#elif defined(LEGACY_WIN32)
|
||||
#if defined(LEGACY_WIN32)
|
||||
FILE *ret = NULL;
|
||||
char * filename_local = utf8_to_local_string_alloc(filename);
|
||||
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <encodings/crc32.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static const uint32_t crc32_table[256] = {
|
||||
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;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
static uint8_t utf8_walkbyte(const char **string)
|
||||
{
|
||||
return *((*string)++);
|
||||
}
|
||||
#define utf8_walkbyte(string) (*((*(string))++))
|
||||
|
||||
/* Does not validate the input, returns garbage if it's not UTF-8. */
|
||||
uint32_t utf8_walk(const char **string)
|
||||
@ -227,14 +224,16 @@ uint32_t utf8_walk(const char **string)
|
||||
|
||||
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
||||
if (first >= 0xE0)
|
||||
{
|
||||
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
||||
if (first >= 0xF0)
|
||||
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
||||
|
||||
if (first >= 0xF0)
|
||||
return ret | (first & 7) << 18;
|
||||
if (first >= 0xE0)
|
||||
if (first >= 0xF0)
|
||||
{
|
||||
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
||||
return ret | (first & 7) << 18;
|
||||
}
|
||||
return ret | (first & 15) << 12;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
|
||||
/* 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)
|
||||
{
|
||||
char *path_buf = NULL;
|
||||
wchar_t *path_buf_wide = NULL;
|
||||
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)
|
||||
return NULL;
|
||||
|
||||
(void)path_buf;
|
||||
(void)path_buf_wide;
|
||||
(void)path_buf_len;
|
||||
(void)path_buf_wide_len;
|
||||
|
||||
#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.
|
||||
/* 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)
|
||||
{
|
||||
@ -355,20 +342,37 @@ static char* mb_to_mb_string_alloc(const char *str,
|
||||
free(path_buf_wide);
|
||||
|
||||
return NULL;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||
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. */
|
||||
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. */
|
||||
@ -447,52 +451,44 @@ wchar_t* utf8_to_utf16_string_alloc(const char *str)
|
||||
char* utf16_to_utf8_string_alloc(const wchar_t *str)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int len = 0;
|
||||
int out_len = 0;
|
||||
int len = 0;
|
||||
#else
|
||||
size_t len = 0;
|
||||
size_t out_len = 0;
|
||||
size_t len = 0;
|
||||
#endif
|
||||
char *buf = NULL;
|
||||
char *buf = NULL;
|
||||
|
||||
if (!str || !*str)
|
||||
return NULL;
|
||||
|
||||
#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));
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
out_len = WideCharToMultiByte(CP_UTF8, 0, str, -1, buf, len, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fallback to ANSI codepage instead */
|
||||
len = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
|
||||
|
||||
if (len)
|
||||
if (WideCharToMultiByte(code_page,
|
||||
0, str, -1, buf, len, NULL, NULL) < 0)
|
||||
{
|
||||
buf = (char*)calloc(len, sizeof(char));
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
out_len = WideCharToMultiByte(CP_ACP, 0, str, -1, buf, len, NULL, NULL);
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_len < 0)
|
||||
{
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
#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;
|
||||
|
||||
if (len)
|
||||
@ -502,13 +498,11 @@ char* utf16_to_utf8_string_alloc(const wchar_t *str)
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
out_len = wcstombs(buf, str, len);
|
||||
}
|
||||
|
||||
if (out_len == (size_t)-1)
|
||||
{
|
||||
free(buf);
|
||||
return NULL;
|
||||
if (wcstombs(buf, str, len) == (size_t)-1)
|
||||
{
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#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 */
|
||||
#endif
|
||||
|
||||
|
@ -41,7 +41,7 @@ RETRO_BEGIN_DECLS
|
||||
/* Count Leading Zero, unsigned 16bit input value */
|
||||
static INLINE unsigned compat_clz_u16(uint16_t val)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(PS2)
|
||||
return __builtin_clz(val << 16 | 0x8000);
|
||||
#else
|
||||
unsigned ret = 0;
|
||||
@ -61,7 +61,7 @@ static INLINE int compat_ctz(unsigned x)
|
||||
{
|
||||
#if defined(__GNUC__) && !defined(RARCH_CONSOLE)
|
||||
return __builtin_ctz(x);
|
||||
#elif _MSC_VER >= 1400 && !defined(_XBOX)
|
||||
#elif _MSC_VER >= 1400 && !defined(_XBOX) && !defined(__WINRT__)
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse((unsigned long*)&r, x);
|
||||
return (int)r;
|
||||
|
@ -39,8 +39,8 @@ extern "C" {
|
||||
int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...);
|
||||
#endif
|
||||
|
||||
/* Pre-MSVC 2010 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
|
||||
#if _MSC_VER < 1600
|
||||
/* Pre-MSVC 2008 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
|
||||
#if _MSC_VER < 1500
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef vsnprintf
|
||||
@ -56,6 +56,8 @@ extern "C" {
|
||||
#undef UNICODE /* Do not bother with UNICODE at this time. */
|
||||
#include <direct.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
|
||||
/* Python headers defines ssize_t and sets HAVE_SSIZE_T.
|
||||
@ -125,4 +127,3 @@ typedef int ssize_t;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -67,7 +67,6 @@ extern "C" {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* 7.18.1 Integer types. */
|
||||
|
||||
/* 7.18.1.1 Exact-width integer types. */
|
||||
@ -94,7 +93,6 @@ extern "C" {
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
|
||||
/* 7.18.1.2 Minimum-width integer types. */
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
@ -255,4 +253,3 @@ typedef uint64_t uintmax_t;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -29,6 +29,10 @@
|
||||
#include <compat/msvc.h>
|
||||
#endif
|
||||
|
||||
#if defined(PS2)
|
||||
#include <compat_ctype.h>
|
||||
#endif
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -55,7 +59,6 @@ int isblank(int c);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -25,6 +25,10 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(PS2)
|
||||
#include <compat_ctype.h>
|
||||
#endif
|
||||
|
||||
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
|
||||
#include "../../../config.h"
|
||||
#endif
|
||||
@ -46,4 +50,3 @@ RETRO_END_DECLS
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -57,4 +57,3 @@ char *strldup(const char *s, size_t n);
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
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
|
||||
|
||||
|
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
|
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 <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 */
|
||||
#elif defined(_WIN32) && !defined(_XBOX)
|
||||
#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>
|
||||
|
||||
#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...
|
||||
*/
|
||||
|
||||
|
||||
/* _LIBRETRO_COMMON_RETRO_COMMON_API_H */
|
||||
#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
|
||||
#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
|
||||
|
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
|
||||
#if defined(__CELLOS_LV2__)
|
||||
#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
|
||||
#else
|
||||
#define PATH_MAX_LENGTH 4096
|
||||
@ -159,14 +159,24 @@ typedef struct
|
||||
# ifdef _WIN64
|
||||
# define PRI_SIZET PRIu64
|
||||
# else
|
||||
#if _MSC_VER == 1800
|
||||
# define PRI_SIZET PRIu32
|
||||
#else
|
||||
# define PRI_SIZET "u"
|
||||
#endif
|
||||
# if _MSC_VER == 1800
|
||||
# define PRI_SIZET PRIu32
|
||||
# else
|
||||
# define PRI_SIZET "u"
|
||||
# endif
|
||||
# endif
|
||||
#elif PS2
|
||||
# define PRI_SIZET "u"
|
||||
#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
|
||||
|
@ -37,6 +37,8 @@
|
||||
#include <pspthreadman.h>
|
||||
#elif defined(VITA)
|
||||
#include <psp2/kernel/threadmgr.h>
|
||||
#elif defined(PS2)
|
||||
#include <SDL/SDL_timer.h>
|
||||
#elif defined(_3DS)
|
||||
#include <3ds.h>
|
||||
#else
|
||||
@ -89,10 +91,12 @@ static INLINE void retro_sleep(unsigned msec)
|
||||
sys_timer_usleep(1000 * msec);
|
||||
#elif defined(PSP) || defined(VITA)
|
||||
sceKernelDelayThread(1000 * msec);
|
||||
#elif defined(PS2)
|
||||
SDL_Delay(msec);
|
||||
#elif defined(_3DS)
|
||||
svcSleepThread(1000000 * (s64)msec);
|
||||
#elif defined(__WINRT__)
|
||||
/* TODO/FIXME */
|
||||
#elif defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
SleepEx(msec, FALSE);
|
||||
#elif defined(_WIN32)
|
||||
Sleep(msec);
|
||||
#elif defined(XENON)
|
||||
|
@ -36,19 +36,22 @@
|
||||
#include <boolean.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <vfs/vfs_implementation.h>
|
||||
|
||||
#define FILESTREAM_REQUIRED_VFS_VERSION 1
|
||||
#define FILESTREAM_REQUIRED_VFS_VERSION 2
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
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);
|
||||
|
||||
int64_t filestream_get_size(RFILE *stream);
|
||||
|
||||
int64_t filestream_truncate(RFILE *stream, int64_t length);
|
||||
|
||||
/**
|
||||
* filestream_open:
|
||||
* @path : path to file
|
||||
@ -104,6 +107,8 @@ bool filestream_exists(const char *path);
|
||||
|
||||
char *filestream_getline(RFILE *stream);
|
||||
|
||||
libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -30,6 +30,8 @@
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#ifndef SKIP_STDIO_REDEFINES
|
||||
|
||||
#define FILE RFILE
|
||||
|
||||
#undef fopen
|
||||
@ -41,9 +43,11 @@ RETRO_BEGIN_DECLS
|
||||
#undef fgetc
|
||||
#undef fwrite
|
||||
#undef fputc
|
||||
#undef fflush
|
||||
#undef fprintf
|
||||
#undef ferror
|
||||
#undef feof
|
||||
#undef fscanf
|
||||
|
||||
#define fopen rfopen
|
||||
#define fclose rfclose
|
||||
@ -54,9 +58,13 @@ RETRO_BEGIN_DECLS
|
||||
#define fgetc rfgetc
|
||||
#define fwrite rfwrite
|
||||
#define fputc rfputc
|
||||
#define fflush rfflush
|
||||
#define fprintf rfprintf
|
||||
#define ferror rferror
|
||||
#define feof rfeof
|
||||
#define fscanf rfscanf
|
||||
|
||||
#endif
|
||||
|
||||
RFILE* rfopen(const char *path, const char *mode);
|
||||
|
||||
@ -78,12 +86,16 @@ int64_t rfwrite(void const* buffer,
|
||||
|
||||
int rfputc(int character, RFILE * stream);
|
||||
|
||||
int64_t rfflush(RFILE * stream);
|
||||
|
||||
int rfprintf(RFILE * stream, const char * format, ...);
|
||||
|
||||
int rferror(RFILE* stream);
|
||||
|
||||
int rfeof(RFILE* stream);
|
||||
|
||||
int rfscanf(RFILE * stream, const char * format, ...);
|
||||
|
||||
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 (stdstring.h).
|
||||
@ -37,35 +37,30 @@ RETRO_BEGIN_DECLS
|
||||
|
||||
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)
|
||||
{
|
||||
if (!a || !b)
|
||||
return false;
|
||||
while(*a && (*a == *b))
|
||||
{
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
return (*(const unsigned char*)a - *(const unsigned char*)b) == 0;
|
||||
return (a && b) ? !strcmp(a, b) : false;
|
||||
}
|
||||
|
||||
static INLINE bool string_is_not_equal(const char *a, const char *b)
|
||||
{
|
||||
return !string_is_equal(a, b);
|
||||
}
|
||||
#define STRLEN_CONST(x) ((sizeof((x))-1))
|
||||
|
||||
#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_is_not_equal(a, b) !string_is_equal((a), (b))
|
||||
|
||||
#define string_add_pair_open(s, size) strlcat((s), " (", (size))
|
||||
#define string_add_pair_close(s, size) strlcat((s), ")", (size))
|
||||
#define string_add_bracket_open(s, size) strlcat((s), "{", (size))
|
||||
#define string_add_bracket_close(s, size) strlcat((s), "}", (size))
|
||||
#define string_add_single_quote(s, size) strlcat((s), "'", (size))
|
||||
#define string_add_quote(s, size) strlcat((s), "\"", (size))
|
||||
#define string_add_colon(s, size) strlcat((s), ":", (size))
|
||||
#define string_add_glob_open(s, size) strlcat((s), "glob('*", (size))
|
||||
#define string_add_glob_close(s, size) strlcat((s), "*')", (size))
|
||||
#define string_add_single_quote(s, size) strlcat((s), "'", (size))
|
||||
#define string_add_quote(s, size) strlcat((s), "\"", (size))
|
||||
#define string_add_colon(s, size) strlcat((s), ":", (size))
|
||||
#define string_add_glob_open(s, size) strlcat((s), "glob('*", (size))
|
||||
#define string_add_glob_close(s, size) strlcat((s), "*')", (size))
|
||||
|
||||
#define string_is_not_equal_fast(a, b, size) (memcmp(a, b, size) != 0)
|
||||
#define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0)
|
||||
|
||||
static INLINE void string_add_between_pairs(char *s, const char *str,
|
||||
size_t size)
|
||||
@ -75,9 +70,6 @@ static INLINE void string_add_between_pairs(char *s, const char *str,
|
||||
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,
|
||||
const char *b)
|
||||
{
|
||||
@ -119,7 +111,7 @@ char *string_to_upper(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,
|
||||
const char *by);
|
||||
@ -133,7 +125,9 @@ char *string_trim_whitespace_right(char *const s);
|
||||
/* Remove leading and trailing whitespaces */
|
||||
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
|
||||
|
||||
|
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).
|
||||
@ -23,20 +23,13 @@
|
||||
#ifndef __LIBRETRO_SDK_VFS_IMPLEMENTATION_H
|
||||
#define __LIBRETRO_SDK_VFS_IMPLEMENTATION_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <libretro.h>
|
||||
#include <retro_environment.h>
|
||||
#include <vfs/vfs.h>
|
||||
|
||||
/* 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
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
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_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_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);
|
||||
|
||||
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
|
||||
|
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_close_t filestream_close_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_seek_t filestream_seek_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_tell_cb = NULL;
|
||||
filestream_size_cb = NULL;
|
||||
filestream_truncate_cb = NULL;
|
||||
filestream_seek_cb = NULL;
|
||||
filestream_read_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_close_cb = vfs_iface->close;
|
||||
filestream_size_cb = vfs_iface->size;
|
||||
filestream_truncate_cb = vfs_iface->truncate;
|
||||
filestream_tell_cb = vfs_iface->tell;
|
||||
filestream_seek_cb = vfs_iface->seek;
|
||||
filestream_read_cb = vfs_iface->read;
|
||||
@ -127,6 +130,21 @@ int64_t filestream_get_size(RFILE *stream)
|
||||
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:
|
||||
* @path : path to file
|
||||
@ -186,9 +204,9 @@ int filestream_getc(RFILE *stream)
|
||||
{
|
||||
char c = 0;
|
||||
if (!stream)
|
||||
return 0;
|
||||
if(filestream_read(stream, &c, 1) == 1)
|
||||
return (int)c;
|
||||
return EOF;
|
||||
if (filestream_read(stream, &c, 1) == 1)
|
||||
return (int)(unsigned char)c;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
@ -197,37 +215,40 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
|
||||
char buf[4096];
|
||||
char subfmt[64];
|
||||
va_list args;
|
||||
|
||||
|
||||
const char * bufiter = buf;
|
||||
int64_t startpos = filestream_tell(stream);
|
||||
int ret = 0;
|
||||
int64_t maxlen = filestream_read(stream, buf, sizeof(buf)-1);
|
||||
|
||||
if (maxlen <= 0)
|
||||
return EOF;
|
||||
|
||||
buf[maxlen] = '\0';
|
||||
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
|
||||
while (*format)
|
||||
{
|
||||
if (*format == '%')
|
||||
{
|
||||
int sublen;
|
||||
|
||||
|
||||
char* subfmtiter = subfmt;
|
||||
bool asterisk = false;
|
||||
|
||||
|
||||
*subfmtiter++ = *format++; /* '%' */
|
||||
|
||||
|
||||
/* %[*][width][length]specifier */
|
||||
|
||||
|
||||
if (*format == '*')
|
||||
{
|
||||
asterisk = true;
|
||||
*subfmtiter++ = *format++;
|
||||
}
|
||||
|
||||
|
||||
while (isdigit(*format)) *subfmtiter++ = *format++; /* width */
|
||||
|
||||
|
||||
/* length */
|
||||
if (*format == 'h' || *format == 'l')
|
||||
{
|
||||
@ -238,7 +259,7 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
|
||||
{
|
||||
*subfmtiter++ = *format++;
|
||||
}
|
||||
|
||||
|
||||
/* specifier - always a single character (except ]) */
|
||||
if (*format == '[')
|
||||
{
|
||||
@ -246,11 +267,11 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
|
||||
*subfmtiter++ = *format++;
|
||||
}
|
||||
else *subfmtiter++ = *format++;
|
||||
|
||||
|
||||
*subfmtiter++ = '%';
|
||||
*subfmtiter++ = 'n';
|
||||
*subfmtiter++ = '\0';
|
||||
|
||||
|
||||
if (sizeof(void*) != sizeof(long*)) abort(); /* all pointers must have the same size */
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
ret++;
|
||||
bufiter += sublen;
|
||||
}
|
||||
@ -277,10 +298,10 @@ int filestream_scanf(RFILE *stream, const char* format, ...)
|
||||
format++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
va_end(args);
|
||||
filestream_seek(stream, startpos+(bufiter-buf), RETRO_VFS_SEEK_POSITION_START);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -305,7 +326,6 @@ int filestream_eof(RFILE *stream)
|
||||
return stream->eof_flag;
|
||||
}
|
||||
|
||||
|
||||
int64_t filestream_tell(RFILE *stream)
|
||||
{
|
||||
int64_t output;
|
||||
@ -407,7 +427,7 @@ int filestream_putc(RFILE *stream, int c)
|
||||
char c_char = (char)c;
|
||||
if (!stream)
|
||||
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)
|
||||
@ -592,3 +612,8 @@ char *filestream_getline(RFILE *stream)
|
||||
newline[idx] = '\0';
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -49,12 +49,12 @@ RFILE* rfopen(const char *path, const char *mode)
|
||||
}
|
||||
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;
|
||||
position_to_end = true;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -99,7 +99,7 @@ int64_t rfseek(RFILE* stream, int64_t offset, int origin)
|
||||
int64_t rfread(void* buffer,
|
||||
size_t elem_size, size_t elem_count, RFILE* stream)
|
||||
{
|
||||
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)
|
||||
@ -109,7 +109,7 @@ char *rfgets(char *buffer, int maxCount, RFILE* stream)
|
||||
|
||||
int rfgetc(RFILE* stream)
|
||||
{
|
||||
return filestream_getc(stream);
|
||||
return filestream_getc(stream);
|
||||
}
|
||||
|
||||
int64_t rfwrite(void const* buffer,
|
||||
@ -123,14 +123,19 @@ int rfputc(int character, RFILE * stream)
|
||||
return filestream_putc(stream, character);
|
||||
}
|
||||
|
||||
int64_t rfflush(RFILE * stream)
|
||||
{
|
||||
return filestream_flush(stream);
|
||||
}
|
||||
|
||||
int rfprintf(RFILE * stream, const char * format, ...)
|
||||
{
|
||||
int result;
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
result = filestream_vprintf(stream, format, vl);
|
||||
va_end(vl);
|
||||
return result;
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
result = filestream_vprintf(stream, format, vl);
|
||||
va_end(vl);
|
||||
return result;
|
||||
}
|
||||
|
||||
int rferror(RFILE* stream)
|
||||
@ -142,3 +147,13 @@ int rfeof(RFILE* 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;
|
||||
out = (char *)malloc(outlen+1);
|
||||
|
||||
if (!out)
|
||||
return NULL;
|
||||
|
||||
outat = out;
|
||||
inat = in;
|
||||
inprev = in;
|
||||
@ -105,18 +109,17 @@ char *string_trim_whitespace_left(char *const s)
|
||||
{
|
||||
if(s && *s)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
char *cur = s;
|
||||
size_t len = strlen(s);
|
||||
char *current = s;
|
||||
|
||||
while(*cur && isspace((unsigned char)*cur))
|
||||
while(*current && isspace((unsigned char)*current))
|
||||
{
|
||||
++cur;
|
||||
++current;
|
||||
--len;
|
||||
}
|
||||
|
||||
if(s != cur)
|
||||
memmove(s, cur, len + 1);
|
||||
|
||||
if(s != current)
|
||||
memmove(s, current, len + 1);
|
||||
}
|
||||
|
||||
return s;
|
||||
@ -127,16 +130,16 @@ char *string_trim_whitespace_right(char *const s)
|
||||
{
|
||||
if(s && *s)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
char *cur = s + len - 1;
|
||||
size_t len = strlen(s);
|
||||
char *current = s + len - 1;
|
||||
|
||||
while(cur != s && isspace((unsigned char)*cur))
|
||||
while(current != s && isspace((unsigned char)*current))
|
||||
{
|
||||
--cur;
|
||||
--current;
|
||||
--len;
|
||||
}
|
||||
|
||||
cur[isspace((unsigned char)*cur) ? 0 : 1] = '\0';
|
||||
current[isspace((unsigned char)*current) ? 0 : 1] = '\0';
|
||||
}
|
||||
|
||||
return s;
|
||||
@ -151,14 +154,16 @@ char *string_trim_whitespace(char *const 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 len = (unsigned)strlen(string);
|
||||
unsigned i = 0;
|
||||
unsigned len = (unsigned)strlen(string);
|
||||
unsigned lines = 1;
|
||||
|
||||
while (i < len)
|
||||
{
|
||||
unsigned counter;
|
||||
int pos = (int)(&buffer[i] - buffer);
|
||||
|
||||
/* copy string until the end of the line is reached */
|
||||
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
|
||||
* and reset the index */
|
||||
if (buffer[j] == '\n')
|
||||
{
|
||||
lines++;
|
||||
counter = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for whitespace */
|
||||
if (string[i] == ' ')
|
||||
{
|
||||
buffer[i] = '\n';
|
||||
i++;
|
||||
if ((max_lines == 0 || lines < max_lines))
|
||||
{
|
||||
buffer[i] = '\n';
|
||||
i++;
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
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 */
|
||||
for (k = i; k > 0; k--)
|
||||
{
|
||||
if (string[k] != ' ')
|
||||
if (string[k] != ' ' || (max_lines != 0 && lines >= max_lines))
|
||||
continue;
|
||||
|
||||
buffer[k] = '\n';
|
||||
/* set string index back to character after this one */
|
||||
i = k + 1;
|
||||
lines++;
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user