mirror of
https://github.com/FunKey-Project/picodrive-irixxxx.git
synced 2026-02-01 12:35:30 +01:00
Merge pull request #113 from negativeExponent/scd_memmap
Update libretro-common, add Sega CD memory map
This commit is contained in:
commit
8cbbdceaf4
@ -36,9 +36,7 @@
|
||||
|
||||
void *fopen_utf8(const char * filename, const char * mode)
|
||||
{
|
||||
#if defined(_XBOX)
|
||||
return fopen(filename, mode);
|
||||
#elif defined(LEGACY_WIN32)
|
||||
#if defined(LEGACY_WIN32)
|
||||
FILE *ret = NULL;
|
||||
char * filename_local = utf8_to_local_string_alloc(filename);
|
||||
|
||||
|
||||
@ -211,10 +211,7 @@ size_t utf8len(const char *string)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t utf8_walkbyte(const char **string)
|
||||
{
|
||||
return *((*string)++);
|
||||
}
|
||||
#define utf8_walkbyte(string) (*((*(string))++))
|
||||
|
||||
/* Does not validate the input, returns garbage if it's not UTF-8. */
|
||||
uint32_t utf8_walk(const char **string)
|
||||
@ -227,14 +224,16 @@ uint32_t utf8_walk(const char **string)
|
||||
|
||||
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
||||
if (first >= 0xE0)
|
||||
{
|
||||
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
||||
if (first >= 0xF0)
|
||||
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
||||
|
||||
if (first >= 0xF0)
|
||||
return ret | (first & 7) << 18;
|
||||
if (first >= 0xE0)
|
||||
if (first >= 0xF0)
|
||||
{
|
||||
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
||||
return ret | (first & 7) << 18;
|
||||
}
|
||||
return ret | (first & 15) << 12;
|
||||
}
|
||||
|
||||
return ret | (first & 31) << 6;
|
||||
}
|
||||
|
||||
@ -273,37 +272,25 @@ bool utf16_to_char_string(const uint16_t *in, char *s, size_t len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
|
||||
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||
static char* mb_to_mb_string_alloc(const char *str,
|
||||
static char *mb_to_mb_string_alloc(const char *str,
|
||||
enum CodePage cp_in, enum CodePage cp_out)
|
||||
{
|
||||
char *path_buf = NULL;
|
||||
wchar_t *path_buf_wide = NULL;
|
||||
int path_buf_len = 0;
|
||||
int path_buf_wide_len = 0;
|
||||
int path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
|
||||
|
||||
if (!str || !*str)
|
||||
return NULL;
|
||||
|
||||
(void)path_buf;
|
||||
(void)path_buf_wide;
|
||||
(void)path_buf_len;
|
||||
(void)path_buf_wide_len;
|
||||
|
||||
#if !defined(_WIN32) || defined(_XBOX)
|
||||
/* assume string needs no modification if not on Windows */
|
||||
return strdup(str);
|
||||
#else
|
||||
#ifdef UNICODE
|
||||
/* TODO/FIXME: Not implemented. */
|
||||
return strdup(str);
|
||||
#else
|
||||
|
||||
/* Windows 95 will return 0 from these functions with a UTF8 codepage set without MSLU. From an unknown MSDN version (others omit this info):
|
||||
* - CP_UTF8 Windows 98/Me, Windows NT 4.0 and later: Translate using UTF-8. When this is set, dwFlags must be zero.
|
||||
* - Windows 95: Under the Microsoft Layer for Unicode, MultiByteToWideChar also supports CP_UTF7 and CP_UTF8.
|
||||
/* Windows 95 will return 0 from these functions with
|
||||
* a UTF8 codepage set without MSLU.
|
||||
*
|
||||
* From an unknown MSDN version (others omit this info):
|
||||
* - CP_UTF8 Windows 98/Me, Windows NT 4.0 and later:
|
||||
* Translate using UTF-8. When this is set, dwFlags must be zero.
|
||||
* - Windows 95: Under the Microsoft Layer for Unicode,
|
||||
* MultiByteToWideChar also supports CP_UTF7 and CP_UTF8.
|
||||
*/
|
||||
path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
|
||||
|
||||
if (path_buf_wide_len)
|
||||
{
|
||||
@ -355,20 +342,37 @@ static char* mb_to_mb_string_alloc(const char *str,
|
||||
free(path_buf_wide);
|
||||
|
||||
return NULL;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||
char* utf8_to_local_string_alloc(const char *str)
|
||||
{
|
||||
return mb_to_mb_string_alloc(str, CODEPAGE_UTF8, CODEPAGE_LOCAL);
|
||||
if (str && *str)
|
||||
{
|
||||
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
|
||||
return mb_to_mb_string_alloc(str, CODEPAGE_UTF8, CODEPAGE_LOCAL);
|
||||
#else
|
||||
/* assume string needs no modification if not on Windows */
|
||||
return strdup(str);
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||
char* local_to_utf8_string_alloc(const char *str)
|
||||
{
|
||||
return mb_to_mb_string_alloc(str, CODEPAGE_LOCAL, CODEPAGE_UTF8);
|
||||
if (str && *str)
|
||||
{
|
||||
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
|
||||
return mb_to_mb_string_alloc(str, CODEPAGE_LOCAL, CODEPAGE_UTF8);
|
||||
#else
|
||||
/* assume string needs no modification if not on Windows */
|
||||
return strdup(str);
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||
@ -447,52 +451,44 @@ wchar_t* utf8_to_utf16_string_alloc(const char *str)
|
||||
char* utf16_to_utf8_string_alloc(const wchar_t *str)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int len = 0;
|
||||
int out_len = 0;
|
||||
int len = 0;
|
||||
#else
|
||||
size_t len = 0;
|
||||
size_t out_len = 0;
|
||||
size_t len = 0;
|
||||
#endif
|
||||
char *buf = NULL;
|
||||
char *buf = NULL;
|
||||
|
||||
if (!str || !*str)
|
||||
return NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
len = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
|
||||
|
||||
if (len)
|
||||
{
|
||||
UINT code_page = CP_UTF8;
|
||||
len = WideCharToMultiByte(code_page,
|
||||
0, str, -1, NULL, 0, NULL, NULL);
|
||||
|
||||
/* fallback to ANSI codepage instead */
|
||||
if (!len)
|
||||
{
|
||||
code_page = CP_ACP;
|
||||
len = WideCharToMultiByte(code_page,
|
||||
0, str, -1, NULL, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
buf = (char*)calloc(len, sizeof(char));
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
out_len = WideCharToMultiByte(CP_UTF8, 0, str, -1, buf, len, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fallback to ANSI codepage instead */
|
||||
len = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
|
||||
|
||||
if (len)
|
||||
if (WideCharToMultiByte(code_page,
|
||||
0, str, -1, buf, len, NULL, NULL) < 0)
|
||||
{
|
||||
buf = (char*)calloc(len, sizeof(char));
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
out_len = WideCharToMultiByte(CP_ACP, 0, str, -1, buf, len, NULL, NULL);
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_len < 0)
|
||||
{
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
/* NOTE: For now, assume non-Windows platforms' locale is already UTF-8. */
|
||||
/* NOTE: For now, assume non-Windows platforms'
|
||||
* locale is already UTF-8. */
|
||||
len = wcstombs(NULL, str, 0) + 1;
|
||||
|
||||
if (len)
|
||||
@ -502,13 +498,11 @@ char* utf16_to_utf8_string_alloc(const wchar_t *str)
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
out_len = wcstombs(buf, str, len);
|
||||
}
|
||||
|
||||
if (out_len == (size_t)-1)
|
||||
{
|
||||
free(buf);
|
||||
return NULL;
|
||||
if (wcstombs(buf, str, len) == (size_t)-1)
|
||||
{
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -72,4 +72,3 @@ RETRO_END_DECLS
|
||||
|
||||
/* pragma once */
|
||||
#endif
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ RETRO_BEGIN_DECLS
|
||||
/* Count Leading Zero, unsigned 16bit input value */
|
||||
static INLINE unsigned compat_clz_u16(uint16_t val)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(PS2)
|
||||
return __builtin_clz(val << 16 | 0x8000);
|
||||
#else
|
||||
unsigned ret = 0;
|
||||
@ -61,7 +61,7 @@ static INLINE int compat_ctz(unsigned x)
|
||||
{
|
||||
#if defined(__GNUC__) && !defined(RARCH_CONSOLE)
|
||||
return __builtin_ctz(x);
|
||||
#elif _MSC_VER >= 1400 && !defined(_XBOX)
|
||||
#elif _MSC_VER >= 1400 && !defined(_XBOX) && !defined(__WINRT__)
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse((unsigned long*)&r, x);
|
||||
return (int)r;
|
||||
|
||||
@ -31,6 +31,7 @@ extern "C" {
|
||||
|
||||
/* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */
|
||||
#if _MSC_VER < 1900
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef snprintf
|
||||
#define snprintf c99_snprintf_retro__
|
||||
@ -39,8 +40,9 @@ extern "C" {
|
||||
int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...);
|
||||
#endif
|
||||
|
||||
/* Pre-MSVC 2010 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
|
||||
#if _MSC_VER < 1600
|
||||
/* Pre-MSVC 2008 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
|
||||
#if _MSC_VER < 1500
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef vsnprintf
|
||||
@ -56,6 +58,8 @@ extern "C" {
|
||||
#undef UNICODE /* Do not bother with UNICODE at this time. */
|
||||
#include <direct.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
|
||||
/* Python headers defines ssize_t and sets HAVE_SSIZE_T.
|
||||
@ -125,4 +129,3 @@ typedef int ssize_t;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@ -67,7 +67,6 @@ extern "C" {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* 7.18.1 Integer types. */
|
||||
|
||||
/* 7.18.1.1 Exact-width integer types. */
|
||||
@ -94,7 +93,6 @@ extern "C" {
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
|
||||
/* 7.18.1.2 Minimum-width integer types. */
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
@ -255,4 +253,3 @@ typedef uint64_t uintmax_t;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -29,6 +29,10 @@
|
||||
#include <compat/msvc.h>
|
||||
#endif
|
||||
|
||||
#if defined(PS2)
|
||||
#include <compat_ctype.h>
|
||||
#endif
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -55,7 +59,6 @@ int isblank(int c);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
@ -25,6 +25,10 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(PS2)
|
||||
#include <compat_ctype.h>
|
||||
#endif
|
||||
|
||||
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
|
||||
#include "../../../config.h"
|
||||
#endif
|
||||
@ -46,4 +50,3 @@ RETRO_END_DECLS
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -57,4 +57,3 @@ char *strldup(const char *s, size_t n);
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -1117,7 +1117,7 @@ enum retro_mod
|
||||
* This may be still be done regardless of the core options
|
||||
* interface version.
|
||||
*
|
||||
* If version is >= 1 however, core options may instead be set by
|
||||
* If version is 1 however, core options may instead be set by
|
||||
* passing an array of retro_core_option_definition structs to
|
||||
* RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of
|
||||
* retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL.
|
||||
@ -1132,8 +1132,8 @@ enum retro_mod
|
||||
* GET_VARIABLE.
|
||||
* This allows the frontend to present these variables to
|
||||
* a user dynamically.
|
||||
* This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION
|
||||
* returns an API version of >= 1.
|
||||
* This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
|
||||
* returns an API version of 1.
|
||||
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
|
||||
* This should be called the first time as early as
|
||||
* possible (ideally in retro_set_environment).
|
||||
@ -1169,6 +1169,8 @@ enum retro_mod
|
||||
* i.e. it should be feasible to cycle through options
|
||||
* without a keyboard.
|
||||
*
|
||||
* First entry should be treated as a default.
|
||||
*
|
||||
* Example entry:
|
||||
* {
|
||||
* "foo_option",
|
||||
@ -1194,8 +1196,8 @@ enum retro_mod
|
||||
* GET_VARIABLE.
|
||||
* This allows the frontend to present these variables to
|
||||
* a user dynamically.
|
||||
* This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION
|
||||
* returns an API version of >= 1.
|
||||
* This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
|
||||
* returns an API version of 1.
|
||||
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
|
||||
* This should be called the first time as early as
|
||||
* possible (ideally in retro_set_environment).
|
||||
@ -1246,6 +1248,16 @@ enum retro_mod
|
||||
* 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 */
|
||||
|
||||
/* File paths:
|
||||
@ -1922,6 +1934,10 @@ enum retro_sensor_action
|
||||
{
|
||||
RETRO_SENSOR_ACCELEROMETER_ENABLE = 0,
|
||||
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
|
||||
};
|
||||
@ -1930,6 +1946,10 @@ enum retro_sensor_action
|
||||
#define RETRO_SENSOR_ACCELEROMETER_X 0
|
||||
#define RETRO_SENSOR_ACCELEROMETER_Y 1
|
||||
#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,
|
||||
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
|
||||
* > Note: We have to set a maximum value due the limitations
|
||||
* of the C language - i.e. it is not possible to create an
|
||||
* 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."
|
||||
*/
|
||||
* NOTE: This may be increased on a core-by-core basis
|
||||
* if required (doing so has no effect on the frontend) */
|
||||
#define RETRO_NUM_CORE_OPTION_VALUES_MAX 128
|
||||
|
||||
struct retro_core_option_value
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(__CELLOS_LV2__) || defined(PSP) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH)
|
||||
#if defined(__CELLOS_LV2__) || defined(PSP) || defined(PS2) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH) || defined(HAVE_LIBNX)
|
||||
/* No mman available */
|
||||
#elif defined(_WIN32) && !defined(_XBOX)
|
||||
#include <windows.h>
|
||||
|
||||
@ -34,4 +34,3 @@ in a public API, you may need this.
|
||||
#include <compat/msvc.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -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 */
|
||||
/* https://stackoverflow.com/questions/8132399/how-to-printf-uint64-t-fails-with-spurious-trailing-in-format */
|
||||
/* https://github.com/libretro/RetroArch/issues/6009 */
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#ifndef __STDC_FORMAT_MACROS
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#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...
|
||||
*/
|
||||
|
||||
|
||||
/* _LIBRETRO_COMMON_RETRO_COMMON_API_H */
|
||||
#endif
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2010-2018 The RetroArch team
|
||||
/* Copyright (C) 2010-2019 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (retro_dirent.h).
|
||||
@ -23,6 +23,7 @@
|
||||
#ifndef __RETRO_DIRENT_H
|
||||
#define __RETRO_DIRENT_H
|
||||
|
||||
#include <libretro.h>
|
||||
#include <retro_common_api.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
@ -30,6 +31,10 @@
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
@ -44,25 +49,27 @@ typedef struct RDIR RDIR;
|
||||
*/
|
||||
struct RDIR *retro_opendir(const char *name);
|
||||
|
||||
struct RDIR *retro_opendir_include_hidden(const char *name, bool include_hidden);
|
||||
|
||||
int retro_readdir(struct RDIR *rdir);
|
||||
|
||||
/* Deprecated, returns false, left for compatibility */
|
||||
bool retro_dirent_error(struct RDIR *rdir);
|
||||
|
||||
void retro_dirent_include_hidden(struct RDIR *rdir, bool include_hidden);
|
||||
|
||||
const char *retro_dirent_get_name(struct RDIR *rdir);
|
||||
|
||||
/**
|
||||
*
|
||||
* retro_dirent_is_dir:
|
||||
* @rdir : pointer to the directory entry.
|
||||
* @unused : deprecated, included for compatibility reasons, pass NULL
|
||||
*
|
||||
* Is the directory listing entry a directory?
|
||||
*
|
||||
* Returns: true if directory listing entry is
|
||||
* a directory, false if not.
|
||||
*/
|
||||
bool retro_dirent_is_dir(struct RDIR *rdir, const char *path);
|
||||
bool retro_dirent_is_dir(struct RDIR *rdir, const char *unused);
|
||||
|
||||
void retro_closedir(struct RDIR *rdir);
|
||||
|
||||
|
||||
@ -73,6 +73,42 @@ printf("This is C++, version %d.\n", __cplusplus);
|
||||
/* This is not standard C. __STDC__ is not defined. */
|
||||
#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
|
||||
|
||||
@ -77,7 +77,7 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
|
||||
#ifndef PATH_MAX_LENGTH
|
||||
#if defined(__CELLOS_LV2__)
|
||||
#define PATH_MAX_LENGTH CELL_FS_MAX_FS_PATH_LENGTH
|
||||
#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(GEKKO)|| defined(WIIU)
|
||||
#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(ORBIS)
|
||||
#define PATH_MAX_LENGTH 512
|
||||
#else
|
||||
#define PATH_MAX_LENGTH 4096
|
||||
@ -155,4 +155,28 @@ typedef struct
|
||||
uint32_t data[8];
|
||||
} 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
|
||||
|
||||
@ -36,19 +36,22 @@
|
||||
#include <boolean.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <vfs/vfs_implementation.h>
|
||||
|
||||
#define FILESTREAM_REQUIRED_VFS_VERSION 1
|
||||
#define FILESTREAM_REQUIRED_VFS_VERSION 2
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef struct RFILE RFILE;
|
||||
|
||||
#define FILESTREAM_REQUIRED_VFS_VERSION 1
|
||||
#define FILESTREAM_REQUIRED_VFS_VERSION 2
|
||||
|
||||
void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info);
|
||||
|
||||
int64_t filestream_get_size(RFILE *stream);
|
||||
|
||||
int64_t filestream_truncate(RFILE *stream, int64_t length);
|
||||
|
||||
/**
|
||||
* filestream_open:
|
||||
* @path : path to file
|
||||
@ -58,7 +61,7 @@ int64_t filestream_get_size(RFILE *stream);
|
||||
* Opens a file for reading or writing, depending on the requested mode.
|
||||
* 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);
|
||||
|
||||
@ -74,10 +77,12 @@ int filestream_close(RFILE *stream);
|
||||
|
||||
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_scanf(RFILE *stream, const char* format, ...);
|
||||
|
||||
int filestream_eof(RFILE *stream);
|
||||
|
||||
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);
|
||||
|
||||
const char *filestream_get_path(RFILE *stream);
|
||||
const char* filestream_get_path(RFILE *stream);
|
||||
|
||||
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
|
||||
|
||||
|
||||
@ -30,6 +30,8 @@
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#ifndef SKIP_STDIO_REDEFINES
|
||||
|
||||
#define FILE RFILE
|
||||
|
||||
#undef fopen
|
||||
@ -41,9 +43,11 @@ RETRO_BEGIN_DECLS
|
||||
#undef fgetc
|
||||
#undef fwrite
|
||||
#undef fputc
|
||||
#undef fflush
|
||||
#undef fprintf
|
||||
#undef ferror
|
||||
#undef feof
|
||||
#undef fscanf
|
||||
|
||||
#define fopen rfopen
|
||||
#define fclose rfclose
|
||||
@ -54,9 +58,13 @@ RETRO_BEGIN_DECLS
|
||||
#define fgetc rfgetc
|
||||
#define fwrite rfwrite
|
||||
#define fputc rfputc
|
||||
#define fflush rfflush
|
||||
#define fprintf rfprintf
|
||||
#define ferror rferror
|
||||
#define feof rfeof
|
||||
#define fscanf rfscanf
|
||||
|
||||
#endif
|
||||
|
||||
RFILE* rfopen(const char *path, const char *mode);
|
||||
|
||||
@ -78,12 +86,16 @@ int64_t rfwrite(void const* buffer,
|
||||
|
||||
int rfputc(int character, RFILE * stream);
|
||||
|
||||
int64_t rfflush(RFILE * stream);
|
||||
|
||||
int rfprintf(RFILE * stream, const char * format, ...);
|
||||
|
||||
int rferror(RFILE* stream);
|
||||
|
||||
int rfeof(RFILE* stream);
|
||||
|
||||
int rfscanf(RFILE * stream, const char * format, ...);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2010-2018 The RetroArch team
|
||||
/* Copyright (C) 2010-2019 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (stdstring.h).
|
||||
@ -37,43 +37,20 @@ RETRO_BEGIN_DECLS
|
||||
|
||||
static INLINE bool string_is_empty(const char *data)
|
||||
{
|
||||
return (data == NULL) || (*data == '\0');
|
||||
return !data || (*data == '\0');
|
||||
}
|
||||
|
||||
static INLINE bool string_is_equal(const char *a, const char *b)
|
||||
{
|
||||
if (!a || !b)
|
||||
return false;
|
||||
while(*a && (*a == *b))
|
||||
a++, b++;
|
||||
return (*(const unsigned char*)a - *(const unsigned char*)b) == 0;
|
||||
return (a && b) ? !strcmp(a, b) : false;
|
||||
}
|
||||
|
||||
static INLINE bool string_is_not_equal(const char *a, const char *b)
|
||||
{
|
||||
return !string_is_equal(a, b);
|
||||
}
|
||||
#define STRLEN_CONST(x) ((sizeof((x))-1))
|
||||
|
||||
#define string_add_pair_open(s, size) strlcat((s), " (", (size))
|
||||
#define string_add_pair_close(s, size) strlcat((s), ")", (size))
|
||||
#define string_add_bracket_open(s, size) strlcat((s), "{", (size))
|
||||
#define string_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(a, b) !string_is_equal((a), (b))
|
||||
|
||||
#define string_is_not_equal_fast(a, b, size) (memcmp(a, b, size) != 0)
|
||||
#define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0)
|
||||
#define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0)
|
||||
|
||||
static INLINE bool string_is_equal_case_insensitive(const char *a,
|
||||
const char *b)
|
||||
@ -116,7 +93,7 @@ char *string_to_upper(char *s);
|
||||
|
||||
char *string_to_lower(char *s);
|
||||
|
||||
char *string_ucwords(char* s);
|
||||
char *string_ucwords(char *s);
|
||||
|
||||
char *string_replace_substring(const char *in, const char *pattern,
|
||||
const char *by);
|
||||
@ -130,7 +107,44 @@ char *string_trim_whitespace_right(char *const s);
|
||||
/* Remove leading and trailing whitespaces */
|
||||
char *string_trim_whitespace(char *const s);
|
||||
|
||||
char *word_wrap(char* buffer, const char *string, int line_width, bool unicode);
|
||||
/* max_lines == 0 means no limit */
|
||||
char *word_wrap(char *buffer, const char *string,
|
||||
int line_width, bool unicode, unsigned max_lines);
|
||||
|
||||
/* 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
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2010-2018 The RetroArch team
|
||||
/* Copyright (C) 2010-2019 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (vfs_implementation.h).
|
||||
@ -23,20 +23,13 @@
|
||||
#ifndef __LIBRETRO_SDK_VFS_IMPLEMENTATION_H
|
||||
#define __LIBRETRO_SDK_VFS_IMPLEMENTATION_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <libretro.h>
|
||||
#include <retro_environment.h>
|
||||
#include <vfs/vfs.h>
|
||||
|
||||
/* Replace the following symbol with something appropriate
|
||||
* to signify the file is being compiled for a front end instead of a core.
|
||||
* This allows the same code to act as reference implementation
|
||||
* for VFS and as fallbacks for when the front end does not provide VFS functionality.
|
||||
*/
|
||||
|
||||
#ifdef VFS_FRONTEND
|
||||
typedef struct retro_vfs_file_handle libretro_vfs_implementation_file;
|
||||
#else
|
||||
typedef struct libretro_vfs_implementation_file libretro_vfs_implementation_file;
|
||||
#endif
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints);
|
||||
|
||||
@ -46,6 +39,8 @@ int retro_vfs_file_error_impl(libretro_vfs_implementation_file *stream);
|
||||
|
||||
int64_t retro_vfs_file_size_impl(libretro_vfs_implementation_file *stream);
|
||||
|
||||
int64_t retro_vfs_file_truncate_impl(libretro_vfs_implementation_file *stream, int64_t length);
|
||||
|
||||
int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream);
|
||||
|
||||
int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file *stream, int64_t offset, int seek_position);
|
||||
@ -62,4 +57,20 @@ int retro_vfs_file_rename_impl(const char *old_path, const char *new_path);
|
||||
|
||||
const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *stream);
|
||||
|
||||
int retro_vfs_stat_impl(const char *path, int32_t *size);
|
||||
|
||||
int retro_vfs_mkdir_impl(const char *dir);
|
||||
|
||||
libretro_vfs_implementation_dir *retro_vfs_opendir_impl(const char *dir, bool include_hidden);
|
||||
|
||||
bool retro_vfs_readdir_impl(libretro_vfs_implementation_dir *dirstream);
|
||||
|
||||
const char *retro_vfs_dirent_get_name_impl(libretro_vfs_implementation_dir *dirstream);
|
||||
|
||||
bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *dirstream);
|
||||
|
||||
int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *dirstream);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.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_close_t filestream_close_cb = NULL;
|
||||
static retro_vfs_size_t filestream_size_cb = NULL;
|
||||
static retro_vfs_truncate_t filestream_truncate_cb = NULL;
|
||||
static retro_vfs_tell_t filestream_tell_cb = NULL;
|
||||
static retro_vfs_seek_t filestream_seek_cb = NULL;
|
||||
static retro_vfs_read_t filestream_read_cb = NULL;
|
||||
@ -66,6 +68,7 @@ void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info)
|
||||
filestream_close_cb = NULL;
|
||||
filestream_tell_cb = NULL;
|
||||
filestream_size_cb = NULL;
|
||||
filestream_truncate_cb = NULL;
|
||||
filestream_seek_cb = NULL;
|
||||
filestream_read_cb = NULL;
|
||||
filestream_write_cb = NULL;
|
||||
@ -83,6 +86,7 @@ void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info)
|
||||
filestream_open_cb = vfs_iface->open;
|
||||
filestream_close_cb = vfs_iface->close;
|
||||
filestream_size_cb = vfs_iface->size;
|
||||
filestream_truncate_cb = vfs_iface->truncate;
|
||||
filestream_tell_cb = vfs_iface->tell;
|
||||
filestream_seek_cb = vfs_iface->seek;
|
||||
filestream_read_cb = vfs_iface->read;
|
||||
@ -126,6 +130,21 @@ int64_t filestream_get_size(RFILE *stream)
|
||||
return output;
|
||||
}
|
||||
|
||||
int64_t filestream_truncate(RFILE *stream, int64_t length)
|
||||
{
|
||||
int64_t output;
|
||||
|
||||
if (filestream_truncate_cb != NULL)
|
||||
output = filestream_truncate_cb(stream->hfile, length);
|
||||
else
|
||||
output = retro_vfs_file_truncate_impl((libretro_vfs_implementation_file*)stream->hfile, length);
|
||||
|
||||
if (output == vfs_error_return_value)
|
||||
stream->error_flag = true;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* filestream_open:
|
||||
* @path : path to file
|
||||
@ -135,7 +154,7 @@ int64_t filestream_get_size(RFILE *stream)
|
||||
* Opens a file for reading or writing, depending on the requested mode.
|
||||
* 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;
|
||||
RFILE* output = NULL;
|
||||
@ -157,7 +176,7 @@ RFILE *filestream_open(const char *path, unsigned mode, unsigned hints)
|
||||
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;
|
||||
char *p = s;
|
||||
@ -185,12 +204,107 @@ int filestream_getc(RFILE *stream)
|
||||
{
|
||||
char c = 0;
|
||||
if (!stream)
|
||||
return 0;
|
||||
if(filestream_read(stream, &c, 1) == 1)
|
||||
return (int)c;
|
||||
return EOF;
|
||||
if (filestream_read(stream, &c, 1) == 1)
|
||||
return (int)(unsigned char)c;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
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 output;
|
||||
@ -212,7 +326,6 @@ int filestream_eof(RFILE *stream)
|
||||
return stream->eof_flag;
|
||||
}
|
||||
|
||||
|
||||
int64_t filestream_tell(RFILE *stream)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
const char *filestream_get_path(RFILE *stream)
|
||||
const char* filestream_get_path(RFILE *stream)
|
||||
{
|
||||
if (filestream_get_path_cb != NULL)
|
||||
return filestream_get_path_cb(stream->hfile);
|
||||
@ -314,7 +427,7 @@ int filestream_putc(RFILE *stream, int c)
|
||||
char c_char = (char)c;
|
||||
if (!stream)
|
||||
return EOF;
|
||||
return filestream_write(stream, &c_char, 1)==1 ? c : EOF;
|
||||
return filestream_write(stream, &c_char, 1)==1 ? (int)(unsigned char)c : EOF;
|
||||
}
|
||||
|
||||
int filestream_vprintf(RFILE *stream, const char* format, va_list args)
|
||||
@ -459,13 +572,14 @@ bool filestream_write_file(const char *path, const void *data, int64_t size)
|
||||
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 idx = 0;
|
||||
int in = 0;
|
||||
char* newline = (char*)malloc(9);
|
||||
char *newline = (char*)malloc(9);
|
||||
|
||||
if (!stream || !newline)
|
||||
{
|
||||
@ -499,3 +613,8 @@ char *filestream_getline(RFILE *stream)
|
||||
newline[idx] = '\0';
|
||||
return newline;
|
||||
}
|
||||
|
||||
libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream)
|
||||
{
|
||||
return (libretro_vfs_implementation_file*)stream->hfile;
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ RFILE* rfopen(const char *path, const char *mode)
|
||||
retro_mode = RETRO_VFS_FILE_ACCESS_READ;
|
||||
if (strstr(mode, "+"))
|
||||
{
|
||||
retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE |
|
||||
retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE |
|
||||
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
|
||||
}
|
||||
}
|
||||
@ -49,12 +49,12 @@ RFILE* rfopen(const char *path, const char *mode)
|
||||
}
|
||||
else if (strstr(mode, "a"))
|
||||
{
|
||||
retro_mode = RETRO_VFS_FILE_ACCESS_WRITE |
|
||||
retro_mode = RETRO_VFS_FILE_ACCESS_WRITE |
|
||||
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
|
||||
position_to_end = true;
|
||||
if (strstr(mode, "+"))
|
||||
{
|
||||
retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE |
|
||||
retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE |
|
||||
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
|
||||
}
|
||||
}
|
||||
@ -99,7 +99,7 @@ int64_t rfseek(RFILE* stream, int64_t offset, int origin)
|
||||
int64_t rfread(void* buffer,
|
||||
size_t elem_size, size_t elem_count, RFILE* stream)
|
||||
{
|
||||
return filestream_read(stream, buffer, elem_size * elem_count);
|
||||
return (filestream_read(stream, buffer, elem_size * elem_count) / elem_size);
|
||||
}
|
||||
|
||||
char *rfgets(char *buffer, int maxCount, RFILE* stream)
|
||||
@ -109,7 +109,7 @@ char *rfgets(char *buffer, int maxCount, RFILE* stream)
|
||||
|
||||
int rfgetc(RFILE* stream)
|
||||
{
|
||||
return filestream_getc(stream);
|
||||
return filestream_getc(stream);
|
||||
}
|
||||
|
||||
int64_t rfwrite(void const* buffer,
|
||||
@ -123,14 +123,19 @@ int rfputc(int character, RFILE * stream)
|
||||
return filestream_putc(stream, character);
|
||||
}
|
||||
|
||||
int64_t rfflush(RFILE * stream)
|
||||
{
|
||||
return filestream_flush(stream);
|
||||
}
|
||||
|
||||
int rfprintf(RFILE * stream, const char * format, ...)
|
||||
{
|
||||
int result;
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
result = filestream_vprintf(stream, format, vl);
|
||||
va_end(vl);
|
||||
return result;
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
result = filestream_vprintf(stream, format, vl);
|
||||
va_end(vl);
|
||||
return result;
|
||||
}
|
||||
|
||||
int rferror(RFILE* stream)
|
||||
@ -142,3 +147,13 @@ int rfeof(RFILE* stream)
|
||||
{
|
||||
return filestream_eof(stream);
|
||||
}
|
||||
|
||||
int rfscanf(RFILE * stream, const char * format, ...)
|
||||
{
|
||||
int result;
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
result = filestream_scanf(stream, format, vl);
|
||||
va_end(vl);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -82,6 +82,10 @@ char *string_replace_substring(const char *in,
|
||||
|
||||
outlen = strlen(in) - pattern_len*numhits + replacement_len*numhits;
|
||||
out = (char *)malloc(outlen+1);
|
||||
|
||||
if (!out)
|
||||
return NULL;
|
||||
|
||||
outat = out;
|
||||
inat = in;
|
||||
inprev = in;
|
||||
@ -105,15 +109,17 @@ char *string_trim_whitespace_left(char *const s)
|
||||
{
|
||||
if(s && *s)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
char *cur = s;
|
||||
size_t len = strlen(s);
|
||||
char *current = s;
|
||||
|
||||
while(*cur && isspace((unsigned char)*cur))
|
||||
++cur, --len;
|
||||
|
||||
if(s != cur)
|
||||
memmove(s, cur, len + 1);
|
||||
while(*current && isspace((unsigned char)*current))
|
||||
{
|
||||
++current;
|
||||
--len;
|
||||
}
|
||||
|
||||
if(s != current)
|
||||
memmove(s, current, len + 1);
|
||||
}
|
||||
|
||||
return s;
|
||||
@ -124,13 +130,16 @@ char *string_trim_whitespace_right(char *const s)
|
||||
{
|
||||
if(s && *s)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
char *cur = s + len - 1;
|
||||
size_t len = strlen(s);
|
||||
char *current = s + len - 1;
|
||||
|
||||
while(cur != s && isspace((unsigned char)*cur))
|
||||
--cur, --len;
|
||||
while(current != s && isspace((unsigned char)*current))
|
||||
{
|
||||
--current;
|
||||
--len;
|
||||
}
|
||||
|
||||
cur[isspace((unsigned char)*cur) ? 0 : 1] = '\0';
|
||||
current[isspace((unsigned char)*current) ? 0 : 1] = '\0';
|
||||
}
|
||||
|
||||
return s;
|
||||
@ -145,14 +154,16 @@ char *string_trim_whitespace(char *const s)
|
||||
return s;
|
||||
}
|
||||
|
||||
char *word_wrap(char* buffer, const char *string, int line_width, bool unicode)
|
||||
char *word_wrap(char* buffer, const char *string, int line_width, bool unicode, unsigned max_lines)
|
||||
{
|
||||
unsigned i = 0;
|
||||
unsigned len = (unsigned)strlen(string);
|
||||
unsigned i = 0;
|
||||
unsigned len = (unsigned)strlen(string);
|
||||
unsigned lines = 1;
|
||||
|
||||
while (i < len)
|
||||
{
|
||||
unsigned counter;
|
||||
int pos = (int)(&buffer[i] - buffer);
|
||||
|
||||
/* copy string until the end of the line is reached */
|
||||
for (counter = 1; counter <= (unsigned)line_width; counter++)
|
||||
@ -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
|
||||
* and reset the index */
|
||||
if (buffer[j] == '\n')
|
||||
{
|
||||
lines++;
|
||||
counter = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for whitespace */
|
||||
if (string[i] == ' ')
|
||||
{
|
||||
buffer[i] = '\n';
|
||||
i++;
|
||||
if ((max_lines == 0 || lines < max_lines))
|
||||
{
|
||||
buffer[i] = '\n';
|
||||
i++;
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -200,14 +218,18 @@ char *word_wrap(char* buffer, const char *string, int line_width, bool unicode)
|
||||
/* check for nearest whitespace back in string */
|
||||
for (k = i; k > 0; k--)
|
||||
{
|
||||
if (string[k] != ' ')
|
||||
if (string[k] != ' ' || (max_lines != 0 && lines >= max_lines))
|
||||
continue;
|
||||
|
||||
buffer[k] = '\n';
|
||||
/* set string index back to character after this one */
|
||||
i = k + 1;
|
||||
lines++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (&buffer[i] - buffer == pos)
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,3 +237,148 @@ char *word_wrap(char* buffer, const char *string, int line_width, bool unicode)
|
||||
|
||||
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
@ -1038,6 +1038,26 @@ static const char *find_bios(int *region, const char *cd_fname)
|
||||
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)
|
||||
{
|
||||
enum media_type_e media_type;
|
||||
@ -1156,6 +1176,9 @@ bool retro_load_game(const struct retro_game_info *info)
|
||||
PicoIn.sndOut = sndBuffer;
|
||||
PsndRerate(0);
|
||||
|
||||
/* Setup retro memory maps */
|
||||
set_memory_maps();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user