Merge pull request #113 from negativeExponent/scd_memmap

Update libretro-common, add Sega CD memory map
This commit is contained in:
Twinaphex
2020-01-12 05:40:19 +01:00
committed by GitHub
25 changed files with 1504 additions and 315 deletions

View File

@@ -36,9 +36,7 @@
void *fopen_utf8(const char * filename, const char * mode) void *fopen_utf8(const char * filename, const char * mode)
{ {
#if defined(_XBOX) #if defined(LEGACY_WIN32)
return fopen(filename, mode);
#elif defined(LEGACY_WIN32)
FILE *ret = NULL; FILE *ret = NULL;
char * filename_local = utf8_to_local_string_alloc(filename); char * filename_local = utf8_to_local_string_alloc(filename);

View File

@@ -211,10 +211,7 @@ size_t utf8len(const char *string)
return ret; return ret;
} }
static uint8_t utf8_walkbyte(const char **string) #define utf8_walkbyte(string) (*((*(string))++))
{
return *((*string)++);
}
/* Does not validate the input, returns garbage if it's not UTF-8. */ /* Does not validate the input, returns garbage if it's not UTF-8. */
uint32_t utf8_walk(const char **string) uint32_t utf8_walk(const char **string)
@@ -227,14 +224,16 @@ uint32_t utf8_walk(const char **string)
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F); ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
if (first >= 0xE0) if (first >= 0xE0)
{
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F); ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
if (first >= 0xF0) if (first >= 0xF0)
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F); {
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
if (first >= 0xF0) return ret | (first & 7) << 18;
return ret | (first & 7) << 18; }
if (first >= 0xE0)
return ret | (first & 15) << 12; return ret | (first & 15) << 12;
}
return ret | (first & 31) << 6; return ret | (first & 31) << 6;
} }
@@ -273,37 +272,25 @@ bool utf16_to_char_string(const uint16_t *in, char *s, size_t len)
return ret; return ret;
} }
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
/* Returned pointer MUST be freed by the caller if non-NULL. */ /* Returned pointer MUST be freed by the caller if non-NULL. */
static char* mb_to_mb_string_alloc(const char *str, static char *mb_to_mb_string_alloc(const char *str,
enum CodePage cp_in, enum CodePage cp_out) enum CodePage cp_in, enum CodePage cp_out)
{ {
char *path_buf = NULL; char *path_buf = NULL;
wchar_t *path_buf_wide = NULL; wchar_t *path_buf_wide = NULL;
int path_buf_len = 0; int path_buf_len = 0;
int path_buf_wide_len = 0; int path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
if (!str || !*str) /* Windows 95 will return 0 from these functions with
return NULL; * a UTF8 codepage set without MSLU.
*
(void)path_buf; * From an unknown MSDN version (others omit this info):
(void)path_buf_wide; * - CP_UTF8 Windows 98/Me, Windows NT 4.0 and later:
(void)path_buf_len; * Translate using UTF-8. When this is set, dwFlags must be zero.
(void)path_buf_wide_len; * - Windows 95: Under the Microsoft Layer for Unicode,
* MultiByteToWideChar also supports CP_UTF7 and CP_UTF8.
#if !defined(_WIN32) || defined(_XBOX)
/* assume string needs no modification if not on Windows */
return strdup(str);
#else
#ifdef UNICODE
/* TODO/FIXME: Not implemented. */
return strdup(str);
#else
/* Windows 95 will return 0 from these functions with a UTF8 codepage set without MSLU. From an unknown MSDN version (others omit this info):
* - CP_UTF8 Windows 98/Me, Windows NT 4.0 and later: Translate using UTF-8. When this is set, dwFlags must be zero.
* - Windows 95: Under the Microsoft Layer for Unicode, MultiByteToWideChar also supports CP_UTF7 and CP_UTF8.
*/ */
path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
if (path_buf_wide_len) if (path_buf_wide_len)
{ {
@@ -355,20 +342,37 @@ static char* mb_to_mb_string_alloc(const char *str,
free(path_buf_wide); free(path_buf_wide);
return NULL; return NULL;
#endif
#endif
} }
#endif
/* Returned pointer MUST be freed by the caller if non-NULL. */ /* Returned pointer MUST be freed by the caller if non-NULL. */
char* utf8_to_local_string_alloc(const char *str) char* utf8_to_local_string_alloc(const char *str)
{ {
return mb_to_mb_string_alloc(str, CODEPAGE_UTF8, CODEPAGE_LOCAL); if (str && *str)
{
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
return mb_to_mb_string_alloc(str, CODEPAGE_UTF8, CODEPAGE_LOCAL);
#else
/* assume string needs no modification if not on Windows */
return strdup(str);
#endif
}
return NULL;
} }
/* Returned pointer MUST be freed by the caller if non-NULL. */ /* Returned pointer MUST be freed by the caller if non-NULL. */
char* local_to_utf8_string_alloc(const char *str) char* local_to_utf8_string_alloc(const char *str)
{ {
return mb_to_mb_string_alloc(str, CODEPAGE_LOCAL, CODEPAGE_UTF8); if (str && *str)
{
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
return mb_to_mb_string_alloc(str, CODEPAGE_LOCAL, CODEPAGE_UTF8);
#else
/* assume string needs no modification if not on Windows */
return strdup(str);
#endif
}
return NULL;
} }
/* Returned pointer MUST be freed by the caller if non-NULL. */ /* Returned pointer MUST be freed by the caller if non-NULL. */
@@ -447,52 +451,44 @@ wchar_t* utf8_to_utf16_string_alloc(const char *str)
char* utf16_to_utf8_string_alloc(const wchar_t *str) char* utf16_to_utf8_string_alloc(const wchar_t *str)
{ {
#ifdef _WIN32 #ifdef _WIN32
int len = 0; int len = 0;
int out_len = 0;
#else #else
size_t len = 0; size_t len = 0;
size_t out_len = 0;
#endif #endif
char *buf = NULL; char *buf = NULL;
if (!str || !*str) if (!str || !*str)
return NULL; return NULL;
#ifdef _WIN32 #ifdef _WIN32
len = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
if (len)
{ {
UINT code_page = CP_UTF8;
len = WideCharToMultiByte(code_page,
0, str, -1, NULL, 0, NULL, NULL);
/* fallback to ANSI codepage instead */
if (!len)
{
code_page = CP_ACP;
len = WideCharToMultiByte(code_page,
0, str, -1, NULL, 0, NULL, NULL);
}
buf = (char*)calloc(len, sizeof(char)); buf = (char*)calloc(len, sizeof(char));
if (!buf) if (!buf)
return NULL; return NULL;
out_len = WideCharToMultiByte(CP_UTF8, 0, str, -1, buf, len, NULL, NULL); if (WideCharToMultiByte(code_page,
} 0, str, -1, buf, len, NULL, NULL) < 0)
else
{
/* fallback to ANSI codepage instead */
len = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
if (len)
{ {
buf = (char*)calloc(len, sizeof(char)); free(buf);
return NULL;
if (!buf)
return NULL;
out_len = WideCharToMultiByte(CP_ACP, 0, str, -1, buf, len, NULL, NULL);
} }
} }
if (out_len < 0)
{
free(buf);
return NULL;
}
#else #else
/* NOTE: For now, assume non-Windows platforms' locale is already UTF-8. */ /* NOTE: For now, assume non-Windows platforms'
* locale is already UTF-8. */
len = wcstombs(NULL, str, 0) + 1; len = wcstombs(NULL, str, 0) + 1;
if (len) if (len)
@@ -502,13 +498,11 @@ char* utf16_to_utf8_string_alloc(const wchar_t *str)
if (!buf) if (!buf)
return NULL; return NULL;
out_len = wcstombs(buf, str, len); if (wcstombs(buf, str, len) == (size_t)-1)
} {
free(buf);
if (out_len == (size_t)-1) return NULL;
{ }
free(buf);
return NULL;
} }
#endif #endif

View File

@@ -72,4 +72,3 @@ RETRO_END_DECLS
/* pragma once */ /* pragma once */
#endif #endif

View File

@@ -41,7 +41,7 @@ RETRO_BEGIN_DECLS
/* Count Leading Zero, unsigned 16bit input value */ /* Count Leading Zero, unsigned 16bit input value */
static INLINE unsigned compat_clz_u16(uint16_t val) static INLINE unsigned compat_clz_u16(uint16_t val)
{ {
#ifdef __GNUC__ #if defined(__GNUC__) && !defined(PS2)
return __builtin_clz(val << 16 | 0x8000); return __builtin_clz(val << 16 | 0x8000);
#else #else
unsigned ret = 0; unsigned ret = 0;
@@ -61,7 +61,7 @@ static INLINE int compat_ctz(unsigned x)
{ {
#if defined(__GNUC__) && !defined(RARCH_CONSOLE) #if defined(__GNUC__) && !defined(RARCH_CONSOLE)
return __builtin_ctz(x); return __builtin_ctz(x);
#elif _MSC_VER >= 1400 && !defined(_XBOX) #elif _MSC_VER >= 1400 && !defined(_XBOX) && !defined(__WINRT__)
unsigned long r = 0; unsigned long r = 0;
_BitScanReverse((unsigned long*)&r, x); _BitScanReverse((unsigned long*)&r, x);
return (int)r; return (int)r;

View File

@@ -31,6 +31,7 @@ extern "C" {
/* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */ /* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */
#if _MSC_VER < 1900 #if _MSC_VER < 1900
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef snprintf #ifndef snprintf
#define snprintf c99_snprintf_retro__ #define snprintf c99_snprintf_retro__
@@ -39,8 +40,9 @@ extern "C" {
int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...); int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...);
#endif #endif
/* Pre-MSVC 2010 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */ /* Pre-MSVC 2008 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
#if _MSC_VER < 1600 #if _MSC_VER < 1500
#include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef vsnprintf #ifndef vsnprintf
@@ -56,6 +58,8 @@ extern "C" {
#undef UNICODE /* Do not bother with UNICODE at this time. */ #undef UNICODE /* Do not bother with UNICODE at this time. */
#include <direct.h> #include <direct.h>
#include <stddef.h> #include <stddef.h>
#define _USE_MATH_DEFINES
#include <math.h> #include <math.h>
/* Python headers defines ssize_t and sets HAVE_SSIZE_T. /* Python headers defines ssize_t and sets HAVE_SSIZE_T.
@@ -125,4 +129,3 @@ typedef int ssize_t;
#endif #endif
#endif #endif

View File

@@ -67,7 +67,6 @@ extern "C" {
# endif # endif
#endif #endif
/* 7.18.1 Integer types. */ /* 7.18.1 Integer types. */
/* 7.18.1.1 Exact-width integer types. */ /* 7.18.1.1 Exact-width integer types. */
@@ -94,7 +93,6 @@ extern "C" {
typedef signed __int64 int64_t; typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t; typedef unsigned __int64 uint64_t;
/* 7.18.1.2 Minimum-width integer types. */ /* 7.18.1.2 Minimum-width integer types. */
typedef int8_t int_least8_t; typedef int8_t int_least8_t;
typedef int16_t int_least16_t; typedef int16_t int_least16_t;
@@ -255,4 +253,3 @@ typedef uint64_t uintmax_t;
#endif #endif
#endif #endif

View File

@@ -29,6 +29,10 @@
#include <compat/msvc.h> #include <compat/msvc.h>
#endif #endif
#if defined(PS2)
#include <compat_ctype.h>
#endif
RETRO_BEGIN_DECLS RETRO_BEGIN_DECLS
#ifdef _WIN32 #ifdef _WIN32
@@ -55,7 +59,6 @@ int isblank(int c);
#endif #endif
RETRO_END_DECLS RETRO_END_DECLS
#endif #endif

View File

@@ -25,6 +25,10 @@
#include <string.h> #include <string.h>
#if defined(PS2)
#include <compat_ctype.h>
#endif
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H) #if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
#include "../../../config.h" #include "../../../config.h"
#endif #endif
@@ -46,4 +50,3 @@ RETRO_END_DECLS
#endif #endif
#endif #endif

View File

@@ -57,4 +57,3 @@ char *strldup(const char *s, size_t n);
RETRO_END_DECLS RETRO_END_DECLS
#endif #endif

View File

@@ -1117,7 +1117,7 @@ enum retro_mod
* This may be still be done regardless of the core options * This may be still be done regardless of the core options
* interface version. * interface version.
* *
* If version is >= 1 however, core options may instead be set by * If version is 1 however, core options may instead be set by
* passing an array of retro_core_option_definition structs to * passing an array of retro_core_option_definition structs to
* RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of * RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of
* retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL. * retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL.
@@ -1132,8 +1132,8 @@ enum retro_mod
* GET_VARIABLE. * GET_VARIABLE.
* This allows the frontend to present these variables to * This allows the frontend to present these variables to
* a user dynamically. * a user dynamically.
* This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION * This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
* returns an API version of >= 1. * returns an API version of 1.
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
* This should be called the first time as early as * This should be called the first time as early as
* possible (ideally in retro_set_environment). * possible (ideally in retro_set_environment).
@@ -1169,6 +1169,8 @@ enum retro_mod
* i.e. it should be feasible to cycle through options * i.e. it should be feasible to cycle through options
* without a keyboard. * without a keyboard.
* *
* First entry should be treated as a default.
*
* Example entry: * Example entry:
* { * {
* "foo_option", * "foo_option",
@@ -1194,8 +1196,8 @@ enum retro_mod
* GET_VARIABLE. * GET_VARIABLE.
* This allows the frontend to present these variables to * This allows the frontend to present these variables to
* a user dynamically. * a user dynamically.
* This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION * This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
* returns an API version of >= 1. * returns an API version of 1.
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
* This should be called the first time as early as * This should be called the first time as early as
* possible (ideally in retro_set_environment). * possible (ideally in retro_set_environment).
@@ -1246,6 +1248,16 @@ enum retro_mod
* default when calling SET_VARIABLES/SET_CORE_OPTIONS. * default when calling SET_VARIABLES/SET_CORE_OPTIONS.
*/ */
#define RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER 56
/* unsigned * --
*
* Allows an implementation to ask frontend preferred hardware
* context to use. Core should use this information to deal
* with what specific context to request with SET_HW_RENDER.
*
* 'data' points to an unsigned variable
*/
/* VFS functionality */ /* VFS functionality */
/* File paths: /* File paths:
@@ -1922,6 +1934,10 @@ enum retro_sensor_action
{ {
RETRO_SENSOR_ACCELEROMETER_ENABLE = 0, RETRO_SENSOR_ACCELEROMETER_ENABLE = 0,
RETRO_SENSOR_ACCELEROMETER_DISABLE, RETRO_SENSOR_ACCELEROMETER_DISABLE,
RETRO_SENSOR_GYROSCOPE_ENABLE,
RETRO_SENSOR_GYROSCOPE_DISABLE,
RETRO_SENSOR_ILLUMINANCE_ENABLE,
RETRO_SENSOR_ILLUMINANCE_DISABLE,
RETRO_SENSOR_DUMMY = INT_MAX RETRO_SENSOR_DUMMY = INT_MAX
}; };
@@ -1930,6 +1946,10 @@ enum retro_sensor_action
#define RETRO_SENSOR_ACCELEROMETER_X 0 #define RETRO_SENSOR_ACCELEROMETER_X 0
#define RETRO_SENSOR_ACCELEROMETER_Y 1 #define RETRO_SENSOR_ACCELEROMETER_Y 1
#define RETRO_SENSOR_ACCELEROMETER_Z 2 #define RETRO_SENSOR_ACCELEROMETER_Z 2
#define RETRO_SENSOR_GYROSCOPE_X 3
#define RETRO_SENSOR_GYROSCOPE_Y 4
#define RETRO_SENSOR_GYROSCOPE_Z 5
#define RETRO_SENSOR_ILLUMINANCE 6
typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port, typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port,
enum retro_sensor_action action, unsigned rate); enum retro_sensor_action action, unsigned rate);
@@ -2502,20 +2522,8 @@ struct retro_core_option_display
}; };
/* Maximum number of values permitted for a core option /* Maximum number of values permitted for a core option
* > Note: We have to set a maximum value due the limitations * NOTE: This may be increased on a core-by-core basis
* of the C language - i.e. it is not possible to create an * if required (doing so has no effect on the frontend) */
* array of structs each containing a variable sized array,
* so the retro_core_option_definition values array must
* have a fixed size. The size limit of 128 is a balancing
* act - it needs to be large enough to support all 'sane'
* core options, but setting it too large may impact low memory
* platforms. In practise, if a core option has more than
* 128 values then the implementation is likely flawed.
* To quote the above API reference:
* "The number of possible options should be very limited
* i.e. it should be feasible to cycle through options
* without a keyboard."
*/
#define RETRO_NUM_CORE_OPTION_VALUES_MAX 128 #define RETRO_NUM_CORE_OPTION_VALUES_MAX 128
struct retro_core_option_value struct retro_core_option_value

View File

@@ -26,7 +26,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#if defined(__CELLOS_LV2__) || defined(PSP) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH) #if defined(__CELLOS_LV2__) || defined(PSP) || defined(PS2) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH) || defined(HAVE_LIBNX)
/* No mman available */ /* No mman available */
#elif defined(_WIN32) && !defined(_XBOX) #elif defined(_WIN32) && !defined(_XBOX)
#include <windows.h> #include <windows.h>

View File

@@ -34,4 +34,3 @@ in a public API, you may need this.
#include <compat/msvc.h> #include <compat/msvc.h>
#endif #endif

View File

@@ -89,7 +89,9 @@ typedef int ssize_t;
/* C++11 says this one isn't needed, but apparently (some versions of) mingw require it anyways */ /* C++11 says this one isn't needed, but apparently (some versions of) mingw require it anyways */
/* https://stackoverflow.com/questions/8132399/how-to-printf-uint64-t-fails-with-spurious-trailing-in-format */ /* https://stackoverflow.com/questions/8132399/how-to-printf-uint64-t-fails-with-spurious-trailing-in-format */
/* https://github.com/libretro/RetroArch/issues/6009 */ /* https://github.com/libretro/RetroArch/issues/6009 */
#define __STDC_FORMAT_MACROS #ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS 1
#endif
#include <inttypes.h> #include <inttypes.h>
#endif #endif
#ifndef PRId64 #ifndef PRId64
@@ -113,6 +115,5 @@ Of course, another school of thought is that you should do as little damage as p
in as few places as possible... in as few places as possible...
*/ */
/* _LIBRETRO_COMMON_RETRO_COMMON_API_H */ /* _LIBRETRO_COMMON_RETRO_COMMON_API_H */
#endif #endif

View File

@@ -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 (retro_dirent.h). * The following license statement only applies to this file (retro_dirent.h).
@@ -23,6 +23,7 @@
#ifndef __RETRO_DIRENT_H #ifndef __RETRO_DIRENT_H
#define __RETRO_DIRENT_H #define __RETRO_DIRENT_H
#include <libretro.h>
#include <retro_common_api.h> #include <retro_common_api.h>
#include <retro_miscellaneous.h> #include <retro_miscellaneous.h>
@@ -30,6 +31,10 @@
RETRO_BEGIN_DECLS 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; typedef struct RDIR RDIR;
/** /**
@@ -44,25 +49,27 @@ typedef struct RDIR RDIR;
*/ */
struct RDIR *retro_opendir(const char *name); 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); int retro_readdir(struct RDIR *rdir);
/* Deprecated, returns false, left for compatibility */
bool retro_dirent_error(struct RDIR *rdir); bool retro_dirent_error(struct RDIR *rdir);
void retro_dirent_include_hidden(struct RDIR *rdir, bool include_hidden);
const char *retro_dirent_get_name(struct RDIR *rdir); const char *retro_dirent_get_name(struct RDIR *rdir);
/** /**
* *
* retro_dirent_is_dir: * retro_dirent_is_dir:
* @rdir : pointer to the directory entry. * @rdir : pointer to the directory entry.
* @unused : deprecated, included for compatibility reasons, pass NULL
* *
* Is the directory listing entry a directory? * Is the directory listing entry a directory?
* *
* Returns: true if directory listing entry is * Returns: true if directory listing entry is
* a directory, false if not. * a directory, false if not.
*/ */
bool retro_dirent_is_dir(struct RDIR *rdir, const char *path); bool retro_dirent_is_dir(struct RDIR *rdir, const char *unused);
void retro_closedir(struct RDIR *rdir); void retro_closedir(struct RDIR *rdir);

View File

@@ -73,6 +73,42 @@ printf("This is C++, version %d.\n", __cplusplus);
/* This is not standard C. __STDC__ is not defined. */ /* This is not standard C. __STDC__ is not defined. */
#endif #endif
#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
/* Try to find out if we're compiling for WinRT or non-WinRT */
#if defined(_MSC_VER) && defined(__has_include)
#if __has_include(<winapifamily.h>)
#define HAVE_WINAPIFAMILY_H 1
#else
#define HAVE_WINAPIFAMILY_H 0
#endif
/* If _USING_V110_SDK71_ is defined it means we are using the Windows XP toolset. */
#elif defined(_MSC_VER) && (_MSC_VER >= 1700 && !_USING_V110_SDK71_) /* _MSC_VER == 1700 for Visual Studio 2012 */
#define HAVE_WINAPIFAMILY_H 1
#else
#define HAVE_WINAPIFAMILY_H 0
#endif
#if HAVE_WINAPIFAMILY_H
#include <winapifamily.h>
#define WINAPI_FAMILY_WINRT (!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP))
#else
#define WINAPI_FAMILY_WINRT 0
#endif /* HAVE_WINAPIFAMILY_H */
#if WINAPI_FAMILY_WINRT
#undef __WINRT__
#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

View File

@@ -77,7 +77,7 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
#ifndef PATH_MAX_LENGTH #ifndef PATH_MAX_LENGTH
#if defined(__CELLOS_LV2__) #if defined(__CELLOS_LV2__)
#define PATH_MAX_LENGTH CELL_FS_MAX_FS_PATH_LENGTH #define PATH_MAX_LENGTH CELL_FS_MAX_FS_PATH_LENGTH
#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(GEKKO)|| defined(WIIU) #elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(ORBIS)
#define PATH_MAX_LENGTH 512 #define PATH_MAX_LENGTH 512
#else #else
#define PATH_MAX_LENGTH 4096 #define PATH_MAX_LENGTH 4096
@@ -155,4 +155,28 @@ typedef struct
uint32_t data[8]; uint32_t data[8];
} retro_bits_t; } retro_bits_t;
#ifdef _WIN32
# ifdef _WIN64
# define PRI_SIZET PRIu64
# else
# if _MSC_VER == 1800
# define PRI_SIZET PRIu32
# else
# define PRI_SIZET "u"
# endif
# endif
#elif PS2
# define PRI_SIZET "u"
#else
# if (SIZE_MAX == 0xFFFF)
# define PRI_SIZET "hu"
# elif (SIZE_MAX == 0xFFFFFFFF)
# define PRI_SIZET "u"
# elif (SIZE_MAX == 0xFFFFFFFFFFFFFFFF)
# define PRI_SIZET "lu"
# else
# error PRI_SIZET: unknown SIZE_MAX
# endif
#endif
#endif #endif

View File

@@ -36,19 +36,22 @@
#include <boolean.h> #include <boolean.h>
#include <stdarg.h> #include <stdarg.h>
#include <vfs/vfs_implementation.h>
#define FILESTREAM_REQUIRED_VFS_VERSION 1 #define FILESTREAM_REQUIRED_VFS_VERSION 2
RETRO_BEGIN_DECLS RETRO_BEGIN_DECLS
typedef struct RFILE RFILE; typedef struct RFILE RFILE;
#define FILESTREAM_REQUIRED_VFS_VERSION 1 #define FILESTREAM_REQUIRED_VFS_VERSION 2
void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info); void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info);
int64_t filestream_get_size(RFILE *stream); int64_t filestream_get_size(RFILE *stream);
int64_t filestream_truncate(RFILE *stream, int64_t length);
/** /**
* filestream_open: * filestream_open:
* @path : path to file * @path : path to file
@@ -58,7 +61,7 @@ int64_t filestream_get_size(RFILE *stream);
* Opens a file for reading or writing, depending on the requested mode. * Opens a file for reading or writing, depending on the requested mode.
* Returns a pointer to an RFILE if opened successfully, otherwise NULL. * Returns a pointer to an RFILE if opened successfully, otherwise NULL.
**/ **/
RFILE *filestream_open(const char *path, unsigned mode, unsigned hints); RFILE* filestream_open(const char *path, unsigned mode, unsigned hints);
int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position); int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position);
@@ -74,10 +77,12 @@ int filestream_close(RFILE *stream);
int64_t filestream_read_file(const char *path, void **buf, int64_t *len); int64_t filestream_read_file(const char *path, void **buf, int64_t *len);
char *filestream_gets(RFILE *stream, char *s, size_t len); char* filestream_gets(RFILE *stream, char *s, size_t len);
int filestream_getc(RFILE *stream); int filestream_getc(RFILE *stream);
int filestream_scanf(RFILE *stream, const char* format, ...);
int filestream_eof(RFILE *stream); int filestream_eof(RFILE *stream);
bool filestream_write_file(const char *path, const void *data, int64_t size); bool filestream_write_file(const char *path, const void *data, int64_t size);
@@ -96,11 +101,14 @@ int filestream_delete(const char *path);
int filestream_rename(const char *old_path, const char *new_path); int filestream_rename(const char *old_path, const char *new_path);
const char *filestream_get_path(RFILE *stream); const char* filestream_get_path(RFILE *stream);
bool filestream_exists(const char *path); bool filestream_exists(const char *path);
char *filestream_getline(RFILE *stream); /* Returned pointer must be freed by the caller. */
char* filestream_getline(RFILE *stream);
libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream);
RETRO_END_DECLS RETRO_END_DECLS

View File

@@ -30,6 +30,8 @@
RETRO_BEGIN_DECLS RETRO_BEGIN_DECLS
#ifndef SKIP_STDIO_REDEFINES
#define FILE RFILE #define FILE RFILE
#undef fopen #undef fopen
@@ -41,9 +43,11 @@ RETRO_BEGIN_DECLS
#undef fgetc #undef fgetc
#undef fwrite #undef fwrite
#undef fputc #undef fputc
#undef fflush
#undef fprintf #undef fprintf
#undef ferror #undef ferror
#undef feof #undef feof
#undef fscanf
#define fopen rfopen #define fopen rfopen
#define fclose rfclose #define fclose rfclose
@@ -54,9 +58,13 @@ RETRO_BEGIN_DECLS
#define fgetc rfgetc #define fgetc rfgetc
#define fwrite rfwrite #define fwrite rfwrite
#define fputc rfputc #define fputc rfputc
#define fflush rfflush
#define fprintf rfprintf #define fprintf rfprintf
#define ferror rferror #define ferror rferror
#define feof rfeof #define feof rfeof
#define fscanf rfscanf
#endif
RFILE* rfopen(const char *path, const char *mode); RFILE* rfopen(const char *path, const char *mode);
@@ -78,12 +86,16 @@ int64_t rfwrite(void const* buffer,
int rfputc(int character, RFILE * stream); int rfputc(int character, RFILE * stream);
int64_t rfflush(RFILE * stream);
int rfprintf(RFILE * stream, const char * format, ...); int rfprintf(RFILE * stream, const char * format, ...);
int rferror(RFILE* stream); int rferror(RFILE* stream);
int rfeof(RFILE* stream); int rfeof(RFILE* stream);
int rfscanf(RFILE * stream, const char * format, ...);
RETRO_END_DECLS RETRO_END_DECLS
#endif #endif

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2019 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (stdstring.h). * The following license statement only applies to this file (stdstring.h).
@@ -37,43 +37,20 @@ RETRO_BEGIN_DECLS
static INLINE bool string_is_empty(const char *data) static INLINE bool string_is_empty(const char *data)
{ {
return (data == NULL) || (*data == '\0'); return !data || (*data == '\0');
} }
static INLINE bool string_is_equal(const char *a, const char *b) static INLINE bool string_is_equal(const char *a, const char *b)
{ {
if (!a || !b) return (a && b) ? !strcmp(a, b) : false;
return false;
while(*a && (*a == *b))
a++, b++;
return (*(const unsigned char*)a - *(const unsigned char*)b) == 0;
} }
static INLINE bool string_is_not_equal(const char *a, const char *b) #define STRLEN_CONST(x) ((sizeof((x))-1))
{
return !string_is_equal(a, b);
}
#define string_add_pair_open(s, size) strlcat((s), " (", (size)) #define string_is_not_equal(a, b) !string_is_equal((a), (b))
#define string_add_pair_close(s, size) strlcat((s), ")", (size))
#define string_add_bracket_open(s, size) strlcat((s), "{", (size))
#define string_add_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))
static INLINE void string_add_between_pairs(char *s, const char *str,
size_t size)
{
string_add_pair_open(s, size);
strlcat(s, str, size);
string_add_pair_close(s, size);
}
#define string_is_not_equal_fast(a, b, size) (memcmp(a, b, size) != 0) #define string_is_not_equal_fast(a, b, size) (memcmp(a, b, size) != 0)
#define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0) #define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0)
static INLINE bool string_is_equal_case_insensitive(const char *a, static INLINE bool string_is_equal_case_insensitive(const char *a,
const char *b) const char *b)
@@ -116,7 +93,7 @@ char *string_to_upper(char *s);
char *string_to_lower(char *s); char *string_to_lower(char *s);
char *string_ucwords(char* s); char *string_ucwords(char *s);
char *string_replace_substring(const char *in, const char *pattern, char *string_replace_substring(const char *in, const char *pattern,
const char *by); const char *by);
@@ -130,7 +107,44 @@ char *string_trim_whitespace_right(char *const s);
/* Remove leading and trailing whitespaces */ /* Remove leading and trailing whitespaces */
char *string_trim_whitespace(char *const s); char *string_trim_whitespace(char *const s);
char *word_wrap(char* buffer, const char *string, int line_width, bool unicode); /* max_lines == 0 means no limit */
char *word_wrap(char *buffer, const char *string,
int line_width, bool unicode, unsigned max_lines);
/* Splits string into tokens seperated by 'delim'
* > Returned token string must be free()'d
* > Returns NULL if token is not found
* > After each call, 'str' is set to the position after the
* last found token
* > Tokens *include* empty strings
* Usage example:
* char *str = "1,2,3,4,5,6,7,,,10,";
* char **str_ptr = &str;
* char *token = NULL;
* while((token = string_tokenize(str_ptr, ",")))
* {
* printf("%s\n", token);
* free(token);
* token = NULL;
* }
*/
char* string_tokenize(char **str, const char *delim);
/* Removes every instance of character 'c' from 'str' */
void string_remove_all_chars(char *str, char c);
/* Replaces every instance of character 'find' in 'str'
* with character 'replace' */
void string_replace_all_chars(char *str, char find, char replace);
/* Converts string to unsigned integer.
* Returns 0 if string is invalid */
unsigned string_to_unsigned(const char *str);
/* Converts hexadecimal string to unsigned integer.
* Handles optional leading '0x'.
* Returns 0 if string is invalid */
unsigned string_hex_to_unsigned(const char *str);
RETRO_END_DECLS RETRO_END_DECLS

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2019 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (vfs_implementation.h). * The following license statement only applies to this file (vfs_implementation.h).
@@ -23,20 +23,13 @@
#ifndef __LIBRETRO_SDK_VFS_IMPLEMENTATION_H #ifndef __LIBRETRO_SDK_VFS_IMPLEMENTATION_H
#define __LIBRETRO_SDK_VFS_IMPLEMENTATION_H #define __LIBRETRO_SDK_VFS_IMPLEMENTATION_H
#include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <libretro.h> #include <libretro.h>
#include <retro_environment.h>
#include <vfs/vfs.h>
/* Replace the following symbol with something appropriate RETRO_BEGIN_DECLS
* to signify the file is being compiled for a front end instead of a core.
* This allows the same code to act as reference implementation
* for VFS and as fallbacks for when the front end does not provide VFS functionality.
*/
#ifdef VFS_FRONTEND
typedef struct retro_vfs_file_handle libretro_vfs_implementation_file;
#else
typedef struct libretro_vfs_implementation_file libretro_vfs_implementation_file;
#endif
libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints); libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints);
@@ -46,6 +39,8 @@ int retro_vfs_file_error_impl(libretro_vfs_implementation_file *stream);
int64_t retro_vfs_file_size_impl(libretro_vfs_implementation_file *stream); int64_t retro_vfs_file_size_impl(libretro_vfs_implementation_file *stream);
int64_t retro_vfs_file_truncate_impl(libretro_vfs_implementation_file *stream, int64_t length);
int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream); int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream);
int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file *stream, int64_t offset, int seek_position); int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file *stream, int64_t offset, int seek_position);
@@ -62,4 +57,20 @@ int retro_vfs_file_rename_impl(const char *old_path, const char *new_path);
const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *stream); const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *stream);
int retro_vfs_stat_impl(const char *path, int32_t *size);
int retro_vfs_mkdir_impl(const char *dir);
libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *dir, bool include_hidden);
bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir *dirstream);
const char *retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir *dirstream);
bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *dirstream);
int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *dirstream);
RETRO_END_DECLS
#endif #endif

View File

@@ -24,6 +24,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
#include <ctype.h>
#include <errno.h> #include <errno.h>
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@@ -40,6 +41,7 @@ static retro_vfs_get_path_t filestream_get_path_cb = NULL;
static retro_vfs_open_t filestream_open_cb = NULL; static retro_vfs_open_t filestream_open_cb = NULL;
static retro_vfs_close_t filestream_close_cb = NULL; static retro_vfs_close_t filestream_close_cb = NULL;
static retro_vfs_size_t filestream_size_cb = NULL; static retro_vfs_size_t filestream_size_cb = NULL;
static retro_vfs_truncate_t filestream_truncate_cb = NULL;
static retro_vfs_tell_t filestream_tell_cb = NULL; static retro_vfs_tell_t filestream_tell_cb = NULL;
static retro_vfs_seek_t filestream_seek_cb = NULL; static retro_vfs_seek_t filestream_seek_cb = NULL;
static retro_vfs_read_t filestream_read_cb = NULL; static retro_vfs_read_t filestream_read_cb = NULL;
@@ -66,6 +68,7 @@ void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info)
filestream_close_cb = NULL; filestream_close_cb = NULL;
filestream_tell_cb = NULL; filestream_tell_cb = NULL;
filestream_size_cb = NULL; filestream_size_cb = NULL;
filestream_truncate_cb = NULL;
filestream_seek_cb = NULL; filestream_seek_cb = NULL;
filestream_read_cb = NULL; filestream_read_cb = NULL;
filestream_write_cb = NULL; filestream_write_cb = NULL;
@@ -83,6 +86,7 @@ void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info)
filestream_open_cb = vfs_iface->open; filestream_open_cb = vfs_iface->open;
filestream_close_cb = vfs_iface->close; filestream_close_cb = vfs_iface->close;
filestream_size_cb = vfs_iface->size; filestream_size_cb = vfs_iface->size;
filestream_truncate_cb = vfs_iface->truncate;
filestream_tell_cb = vfs_iface->tell; filestream_tell_cb = vfs_iface->tell;
filestream_seek_cb = vfs_iface->seek; filestream_seek_cb = vfs_iface->seek;
filestream_read_cb = vfs_iface->read; filestream_read_cb = vfs_iface->read;
@@ -126,6 +130,21 @@ int64_t filestream_get_size(RFILE *stream)
return output; return output;
} }
int64_t filestream_truncate(RFILE *stream, int64_t length)
{
int64_t output;
if (filestream_truncate_cb != NULL)
output = filestream_truncate_cb(stream->hfile, length);
else
output = retro_vfs_file_truncate_impl((libretro_vfs_implementation_file*)stream->hfile, length);
if (output == vfs_error_return_value)
stream->error_flag = true;
return output;
}
/** /**
* filestream_open: * filestream_open:
* @path : path to file * @path : path to file
@@ -135,7 +154,7 @@ int64_t filestream_get_size(RFILE *stream)
* Opens a file for reading or writing, depending on the requested mode. * Opens a file for reading or writing, depending on the requested mode.
* Returns a pointer to an RFILE if opened successfully, otherwise NULL. * Returns a pointer to an RFILE if opened successfully, otherwise NULL.
**/ **/
RFILE *filestream_open(const char *path, unsigned mode, unsigned hints) RFILE* filestream_open(const char *path, unsigned mode, unsigned hints)
{ {
struct retro_vfs_file_handle *fp = NULL; struct retro_vfs_file_handle *fp = NULL;
RFILE* output = NULL; RFILE* output = NULL;
@@ -157,7 +176,7 @@ RFILE *filestream_open(const char *path, unsigned mode, unsigned hints)
return output; return output;
} }
char *filestream_gets(RFILE *stream, char *s, size_t len) char* filestream_gets(RFILE *stream, char *s, size_t len)
{ {
int c = 0; int c = 0;
char *p = s; char *p = s;
@@ -185,12 +204,107 @@ int filestream_getc(RFILE *stream)
{ {
char c = 0; char c = 0;
if (!stream) if (!stream)
return 0; return EOF;
if(filestream_read(stream, &c, 1) == 1) if (filestream_read(stream, &c, 1) == 1)
return (int)c; return (int)(unsigned char)c;
return EOF; return EOF;
} }
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')
{
if (format[1] == format[0]) *subfmtiter++ = *format++;
*subfmtiter++ = *format++;
}
else if (*format == 'j' || *format == 'z' || *format == 't' || *format == 'L')
{
*subfmtiter++ = *format++;
}
/* specifier - always a single character (except ]) */
if (*format == '[')
{
while (*format != ']') *subfmtiter++ = *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)
{
if (sscanf(bufiter, subfmt, &sublen) != 0) break;
}
else
{
if (sscanf(bufiter, subfmt, va_arg(args, void*), &sublen) != 1) break;
}
ret++;
bufiter += sublen;
}
else if (isspace(*format))
{
while (isspace(*bufiter)) bufiter++;
format++;
}
else
{
if (*bufiter != *format)
break;
bufiter++;
format++;
}
}
va_end(args);
filestream_seek(stream, startpos+(bufiter-buf), RETRO_VFS_SEEK_POSITION_START);
return ret;
}
int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position) int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position)
{ {
int64_t output; int64_t output;
@@ -212,7 +326,6 @@ int filestream_eof(RFILE *stream)
return stream->eof_flag; return stream->eof_flag;
} }
int64_t filestream_tell(RFILE *stream) int64_t filestream_tell(RFILE *stream)
{ {
int64_t output; int64_t output;
@@ -286,7 +399,7 @@ int filestream_rename(const char *old_path, const char *new_path)
return retro_vfs_file_rename_impl(old_path, new_path); return retro_vfs_file_rename_impl(old_path, new_path);
} }
const char *filestream_get_path(RFILE *stream) const char* filestream_get_path(RFILE *stream)
{ {
if (filestream_get_path_cb != NULL) if (filestream_get_path_cb != NULL)
return filestream_get_path_cb(stream->hfile); return filestream_get_path_cb(stream->hfile);
@@ -314,7 +427,7 @@ int filestream_putc(RFILE *stream, int c)
char c_char = (char)c; char c_char = (char)c;
if (!stream) if (!stream)
return EOF; return EOF;
return filestream_write(stream, &c_char, 1)==1 ? c : EOF; return filestream_write(stream, &c_char, 1)==1 ? (int)(unsigned char)c : EOF;
} }
int filestream_vprintf(RFILE *stream, const char* format, va_list args) int filestream_vprintf(RFILE *stream, const char* format, va_list args)
@@ -459,13 +572,14 @@ bool filestream_write_file(const char *path, const void *data, int64_t size)
return true; return true;
} }
char *filestream_getline(RFILE *stream) /* Returned pointer must be freed by the caller. */
char* filestream_getline(RFILE *stream)
{ {
char* newline_tmp = NULL; char *newline_tmp = NULL;
size_t cur_size = 8; size_t cur_size = 8;
size_t idx = 0; size_t idx = 0;
int in = 0; int in = 0;
char* newline = (char*)malloc(9); char *newline = (char*)malloc(9);
if (!stream || !newline) if (!stream || !newline)
{ {
@@ -499,3 +613,8 @@ char *filestream_getline(RFILE *stream)
newline[idx] = '\0'; newline[idx] = '\0';
return newline; return newline;
} }
libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream)
{
return (libretro_vfs_implementation_file*)stream->hfile;
}

View File

@@ -37,7 +37,7 @@ RFILE* rfopen(const char *path, const char *mode)
retro_mode = RETRO_VFS_FILE_ACCESS_READ; retro_mode = RETRO_VFS_FILE_ACCESS_READ;
if (strstr(mode, "+")) if (strstr(mode, "+"))
{ {
retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE | retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE |
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING; RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
} }
} }
@@ -49,12 +49,12 @@ RFILE* rfopen(const char *path, const char *mode)
} }
else if (strstr(mode, "a")) else if (strstr(mode, "a"))
{ {
retro_mode = RETRO_VFS_FILE_ACCESS_WRITE | retro_mode = RETRO_VFS_FILE_ACCESS_WRITE |
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING; RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
position_to_end = true; position_to_end = true;
if (strstr(mode, "+")) if (strstr(mode, "+"))
{ {
retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE | retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE |
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING; RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
} }
} }
@@ -99,7 +99,7 @@ int64_t rfseek(RFILE* stream, int64_t offset, int origin)
int64_t rfread(void* buffer, int64_t rfread(void* buffer,
size_t elem_size, size_t elem_count, RFILE* stream) size_t elem_size, size_t elem_count, RFILE* stream)
{ {
return filestream_read(stream, buffer, elem_size * elem_count); return (filestream_read(stream, buffer, elem_size * elem_count) / elem_size);
} }
char *rfgets(char *buffer, int maxCount, RFILE* stream) char *rfgets(char *buffer, int maxCount, RFILE* stream)
@@ -109,7 +109,7 @@ char *rfgets(char *buffer, int maxCount, RFILE* stream)
int rfgetc(RFILE* stream) int rfgetc(RFILE* stream)
{ {
return filestream_getc(stream); return filestream_getc(stream);
} }
int64_t rfwrite(void const* buffer, int64_t rfwrite(void const* buffer,
@@ -123,14 +123,19 @@ int rfputc(int character, RFILE * stream)
return filestream_putc(stream, character); return filestream_putc(stream, character);
} }
int64_t rfflush(RFILE * stream)
{
return filestream_flush(stream);
}
int rfprintf(RFILE * stream, const char * format, ...) int rfprintf(RFILE * stream, const char * format, ...)
{ {
int result; int result;
va_list vl; va_list vl;
va_start(vl, format); va_start(vl, format);
result = filestream_vprintf(stream, format, vl); result = filestream_vprintf(stream, format, vl);
va_end(vl); va_end(vl);
return result; return result;
} }
int rferror(RFILE* stream) int rferror(RFILE* stream)
@@ -142,3 +147,13 @@ int rfeof(RFILE* stream)
{ {
return filestream_eof(stream); return filestream_eof(stream);
} }
int rfscanf(RFILE * stream, const char * format, ...)
{
int result;
va_list vl;
va_start(vl, format);
result = filestream_scanf(stream, format, vl);
va_end(vl);
return result;
}

View File

@@ -82,6 +82,10 @@ char *string_replace_substring(const char *in,
outlen = strlen(in) - pattern_len*numhits + replacement_len*numhits; outlen = strlen(in) - pattern_len*numhits + replacement_len*numhits;
out = (char *)malloc(outlen+1); out = (char *)malloc(outlen+1);
if (!out)
return NULL;
outat = out; outat = out;
inat = in; inat = in;
inprev = in; inprev = in;
@@ -105,15 +109,17 @@ char *string_trim_whitespace_left(char *const s)
{ {
if(s && *s) if(s && *s)
{ {
size_t len = strlen(s); size_t len = strlen(s);
char *cur = s; char *current = s;
while(*cur && isspace((unsigned char)*cur)) while(*current && isspace((unsigned char)*current))
++cur, --len; {
++current;
if(s != cur) --len;
memmove(s, cur, len + 1); }
if(s != current)
memmove(s, current, len + 1);
} }
return s; return s;
@@ -124,13 +130,16 @@ char *string_trim_whitespace_right(char *const s)
{ {
if(s && *s) if(s && *s)
{ {
size_t len = strlen(s); size_t len = strlen(s);
char *cur = s + len - 1; char *current = s + len - 1;
while(cur != s && isspace((unsigned char)*cur)) while(current != s && isspace((unsigned char)*current))
--cur, --len; {
--current;
--len;
}
cur[isspace((unsigned char)*cur) ? 0 : 1] = '\0'; current[isspace((unsigned char)*current) ? 0 : 1] = '\0';
} }
return s; return s;
@@ -145,14 +154,16 @@ char *string_trim_whitespace(char *const s)
return s; return s;
} }
char *word_wrap(char* buffer, const char *string, int line_width, bool unicode) char *word_wrap(char* buffer, const char *string, int line_width, bool unicode, unsigned max_lines)
{ {
unsigned i = 0; unsigned i = 0;
unsigned len = (unsigned)strlen(string); unsigned len = (unsigned)strlen(string);
unsigned lines = 1;
while (i < len) while (i < len)
{ {
unsigned counter; unsigned counter;
int pos = (int)(&buffer[i] - buffer);
/* copy string until the end of the line is reached */ /* copy string until the end of the line is reached */
for (counter = 1; counter <= (unsigned)line_width; counter++) for (counter = 1; counter <= (unsigned)line_width; counter++)
@@ -184,14 +195,21 @@ char *word_wrap(char* buffer, const char *string, int line_width, bool unicode)
/* check for newlines embedded in the original input /* check for newlines embedded in the original input
* and reset the index */ * and reset the index */
if (buffer[j] == '\n') if (buffer[j] == '\n')
{
lines++;
counter = 1; counter = 1;
}
} }
/* check for whitespace */ /* check for whitespace */
if (string[i] == ' ') if (string[i] == ' ')
{ {
buffer[i] = '\n'; if ((max_lines == 0 || lines < max_lines))
i++; {
buffer[i] = '\n';
i++;
lines++;
}
} }
else else
{ {
@@ -200,14 +218,18 @@ char *word_wrap(char* buffer, const char *string, int line_width, bool unicode)
/* check for nearest whitespace back in string */ /* check for nearest whitespace back in string */
for (k = i; k > 0; k--) for (k = i; k > 0; k--)
{ {
if (string[k] != ' ') if (string[k] != ' ' || (max_lines != 0 && lines >= max_lines))
continue; continue;
buffer[k] = '\n'; buffer[k] = '\n';
/* set string index back to character after this one */ /* set string index back to character after this one */
i = k + 1; i = k + 1;
lines++;
break; break;
} }
if (&buffer[i] - buffer == pos)
return buffer;
} }
} }
@@ -215,3 +237,148 @@ char *word_wrap(char* buffer, const char *string, int line_width, bool unicode)
return buffer; return buffer;
} }
/* Splits string into tokens seperated by 'delim'
* > Returned token string must be free()'d
* > Returns NULL if token is not found
* > After each call, 'str' is set to the position after the
* last found token
* > Tokens *include* empty strings
* Usage example:
* char *str = "1,2,3,4,5,6,7,,,10,";
* char **str_ptr = &str;
* char *token = NULL;
* while((token = string_tokenize(str_ptr, ",")))
* {
* printf("%s\n", token);
* free(token);
* token = NULL;
* }
*/
char* string_tokenize(char **str, const char *delim)
{
/* Taken from https://codereview.stackexchange.com/questions/216956/strtok-function-thread-safe-supports-empty-tokens-doesnt-change-string# */
char *str_ptr = NULL;
char *delim_ptr = NULL;
char *token = NULL;
size_t token_len = 0;
/* Sanity checks */
if (!str || string_is_empty(delim))
return NULL;
str_ptr = *str;
/* Note: we don't check string_is_empty() here,
* empty strings are valid */
if (!str_ptr)
return NULL;
/* Search for delimiter */
delim_ptr = strstr(str_ptr, delim);
if (delim_ptr)
token_len = delim_ptr - str_ptr;
else
token_len = strlen(str_ptr);
/* Allocate token string */
token = (char *)malloc((token_len + 1) * sizeof(char));
if (!token)
return NULL;
/* Copy token */
strlcpy(token, str_ptr, (token_len + 1) * sizeof(char));
token[token_len] = '\0';
/* Update input string pointer */
*str = delim_ptr ? delim_ptr + strlen(delim) : NULL;
return token;
}
/* Removes every instance of character 'c' from 'str' */
void string_remove_all_chars(char *str, char c)
{
char *read_ptr = NULL;
char *write_ptr = NULL;
if (string_is_empty(str))
return;
read_ptr = str;
write_ptr = str;
while (*read_ptr != '\0')
{
*write_ptr = *read_ptr++;
write_ptr += (*write_ptr != c) ? 1 : 0;
}
*write_ptr = '\0';
}
/* Replaces every instance of character 'find' in 'str'
* with character 'replace' */
void string_replace_all_chars(char *str, char find, char replace)
{
char *str_ptr = str;
if (string_is_empty(str))
return;
while((str_ptr = strchr(str_ptr, find)) != NULL)
*str_ptr++ = replace;
}
/* Converts string to unsigned integer.
* Returns 0 if string is invalid */
unsigned string_to_unsigned(const char *str)
{
const char *ptr = NULL;
if (string_is_empty(str))
return 0;
for (ptr = str; *ptr != '\0'; ptr++)
{
if (!isdigit(*ptr))
return 0;
}
return (unsigned)strtoul(str, NULL, 10);
}
/* Converts hexadecimal string to unsigned integer.
* Handles optional leading '0x'.
* Returns 0 if string is invalid */
unsigned string_hex_to_unsigned(const char *str)
{
const char *hex_str = str;
const char *ptr = NULL;
size_t len;
if (string_is_empty(str))
return 0;
/* Remove leading '0x', if required */
len = strlen(str);
if (len >= 2)
if ((str[0] == '0') &&
((str[1] == 'x') || (str[1] == 'X')))
hex_str = str + 2;
if (string_is_empty(hex_str))
return 0;
/* Check for valid characters */
for (ptr = hex_str; *ptr != '\0'; ptr++)
{
if (!isxdigit(*ptr))
return 0;
}
return (unsigned)strtoul(hex_str, NULL, 16);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1038,6 +1038,26 @@ static const char *find_bios(int *region, const char *cd_fname)
return NULL; return NULL;
} }
static void set_memory_maps(void)
{
if (PicoIn.AHW & PAHW_MCD)
{
const size_t SCD_BIT = 1ULL << 31ULL;
const uint64_t mem = RETRO_MEMDESC_SYSTEM_RAM;
struct retro_memory_map mmaps;
struct retro_memory_descriptor descs[] = {
{ mem, PicoMem.ram, 0, 0xFF0000, 0, 0, 0x10000, "68KRAM" },
/* virtual address using SCD_BIT so all 512M of prg_ram can be accessed */
/* at address $80020000 */
{ mem, Pico_mcd->prg_ram, 0, SCD_BIT | 0x020000, 0, 0, 0x80000, "PRGRAM" },
};
mmaps.descriptors = descs;
mmaps.num_descriptors = sizeof(descs) / sizeof(descs[0]);
environ_cb(RETRO_ENVIRONMENT_SET_MEMORY_MAPS, &mmaps);
}
}
bool retro_load_game(const struct retro_game_info *info) bool retro_load_game(const struct retro_game_info *info)
{ {
enum media_type_e media_type; enum media_type_e media_type;
@@ -1156,6 +1176,9 @@ bool retro_load_game(const struct retro_game_info *info)
PicoIn.sndOut = sndBuffer; PicoIn.sndOut = sndBuffer;
PsndRerate(0); PsndRerate(0);
/* Setup retro memory maps */
set_memory_maps();
return true; return true;
} }