Update libretro-common

This commit is contained in:
negativeExponent
2020-10-25 12:01:27 +08:00
parent 565f60c0f2
commit 6eccb4401f
17 changed files with 467 additions and 187 deletions

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_snprintf.c). * The following license statement only applies to this file (compat_snprintf.c).
@@ -33,12 +33,12 @@
#if _MSC_VER < 1300 #if _MSC_VER < 1300
#define _vscprintf c89_vscprintf_retro__ #define _vscprintf c89_vscprintf_retro__
static int c89_vscprintf_retro__(const char *format, va_list pargs) static int c89_vscprintf_retro__(const char *fmt, va_list pargs)
{ {
int retval; int retval;
va_list argcopy; va_list argcopy;
va_copy(argcopy, pargs); va_copy(argcopy, pargs);
retval = vsnprintf(NULL, 0, format, argcopy); retval = vsnprintf(NULL, 0, fmt, argcopy);
va_end(argcopy); va_end(argcopy);
return retval; return retval;
} }
@@ -46,38 +46,36 @@ static int c89_vscprintf_retro__(const char *format, va_list pargs)
/* http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 */ /* http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 */
int c99_vsnprintf_retro__(char *outBuf, size_t size, const char *format, va_list ap) int c99_vsnprintf_retro__(char *s, size_t len, const char *fmt, va_list ap)
{ {
int count = -1; int count = -1;
if (size != 0) if (len != 0)
{ {
#if (_MSC_VER <= 1310) #if (_MSC_VER <= 1310)
count = _vsnprintf(outBuf, size - 1, format, ap); count = _vsnprintf(s, len - 1, fmt, ap);
#else #else
count = _vsnprintf_s(outBuf, size, size - 1, format, ap); count = _vsnprintf_s(s, len, len - 1, fmt, ap);
#endif #endif
} }
if (count == -1) if (count == -1)
count = _vscprintf(format, ap); count = _vscprintf(fmt, ap);
if (count == size)
{
/* there was no room for a NULL, so truncate the last character */ /* there was no room for a NULL, so truncate the last character */
outBuf[size - 1] = '\0'; if (count == len && len)
} s[len - 1] = '\0';
return count; return count;
} }
int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...) int c99_snprintf_retro__(char *s, size_t len, const char *fmt, ...)
{ {
int count; int count;
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, fmt);
count = c99_vsnprintf_retro__(outBuf, size, format, ap); count = c99_vsnprintf_retro__(s, len, fmt, ap);
va_end(ap); va_end(ap);
return count; return count;

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_strl.c). * The following license statement only applies to this file (compat_strl.c).

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (encoding_utf.c). * The following license statement only applies to this file (encoding_utf.c).
@@ -37,6 +37,8 @@
#include <xtl.h> #include <xtl.h>
#endif #endif
#define UTF8_WALKBYTE(string) (*((*(string))++))
static unsigned leading_ones(uint8_t c) static unsigned leading_ones(uint8_t c)
{ {
unsigned ones = 0; unsigned ones = 0;
@@ -89,13 +91,14 @@ size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
bool utf16_conv_utf8(uint8_t *out, size_t *out_chars, bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
const uint16_t *in, size_t in_size) const uint16_t *in, size_t in_size)
{ {
static uint8_t kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
size_t out_pos = 0; size_t out_pos = 0;
size_t in_pos = 0; size_t in_pos = 0;
static const
uint8_t utf8_limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
for (;;) for (;;)
{ {
unsigned numAdds; unsigned num_adds;
uint32_t value; uint32_t value;
if (in_pos == in_size) if (in_pos == in_size)
@@ -124,21 +127,21 @@ bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
} }
for (numAdds = 1; numAdds < 5; numAdds++) for (num_adds = 1; num_adds < 5; num_adds++)
if (value < (((uint32_t)1) << (numAdds * 5 + 6))) if (value < (((uint32_t)1) << (num_adds * 5 + 6)))
break; break;
if (out) if (out)
out[out_pos] = (char)(kUtf8Limits[numAdds - 1] out[out_pos] = (char)(utf8_limits[num_adds - 1]
+ (value >> (6 * numAdds))); + (value >> (6 * num_adds)));
out_pos++; out_pos++;
do do
{ {
numAdds--; num_adds--;
if (out) if (out)
out[out_pos] = (char)(0x80 out[out_pos] = (char)(0x80
+ ((value >> (6 * numAdds)) & 0x3F)); + ((value >> (6 * num_adds)) & 0x3F));
out_pos++; out_pos++;
}while (numAdds != 0); }while (num_adds != 0);
} }
*out_chars = out_pos; *out_chars = out_pos;
@@ -166,13 +169,15 @@ size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars)
while (*sb && chars-- > 0) while (*sb && chars-- > 0)
{ {
sb++; sb++;
while ((*sb & 0xC0) == 0x80) sb++; while ((*sb & 0xC0) == 0x80)
sb++;
} }
if ((size_t)(sb - sb_org) > d_len-1 /* NUL */) if ((size_t)(sb - sb_org) > d_len-1 /* NUL */)
{ {
sb = sb_org + d_len-1; sb = sb_org + d_len-1;
while ((*sb & 0xC0) == 0x80) sb--; while ((*sb & 0xC0) == 0x80)
sb--;
} }
memcpy(d, sb_org, sb-sb_org); memcpy(d, sb_org, sb-sb_org);
@@ -184,14 +189,18 @@ size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars)
const char *utf8skip(const char *str, size_t chars) const char *utf8skip(const char *str, size_t chars)
{ {
const uint8_t *strb = (const uint8_t*)str; const uint8_t *strb = (const uint8_t*)str;
if (!chars) if (!chars)
return str; return str;
do do
{ {
strb++; strb++;
while ((*strb & 0xC0)==0x80) strb++; while ((*strb & 0xC0)==0x80)
strb++;
chars--; chars--;
} while(chars); }while (chars);
return (const char*)strb; return (const char*)strb;
} }
@@ -211,24 +220,22 @@ size_t utf8len(const char *string)
return ret; return ret;
} }
#define utf8_walkbyte(string) (*((*(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)
{ {
uint8_t first = utf8_walkbyte(string); uint8_t first = UTF8_WALKBYTE(string);
uint32_t ret = 0; uint32_t ret = 0;
if (first < 128) if (first < 128)
return first; return first;
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);
return ret | (first & 7) << 18; return ret | (first & 7) << 18;
} }
return ret | (first & 15) << 12; return ret | (first & 15) << 12;
@@ -277,9 +284,7 @@ bool utf16_to_char_string(const uint16_t *in, char *s, size_t len)
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;
wchar_t *path_buf_wide = NULL; wchar_t *path_buf_wide = NULL;
int path_buf_len = 0;
int path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0); int path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
/* Windows 95 will return 0 from these functions with /* Windows 95 will return 0 from these functions with
@@ -292,8 +297,9 @@ static char *mb_to_mb_string_alloc(const char *str,
* MultiByteToWideChar also supports CP_UTF7 and CP_UTF8. * MultiByteToWideChar also supports CP_UTF7 and CP_UTF8.
*/ */
if (path_buf_wide_len) if (!path_buf_wide_len)
{ return strdup(str);
path_buf_wide = (wchar_t*) path_buf_wide = (wchar_t*)
calloc(path_buf_wide_len + sizeof(wchar_t), sizeof(wchar_t)); calloc(path_buf_wide_len + sizeof(wchar_t), sizeof(wchar_t));
@@ -304,12 +310,12 @@ static char *mb_to_mb_string_alloc(const char *str,
if (*path_buf_wide) if (*path_buf_wide)
{ {
path_buf_len = WideCharToMultiByte(cp_out, 0, int path_buf_len = WideCharToMultiByte(cp_out, 0,
path_buf_wide, -1, NULL, 0, NULL, NULL); path_buf_wide, -1, NULL, 0, NULL, NULL);
if (path_buf_len) if (path_buf_len)
{ {
path_buf = (char*) char *path_buf = (char*)
calloc(path_buf_len + sizeof(char), sizeof(char)); calloc(path_buf_len + sizeof(char), sizeof(char));
if (path_buf) if (path_buf)
@@ -333,13 +339,9 @@ static char *mb_to_mb_string_alloc(const char *str,
return strdup(str); return strdup(str);
} }
} }
}
}
else
return strdup(str);
if (path_buf_wide)
free(path_buf_wide); free(path_buf_wide);
}
return NULL; return NULL;
} }

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (boolean.h). * The following license statement only applies to this file (boolean.h).

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (msvc.h). * The following license statement only applies to this file (msvc.h).
@@ -29,22 +29,17 @@
extern "C" { extern "C" {
#endif #endif
/* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */ /* Pre-MSVC 2015 compilers don't implement snprintf, vsnprintf in a cross-platform manner. */
#if _MSC_VER < 1900 #if _MSC_VER < 1900
#include <stdio.h>
#include <stdlib.h>
#ifndef snprintf
#define snprintf c99_snprintf_retro__
#endif
int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...);
#endif
/* Pre-MSVC 2008 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
#if _MSC_VER < 1500
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef snprintf
#define snprintf c99_snprintf_retro__
#endif
int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...);
#ifndef vsnprintf #ifndef vsnprintf
#define vsnprintf c99_vsnprintf_retro__ #define vsnprintf c99_vsnprintf_retro__
#endif #endif

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (strl.h). * The following license statement only applies to this file (strl.h).

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (crc32.h). * The following license statement only applies to this file (crc32.h).

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (utf.h). * The following license statement only applies to this file (utf.h).

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (utf.h). * The following license statement only applies to this file (utf.h).

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this libretro API header (libretro.h). * The following license statement only applies to this libretro API header (libretro.h).
@@ -278,6 +278,10 @@ enum retro_language
RETRO_LANGUAGE_ARABIC = 16, RETRO_LANGUAGE_ARABIC = 16,
RETRO_LANGUAGE_GREEK = 17, RETRO_LANGUAGE_GREEK = 17,
RETRO_LANGUAGE_TURKISH = 18, RETRO_LANGUAGE_TURKISH = 18,
RETRO_LANGUAGE_SLOVAK = 19,
RETRO_LANGUAGE_PERSIAN = 20,
RETRO_LANGUAGE_HEBREW = 21,
RETRO_LANGUAGE_ASTURIAN = 22,
RETRO_LANGUAGE_LAST, RETRO_LANGUAGE_LAST,
/* Ensure sizeof(enum) == sizeof(int) */ /* Ensure sizeof(enum) == sizeof(int) */
@@ -1287,6 +1291,89 @@ enum retro_mod
* based systems). * based systems).
*/ */
#define RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION 59
/* unsigned * --
* Unsigned value is the API version number of the message
* interface supported by the frontend. If callback returns
* false, API version is assumed to be 0.
*
* In legacy code, messages may be displayed in an
* implementation-specific manner by passing a struct
* of type retro_message to RETRO_ENVIRONMENT_SET_MESSAGE.
* This may be still be done regardless of the message
* interface version.
*
* If version is >= 1 however, messages may instead be
* displayed by passing a struct of type retro_message_ext
* to RETRO_ENVIRONMENT_SET_MESSAGE_EXT. This allows the
* core to specify message logging level, priority and
* destination (OSD, logging interface or both).
*/
#define RETRO_ENVIRONMENT_SET_MESSAGE_EXT 60
/* const struct retro_message_ext * --
* Sets a message to be displayed in an implementation-specific
* manner for a certain amount of 'frames'. Additionally allows
* the core to specify message logging level, priority and
* destination (OSD, logging interface or both).
* Should not be used for trivial messages, which should simply be
* logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a
* fallback, stderr).
*/
#define RETRO_ENVIRONMENT_GET_INPUT_MAX_USERS 61
/* unsigned * --
* Unsigned value is the number of active input devices
* provided by the frontend. This may change between
* frames, but will remain constant for the duration
* of each frame.
* If callback returns true, a core need not poll any
* input device with an index greater than or equal to
* the number of active devices.
* If callback returns false, the number of active input
* devices is unknown. In this case, all input devices
* should be considered active.
*/
#define RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK 62
/* const struct retro_audio_buffer_status_callback * --
* Lets the core know the occupancy level of the frontend
* audio buffer. Can be used by a core to attempt frame
* skipping in order to avoid buffer under-runs.
* A core may pass NULL to disable buffer status reporting
* in the frontend.
*/
#define RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY 63
/* const unsigned * --
* Sets minimum frontend audio latency in milliseconds.
* Resultant audio latency may be larger than set value,
* or smaller if a hardware limit is encountered. A frontend
* is expected to honour requests up to 512 ms.
*
* - If value is less than current frontend
* audio latency, callback has no effect
* - If value is zero, default frontend audio
* latency is set
*
* May be used by a core to increase audio latency and
* therefore decrease the probability of buffer under-runs
* (crackling) when performing 'intensive' operations.
* A core utilising RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK
* to implement audio-buffer-based frame skipping may achieve
* optimal results by setting the audio latency to a 'high'
* (typically 6x or 8x) integer multiple of the expected
* frame time.
*
* WARNING: This can only be called from within retro_run().
* Calling this can require a full reinitialization of audio
* drivers in the frontend, so it is important to call it very
* sparingly, and usually only with the users explicit consent.
* An eventual driver reinitialize will happen so that audio
* callbacks happening after this call within the same retro_run()
* call will target the newly initialized driver.
*/
/* VFS functionality */ /* VFS functionality */
/* File paths: /* File paths:
@@ -2176,6 +2263,30 @@ struct retro_frame_time_callback
retro_usec_t reference; retro_usec_t reference;
}; };
/* Notifies a libretro core of the current occupancy
* level of the frontend audio buffer.
*
* - active: 'true' if audio buffer is currently
* in use. Will be 'false' if audio is
* disabled in the frontend
*
* - occupancy: Given as a value in the range [0,100],
* corresponding to the occupancy percentage
* of the audio buffer
*
* - underrun_likely: 'true' if the frontend expects an
* audio buffer underrun during the
* next frame (indicates that a core
* should attempt frame skipping)
*
* It will be called right before retro_run() every frame. */
typedef void (RETRO_CALLCONV *retro_audio_buffer_status_callback_t)(
bool active, unsigned occupancy, bool underrun_likely);
struct retro_audio_buffer_status_callback
{
retro_audio_buffer_status_callback_t callback;
};
/* Pass this to retro_video_refresh_t if rendering to hardware. /* Pass this to retro_video_refresh_t if rendering to hardware.
* Passing NULL to retro_video_refresh_t is still a frame dupe as normal. * Passing NULL to retro_video_refresh_t is still a frame dupe as normal.
* */ * */
@@ -2506,6 +2617,104 @@ struct retro_message
unsigned frames; /* Duration in frames of message. */ unsigned frames; /* Duration in frames of message. */
}; };
enum retro_message_target
{
RETRO_MESSAGE_TARGET_ALL = 0,
RETRO_MESSAGE_TARGET_OSD,
RETRO_MESSAGE_TARGET_LOG
};
enum retro_message_type
{
RETRO_MESSAGE_TYPE_NOTIFICATION = 0,
RETRO_MESSAGE_TYPE_NOTIFICATION_ALT,
RETRO_MESSAGE_TYPE_STATUS,
RETRO_MESSAGE_TYPE_PROGRESS
};
struct retro_message_ext
{
/* Message string to be displayed/logged */
const char *msg;
/* Duration (in ms) of message when targeting the OSD */
unsigned duration;
/* Message priority when targeting the OSD
* > When multiple concurrent messages are sent to
* the frontend and the frontend does not have the
* capacity to display them all, messages with the
* *highest* priority value should be shown
* > There is no upper limit to a message priority
* value (within the bounds of the unsigned data type)
* > In the reference frontend (RetroArch), the same
* priority values are used for frontend-generated
* notifications, which are typically assigned values
* between 0 and 3 depending upon importance */
unsigned priority;
/* Message logging level (info, warn, error, etc.) */
enum retro_log_level level;
/* Message destination: OSD, logging interface or both */
enum retro_message_target target;
/* Message 'type' when targeting the OSD
* > RETRO_MESSAGE_TYPE_NOTIFICATION: Specifies that a
* message should be handled in identical fashion to
* a standard frontend-generated notification
* > RETRO_MESSAGE_TYPE_NOTIFICATION_ALT: Specifies that
* message is a notification that requires user attention
* or action, but that it should be displayed in a manner
* that differs from standard frontend-generated notifications.
* This would typically correspond to messages that should be
* displayed immediately (independently from any internal
* frontend message queue), and/or which should be visually
* distinguishable from frontend-generated notifications.
* For example, a core may wish to inform the user of
* information related to a disk-change event. It is
* expected that the frontend itself may provide a
* notification in this case; if the core sends a
* message of type RETRO_MESSAGE_TYPE_NOTIFICATION, an
* uncomfortable 'double-notification' may occur. A message
* of RETRO_MESSAGE_TYPE_NOTIFICATION_ALT should therefore
* be presented such that visual conflict with regular
* notifications does not occur
* > RETRO_MESSAGE_TYPE_STATUS: Indicates that message
* is not a standard notification. This typically
* corresponds to 'status' indicators, such as a core's
* internal FPS, which are intended to be displayed
* either permanently while a core is running, or in
* a manner that does not suggest user attention or action
* is required. 'Status' type messages should therefore be
* displayed in a different on-screen location and in a manner
* easily distinguishable from both standard frontend-generated
* notifications and messages of type RETRO_MESSAGE_TYPE_NOTIFICATION_ALT
* > RETRO_MESSAGE_TYPE_PROGRESS: Indicates that message reports
* the progress of an internal core task. For example, in cases
* where a core itself handles the loading of content from a file,
* this may correspond to the percentage of the file that has been
* read. Alternatively, an audio/video playback core may use a
* message of type RETRO_MESSAGE_TYPE_PROGRESS to display the current
* playback position as a percentage of the runtime. 'Progress' type
* messages should therefore be displayed as a literal progress bar,
* where:
* - 'retro_message_ext.msg' is the progress bar title/label
* - 'retro_message_ext.progress' determines the length of
* the progress bar
* NOTE: Message type is a *hint*, and may be ignored
* by the frontend. If a frontend lacks support for
* displaying messages via alternate means than standard
* frontend-generated notifications, it will treat *all*
* messages as having the type RETRO_MESSAGE_TYPE_NOTIFICATION */
enum retro_message_type type;
/* Task progress when targeting the OSD and message is
* of type RETRO_MESSAGE_TYPE_PROGRESS
* > -1: Unmetered/indeterminate
* > 0-100: Current progress percentage
* NOTE: Since message type is a hint, a frontend may ignore
* progress values. Where relevant, a core should therefore
* include progress percentage within the message string,
* such that the message intent remains clear when displayed
* as a standard frontend-generated notification */
int8_t progress;
};
/* Describes how the libretro implementation maps a libretro input bind /* Describes how the libretro implementation maps a libretro input bind
* to its internal input system through a human readable string. * to its internal input system through a human readable string.
* This string can be used to better let a user configure input. */ * This string can be used to better let a user configure input. */
@@ -2526,7 +2735,7 @@ struct retro_input_descriptor
struct retro_system_info struct retro_system_info
{ {
/* All pointers are owned by libretro implementation, and pointers must /* All pointers are owned by libretro implementation, and pointers must
* remain valid until retro_deinit() is called. */ * remain valid until it is unloaded. */
const char *library_name; /* Descriptive name of library. Should not const char *library_name; /* Descriptive name of library. Should not
* contain any version numbers, etc. */ * contain any version numbers, etc. */

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_common.h). * The following license statement only applies to this file (retro_common.h).

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_common_api.h). * The following license statement only applies to this file (retro_common_api.h).

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_inline.h). * The following license statement only applies to this file (retro_inline.h).

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (memory_stream.h). * The following license statement only applies to this file (memory_stream.h).

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2019 The RetroArch team /* Copyright (C) 2010-2020 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).
@@ -35,6 +35,33 @@
RETRO_BEGIN_DECLS RETRO_BEGIN_DECLS
#define STRLEN_CONST(x) ((sizeof((x))-1))
#define strcpy_literal(a, b) strcpy(a, b)
#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 TOLOWER(c) (c | (lr_char_props[c] & 0x20))
#define TOUPPER(c) (c & ~(lr_char_props[c] & 0x20))
/* C standard says \f \v are space, but this one disagrees */
#define ISSPACE(c) (lr_char_props[c] & 0x80)
#define ISDIGIT(c) (lr_char_props[c] & 0x40)
#define ISALPHA(c) (lr_char_props[c] & 0x20)
#define ISLOWER(c) (lr_char_props[c] & 0x04)
#define ISUPPER(c) (lr_char_props[c] & 0x02)
#define ISALNUM(c) (lr_char_props[c] & 0x60)
#define ISUALPHA(c) (lr_char_props[c] & 0x28)
#define ISUALNUM(c) (lr_char_props[c] & 0x68)
#define IS_XDIGIT(c) (lr_char_props[c] & 0x01)
/* Deprecated alias, all callers should use string_is_equal_case_insensitive instead */
#define string_is_equal_noncase string_is_equal_case_insensitive
static INLINE bool string_is_empty(const char *data) static INLINE bool string_is_empty(const char *data)
{ {
return !data || (*data == '\0'); return !data || (*data == '\0');
@@ -45,12 +72,44 @@ static INLINE bool string_is_equal(const char *a, const char *b)
return (a && b) ? !strcmp(a, b) : false; return (a && b) ? !strcmp(a, b) : false;
} }
#define STRLEN_CONST(x) ((sizeof((x))-1)) static INLINE bool string_starts_with_size(const char *str, const char *prefix,
size_t size)
{
return (str && prefix) ? !strncmp(prefix, str, size) : false;
}
#define string_is_not_equal(a, b) !string_is_equal((a), (b)) static INLINE bool string_starts_with(const char *str, const char *prefix)
{
return (str && prefix) ? !strncmp(prefix, str, strlen(prefix)) : false;
}
static INLINE bool string_ends_with_size(const char *str, const char *suffix,
size_t str_len, size_t suffix_len)
{
return (str_len < suffix_len) ? false :
!memcmp(suffix, str + (str_len - suffix_len), suffix_len);
}
static INLINE bool string_ends_with(const char *str, const char *suffix)
{
if (!str || !suffix)
return false;
return string_ends_with_size(str, suffix, strlen(str), strlen(suffix));
}
/* Returns the length of 'str' (c.f. strlen()), but only
* checks the first 'size' characters
* - If 'str' is NULL, returns 0
* - If 'str' is not NULL and no '\0' character is found
* in the first 'size' characters, returns 'size' */
static INLINE size_t strlen_size(const char *str, size_t size)
{
size_t i = 0;
if (str)
while (i < size && str[i]) i++;
return i;
}
#define string_is_not_equal_fast(a, b, size) (memcmp(a, b, size) != 0)
#define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0)
static INLINE bool string_is_equal_case_insensitive(const char *a, static INLINE bool string_is_equal_case_insensitive(const char *a,
const char *b) const char *b)
@@ -71,24 +130,6 @@ static INLINE bool string_is_equal_case_insensitive(const char *a,
return (result == 0); return (result == 0);
} }
static INLINE bool string_is_equal_noncase(const char *a, const char *b)
{
int result = 0;
const unsigned char *p1 = (const unsigned char*)a;
const unsigned char *p2 = (const unsigned char*)b;
if (!a || !b)
return false;
if (p1 == p2)
return false;
while ((result = tolower (*p1) - tolower (*p2++)) == 0)
if (*p1++ == '\0')
break;
return (result == 0);
}
char *string_to_upper(char *s); char *string_to_upper(char *s);
char *string_to_lower(char *s); char *string_to_lower(char *s);
@@ -121,7 +162,7 @@ char *word_wrap(char *buffer, const char *string,
* char *str = "1,2,3,4,5,6,7,,,10,"; * char *str = "1,2,3,4,5,6,7,,,10,";
* char **str_ptr = &str; * char **str_ptr = &str;
* char *token = NULL; * char *token = NULL;
* while((token = string_tokenize(str_ptr, ","))) * while ((token = string_tokenize(str_ptr, ",")))
* { * {
* printf("%s\n", token); * printf("%s\n", token);
* free(token); * free(token);
@@ -146,6 +187,12 @@ unsigned string_to_unsigned(const char *str);
* Returns 0 if string is invalid */ * Returns 0 if string is invalid */
unsigned string_hex_to_unsigned(const char *str); unsigned string_hex_to_unsigned(const char *str);
char *string_init(const char *src);
void string_set(char **string, const char *src);
extern const unsigned char lr_char_props[256];
RETRO_END_DECLS RETRO_END_DECLS
#endif #endif

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (memory_stream.c). * The following license statement only applies to this file (memory_stream.c).
@@ -26,25 +26,20 @@
#include <streams/memory_stream.h> #include <streams/memory_stream.h>
/* TODO/FIXME - static globals */
static uint8_t* g_buffer = NULL; static uint8_t* g_buffer = NULL;
static uint64_t g_size = 0; static uint64_t g_size = 0;
static uint64_t last_file_size = 0; static uint64_t last_file_size = 0;
struct memstream struct memstream
{ {
uint8_t *buf;
uint64_t size; uint64_t size;
uint64_t ptr; uint64_t ptr;
uint64_t max_ptr; uint64_t max_ptr;
uint8_t *buf;
unsigned writing; unsigned writing;
}; };
static void memstream_update_pos(memstream_t *stream)
{
if (stream && stream->ptr > stream->max_ptr)
stream->max_ptr = stream->ptr;
}
void memstream_set_buffer(uint8_t *buffer, uint64_t size) void memstream_set_buffer(uint8_t *buffer, uint64_t size)
{ {
g_buffer = buffer; g_buffer = buffer;
@@ -56,30 +51,26 @@ uint64_t memstream_get_last_size(void)
return last_file_size; return last_file_size;
} }
static void memstream_init(memstream_t *stream,
uint8_t *buffer, uint64_t max_size, unsigned writing)
{
if (!stream)
return;
stream->buf = buffer;
stream->size = max_size;
stream->ptr = 0;
stream->max_ptr = 0;
stream->writing = writing;
}
memstream_t *memstream_open(unsigned writing) memstream_t *memstream_open(unsigned writing)
{ {
memstream_t *stream; memstream_t *stream;
if (!g_buffer || !g_size) if (!g_buffer || !g_size)
return NULL; return NULL;
stream = (memstream_t*)calloc(1, sizeof(*stream)); stream = (memstream_t*)malloc(sizeof(*stream));
memstream_init(stream, g_buffer, g_size, writing);
if (!stream)
return NULL;
stream->buf = g_buffer;
stream->size = g_size;
stream->ptr = 0;
stream->max_ptr = 0;
stream->writing = writing;
g_buffer = NULL; g_buffer = NULL;
g_size = 0; g_size = 0;
return stream; return stream;
} }
@@ -110,11 +101,13 @@ uint64_t memstream_read(memstream_t *stream, void *data, uint64_t bytes)
memcpy(data, stream->buf + stream->ptr, (size_t)bytes); memcpy(data, stream->buf + stream->ptr, (size_t)bytes);
stream->ptr += bytes; stream->ptr += bytes;
memstream_update_pos(stream); if (stream->ptr > stream->max_ptr)
stream->max_ptr = stream->ptr;
return bytes; return bytes;
} }
uint64_t memstream_write(memstream_t *stream, const void *data, uint64_t bytes) uint64_t memstream_write(memstream_t *stream,
const void *data, uint64_t bytes)
{ {
uint64_t avail = 0; uint64_t avail = 0;
@@ -127,7 +120,8 @@ uint64_t memstream_write(memstream_t *stream, const void *data, uint64_t bytes)
memcpy(stream->buf + stream->ptr, data, (size_t)bytes); memcpy(stream->buf + stream->ptr, data, (size_t)bytes);
stream->ptr += bytes; stream->ptr += bytes;
memstream_update_pos(stream); if (stream->ptr > stream->max_ptr)
stream->max_ptr = stream->ptr;
return bytes; return bytes;
} }
@@ -181,7 +175,8 @@ int memstream_getc(memstream_t *stream)
return EOF; return EOF;
ret = stream->buf[stream->ptr++]; ret = stream->buf[stream->ptr++];
memstream_update_pos(stream); if (stream->ptr > stream->max_ptr)
stream->max_ptr = stream->ptr;
return ret; return ret;
} }
@@ -191,5 +186,6 @@ void memstream_putc(memstream_t *stream, int c)
if (stream->ptr < stream->size) if (stream->ptr < stream->size)
stream->buf[stream->ptr++] = c; stream->buf[stream->ptr++] = c;
memstream_update_pos(stream); if (stream->ptr > stream->max_ptr)
stream->max_ptr = stream->ptr;
} }

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2010-2018 The RetroArch team /* Copyright (C) 2010-2020 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (stdstring.c). * The following license statement only applies to this file (stdstring.c).
@@ -22,10 +22,43 @@
#include <stdint.h> #include <stdint.h>
#include <ctype.h> #include <ctype.h>
#include <string.h>
#include <string/stdstring.h> #include <string/stdstring.h>
#include <encodings/utf.h> #include <encodings/utf.h>
const uint8_t lr_char_props[256] = {
/*x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x00,0x00, /* 0x */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 1x */
0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 2x !"#$%&'()*+,-./ */
0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x00,0x00,0x00,0x00,0x00,0x00, /* 3x 0123456789:;<=>? */
0x00,0x23,0x23,0x23,0x23,0x23,0x23,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, /* 4x @ABCDEFGHIJKLMNO */
0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x00,0x00,0x00,0x00,0x08, /* 5x PQRSTUVWXYZ[\]^_ */
0x00,0x25,0x25,0x25,0x25,0x25,0x25,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, /* 6x `abcdefghijklmno */
0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x00,0x00,0x00,0x00,0x00, /* 7x pqrstuvwxyz{|}~ */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8x */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 9x */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Ax */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Bx */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Cx */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Dx */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Ex */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Fx */
};
char *string_init(const char *src)
{
return src ? strdup(src) : NULL;
}
void string_set(char **string, const char *src)
{
free(*string);
*string = string_init(src);
}
char *string_to_upper(char *s) char *string_to_upper(char *s)
{ {
char *cs = (char *)s; char *cs = (char *)s;
@@ -107,18 +140,18 @@ char *string_replace_substring(const char *in,
/* Remove leading whitespaces */ /* Remove leading whitespaces */
char *string_trim_whitespace_left(char *const s) 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 *current = s; char *current = s;
while(*current && isspace((unsigned char)*current)) while (*current && ISSPACE((unsigned char)*current))
{ {
++current; ++current;
--len; --len;
} }
if(s != current) if (s != current)
memmove(s, current, len + 1); memmove(s, current, len + 1);
} }
@@ -128,18 +161,18 @@ char *string_trim_whitespace_left(char *const s)
/* Remove trailing whitespaces */ /* Remove trailing whitespaces */
char *string_trim_whitespace_right(char *const s) 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 *current = s + len - 1; char *current = s + len - 1;
while(current != s && isspace((unsigned char)*current)) while (current != s && ISSPACE((unsigned char)*current))
{ {
--current; --current;
--len; --len;
} }
current[isspace((unsigned char)*current) ? 0 : 1] = '\0'; current[ISSPACE((unsigned char)*current) ? 0 : 1] = '\0';
} }
return s; return s;
@@ -190,7 +223,7 @@ char *word_wrap(char* buffer, const char *string, int line_width, bool unicode,
buffer[i] = string[i]; buffer[i] = string[i];
char_len--; char_len--;
i++; i++;
} while(char_len); } while (char_len);
/* check for newlines embedded in the original input /* check for newlines embedded in the original input
* and reset the index */ * and reset the index */
@@ -248,7 +281,7 @@ char *word_wrap(char* buffer, const char *string, int line_width, bool unicode,
* char *str = "1,2,3,4,5,6,7,,,10,"; * char *str = "1,2,3,4,5,6,7,,,10,";
* char **str_ptr = &str; * char **str_ptr = &str;
* char *token = NULL; * char *token = NULL;
* while((token = string_tokenize(str_ptr, ","))) * while ((token = string_tokenize(str_ptr, ",")))
* { * {
* printf("%s\n", token); * printf("%s\n", token);
* free(token); * free(token);
@@ -328,7 +361,7 @@ void string_replace_all_chars(char *str, char find, char replace)
if (string_is_empty(str)) if (string_is_empty(str))
return; return;
while((str_ptr = strchr(str_ptr, find)) != NULL) while ((str_ptr = strchr(str_ptr, find)))
*str_ptr++ = replace; *str_ptr++ = replace;
} }
@@ -343,7 +376,7 @@ unsigned string_to_unsigned(const char *str)
for (ptr = str; *ptr != '\0'; ptr++) for (ptr = str; *ptr != '\0'; ptr++)
{ {
if (!isdigit(*ptr)) if (!ISDIGIT((unsigned char)*ptr))
return 0; return 0;
} }
@@ -376,7 +409,7 @@ unsigned string_hex_to_unsigned(const char *str)
/* Check for valid characters */ /* Check for valid characters */
for (ptr = hex_str; *ptr != '\0'; ptr++) for (ptr = hex_str; *ptr != '\0'; ptr++)
{ {
if (!isxdigit(*ptr)) if (!isxdigit((unsigned char)*ptr))
return 0; return 0;
} }