Update libretro-common

This commit is contained in:
twinaphex 2016-03-24 06:33:52 +01:00
parent 51eb6a241a
commit 79f0550469
27 changed files with 2495 additions and 474 deletions

View File

@ -119,7 +119,7 @@ SOURCES_C += $(MEDNAFEN_DIR)/trio/trio.c \
$(MEDNAFEN_DIR)/trio/triostr.c
ifneq ($(STATIC_LINKING), 1)
SOURCES_C += $(LIBRETRO_DIR)/file/retro_file.c \
SOURCES_C += $(LIBRETRO_DIR)/streams/file_stream.c \
$(LIBRETRO_DIR)/file/retro_stat.c
ifeq ($(NEED_THREADING), 1)

View File

@ -1,388 +0,0 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_file.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 <errno.h>
#if defined(_WIN32)
# ifdef _MSC_VER
# define setmode _setmode
# endif
# ifdef _XBOX
# include <xtl.h>
# define INVALID_FILE_ATTRIBUTES -1
# else
# include <io.h>
# include <fcntl.h>
# include <direct.h>
# include <windows.h>
# endif
#elif defined(VITA)
# include <psp2/io/fcntl.h>
# include <psp2/io/dirent.h>
#define PSP_O_RDONLY PSP2_O_RDONLY
#define PSP_O_RDWR PSP2_O_RDWR
#define PSP_O_CREAT PSP2_O_CREAT
#define PSP_O_WRONLY PSP2_O_WRONLY
#define PSP_O_TRUNC PSP2_O_TRUNC
#else
# if defined(PSP)
# include <pspiofilemgr.h>
# endif
# include <sys/types.h>
# include <sys/stat.h>
# include <dirent.h>
# include <unistd.h>
#endif
#ifdef __CELLOS_LV2__
#include <cell/cell_fs.h>
#else
#include <fcntl.h>
#endif
#ifdef RARCH_INTERNAL
#include <retro_log.h>
#endif
#include <retro_file.h>
#if 1
#define HAVE_BUFFERED_IO 1
#endif
struct RFILE
{
#if defined(PSP) || defined(VITA)
SceUID fd;
#elif defined(__CELLOS_LV2__)
int fd;
#elif defined(HAVE_BUFFERED_IO)
FILE *fd;
#else
int fd;
#endif
};
int retro_get_fd(RFILE *stream)
{
if (!stream)
return -1;
#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__)
return stream->fd;
#elif defined(HAVE_BUFFERED_IO)
return fileno(stream->fd);
#else
return stream->fd;
#endif
}
RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len)
{
int flags = 0;
int mode_int = 0;
const char *mode_str = NULL;
RFILE *stream = (RFILE*)calloc(1, sizeof(*stream));
if (!stream)
return NULL;
(void)mode_str;
(void)mode_int;
(void)flags;
switch (mode)
{
case RFILE_MODE_READ:
#if defined(VITA) || defined(PSP)
mode_int = 0777;
flags = PSP_O_RDONLY;
#elif defined(__CELLOS_LV2__)
mode_int = 0777;
flags = CELL_FS_O_RDONLY;
#elif defined(HAVE_BUFFERED_IO)
mode_str = "rb";
#else
flags = O_RDONLY;
#endif
break;
case RFILE_MODE_WRITE:
#if defined(VITA) || defined(PSP)
mode_int = 0777;
flags = PSP_O_CREAT | PSP_O_WRONLY | PSP_O_TRUNC;
#elif defined(__CELLOS_LV2__)
mode_int = 0777;
flags = CELL_FS_O_CREAT | CELL_FS_O_WRONLY | CELL_FS_O_TRUNC;
#elif defined(HAVE_BUFFERED_IO)
mode_str = "wb";
#else
flags = O_WRONLY | O_CREAT | O_TRUNC | S_IRUSR | S_IWUSR;
#endif
break;
case RFILE_MODE_READ_WRITE:
#if defined(VITA) || defined(PSP)
mode_int = 0777;
flags = PSP_O_RDWR;
#elif defined(__CELLOS_LV2__)
mode_int = 0777;
flags = CELL_FS_O_RDWR;
#elif defined(HAVE_BUFFERED_IO)
mode_str = "w+";
#else
flags = O_RDWR;
#ifdef _WIN32
flags |= O_BINARY;
#endif
#endif
break;
}
#if defined(VITA) || defined(PSP)
stream->fd = sceIoOpen(path, flags, mode_int);
#elif defined(__CELLOS_LV2__)
cellFsOpen(path, flags, &stream->fd, NULL, 0);
#elif defined(HAVE_BUFFERED_IO)
stream->fd = fopen(path, mode_str);
#else
stream->fd = open(path, flags);
#endif
#if defined(HAVE_BUFFERED_IO)
if (!stream->fd)
goto error;
#else
if (stream->fd == -1)
goto error;
#endif
return stream;
error:
retro_fclose(stream);
return NULL;
}
ssize_t retro_fseek(RFILE *stream, ssize_t offset, int whence)
{
int ret = 0;
if (!stream)
return -1;
(void)ret;
#if defined(VITA) || defined(PSP)
ret = sceIoLseek(stream->fd, (SceOff)offset, whence);
if (ret == -1)
return -1;
return 0;
#elif defined(__CELLOS_LV2__)
uint64_t pos = 0;
if (cellFsLseek(stream->fd, offset, whence, &pos) != CELL_FS_SUCCEEDED)
return -1;
return 0;
#elif defined(HAVE_BUFFERED_IO)
return fseek(stream->fd, (long)offset, whence);
#else
ret = lseek(stream->fd, offset, whence);
if (ret == -1)
return -1;
return 0;
#endif
}
ssize_t retro_ftell(RFILE *stream)
{
if (!stream)
return -1;
#if defined(VITA) || defined(PSP)
return sceIoLseek(stream->fd, 0, SEEK_CUR);
#elif defined(__CELLOS_LV2__)
uint64_t pos = 0;
if (cellFsLseek(stream->fd, 0, CELL_FS_SEEK_CUR, &pos) != CELL_FS_SUCCEEDED)
return -1;
return 0;
#elif defined(HAVE_BUFFERED_IO)
return ftell(stream->fd);
#else
return lseek(stream->fd, 0, SEEK_CUR);
#endif
}
void retro_frewind(RFILE *stream)
{
retro_fseek(stream, 0L, SEEK_SET);
}
ssize_t retro_fread(RFILE *stream, void *s, size_t len)
{
if (!stream || !s)
return -1;
#if defined(VITA) || defined(PSP)
return sceIoRead(stream->fd, s, len);
#elif defined(__CELLOS_LV2__)
uint64_t bytes_written;
if (cellFsRead(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED)
return -1;
return bytes_written;
#elif defined(HAVE_BUFFERED_IO)
return fread(s, 1, len, stream->fd);
#else
return read(stream->fd, s, len);
#endif
}
ssize_t retro_fwrite(RFILE *stream, const void *s, size_t len)
{
if (!stream)
return -1;
#if defined(VITA) || defined(PSP)
return sceIoWrite(stream->fd, s, len);
#elif defined(__CELLOS_LV2__)
uint64_t bytes_written;
if (cellFsWrite(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED)
return -1;
return bytes_written;
#elif defined(HAVE_BUFFERED_IO)
return fwrite(s, 1, len, stream->fd);
#else
return write(stream->fd, s, len);
#endif
}
int retro_fclose(RFILE *stream)
{
if (!stream)
return -1;
#if defined(VITA) || defined(PSP)
if (stream->fd > 0)
sceIoClose(stream->fd);
#elif defined(__CELLOS_LV2__)
if (stream->fd > 0)
cellFsClose(stream->fd);
#elif defined(HAVE_BUFFERED_IO)
if (stream->fd)
fclose(stream->fd);
#else
if (stream->fd > 0)
close(stream->fd);
#endif
free(stream);
return 0;
}
/**
* retro_read_file:
* @path : path to file.
* @buf : buffer to allocate and read the contents of the
* file into. Needs to be freed manually.
*
* Read the contents of a file into @buf.
*
* Returns: number of items read, -1 on error.
*/
int retro_read_file(const char *path, void **buf, ssize_t *len)
{
ssize_t ret = 0;
ssize_t content_buf_size = 0;
void *content_buf = NULL;
RFILE *file = retro_fopen(path, RFILE_MODE_READ, -1);
if (!file)
goto error;
if (retro_fseek(file, 0, SEEK_END) != 0)
goto error;
content_buf_size = retro_ftell(file);
if (content_buf_size < 0)
goto error;
retro_frewind(file);
content_buf = malloc(content_buf_size + 1);
if (!content_buf)
goto error;
if ((ret = retro_fread(file, content_buf, content_buf_size)) < content_buf_size)
{
#ifdef RARCH_INTERNAL
RARCH_WARN("Didn't read whole file: %s.\n", path);
#else
printf("Didn't read whole file: %s.\n", path);
#endif
}
if (!content_buf)
goto error;
*buf = content_buf;
/* Allow for easy reading of strings to be safe.
* Will only work with sane character formatting (Unix). */
((char*)content_buf)[content_buf_size] = '\0';
if (retro_fclose(file) != 0)
printf("Failed to close file stream.\n");
if (len)
*len = ret;
return 1;
error:
retro_fclose(file);
if (content_buf)
free(content_buf);
if (len)
*len = -1;
*buf = NULL;
return 0;
}
/**
* retro_write_file:
* @path : path to file.
* @data : contents to write to the file.
* @size : size of the contents.
*
* Writes data to a file.
*
* Returns: true (1) on success, false (0) otherwise.
*/
bool retro_write_file(const char *path, const void *data, ssize_t size)
{
ssize_t ret = 0;
RFILE *file = retro_fopen(path, RFILE_MODE_WRITE, -1);
if (!file)
return false;
ret = retro_fwrite(file, data, size);
retro_fclose(file);
return (ret == size);
}

View File

@ -1,20 +1,27 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
/* Copyright (C) 2010-2015 The RetroArch team
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (boolean.h).
* ---------------------------------------------------------------------------------------
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
* 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:
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
* 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 __RARCH_BOOLEAN_H
#define __RARCH_BOOLEAN_H
#ifndef __LIBRETRO_SDK_BOOLEAN_H
#define __LIBRETRO_SDK_BOOLEAN_H
#ifndef __cplusplus
@ -30,4 +37,3 @@
#endif
#endif

View File

@ -0,0 +1,49 @@
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (apple_compat.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.
*/
#ifdef __APPLE__
#include <AvailabilityMacros.h>
#endif
#ifdef __OBJC__
#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4)
typedef int NSInteger;
typedef unsigned NSUInteger;
typedef float CGFloat;
#endif
#endif
#ifdef IOS
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <GLKit/GLKit.h>
#import <Foundation/Foundation.h>
#include <objc/objc-runtime.h>
#endif
#endif

View File

@ -0,0 +1,30 @@
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_fnmatch.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_COMPAT_FNMATCH_H__
#define __LIBRETRO_SDK_COMPAT_FNMATCH_H__
#define FNM_NOMATCH 1
int rl_fnmatch(const char *pattern, const char *string, int flags);
#endif

View File

@ -0,0 +1,76 @@
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_getopt.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_COMPAT_GETOPT_H
#define __LIBRETRO_SDK_COMPAT_GETOPT_H
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
#include "../../../config.h"
#endif
/* Custom implementation of the GNU getopt_long for portability.
* Not designed to be fully compatible, but compatible with
* the features RetroArch uses. */
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#else
/* Avoid possible naming collisions during link since we
* prefer to use the actual name. */
#define getopt_long(argc, argv, optstring, longopts, longindex) __getopt_long_retro(argc, argv, optstring, longopts, longindex)
#ifdef __cplusplus
extern "C" {
#endif
struct option
{
const char *name;
int has_arg;
int *flag;
int val;
};
/* argv[] is declared with char * const argv[] in GNU,
* but this makes no sense, as non-POSIX getopt_long
* mutates argv (non-opts are moved to the end). */
int getopt_long(int argc, char *argv[],
const char *optstring, const struct option *longopts, int *longindex);
extern char *optarg;
extern int optind, opterr, optopt;
#ifdef __cplusplus
}
#endif
/* If these are variously #defined, then we have bigger problems */
#ifndef no_argument
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#endif
/* HAVE_GETOPT_LONG */
#endif
/* pragma once */
#endif

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 1995, 1999
* Berkeley Software Design, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
*/
#ifndef _IFADDRS_H_
#define _IFADDRS_H_
struct ifaddrs
{
struct ifaddrs *ifa_next;
char *ifa_name;
unsigned int ifa_flags;
struct sockaddr *ifa_addr;
struct sockaddr *ifa_netmask;
struct sockaddr *ifa_dstaddr;
void *ifa_data;
};
/*
* This may have been defined in <net/if.h>. Note that if <net/if.h> is
* to be included it must be included before this header file.
*/
#ifndef ifa_broadaddr
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
#endif
#include <sys/cdefs.h>
extern int getifaddrs(struct ifaddrs **ifap);
extern void freeifaddrs(struct ifaddrs *ifa);
#endif

View File

@ -0,0 +1,104 @@
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (msvc_compat.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_COMPAT_MSVC_H
#define __LIBRETRO_SDK_COMPAT_MSVC_H
#ifdef _MSC_VER
#ifdef __cplusplus
extern "C" {
#endif
/* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */
#if _MSC_VER < 1900
#include <stdlib.h>
#ifndef snprintf
#define snprintf c99_snprintf_retro__
#endif
int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...);
#endif
/* Pre-MSVC 2010 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
#if _MSC_VER < 1600
#include <stdarg.h>
#include <stdlib.h>
#ifndef vsnprintf
#define vsnprintf c99_vsnprintf_retro__
#endif
int c99_vsnprintf_retro__(char *outBuf, size_t size, const char *format, va_list ap);
#endif
#ifdef __cplusplus
}
#endif
#undef UNICODE /* Do not bother with UNICODE at this time. */
#include <direct.h>
#include <stddef.h>
#include <math.h>
/* Python headers defines ssize_t and sets HAVE_SSIZE_T.
* Cannot duplicate these efforts.
*/
#ifndef HAVE_SSIZE_T
#if defined(_WIN64)
typedef __int64 ssize_t;
#elif defined(_WIN32)
typedef int ssize_t;
#endif
#endif
#define mkdir(dirname, unused) _mkdir(dirname)
#define strtoull _strtoui64
#undef strcasecmp
#define strcasecmp _stricmp
#undef strncasecmp
#define strncasecmp _strnicmp
/* Disable some of the annoying warnings. */
#pragma warning(disable : 4800)
#pragma warning(disable : 4805)
#pragma warning(disable : 4244)
#pragma warning(disable : 4305)
#pragma warning(disable : 4146)
#pragma warning(disable : 4267)
#pragma warning(disable : 4723)
#pragma warning(disable : 4996)
/* roundf is available since MSVC 2013 */
#if _MSC_VER < 1800
#define roundf(in) (in >= 0.0f ? floorf(in + 0.5f) : ceilf(in - 0.5f))
#endif
#ifndef PATH_MAX
#define PATH_MAX _MAX_PATH
#endif
#ifndef SIZE_MAX
#define SIZE_MAX _UI32_MAX
#endif
#endif
#endif

View File

@ -0,0 +1,254 @@
/* ISO C9x compliant stdint.h for Microsoft Visual Studio
* Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
*
* Copyright (c) 2006-2008 Alexander Chemeris
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __RARCH_STDINT_H
#define __RARCH_STDINT_H
#if _MSC_VER && (_MSC_VER < 1600)
/* Pre-MSVC 2010 needs an implementation of stdint.h. */
#if _MSC_VER > 1000
#pragma once
#endif
#include <limits.h>
/* For Visual Studio 6 in C++ mode and for many Visual Studio versions when
* compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
* or compiler give many errors like this:
*
* error C2733: second C linkage of overloaded function 'wmemchr' not allowed
*/
#ifdef __cplusplus
extern "C" {
#endif
# include <wchar.h>
#ifdef __cplusplus
}
#endif
/* Define _W64 macros to mark types changing their size, like intptr_t. */
#ifndef _W64
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
# define _W64 __w64
# else
# define _W64
# endif
#endif
/* 7.18.1 Integer types. */
/* 7.18.1.1 Exact-width integer types. */
/* Visual Studio 6 and Embedded Visual C++ 4 doesn't
* realize that, e.g. char has the same size as __int8
* so we give up on __intX for them.
*/
#if (_MSC_VER < 1300)
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#else
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
#endif
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;
typedef int32_t int_least32_t;
typedef int64_t int_least64_t;
typedef uint8_t uint_least8_t;
typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
typedef uint64_t uint_least64_t;
/* 7.18.1.3 Fastest minimum-width integer types. */
typedef int8_t int_fast8_t;
typedef int16_t int_fast16_t;
typedef int32_t int_fast32_t;
typedef int64_t int_fast64_t;
typedef uint8_t uint_fast8_t;
typedef uint16_t uint_fast16_t;
typedef uint32_t uint_fast32_t;
typedef uint64_t uint_fast64_t;
/* 7.18.1.4 Integer types capable of holding object pointers. */
#ifdef _WIN64 /* [ */
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
#else /* _WIN64 ][ */
typedef _W64 signed int intptr_t;
typedef _W64 unsigned int uintptr_t;
#endif /* _WIN64 ] */
/* 7.18.1.5 Greatest-width integer types. */
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
/* 7.18.2 Limits of specified-width integer types. */
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS)
/* [ See footnote 220 at page 257 and footnote 221 at page 259. */
/* 7.18.2.1 Limits of exact-width integer types. */
#define INT8_MIN ((int8_t)_I8_MIN)
#define INT8_MAX _I8_MAX
#define INT16_MIN ((int16_t)_I16_MIN)
#define INT16_MAX _I16_MAX
#define INT32_MIN ((int32_t)_I32_MIN)
#define INT32_MAX _I32_MAX
#define INT64_MIN ((int64_t)_I64_MIN)
#define INT64_MAX _I64_MAX
#define UINT8_MAX _UI8_MAX
#define UINT16_MAX _UI16_MAX
#define UINT32_MAX _UI32_MAX
#define UINT64_MAX _UI64_MAX
/* 7.18.2.2 Limits of minimum-width integer types. */
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST64_MIN INT64_MIN
#define INT_LEAST64_MAX INT64_MAX
#define UINT_LEAST8_MAX UINT8_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX
/* 7.18.2.3 Limits of fastest minimum-width integer types. */
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MIN INT16_MIN
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST32_MIN INT32_MIN
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST64_MIN INT64_MIN
#define INT_FAST64_MAX INT64_MAX
#define UINT_FAST8_MAX UINT8_MAX
#define UINT_FAST16_MAX UINT16_MAX
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX
/* 7.18.2.4 Limits of integer types capable of holding object pointers. */
#ifdef _WIN64 /* [ */
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
#else /* _WIN64 ][ */
# define INTPTR_MIN INT32_MIN
# define INTPTR_MAX INT32_MAX
# define UINTPTR_MAX UINT32_MAX
#endif /* _WIN64 ] */
/* 7.18.2.5 Limits of greatest-width integer types */
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
/* 7.18.3 Limits of other integer types */
#ifdef _WIN64 /* [ */
# define PTRDIFF_MIN _I64_MIN
# define PTRDIFF_MAX _I64_MAX
#else /* _WIN64 ][ */
# define PTRDIFF_MIN _I32_MIN
# define PTRDIFF_MAX _I32_MAX
#endif /* _WIN64 ] */
#define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX
#ifndef SIZE_MAX /* [ */
# ifdef _WIN64 /* [ */
# define SIZE_MAX _UI64_MAX
# else /* _WIN64 ][ */
# define SIZE_MAX _UI32_MAX
# endif /* _WIN64 ] */
#endif /* SIZE_MAX ] */
/* WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> */
#ifndef WCHAR_MIN /* [ */
# define WCHAR_MIN 0
#endif /* WCHAR_MIN ] */
#ifndef WCHAR_MAX // [
# define WCHAR_MAX _UI16_MAX
#endif /* WCHAR_MAX ] */
#define WINT_MIN 0
#define WINT_MAX _UI16_MAX
#endif /* __STDC_LIMIT_MACROS ] */
/* 7.18.4 Limits of other integer types */
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS)
/* [ See footnote 224 at page 260 */
/* 7.18.4.1 Macros for minimum-width integer constants */
#define INT8_C(val) val##i8
#define INT16_C(val) val##i16
#define INT32_C(val) val##i32
#define INT64_C(val) val##i64
#define UINT8_C(val) val##ui8
#define UINT16_C(val) val##ui16
#define UINT32_C(val) val##ui32
#define UINT64_C(val) val##ui64
/* 7.18.4.2 Macros for greatest-width integer constants */
#define INTMAX_C INT64_C
#define UINTMAX_C UINT64_C
#endif
/* __STDC_CONSTANT_MACROS ] */
#else
/* Sanity for everything else. */
#include <stdint.h>
#endif
#endif

View File

@ -0,0 +1,63 @@
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (posix_string.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_COMPAT_POSIX_STRING_H
#define __LIBRETRO_SDK_COMPAT_POSIX_STRING_H
#ifdef _MSC_VER
#include <compat/msvc.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
#undef strtok_r
#define strtok_r(str, delim, saveptr) retro_strtok_r__(str, delim, saveptr)
char *strtok_r(char *str, const char *delim, char **saveptr);
#endif
#ifdef _MSC_VER
#undef strcasecmp
#undef strdup
#define strcasecmp(a, b) retro_strcasecmp__(a, b)
#define strdup(orig) retro_strdup__(orig)
int strcasecmp(const char *a, const char *b);
char *strdup(const char *orig);
/* isblank is available since MSVC 2013 */
#if _MSC_VER < 1800
#undef isblank
#define isblank(c) retro_isblank__(c)
int isblank(int c);
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,49 @@
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (strcasestr.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_COMPAT_STRCASESTR_H
#define __LIBRETRO_SDK_COMPAT_STRCASESTR_H
#include <string.h>
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
#include "../../../config.h"
#endif
#ifndef HAVE_STRCASESTR
#ifdef __cplusplus
extern "C" {
#endif
/* Avoid possible naming collisions during link
* since we prefer to use the actual name. */
#define strcasestr(haystack, needle) strcasestr_retro__(haystack, needle)
char *strcasestr(const char *haystack, const char *needle);
#ifdef __cplusplus
}
#endif
#endif
#endif

View File

@ -1,7 +1,7 @@
/* Copyright (C) 2010-2015 The RetroArch team
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_file.h).
* The following license statement only applies to this file (strl.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
@ -20,51 +20,41 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __RETRO_FILE_H
#define __RETRO_FILE_H
#ifndef __LIBRETRO_SDK_COMPAT_STRL_H
#define __LIBRETRO_SDK_COMPAT_STRL_H
#include <stdint.h>
#include <string.h>
#include <stddef.h>
#include <sys/types.h>
#include <boolean.h>
#ifdef HAVE_CONFIG_H
#include "../../../config.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct RFILE RFILE;
#ifdef __MACH__
#ifndef HAVE_STRL
#define HAVE_STRL
#endif
#endif
enum
{
RFILE_MODE_READ = 0,
RFILE_MODE_WRITE,
RFILE_MODE_READ_WRITE
};
#ifndef HAVE_STRL
/* Avoid possible naming collisions during link since
* we prefer to use the actual name. */
#define strlcpy(dst, src, size) strlcpy_retro__(dst, src, size)
RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len);
#define strlcat(dst, src, size) strlcat_retro__(dst, src, size)
ssize_t retro_fseek(RFILE *stream, ssize_t offset, int whence);
size_t strlcpy(char *dest, const char *source, size_t size);
size_t strlcat(char *dest, const char *source, size_t size);
ssize_t retro_fread(RFILE *stream, void *s, size_t len);
ssize_t retro_fwrite(RFILE *stream, const void *s, size_t len);
ssize_t retro_ftell(RFILE *stream);
void retro_frewind(RFILE *stream);
int retro_fclose(RFILE *stream);
int retro_read_file(const char *path, void **buf, ssize_t *len);
bool retro_write_file(const char *path, const void *data, ssize_t size);
int retro_get_fd(RFILE *stream);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,34 @@
/*
libco
version: 0.16 (2010-12-24)
license: public domain
*/
#ifndef LIBCO_H
#define LIBCO_H
#ifdef LIBCO_C
#ifdef LIBCO_MP
#define thread_local __thread
#else
#define thread_local
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef void* cothread_t;
cothread_t co_active();
cothread_t co_create(unsigned int, void (*)(void));
void co_delete(cothread_t);
void co_switch(cothread_t);
#ifdef __cplusplus
}
#endif
/* ifndef LIBCO_H */
#endif

View File

@ -0,0 +1,49 @@
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (memmap.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_MEMMAP_H
#define _LIBRETRO_MEMMAP_H
#if defined(__CELLOS_LV2__) || defined(PSP) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS)
/* No mman available */
#elif defined(_WIN32) && !defined(_XBOX)
#include <windows.h>
#include <errno.h>
#include <io.h>
#else
#define HAVE_MMAN
#include <sys/mman.h>
#endif
#if !defined(HAVE_MMAN) || defined(_WIN32)
void* mmap(void *addr, size_t len, int mmap_prot, int mmap_flags, int fildes, size_t off);
int munmap(void *addr, size_t len);
int mprotect(void *addr, size_t len, int prot);
#endif
int memsync(void *start, void *end);
int memprotect(void *addr, size_t len);
#endif

View File

@ -0,0 +1,155 @@
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (task_queue.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_TASK_QUEUE_H__
#define __LIBRETRO_SDK_TASK_QUEUE_H__
#include <stdint.h>
#include <boolean.h>
#ifdef __cplusplus
extern "C" {
#endif
enum task_queue_ctl_state
{
TASK_QUEUE_CTL_NONE = 0,
/* Deinitializes the task system.
* This deinitializes the task system.
* The tasks that are running at
* the moment will stay on hold
* until TASK_QUEUE_CTL_INIT is called again. */
TASK_QUEUE_CTL_DEINIT,
/* Initializes the task system.
* This initializes the task system
* and chooses an appropriate
* implementation according to the settings.
*
* This must only be called from the main thread. */
TASK_QUEUE_CTL_INIT,
/**
* Calls func for every running task
* until it returns true.
* Returns a task or NULL if not found.
*/
TASK_QUEUE_CTL_FIND,
/* Blocks until all tasks have finished.
* This must only be called from the main thread. */
TASK_QUEUE_CTL_WAIT,
/* Checks for finished tasks
* Takes the finished tasks, if any,
* and runs their callbacks.
* This must only be called from the main thread. */
TASK_QUEUE_CTL_CHECK,
/* Pushes a task
* The task will start as soon as possible. */
TASK_QUEUE_CTL_PUSH,
/* Sends a signal to terminate all the tasks.
*
* This won't terminate the tasks immediately.
* They will finish as soon as possible.
*
* This must only be called from the main thread. */
TASK_QUEUE_CTL_RESET,
TASK_QUEUE_CTL_SET_THREADED,
TASK_QUEUE_CTL_UNSET_THREADED,
TASK_QUEUE_CTL_IS_THREADED
};
typedef struct retro_task retro_task_t;
typedef void (*retro_task_callback_t)(void *task_data,
void *user_data, const char *error);
typedef void (*retro_task_handler_t)(retro_task_t *task);
typedef bool (*retro_task_finder_t)(retro_task_t *task,
void *userdata);
typedef struct
{
char *source_file;
} decompress_task_data_t;
struct retro_task
{
retro_task_handler_t handler;
/* always called from the main loop */
retro_task_callback_t callback;
/* set to true by the handler to signal
* the task has finished executing. */
bool finished;
/* set to true by the task system
* to signal the task *must* end. */
bool cancelled;
/* created by the handler, destroyed by the user */
void *task_data;
/* owned by the user */
void *user_data;
/* created and destroyed by the code related to the handler */
void *state;
/* created by task handler; destroyed by main loop
* (after calling the callback) */
char *error;
/* -1 = unmettered, 0-100 progress value */
int8_t progress;
/* handler can modify but will be
* free()d automatically if non-NULL. */
char *title;
/* don't touch this. */
retro_task_t *next;
};
typedef struct task_finder_data
{
retro_task_finder_t func;
void *userdata;
} task_finder_data_t;
void task_queue_push_progress(retro_task_t *task);
bool task_queue_ctl(enum task_queue_ctl_state state, void *data);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,36 @@
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_common.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_RETRO_COMMON_H
#define _LIBRETRO_COMMON_RETRO_COMMON_H
/*
This file is designed to normalize the libretro-common compiling environment.
It is not to be used in public API headers, as they should be designed as leanly as possible.
Nonetheless.. in the meantime, if you do something like use ssize_t, which is not fully portable,
in a public API, you may need this.
*/
/* conditional compilation is handled inside here */
#include <compat/msvc.h>
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2015 The RetroArch team
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_miscellaneous.h).
@ -24,6 +24,7 @@
#define __RARCH_MISCELLANEOUS_H
#include <stdint.h>
#include <math.h>
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
#include <sys/timer.h>
@ -56,8 +57,24 @@
#include <retro_inline.h>
#ifndef PATH_MAX_LENGTH
#if defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(GEKKO)
#define PATH_MAX_LENGTH 512
#else
#define PATH_MAX_LENGTH 4096
#endif
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846264338327
#endif
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define RARCH_SCALE_BASE 256
@ -128,13 +145,26 @@ static INLINE uint32_t prev_pow2(uint32_t v)
return v - (v >> 1);
}
/**
* db_to_gain:
* @db : Decibels.
*
* Converts decibels to voltage gain.
*
* Returns: voltage gain value.
**/
static INLINE float db_to_gain(float db)
{
return powf(10.0f, db / 20.0f);
}
/* Helper macros and struct to keep track of many booleans.
* To check for multiple bits, use &&, not &.
* For OR, | can be used. */
typedef struct
{
uint32_t data[8];
} rarch_bits_t;
} retro_bits_t;
#define BIT_SET(a, bit) ((a)[(bit) >> 3] |= (1 << ((bit) & 7)))
#define BIT_CLEAR(a, bit) ((a)[(bit) >> 3] &= ~(1 << ((bit) & 7)))

View File

@ -0,0 +1,35 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (async_job.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_ASYNC_JOB_H
#define __LIBRETRO_SDK_ASYNC_JOB_H
typedef struct async_job async_job_t;
typedef void (*async_task_t)(void *payload);
async_job_t *async_job_new(void);
void async_job_free(async_job_t *ajob);
int async_job_add(async_job_t *ajob, async_task_t task, void *payload);
#endif /* __LIBRETRO_SDK_ASYNC_JOB_H */

View File

@ -0,0 +1,44 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rsemaphore.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_SEMAPHORE_H
#define __LIBRETRO_SDK_SEMAPHORE_H
typedef struct ssem ssem_t;
/**
* ssem_create:
* @value : initial value for the semaphore
*
* Create a new semaphore.
*
* Returns: pointer to new semaphore if successful, otherwise NULL.
*/
ssem_t *ssem_new(int value);
void ssem_free(ssem_t *semaphore);
void ssem_wait(ssem_t *semaphore);
void ssem_signal(ssem_t *semaphore);
#endif /* __LIBRETRO_SDK_SEMAPHORE_H */

View File

@ -0,0 +1,75 @@
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream.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_STREAM_H
#define __LIBRETRO_SDK_FILE_STREAM_H
#include <stdint.h>
#include <stddef.h>
#include <sys/types.h>
#include <retro_common.h>
#include <boolean.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct RFILE RFILE;
enum
{
RFILE_MODE_READ = 0,
RFILE_MODE_WRITE,
RFILE_MODE_READ_WRITE,
/* There is no garantee these requests will be attended. */
RFILE_HINT_UNBUFFERED = 1<<8,
RFILE_HINT_MMAP = 1<<9 /* requires RFILE_MODE_READ */
};
RFILE *filestream_open(const char *path, unsigned mode, ssize_t len);
ssize_t filestream_seek(RFILE *stream, ssize_t offset, int whence);
ssize_t filestream_read(RFILE *stream, void *data, size_t len);
ssize_t filestream_write(RFILE *stream, const void *data, size_t len);
ssize_t filestream_tell(RFILE *stream);
void filestream_rewind(RFILE *stream);
int filestream_close(RFILE *stream);
int filestream_read_file(const char *path, void **buf, ssize_t *len);
bool filestream_write_file(const char *path, const void *data, ssize_t size);
int filestream_get_fd(RFILE *stream);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,461 @@
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (task_queue.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 <stdarg.h>
#include <queues/task_queue.h>
#ifdef HAVE_THREADS
#include <rthreads/rthreads.h>
#endif
typedef struct
{
retro_task_t *front;
retro_task_t *back;
} task_queue_t;
struct retro_task_impl
{
void (*push_running)(retro_task_t *);
void (*reset)(void);
void (*wait)(void);
void (*gather)(void);
bool (*find)(retro_task_finder_t, void*);
void (*init)(void);
void (*deinit)(void);
};
static task_queue_t tasks_running = {NULL, NULL};
static task_queue_t tasks_finished = {NULL, NULL};
#ifndef RARCH_INTERNAL
static void task_queue_msg_push(unsigned prio, unsigned duration,
bool flush, const char *fmt, ...)
{
char buf[1024];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
/* print something here */
}
void task_queue_push_progress(retro_task_t *task)
{
if (task->title)
{
if (task->finished)
{
if (task->error)
task_queue_msg_push(1, 60, true, "%s: %s",
"Task failed\n", task->title);
else
task_queue_msg_push(1, 60, true, "100%%: %s", task->title);
}
else
{
if (task->progress >= 0 && task->progress <= 100)
task_queue_msg_push(1, 60, true, "%i%%: %s",
task->progress, task->title);
else
task_queue_msg_push(1, 60, true, "%s...", task->title);
}
}
}
#endif
static void task_queue_put(task_queue_t *queue, retro_task_t *task)
{
task->next = NULL;
if (queue->front)
queue->back->next = task;
else
queue->front = task;
queue->back = task;
}
static retro_task_t *task_queue_get(task_queue_t *queue)
{
retro_task_t *task = queue->front;
if (task)
{
queue->front = task->next;
task->next = NULL;
}
return task;
}
static void retro_task_internal_gather(void)
{
retro_task_t *task = NULL;
while ((task = task_queue_get(&tasks_finished)) != NULL)
{
task_queue_push_progress(task);
if (task->callback)
task->callback(task->task_data, task->user_data, task->error);
if (task->error)
free(task->error);
if (task->title)
free(task->title);
free(task);
}
}
static void retro_task_regular_push_running(retro_task_t *task)
{
task_queue_put(&tasks_running, task);
}
static void retro_task_regular_gather(void)
{
retro_task_t *task = NULL;
retro_task_t *queue = NULL;
retro_task_t *next = NULL;
while ((task = task_queue_get(&tasks_running)) != NULL)
{
task->next = queue;
queue = task;
}
for (task = queue; task; task = next)
{
next = task->next;
task->handler(task);
task_queue_push_progress(task);
if (task->finished)
task_queue_put(&tasks_finished, task);
else
retro_task_regular_push_running(task);
}
retro_task_internal_gather();
}
static void retro_task_regular_wait(void)
{
while (tasks_running.front)
retro_task_regular_gather();
}
static void retro_task_regular_reset(void)
{
retro_task_t *task = tasks_running.front;
for (; task; task = task->next)
task->cancelled = true;
}
static void retro_task_regular_init(void)
{
}
static void retro_task_regular_deinit(void)
{
}
static bool retro_task_regular_find(retro_task_finder_t func, void *user_data)
{
retro_task_t *task = tasks_running.front;
for (; task; task = task->next)
{
if (func(task, user_data))
return true;
}
return false;
}
static struct retro_task_impl impl_regular = {
retro_task_regular_push_running,
retro_task_regular_reset,
retro_task_regular_wait,
retro_task_regular_gather,
retro_task_regular_find,
retro_task_regular_init,
retro_task_regular_deinit
};
#ifdef HAVE_THREADS
static slock_t *running_lock = NULL;
static slock_t *finished_lock = NULL;
static scond_t *worker_cond = NULL;
static sthread_t *worker_thread = NULL;
static bool worker_continue = true; /* use running_lock when touching it */
static void retro_task_threaded_push_running(retro_task_t *task)
{
slock_lock(running_lock);
task_queue_put(&tasks_running, task);
scond_signal(worker_cond);
slock_unlock(running_lock);
}
static void retro_task_threaded_gather(void)
{
retro_task_t *task = NULL;
slock_lock(running_lock);
for (task = tasks_running.front; task; task = task->next)
task_queue_push_progress(task);
slock_unlock(running_lock);
slock_lock(finished_lock);
retro_task_internal_gather();
slock_unlock(finished_lock);
}
static void retro_task_threaded_wait(void)
{
bool wait = false;
do
{
retro_task_threaded_gather();
slock_lock(running_lock);
wait = (tasks_running.front != NULL);
slock_unlock(running_lock);
} while (wait);
}
static void retro_task_threaded_reset(void)
{
retro_task_t *task = NULL;
slock_lock(running_lock);
for (task = tasks_running.front; task; task = task->next)
task->cancelled = true;
slock_unlock(running_lock);
}
static bool retro_task_threaded_find(
retro_task_finder_t func, void *user_data)
{
retro_task_t *task = NULL;
slock_lock(running_lock);
for (task = tasks_running.front; task; task = task->next)
{
if (func(task, user_data))
return true;
}
slock_unlock(running_lock);
return false;
}
static void threaded_worker(void *userdata)
{
(void)userdata;
for (;;)
{
retro_task_t *queue = NULL;
retro_task_t *task = NULL;
retro_task_t *next = NULL;
/* pop all into a local queue,
* tasks are in the reverse order here. */
slock_lock(running_lock);
if (!worker_continue)
break; /* should we keep running until all tasks finished? */
while ((task = task_queue_get(&tasks_running)) != NULL)
{
task->next = queue;
queue = task;
}
if (queue == NULL) /* no tasks running, lets wait a bit */
{
scond_wait(worker_cond, running_lock);
slock_unlock(running_lock);
continue;
}
slock_unlock(running_lock);
for (task = queue; task; task = next)
{
next = task->next;
task->handler(task);
if (task->finished)
{
slock_lock(finished_lock);
task_queue_put(&tasks_finished, task);
slock_unlock(finished_lock);
}
else
retro_task_threaded_push_running(task);
}
}
slock_unlock(running_lock);
}
static void retro_task_threaded_init(void)
{
running_lock = slock_new();
finished_lock = slock_new();
worker_cond = scond_new();
slock_lock(running_lock);
worker_continue = true;
slock_unlock(running_lock);
worker_thread = sthread_create(threaded_worker, NULL);
}
static void retro_task_threaded_deinit(void)
{
slock_lock(running_lock);
worker_continue = false;
scond_signal(worker_cond);
slock_unlock(running_lock);
sthread_join(worker_thread);
scond_free(worker_cond);
slock_free(running_lock);
slock_free(finished_lock);
worker_thread = NULL;
worker_cond = NULL;
running_lock = NULL;
finished_lock = NULL;
}
static struct retro_task_impl impl_threaded = {
retro_task_threaded_push_running,
retro_task_threaded_reset,
retro_task_threaded_wait,
retro_task_threaded_gather,
retro_task_threaded_find,
retro_task_threaded_init,
retro_task_threaded_deinit
};
#endif
bool task_queue_ctl(enum task_queue_ctl_state state, void *data)
{
static struct retro_task_impl *impl_current = NULL;
static bool task_threaded_enable = false;
switch (state)
{
case TASK_QUEUE_CTL_DEINIT:
if (impl_current)
impl_current->deinit();
impl_current = NULL;
break;
case TASK_QUEUE_CTL_SET_THREADED:
task_threaded_enable = true;
break;
case TASK_QUEUE_CTL_UNSET_THREADED:
task_threaded_enable = false;
break;
case TASK_QUEUE_CTL_IS_THREADED:
return task_threaded_enable;
case TASK_QUEUE_CTL_INIT:
{
#ifdef HAVE_THREADS
bool *boolean_val = (bool*)data;
#endif
impl_current = &impl_regular;
#ifdef HAVE_THREADS
if (*boolean_val)
{
task_queue_ctl(TASK_QUEUE_CTL_SET_THREADED, NULL);
impl_current = &impl_threaded;
}
#endif
impl_current->init();
}
break;
case TASK_QUEUE_CTL_FIND:
{
task_finder_data_t *find_data = (task_finder_data_t*)data;
if (!impl_current->find(find_data->func, find_data->userdata))
return false;
}
break;
case TASK_QUEUE_CTL_CHECK:
{
#ifdef HAVE_THREADS
bool current_threaded = (impl_current == &impl_threaded);
bool want_threaded =
task_queue_ctl(TASK_QUEUE_CTL_IS_THREADED, NULL);
if (want_threaded != current_threaded)
task_queue_ctl(TASK_QUEUE_CTL_DEINIT, NULL);
if (!impl_current)
task_queue_ctl(TASK_QUEUE_CTL_INIT, NULL);
#endif
impl_current->gather();
}
break;
case TASK_QUEUE_CTL_PUSH:
{
/* The lack of NULL checks in the following functions
* is proposital to ensure correct control flow by the users. */
retro_task_t *task = (retro_task_t*)data;
impl_current->push_running(task);
break;
}
case TASK_QUEUE_CTL_RESET:
impl_current->reset();
break;
case TASK_QUEUE_CTL_WAIT:
impl_current->wait();
break;
case TASK_QUEUE_CTL_NONE:
default:
break;
}
return true;
}

View File

@ -0,0 +1,149 @@
/* Copyright (C) 2010-2015 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (async_job.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>
#include <rthreads/rthreads.h>
#include <rthreads/rsemaphore.h>
#include <rthreads/async_job.h>
typedef struct async_job_node async_job_node_t;
struct async_job_node
{
async_task_t task;
void *payload;
async_job_node_t *next;
};
struct async_job
{
async_job_node_t *first;
async_job_node_t *last;
volatile int finish;
slock_t *lock;
ssem_t *sem;
sthread_t* thread;
};
static void async_job_processor(void *userdata)
{
async_job_node_t *node = NULL;
async_job_t *ajob = (async_job_t*)userdata;
for (;;)
{
ssem_wait(ajob->sem);
if (ajob->finish)
return;
slock_lock(ajob->lock);
node = ajob->first;
ajob->first = node->next;
slock_unlock(ajob->lock);
node->task(node->payload);
free((void*)node);
}
}
async_job_t *async_job_new(void)
{
async_job_t *ajob = (async_job_t*)calloc(1, sizeof(*ajob));
if (!ajob)
return NULL;
ajob->lock = slock_new();
if (!ajob->lock)
goto error;
ajob->sem = ssem_new(0);
if (!ajob->sem)
goto error;
ajob->thread = sthread_create(async_job_processor, (void*)ajob);
if (!ajob->thread)
goto error;
return ajob;
error:
if (ajob->lock)
slock_free(ajob->lock);
ajob->lock = NULL;
if (ajob->sem)
ssem_free(ajob->sem);
if (ajob)
free((void*)ajob);
return NULL;
}
void async_job_free(async_job_t *ajob)
{
if (!ajob)
return;
ajob->finish = 1;
ssem_signal(ajob->sem);
sthread_join(ajob->thread);
ssem_free(ajob->sem);
free((void*)ajob);
}
int async_job_add(async_job_t *ajob, async_task_t task, void *payload)
{
async_job_node_t *node;
if (!ajob)
return -1;
node = (async_job_node_t*)calloc(1, sizeof(*node));
if (!node)
return -1;
node->task = task;
node->payload = payload;
slock_lock(ajob->lock);
if (ajob->first)
{
ajob->last->next = node;
ajob->last = node;
}
else
ajob->first = ajob->last = node;
slock_unlock(ajob->lock);
ssem_signal(ajob->sem);
return 0;
}

View File

@ -0,0 +1,116 @@
/*
Copyright 2005 Allen B. Downey
This file contains an example program from The Little Book of
Semaphores, available from Green Tea Press, greenteapress.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see http://www.gnu.org/licenses/gpl.html
or write to the Free Software Foundation, Inc., 51 Franklin St,
Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Code taken from http://greenteapress.com/semaphores/semaphore.c
* and changed to use libretro-common's mutexes and conditions.
*/
#include <stdlib.h>
#include <rthreads/rthreads.h>
#include <rthreads/rsemaphore.h>
struct ssem
{
int value;
int wakeups;
slock_t *mutex;
scond_t *cond;
};
ssem_t *ssem_new(int value)
{
ssem_t *semaphore = (ssem_t*)calloc(1, sizeof(*semaphore));
if (!semaphore)
goto error;
semaphore->value = value;
semaphore->wakeups = 0;
semaphore->mutex = slock_new();
if (!semaphore->mutex)
goto error;
semaphore->cond = scond_new();
if (!semaphore->cond)
goto error;
return semaphore;
error:
if (semaphore->mutex)
slock_free(semaphore->mutex);
semaphore->mutex = NULL;
if (semaphore)
free((void*)semaphore);
return NULL;
}
void ssem_free(ssem_t *semaphore)
{
if (!semaphore)
return;
scond_free(semaphore->cond);
slock_free(semaphore->mutex);
free((void*)semaphore);
}
void ssem_wait(ssem_t *semaphore)
{
if (!semaphore)
return;
slock_lock(semaphore->mutex);
semaphore->value--;
if (semaphore->value < 0)
{
do
{
scond_wait(semaphore->cond, semaphore->mutex);
}while (semaphore->wakeups < 1);
semaphore->wakeups--;
}
slock_unlock(semaphore->mutex);
}
void ssem_signal(ssem_t *semaphore)
{
if (!semaphore)
return;
slock_lock(semaphore->mutex);
semaphore->value++;
if (semaphore->value <= 0)
{
semaphore->wakeups++;
scond_signal(semaphore->cond);
}
slock_unlock(semaphore->mutex);
}

View File

@ -22,6 +22,7 @@
#include <stdlib.h>
#include <boolean.h>
#include <rthreads/rthreads.h>
#if defined(_WIN32)
@ -104,36 +105,39 @@ static void *thread_wrap(void *data_)
*/
sthread_t *sthread_create(void (*thread_func)(void*), void *userdata)
{
bool thread_created = false;
struct thread_data *data = NULL;
sthread_t *thread = (sthread_t*)calloc(1, sizeof(*thread));
struct thread_data *data;
if (!thread)
return NULL;
data = (struct thread_data*)calloc(1, sizeof(*data));
if (!data)
{
free(thread);
return NULL;
}
goto error;
data->func = thread_func;
data->userdata = userdata;
#ifdef _WIN32
thread->thread = CreateThread(NULL, 0, thread_wrap, data, 0, NULL);
if (!thread->thread)
thread_created = thread->thread;
#else
if (pthread_create(&thread->id, NULL, thread_wrap, data) < 0)
thread_created = pthread_create(&thread->id, NULL, thread_wrap, data) == 0;
#endif
{
if (!thread_created)
goto error;
return thread;
error:
if (data)
free(data);
free(thread);
return NULL;
}
return thread;
}
/**
* sthread_detach:
* @thread : pointer to thread object
@ -188,22 +192,26 @@ void sthread_join(sthread_t *thread)
**/
slock_t *slock_new(void)
{
bool mutex_created = false;
slock_t *lock = (slock_t*)calloc(1, sizeof(*lock));
if (!lock)
return NULL;
#ifdef _WIN32
lock->lock = CreateMutex(NULL, FALSE, NULL);
if (!lock->lock)
mutex_created = lock->lock;
#else
if (pthread_mutex_init(&lock->lock, NULL) < 0)
mutex_created = (pthread_mutex_init(&lock->lock, NULL) == 0);
#endif
{
free(lock);
return NULL;
}
if (!mutex_created)
goto error;
return lock;
error:
free(lock);
return NULL;
}
/**
@ -268,22 +276,27 @@ void slock_unlock(slock_t *lock)
**/
scond_t *scond_new(void)
{
bool event_created = false;
scond_t *cond = (scond_t*)calloc(1, sizeof(*cond));
if (!cond)
return NULL;
#ifdef _WIN32
cond->event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!cond->event)
event_created = cond->event;
#else
if (pthread_cond_init(&cond->cond, NULL) < 0)
event_created = (pthread_cond_init(&cond->cond, NULL) == 0);
#endif
{
free(cond);
return NULL;
}
if (!event_created)
goto error;
return cond;
error:
free(cond);
return NULL;
}
/**

View File

@ -0,0 +1,538 @@
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream.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 <errno.h>
#if defined(_WIN32)
# ifdef _MSC_VER
# define setmode _setmode
# endif
# ifdef _XBOX
# include <xtl.h>
# define INVALID_FILE_ATTRIBUTES -1
# else
# include <io.h>
# include <fcntl.h>
# include <direct.h>
# include <windows.h>
# endif
#elif defined(VITA)
# include <psp2/io/fcntl.h>
# include <psp2/io/dirent.h>
#define PSP_O_RDONLY PSP2_O_RDONLY
#define PSP_O_RDWR PSP2_O_RDWR
#define PSP_O_CREAT PSP2_O_CREAT
#define PSP_O_WRONLY PSP2_O_WRONLY
#define PSP_O_TRUNC PSP2_O_TRUNC
#else
# if defined(PSP)
# include <pspiofilemgr.h>
# endif
# include <sys/types.h>
# include <sys/stat.h>
# include <dirent.h>
# include <unistd.h>
#endif
#ifdef __CELLOS_LV2__
#include <cell/cell_fs.h>
#else
#include <fcntl.h>
#endif
#include <streams/file_stream.h>
#include <memmap.h>
#if 1
#define HAVE_BUFFERED_IO 1
#endif
struct RFILE
{
unsigned hints;
#if defined(PSP) || defined(VITA)
SceUID fd;
#elif defined(__CELLOS_LV2__)
int fd;
#else
#if defined(HAVE_BUFFERED_IO)
FILE *fp;
#endif
#if defined(HAVE_MMAP)
uint8_t *mapped;
uint64_t mappos;
uint64_t mapsize;
#endif
int fd;
#endif
};
int filestream_get_fd(RFILE *stream)
{
if (!stream)
return -1;
#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__)
return stream->fd;
#else
#if defined(HAVE_BUFFERED_IO)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
return fileno(stream->fp);
#endif
return stream->fd;
#endif
}
RFILE *filestream_open(const char *path, unsigned mode, ssize_t len)
{
int flags = 0;
int mode_int = 0;
const char *mode_str = NULL;
RFILE *stream = (RFILE*)calloc(1, sizeof(*stream));
if (!stream)
return NULL;
(void)mode_str;
(void)mode_int;
(void)flags;
stream->hints = mode;
#ifdef HAVE_MMAP
if (stream->hints & RFILE_HINT_MMAP && (stream->hints & 0xff) == RFILE_MODE_READ)
stream->hints |= RFILE_HINT_UNBUFFERED;
else
#endif
stream->hints &= ~RFILE_HINT_MMAP;
switch (mode & 0xff)
{
case RFILE_MODE_READ:
#if defined(VITA) || defined(PSP)
mode_int = 0777;
flags = PSP_O_RDONLY;
#elif defined(__CELLOS_LV2__)
mode_int = 0777;
flags = CELL_FS_O_RDONLY;
#else
#if defined(HAVE_BUFFERED_IO)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
mode_str = "rb";
#endif
/* No "else" here */
flags = O_RDONLY;
#endif
break;
case RFILE_MODE_WRITE:
#if defined(VITA) || defined(PSP)
mode_int = 0777;
flags = PSP_O_CREAT | PSP_O_WRONLY | PSP_O_TRUNC;
#elif defined(__CELLOS_LV2__)
mode_int = 0777;
flags = CELL_FS_O_CREAT | CELL_FS_O_WRONLY | CELL_FS_O_TRUNC;
#else
#if defined(HAVE_BUFFERED_IO)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
mode_str = "wb";
#endif
else
{
flags = O_WRONLY | O_CREAT | O_TRUNC;
#ifndef _WIN32
flags |= S_IRUSR | S_IWUSR;
#endif
}
#endif
break;
case RFILE_MODE_READ_WRITE:
#if defined(VITA) || defined(PSP)
mode_int = 0777;
flags = PSP_O_RDWR;
#elif defined(__CELLOS_LV2__)
mode_int = 0777;
flags = CELL_FS_O_RDWR;
#else
#if defined(HAVE_BUFFERED_IO)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
mode_str = "w+";
#endif
else
{
flags = O_RDWR;
#ifdef _WIN32
flags |= O_BINARY;
#endif
}
#endif
break;
}
#if defined(VITA) || defined(PSP)
stream->fd = sceIoOpen(path, flags, mode_int);
#elif defined(__CELLOS_LV2__)
cellFsOpen(path, flags, &stream->fd, NULL, 0);
#else
#if defined(HAVE_BUFFERED_IO)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
{
stream->fp = fopen(path, mode_str);
if (!stream->fp)
goto error;
}
else
#endif
{
stream->fd = open(path, flags);
if (stream->fd == -1)
goto error;
#ifdef HAVE_MMAP
if (stream->hints & RFILE_HINT_MMAP)
{
stream->mappos = 0;
stream->mapped = NULL;
stream->mapsize = filestream_seek(stream, 0, SEEK_END);
if (stream->mapsize == (uint64_t)-1)
goto error;
filestream_rewind(stream);
stream->mapped = (uint8_t*)mmap((void*)0, stream->mapsize, PROT_READ, MAP_SHARED, stream->fd, 0);
if (stream->mapped == MAP_FAILED)
stream->hints &= ~RFILE_HINT_MMAP;
}
#endif
}
#endif
#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__)
if (stream->fd == -1)
goto error;
#endif
return stream;
error:
filestream_close(stream);
return NULL;
}
ssize_t filestream_seek(RFILE *stream, ssize_t offset, int whence)
{
int ret = 0;
if (!stream)
return -1;
(void)ret;
#if defined(VITA) || defined(PSP)
ret = sceIoLseek(stream->fd, (SceOff)offset, whence);
if (ret == -1)
return -1;
return 0;
#elif defined(__CELLOS_LV2__)
uint64_t pos = 0;
if (cellFsLseek(stream->fd, offset, whence, &pos) != CELL_FS_SUCCEEDED)
return -1;
return 0;
#else
#if defined(HAVE_BUFFERED_IO)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
return fseek(stream->fp, (long)offset, whence);
else
#endif
#ifdef HAVE_MMAP
/* Need to check stream->mapped because this function is
* called in filestream_open() */
if (stream->mapped && stream->hints & RFILE_HINT_MMAP)
{
/* fseek() returns error on under/overflow but allows cursor > EOF for
read-only file descriptors. */
switch (whence)
{
case SEEK_SET:
if (offset < 0)
return -1;
stream->mappos = offset;
break;
case SEEK_CUR:
if ((offset < 0 && stream->mappos + offset > stream->mappos) ||
(offset > 0 && stream->mappos + offset < stream->mappos))
return -1;
stream->mappos += offset;
break;
case SEEK_END:
if (stream->mapsize + offset < stream->mapsize)
return -1;
stream->mappos = stream->mapsize + offset;
break;
}
return stream->mappos;
}
else
#endif
{
ret = lseek(stream->fd, offset, whence);
return ret < 0 ? -1 : ret;
}
#endif
}
ssize_t filestream_tell(RFILE *stream)
{
if (!stream)
return -1;
#if defined(VITA) || defined(PSP)
return sceIoLseek(stream->fd, 0, SEEK_CUR);
#elif defined(__CELLOS_LV2__)
uint64_t pos = 0;
if (cellFsLseek(stream->fd, 0, CELL_FS_SEEK_CUR, &pos) != CELL_FS_SUCCEEDED)
return -1;
return 0;
#else
#if defined(HAVE_BUFFERED_IO)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
return ftell(stream->fp);
else
#endif
#ifdef HAVE_MMAP
/* Need to check stream->mapped because this function
* is called in filestream_open() */
if (stream->mapped && stream->hints & RFILE_HINT_MMAP)
return stream->mappos;
else
#endif
return lseek(stream->fd, 0, SEEK_CUR);
#endif
}
void filestream_rewind(RFILE *stream)
{
filestream_seek(stream, 0L, SEEK_SET);
}
ssize_t filestream_read(RFILE *stream, void *s, size_t len)
{
if (!stream || !s)
return -1;
#if defined(VITA) || defined(PSP)
return sceIoRead(stream->fd, s, len);
#elif defined(__CELLOS_LV2__)
uint64_t bytes_written;
if (cellFsRead(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED)
return -1;
return bytes_written;
#else
#if defined(HAVE_BUFFERED_IO)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
return fread(s, 1, len, stream->fp);
else
#endif
#ifdef HAVE_MMAP
if (stream->hints & RFILE_HINT_MMAP)
{
if (stream->mappos > stream->mapsize)
return -1;
if (stream->mappos + len > stream->mapsize)
len = stream->mapsize - stream->mappos;
memcpy(s, &stream->mapped[stream->mappos], len);
stream->mappos += len;
return len;
}
else
#endif
return read(stream->fd, s, len);
#endif
}
ssize_t filestream_write(RFILE *stream, const void *s, size_t len)
{
if (!stream)
return -1;
#if defined(VITA) || defined(PSP)
return sceIoWrite(stream->fd, s, len);
#elif defined(__CELLOS_LV2__)
uint64_t bytes_written;
if (cellFsWrite(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED)
return -1;
return bytes_written;
#else
#if defined(HAVE_BUFFERED_IO)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
return fwrite(s, 1, len, stream->fp);
else
#endif
#ifdef HAVE_MMAP
if (stream->hints & RFILE_HINT_MMAP)
return -1;
else
#endif
return write(stream->fd, s, len);
#endif
}
int filestream_close(RFILE *stream)
{
if (!stream)
return -1;
#if defined(VITA) || defined(PSP)
if (stream->fd > 0)
sceIoClose(stream->fd);
#elif defined(__CELLOS_LV2__)
if (stream->fd > 0)
cellFsClose(stream->fd);
#else
#if defined(HAVE_BUFFERED_IO)
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
{
if (stream->fp)
fclose(stream->fp);
}
else
#endif
#ifdef HAVE_MMAP
if (stream->hints & RFILE_HINT_MMAP)
munmap(stream->mapped, stream->mapsize);
#endif
if (stream->fd > 0)
close(stream->fd);
#endif
free(stream);
return 0;
}
/**
* filestream_read_file:
* @path : path to file.
* @buf : buffer to allocate and read the contents of the
* file into. Needs to be freed manually.
*
* Read the contents of a file into @buf.
*
* Returns: number of items read, -1 on error.
*/
int filestream_read_file(const char *path, void **buf, ssize_t *len)
{
ssize_t ret = 0;
ssize_t content_buf_size = 0;
void *content_buf = NULL;
RFILE *file = filestream_open(path, RFILE_MODE_READ, -1);
if (!file)
{
#if __STDC_VERSION__ >= 199901L
fprintf(stderr, "%s: Failed to open %s: %s\n", __FUNCTION__, path, strerror(errno));
#else
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
#endif
goto error;
}
if (filestream_seek(file, 0, SEEK_END) != 0)
goto error;
content_buf_size = filestream_tell(file);
if (content_buf_size < 0)
goto error;
filestream_rewind(file);
content_buf = malloc(content_buf_size + 1);
if (!content_buf)
goto error;
ret = filestream_read(file, content_buf, content_buf_size);
if (ret < 0)
{
#if __STDC_VERSION__ >= 199901L
fprintf(stderr, "%s: Failed to read %s: %s\n", __FUNCTION__, path, strerror(errno));
#else
fprintf(stderr, "Failed to read %s: %s\n", path, strerror(errno));
#endif
goto error;
}
filestream_close(file);
*buf = content_buf;
/* Allow for easy reading of strings to be safe.
* Will only work with sane character formatting (Unix). */
((char*)content_buf)[content_buf_size] = '\0';
if (len)
*len = ret;
return 1;
error:
if (file)
filestream_close(file);
if (content_buf)
free(content_buf);
if (len)
*len = -1;
*buf = NULL;
return 0;
}
/**
* filestream_write_file:
* @path : path to file.
* @data : contents to write to the file.
* @size : size of the contents.
*
* Writes data to a file.
*
* Returns: true (1) on success, false (0) otherwise.
*/
bool filestream_write_file(const char *path, const void *data, ssize_t size)
{
ssize_t ret = 0;
RFILE *file = filestream_open(path, RFILE_MODE_WRITE, -1);
if (!file)
return false;
ret = filestream_write(file, data, size);
filestream_close(file);
return (ret == size);
}

View File

@ -27,7 +27,7 @@
FileStream::FileStream(const char *path, const int mode): OpenedMode(mode)
{
fp = retro_fopen(path, (mode == MODE_WRITE) ? RFILE_MODE_WRITE : RFILE_MODE_READ, -1);
fp = filestream_open(path, (mode == MODE_WRITE) ? RFILE_MODE_WRITE : RFILE_MODE_READ, -1);
if (!fp)
{
@ -68,28 +68,28 @@ uint64_t FileStream::read(void *data, uint64_t count, bool error_on_eos)
{
if (!fp)
return 0;
return retro_fread(fp, data, count);
return filestream_read(fp, data, count);
}
void FileStream::write(const void *data, uint64_t count)
{
if (!fp)
return;
retro_fwrite(fp, data, count);
filestream_write(fp, data, count);
}
void FileStream::seek(int64_t offset, int whence)
{
if (!fp)
return;
retro_fseek(fp, offset, whence);
filestream_seek(fp, offset, whence);
}
int64_t FileStream::tell(void)
{
if (!fp)
return -1;
return retro_ftell(fp);
return filestream_tell(fp);
}
int64_t FileStream::size(void)
@ -104,5 +104,5 @@ void FileStream::close(void)
{
if (!fp)
return;
retro_fclose(fp);
filestream_close(fp);
}

View File

@ -20,7 +20,7 @@
#ifndef __MDFN_FILESTREAM_H
#define __MDFN_FILESTREAM_H
#include <retro_file.h>
#include <streams/file_stream.h>
#include <retro_stat.h>
#include "Stream.h"