mirror of
https://github.com/libretro/hatari.git
synced 2025-02-17 06:37:30 +00:00
In preperation for future updates. Updated core options to v2. Moved some items into submenus. Updated Disk Control Interface for extra disk control functionality.
This commit is contained in:
parent
00a46e1ed2
commit
2d9cf221c2
@ -156,7 +156,16 @@ SOURCES_C += $(CPU_PREGEN)/cpudefs.c \
|
||||
$(LIBRETRO_DIR)/graph.c \
|
||||
$(LIBRETRO_DIR)/bmp.c \
|
||||
$(LIBRETRO_DIR)/retro_strings.c \
|
||||
$(LIBRETRO_DIR)/retro_files.c \
|
||||
$(LIBRETRO_DIR)/retro_utils.c \
|
||||
$(LIBRETRO_DIR)/retro_disk_control.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/compat_strl.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/compat_strcasestr.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/fopen_utf8.c \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \
|
||||
$(LIBRETRO_COMM_DIR)/file/file_path.c \
|
||||
$(LIBRETRO_COMM_DIR)/file/file_path_io.c \
|
||||
$(LIBRETRO_COMM_DIR)/string/stdstring.c \
|
||||
$(LIBRETRO_COMM_DIR)/time/rtime.c \
|
||||
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c \
|
||||
$(LIBRETRO_DIR)/stub/dlgAlert.c \
|
||||
$(ZLIB_SRCS)
|
||||
|
58
libretro/libretro-common/compat/compat_strcasestr.c
Normal file
58
libretro/libretro-common/compat/compat_strcasestr.c
Normal file
@ -0,0 +1,58 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (compat_strcasestr.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include <compat/strcasestr.h>
|
||||
|
||||
/* Pretty much strncasecmp. */
|
||||
static int casencmp(const char *a, const char *b, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
int a_lower = tolower(a[i]);
|
||||
int b_lower = tolower(b[i]);
|
||||
if (a_lower != b_lower)
|
||||
return a_lower - b_lower;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *strcasestr_retro__(const char *haystack, const char *needle)
|
||||
{
|
||||
size_t i, search_off;
|
||||
size_t hay_len = strlen(haystack);
|
||||
size_t needle_len = strlen(needle);
|
||||
|
||||
if (needle_len > hay_len)
|
||||
return NULL;
|
||||
|
||||
search_off = hay_len - needle_len;
|
||||
for (i = 0; i <= search_off; i++)
|
||||
if (!casencmp(haystack + i, needle, needle_len))
|
||||
return (char*)haystack + i;
|
||||
|
||||
return NULL;
|
||||
}
|
69
libretro/libretro-common/compat/compat_strl.c
Normal file
69
libretro/libretro-common/compat/compat_strl.c
Normal file
@ -0,0 +1,69 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (compat_strl.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <compat/strl.h>
|
||||
|
||||
/* Implementation of strlcpy()/strlcat() based on OpenBSD. */
|
||||
|
||||
#ifndef __MACH__
|
||||
|
||||
size_t strlcpy(char *dest, const char *source, size_t size)
|
||||
{
|
||||
size_t src_size = 0;
|
||||
size_t n = size;
|
||||
|
||||
if (n)
|
||||
while (--n && (*dest++ = *source++)) src_size++;
|
||||
|
||||
if (!n)
|
||||
{
|
||||
if (size) *dest = '\0';
|
||||
while (*source++) src_size++;
|
||||
}
|
||||
|
||||
return src_size;
|
||||
}
|
||||
|
||||
size_t strlcat(char *dest, const char *source, size_t size)
|
||||
{
|
||||
size_t len = strlen(dest);
|
||||
|
||||
dest += len;
|
||||
|
||||
if (len > size)
|
||||
size = 0;
|
||||
else
|
||||
size -= len;
|
||||
|
||||
return len + strlcpy(dest, source, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
char *strldup(const char *s, size_t n)
|
||||
{
|
||||
char *dst = (char*)malloc(sizeof(char) * (n + 1));
|
||||
strlcpy(dst, s, n);
|
||||
return dst;
|
||||
}
|
58
libretro/libretro-common/compat/fopen_utf8.c
Normal file
58
libretro/libretro-common/compat/fopen_utf8.c
Normal file
@ -0,0 +1,58 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (fopen_utf8.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <compat/fopen_utf8.h>
|
||||
#include <encodings/utf.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 || defined(_XBOX)
|
||||
#ifndef LEGACY_WIN32
|
||||
#define LEGACY_WIN32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#undef fopen
|
||||
|
||||
void *fopen_utf8(const char * filename, const char * mode)
|
||||
{
|
||||
#if defined(LEGACY_WIN32)
|
||||
FILE *ret = NULL;
|
||||
char * filename_local = utf8_to_local_string_alloc(filename);
|
||||
|
||||
if (!filename_local)
|
||||
return NULL;
|
||||
ret = fopen(filename_local, mode);
|
||||
if (filename_local)
|
||||
free(filename_local);
|
||||
return ret;
|
||||
#else
|
||||
wchar_t * filename_w = utf8_to_utf16_string_alloc(filename);
|
||||
wchar_t * mode_w = utf8_to_utf16_string_alloc(mode);
|
||||
FILE* ret = _wfopen(filename_w, mode_w);
|
||||
free(filename_w);
|
||||
free(mode_w);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
#endif
|
512
libretro/libretro-common/encodings/encoding_utf.c
Normal file
512
libretro/libretro-common/encodings/encoding_utf.c
Normal file
@ -0,0 +1,512 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (encoding_utf.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <compat/strl.h>
|
||||
#include <retro_inline.h>
|
||||
|
||||
#include <encodings/utf.h>
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
#include <windows.h>
|
||||
#elif defined(_XBOX)
|
||||
#include <xtl.h>
|
||||
#endif
|
||||
|
||||
#define UTF8_WALKBYTE(string) (*((*(string))++))
|
||||
|
||||
static unsigned leading_ones(uint8_t c)
|
||||
{
|
||||
unsigned ones = 0;
|
||||
while (c & 0x80)
|
||||
{
|
||||
ones++;
|
||||
c <<= 1;
|
||||
}
|
||||
|
||||
return ones;
|
||||
}
|
||||
|
||||
/* Simple implementation. Assumes the sequence is
|
||||
* properly synchronized and terminated. */
|
||||
|
||||
size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
|
||||
const char *in, size_t in_size)
|
||||
{
|
||||
unsigned i;
|
||||
size_t ret = 0;
|
||||
while (in_size && out_chars)
|
||||
{
|
||||
unsigned extra, shift;
|
||||
uint32_t c;
|
||||
uint8_t first = *in++;
|
||||
unsigned ones = leading_ones(first);
|
||||
|
||||
if (ones > 6 || ones == 1) /* Invalid or desync. */
|
||||
break;
|
||||
|
||||
extra = ones ? ones - 1 : ones;
|
||||
if (1 + extra > in_size) /* Overflow. */
|
||||
break;
|
||||
|
||||
shift = (extra - 1) * 6;
|
||||
c = (first & ((1 << (7 - ones)) - 1)) << (6 * extra);
|
||||
|
||||
for (i = 0; i < extra; i++, in++, shift -= 6)
|
||||
c |= (*in & 0x3f) << shift;
|
||||
|
||||
*out++ = c;
|
||||
in_size -= 1 + extra;
|
||||
out_chars--;
|
||||
ret++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
|
||||
const uint16_t *in, size_t in_size)
|
||||
{
|
||||
size_t out_pos = 0;
|
||||
size_t in_pos = 0;
|
||||
static const
|
||||
uint8_t utf8_limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned num_adds;
|
||||
uint32_t value;
|
||||
|
||||
if (in_pos == in_size)
|
||||
{
|
||||
*out_chars = out_pos;
|
||||
return true;
|
||||
}
|
||||
value = in[in_pos++];
|
||||
if (value < 0x80)
|
||||
{
|
||||
if (out)
|
||||
out[out_pos] = (char)value;
|
||||
out_pos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value >= 0xD800 && value < 0xE000)
|
||||
{
|
||||
uint32_t c2;
|
||||
|
||||
if (value >= 0xDC00 || in_pos == in_size)
|
||||
break;
|
||||
c2 = in[in_pos++];
|
||||
if (c2 < 0xDC00 || c2 >= 0xE000)
|
||||
break;
|
||||
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
|
||||
}
|
||||
|
||||
for (num_adds = 1; num_adds < 5; num_adds++)
|
||||
if (value < (((uint32_t)1) << (num_adds * 5 + 6)))
|
||||
break;
|
||||
if (out)
|
||||
out[out_pos] = (char)(utf8_limits[num_adds - 1]
|
||||
+ (value >> (6 * num_adds)));
|
||||
out_pos++;
|
||||
do
|
||||
{
|
||||
num_adds--;
|
||||
if (out)
|
||||
out[out_pos] = (char)(0x80
|
||||
+ ((value >> (6 * num_adds)) & 0x3F));
|
||||
out_pos++;
|
||||
}while (num_adds != 0);
|
||||
}
|
||||
|
||||
*out_chars = out_pos;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Acts mostly like strlcpy.
|
||||
*
|
||||
* Copies the given number of UTF-8 characters,
|
||||
* but at most d_len bytes.
|
||||
*
|
||||
* Always NULL terminates.
|
||||
* Does not copy half a character.
|
||||
*
|
||||
* Returns number of bytes. 's' is assumed valid UTF-8.
|
||||
* Use only if 'chars' is considerably less than 'd_len'. */
|
||||
size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars)
|
||||
{
|
||||
const uint8_t *sb = (const uint8_t*)s;
|
||||
const uint8_t *sb_org = sb;
|
||||
|
||||
if (!s)
|
||||
return 0;
|
||||
|
||||
while (*sb && chars-- > 0)
|
||||
{
|
||||
sb++;
|
||||
while ((*sb & 0xC0) == 0x80)
|
||||
sb++;
|
||||
}
|
||||
|
||||
if ((size_t)(sb - sb_org) > d_len-1 /* NUL */)
|
||||
{
|
||||
sb = sb_org + d_len-1;
|
||||
while ((*sb & 0xC0) == 0x80)
|
||||
sb--;
|
||||
}
|
||||
|
||||
memcpy(d, sb_org, sb-sb_org);
|
||||
d[sb-sb_org] = '\0';
|
||||
|
||||
return sb-sb_org;
|
||||
}
|
||||
|
||||
const char *utf8skip(const char *str, size_t chars)
|
||||
{
|
||||
const uint8_t *strb = (const uint8_t*)str;
|
||||
|
||||
if (!chars)
|
||||
return str;
|
||||
|
||||
do
|
||||
{
|
||||
strb++;
|
||||
while ((*strb & 0xC0)==0x80)
|
||||
strb++;
|
||||
chars--;
|
||||
}while (chars);
|
||||
|
||||
return (const char*)strb;
|
||||
}
|
||||
|
||||
size_t utf8len(const char *string)
|
||||
{
|
||||
size_t ret = 0;
|
||||
|
||||
if (!string)
|
||||
return 0;
|
||||
|
||||
while (*string)
|
||||
{
|
||||
if ((*string & 0xC0) != 0x80)
|
||||
ret++;
|
||||
string++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Does not validate the input, returns garbage if it's not UTF-8. */
|
||||
uint32_t utf8_walk(const char **string)
|
||||
{
|
||||
uint8_t first = UTF8_WALKBYTE(string);
|
||||
uint32_t ret = 0;
|
||||
|
||||
if (first < 128)
|
||||
return first;
|
||||
|
||||
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);
|
||||
return ret | (first & 7) << 18;
|
||||
}
|
||||
return ret | (first & 15) << 12;
|
||||
}
|
||||
|
||||
return ret | (first & 31) << 6;
|
||||
}
|
||||
|
||||
static bool utf16_to_char(uint8_t **utf_data,
|
||||
size_t *dest_len, const uint16_t *in)
|
||||
{
|
||||
unsigned len = 0;
|
||||
|
||||
while (in[len] != '\0')
|
||||
len++;
|
||||
|
||||
utf16_conv_utf8(NULL, dest_len, in, len);
|
||||
*dest_len += 1;
|
||||
*utf_data = (uint8_t*)malloc(*dest_len);
|
||||
if (*utf_data == 0)
|
||||
return false;
|
||||
|
||||
return utf16_conv_utf8(*utf_data, dest_len, in, len);
|
||||
}
|
||||
|
||||
bool utf16_to_char_string(const uint16_t *in, char *s, size_t len)
|
||||
{
|
||||
size_t dest_len = 0;
|
||||
uint8_t *utf16_data = NULL;
|
||||
bool ret = utf16_to_char(&utf16_data, &dest_len, in);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
utf16_data[dest_len] = 0;
|
||||
strlcpy(s, (const char*)utf16_data, len);
|
||||
}
|
||||
|
||||
free(utf16_data);
|
||||
utf16_data = NULL;
|
||||
|
||||
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,
|
||||
enum CodePage cp_in, enum CodePage cp_out)
|
||||
{
|
||||
wchar_t *path_buf_wide = NULL;
|
||||
int path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
if (!path_buf_wide_len)
|
||||
return strdup(str);
|
||||
|
||||
path_buf_wide = (wchar_t*)
|
||||
calloc(path_buf_wide_len + sizeof(wchar_t), sizeof(wchar_t));
|
||||
|
||||
if (path_buf_wide)
|
||||
{
|
||||
MultiByteToWideChar(cp_in, 0,
|
||||
str, -1, path_buf_wide, path_buf_wide_len);
|
||||
|
||||
if (*path_buf_wide)
|
||||
{
|
||||
int path_buf_len = WideCharToMultiByte(cp_out, 0,
|
||||
path_buf_wide, -1, NULL, 0, NULL, NULL);
|
||||
|
||||
if (path_buf_len)
|
||||
{
|
||||
char *path_buf = (char*)
|
||||
calloc(path_buf_len + sizeof(char), sizeof(char));
|
||||
|
||||
if (path_buf)
|
||||
{
|
||||
WideCharToMultiByte(cp_out, 0,
|
||||
path_buf_wide, -1, path_buf,
|
||||
path_buf_len, NULL, NULL);
|
||||
|
||||
free(path_buf_wide);
|
||||
|
||||
if (*path_buf)
|
||||
return path_buf;
|
||||
|
||||
free(path_buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free(path_buf_wide);
|
||||
return strdup(str);
|
||||
}
|
||||
}
|
||||
|
||||
free(path_buf_wide);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||
char* utf8_to_local_string_alloc(const char *str)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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. */
|
||||
wchar_t* utf8_to_utf16_string_alloc(const char *str)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int len = 0;
|
||||
int out_len = 0;
|
||||
#else
|
||||
size_t len = 0;
|
||||
size_t out_len = 0;
|
||||
#endif
|
||||
wchar_t *buf = NULL;
|
||||
|
||||
if (!str || !*str)
|
||||
return NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
|
||||
|
||||
if (len)
|
||||
{
|
||||
buf = (wchar_t*)calloc(len, sizeof(wchar_t));
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
out_len = MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fallback to ANSI codepage instead */
|
||||
len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
|
||||
|
||||
if (len)
|
||||
{
|
||||
buf = (wchar_t*)calloc(len, sizeof(wchar_t));
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
out_len = MultiByteToWideChar(CP_ACP, 0, str, -1, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
if (out_len < 0)
|
||||
{
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
/* NOTE: For now, assume non-Windows platforms' locale is already UTF-8. */
|
||||
len = mbstowcs(NULL, str, 0) + 1;
|
||||
|
||||
if (len)
|
||||
{
|
||||
buf = (wchar_t*)calloc(len, sizeof(wchar_t));
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
out_len = mbstowcs(buf, str, len);
|
||||
}
|
||||
|
||||
if (out_len == (size_t)-1)
|
||||
{
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||
char* utf16_to_utf8_string_alloc(const wchar_t *str)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int len = 0;
|
||||
#else
|
||||
size_t len = 0;
|
||||
#endif
|
||||
char *buf = NULL;
|
||||
|
||||
if (!str || !*str)
|
||||
return NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
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;
|
||||
|
||||
if (WideCharToMultiByte(code_page,
|
||||
0, str, -1, buf, len, NULL, NULL) < 0)
|
||||
{
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* NOTE: For now, assume non-Windows platforms'
|
||||
* locale is already UTF-8. */
|
||||
len = wcstombs(NULL, str, 0) + 1;
|
||||
|
||||
if (len)
|
||||
{
|
||||
buf = (char*)calloc(len, sizeof(char));
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
if (wcstombs(buf, str, len) == (size_t)-1)
|
||||
{
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return buf;
|
||||
}
|
1289
libretro/libretro-common/file/file_path.c
Normal file
1289
libretro/libretro-common/file/file_path.c
Normal file
File diff suppressed because it is too large
Load Diff
220
libretro/libretro-common/file/file_path_io.c
Normal file
220
libretro/libretro-common/file/file_path_io.c
Normal file
@ -0,0 +1,220 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (file_path_io.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <file/file_path.h>
|
||||
#include <retro_assert.h>
|
||||
#include <string/stdstring.h>
|
||||
#define VFS_FRONTEND
|
||||
#include <vfs/vfs_implementation.h>
|
||||
|
||||
/* TODO: There are probably some unnecessary things on this huge include list now but I'm too afraid to touch it */
|
||||
#ifdef __APPLE__
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#endif
|
||||
#ifdef __HAIKU__
|
||||
#include <kernel/image.h>
|
||||
#endif
|
||||
#ifndef __MACH__
|
||||
#include <compat/strl.h>
|
||||
#include <compat/posix_string.h>
|
||||
#endif
|
||||
#include <compat/strcasestr.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <encodings/utf.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifdef _MSC_VER
|
||||
#define setmode _setmode
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#ifdef _XBOX
|
||||
#include <xtl.h>
|
||||
#define INVALID_FILE_ATTRIBUTES -1
|
||||
#else
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1200
|
||||
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
|
||||
#endif
|
||||
#endif
|
||||
#elif defined(VITA)
|
||||
#define SCE_ERROR_ERRNO_EEXIST 0x80010011
|
||||
#include <psp2/io/fcntl.h>
|
||||
#include <psp2/io/dirent.h>
|
||||
#include <psp2/io/stat.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(PSP)
|
||||
#include <pspkernel.h>
|
||||
#endif
|
||||
|
||||
#if defined(VITA)
|
||||
#define FIO_S_ISDIR SCE_S_ISDIR
|
||||
#endif
|
||||
|
||||
#if defined(__QNX__) || defined(PSP) || defined(PS2)
|
||||
#include <unistd.h> /* stat() is defined here */
|
||||
#endif
|
||||
|
||||
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
|
||||
#ifdef __WINRT__
|
||||
#include <uwp/uwp_func.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Assume W-functions do not work below Win2K and Xbox platforms */
|
||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 || defined(_XBOX)
|
||||
|
||||
#ifndef LEGACY_WIN32
|
||||
#define LEGACY_WIN32
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* TODO/FIXME - globals */
|
||||
static retro_vfs_stat_t path_stat_cb = retro_vfs_stat_impl;
|
||||
static retro_vfs_mkdir_t path_mkdir_cb = retro_vfs_mkdir_impl;
|
||||
|
||||
void path_vfs_init(const struct retro_vfs_interface_info* vfs_info)
|
||||
{
|
||||
const struct retro_vfs_interface*
|
||||
vfs_iface = vfs_info->iface;
|
||||
|
||||
path_stat_cb = retro_vfs_stat_impl;
|
||||
path_mkdir_cb = retro_vfs_mkdir_impl;
|
||||
|
||||
if (vfs_info->required_interface_version < PATH_REQUIRED_VFS_VERSION || !vfs_iface)
|
||||
return;
|
||||
|
||||
path_stat_cb = vfs_iface->stat;
|
||||
path_mkdir_cb = vfs_iface->mkdir;
|
||||
}
|
||||
|
||||
int path_stat(const char *path)
|
||||
{
|
||||
return path_stat_cb(path, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* path_is_directory:
|
||||
* @path : path
|
||||
*
|
||||
* Checks if path is a directory.
|
||||
*
|
||||
* Returns: true (1) if path is a directory, otherwise false (0).
|
||||
*/
|
||||
bool path_is_directory(const char *path)
|
||||
{
|
||||
return (path_stat_cb(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0;
|
||||
}
|
||||
|
||||
bool path_is_character_special(const char *path)
|
||||
{
|
||||
return (path_stat_cb(path, NULL) & RETRO_VFS_STAT_IS_CHARACTER_SPECIAL) != 0;
|
||||
}
|
||||
|
||||
bool path_is_valid(const char *path)
|
||||
{
|
||||
return (path_stat_cb(path, NULL) & RETRO_VFS_STAT_IS_VALID) != 0;
|
||||
}
|
||||
|
||||
int32_t path_get_size(const char *path)
|
||||
{
|
||||
int32_t filesize = 0;
|
||||
if (path_stat_cb(path, &filesize) != 0)
|
||||
return filesize;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* path_mkdir:
|
||||
* @dir : directory
|
||||
*
|
||||
* Create directory on filesystem.
|
||||
*
|
||||
* Returns: true (1) if directory could be created, otherwise false (0).
|
||||
**/
|
||||
bool path_mkdir(const char *dir)
|
||||
{
|
||||
bool sret = false;
|
||||
bool norecurse = false;
|
||||
char *basedir = NULL;
|
||||
|
||||
if (!(dir && *dir))
|
||||
return false;
|
||||
|
||||
/* Use heap. Real chance of stack
|
||||
* overflow if we recurse too hard. */
|
||||
basedir = strdup(dir);
|
||||
|
||||
if (!basedir)
|
||||
return false;
|
||||
|
||||
path_parent_dir(basedir);
|
||||
|
||||
if (!*basedir || !strcmp(basedir, dir))
|
||||
{
|
||||
free(basedir);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (path_is_directory(basedir))
|
||||
norecurse = true;
|
||||
else
|
||||
{
|
||||
sret = path_mkdir(basedir);
|
||||
|
||||
if (sret)
|
||||
norecurse = true;
|
||||
}
|
||||
|
||||
free(basedir);
|
||||
|
||||
if (norecurse)
|
||||
{
|
||||
int ret = path_mkdir_cb(dir);
|
||||
|
||||
/* Don't treat this as an error. */
|
||||
if (ret == -2 && path_is_directory(dir))
|
||||
return true;
|
||||
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
return sret;
|
||||
}
|
39
libretro/libretro-common/include/boolean.h
Normal file
39
libretro/libretro-common/include/boolean.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (boolean.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_BOOLEAN_H
|
||||
#define __LIBRETRO_SDK_BOOLEAN_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1800 && !defined(SN_TARGET_PS3)
|
||||
/* Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. */
|
||||
#define bool unsigned char
|
||||
#define true 1
|
||||
#define false 0
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
34
libretro/libretro-common/include/compat/fopen_utf8.h
Normal file
34
libretro/libretro-common/include/compat/fopen_utf8.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (fopen_utf8.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_COMPAT_FOPEN_UTF8_H
|
||||
#define __LIBRETRO_SDK_COMPAT_FOPEN_UTF8_H
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Defined to error rather than fopen_utf8, to make it clear to everyone reading the code that not worrying about utf16 is fine */
|
||||
/* TODO: enable */
|
||||
/* #define fopen (use fopen_utf8 instead) */
|
||||
void *fopen_utf8(const char * filename, const char * mode);
|
||||
#else
|
||||
#define fopen_utf8 fopen
|
||||
#endif
|
||||
#endif
|
60
libretro/libretro-common/include/compat/posix_string.h
Normal file
60
libretro/libretro-common/include/compat/posix_string.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (posix_string.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_COMPAT_POSIX_STRING_H
|
||||
#define __LIBRETRO_SDK_COMPAT_POSIX_STRING_H
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <compat/msvc.h>
|
||||
#endif
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#ifdef _WIN32
|
||||
#undef strtok_r
|
||||
#define strtok_r(str, delim, saveptr) retro_strtok_r__(str, delim, saveptr)
|
||||
|
||||
char *strtok_r(char *str, const char *delim, char **saveptr);
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#undef strcasecmp
|
||||
#undef strdup
|
||||
#define strcasecmp(a, b) retro_strcasecmp__(a, b)
|
||||
#define strdup(orig) retro_strdup__(orig)
|
||||
int strcasecmp(const char *a, const char *b);
|
||||
char *strdup(const char *orig);
|
||||
|
||||
/* isblank is available since MSVC 2013 */
|
||||
#if _MSC_VER < 1800
|
||||
#undef isblank
|
||||
#define isblank(c) retro_isblank__(c)
|
||||
int isblank(int c);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
48
libretro/libretro-common/include/compat/strcasestr.h
Normal file
48
libretro/libretro-common/include/compat/strcasestr.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (strcasestr.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_COMPAT_STRCASESTR_H
|
||||
#define __LIBRETRO_SDK_COMPAT_STRCASESTR_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
|
||||
#include "../../../config.h"
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRCASESTR
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/* Avoid possible naming collisions during link
|
||||
* since we prefer to use the actual name. */
|
||||
#define strcasestr(haystack, needle) strcasestr_retro__(haystack, needle)
|
||||
|
||||
char *strcasestr(const char *haystack, const char *needle);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
59
libretro/libretro-common/include/compat/strl.h
Normal file
59
libretro/libretro-common/include/compat/strl.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (strl.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_COMPAT_STRL_H
|
||||
#define __LIBRETRO_SDK_COMPAT_STRL_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
|
||||
#include "../../../config.h"
|
||||
#endif
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#ifdef __MACH__
|
||||
#ifndef HAVE_STRL
|
||||
#define HAVE_STRL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRL
|
||||
/* Avoid possible naming collisions during link since
|
||||
* we prefer to use the actual name. */
|
||||
#define strlcpy(dst, src, size) strlcpy_retro__(dst, src, size)
|
||||
|
||||
#define strlcat(dst, src, size) strlcat_retro__(dst, src, size)
|
||||
|
||||
size_t strlcpy(char *dest, const char *source, size_t size);
|
||||
size_t strlcat(char *dest, const char *source, size_t size);
|
||||
|
||||
#endif
|
||||
|
||||
char *strldup(const char *s, size_t n);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
67
libretro/libretro-common/include/encodings/utf.h
Normal file
67
libretro/libretro-common/include/encodings/utf.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (utf.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _LIBRETRO_ENCODINGS_UTF_H
|
||||
#define _LIBRETRO_ENCODINGS_UTF_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
enum CodePage
|
||||
{
|
||||
CODEPAGE_LOCAL = 0, /* CP_ACP */
|
||||
CODEPAGE_UTF8 = 65001 /* CP_UTF8 */
|
||||
};
|
||||
|
||||
size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
|
||||
const char *in, size_t in_size);
|
||||
|
||||
bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
|
||||
const uint16_t *in, size_t in_size);
|
||||
|
||||
size_t utf8len(const char *string);
|
||||
|
||||
size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars);
|
||||
|
||||
const char *utf8skip(const char *str, size_t chars);
|
||||
|
||||
uint32_t utf8_walk(const char **string);
|
||||
|
||||
bool utf16_to_char_string(const uint16_t *in, char *s, size_t len);
|
||||
|
||||
char* utf8_to_local_string_alloc(const char *str);
|
||||
|
||||
char* local_to_utf8_string_alloc(const char *str);
|
||||
|
||||
wchar_t* utf8_to_utf16_string_alloc(const char *str);
|
||||
|
||||
char* utf16_to_utf8_string_alloc(const wchar_t *str);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
531
libretro/libretro-common/include/file/file_path.h
Normal file
531
libretro/libretro-common/include/file/file_path.h
Normal file
@ -0,0 +1,531 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (file_path.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_FILE_PATH_H
|
||||
#define __LIBRETRO_SDK_FILE_PATH_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <libretro.h>
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#define PATH_REQUIRED_VFS_VERSION 3
|
||||
|
||||
void path_vfs_init(const struct retro_vfs_interface_info* vfs_info);
|
||||
|
||||
/* Order in this enum is equivalent to negative sort order in filelist
|
||||
* (i.e. DIRECTORY is on top of PLAIN_FILE) */
|
||||
enum
|
||||
{
|
||||
RARCH_FILETYPE_UNSET,
|
||||
RARCH_PLAIN_FILE,
|
||||
RARCH_COMPRESSED_FILE_IN_ARCHIVE,
|
||||
RARCH_COMPRESSED_ARCHIVE,
|
||||
RARCH_DIRECTORY,
|
||||
RARCH_FILE_UNSUPPORTED
|
||||
};
|
||||
|
||||
/**
|
||||
* path_is_compressed_file:
|
||||
* @path : path
|
||||
*
|
||||
* Checks if path is a compressed file.
|
||||
*
|
||||
* Returns: true (1) if path is a compressed file, otherwise false (0).
|
||||
**/
|
||||
bool path_is_compressed_file(const char *path);
|
||||
|
||||
/**
|
||||
* path_contains_compressed_file:
|
||||
* @path : path
|
||||
*
|
||||
* Checks if path contains a compressed file.
|
||||
*
|
||||
* Currently we only check for hash symbol (#) inside the pathname.
|
||||
* If path is ever expanded to a general URI, we should check for that here.
|
||||
*
|
||||
* Example: Somewhere in the path there might be a compressed file
|
||||
* E.g.: /path/to/file.7z#mygame.img
|
||||
*
|
||||
* Returns: true (1) if path contains compressed file, otherwise false (0).
|
||||
**/
|
||||
#define path_contains_compressed_file(path) (path_get_archive_delim((path)) != NULL)
|
||||
|
||||
/**
|
||||
* path_get_archive_delim:
|
||||
* @path : path
|
||||
*
|
||||
* Gets delimiter of an archive file. Only the first '#'
|
||||
* after a compression extension is considered.
|
||||
*
|
||||
* Returns: pointer to the delimiter in the path if it contains
|
||||
* a compressed file, otherwise NULL.
|
||||
*/
|
||||
const char *path_get_archive_delim(const char *path);
|
||||
|
||||
/**
|
||||
* path_get_extension:
|
||||
* @path : path
|
||||
*
|
||||
* Gets extension of file. Only '.'s
|
||||
* after the last slash are considered.
|
||||
*
|
||||
* Returns: extension part from the path.
|
||||
*/
|
||||
const char *path_get_extension(const char *path);
|
||||
|
||||
/**
|
||||
* path_remove_extension:
|
||||
* @path : path
|
||||
*
|
||||
* Mutates path by removing its extension. Removes all
|
||||
* text after and including the last '.'.
|
||||
* Only '.'s after the last slash are considered.
|
||||
*
|
||||
* Returns:
|
||||
* 1) If path has an extension, returns path with the
|
||||
* extension removed.
|
||||
* 2) If there is no extension, returns NULL.
|
||||
* 3) If path is empty or NULL, returns NULL
|
||||
*/
|
||||
char *path_remove_extension(char *path);
|
||||
|
||||
/**
|
||||
* path_basename:
|
||||
* @path : path
|
||||
*
|
||||
* Get basename from @path.
|
||||
*
|
||||
* Returns: basename from path.
|
||||
**/
|
||||
const char *path_basename(const char *path);
|
||||
|
||||
/**
|
||||
* path_basedir:
|
||||
* @path : path
|
||||
*
|
||||
* Extracts base directory by mutating path.
|
||||
* Keeps trailing '/'.
|
||||
**/
|
||||
void path_basedir(char *path);
|
||||
|
||||
/**
|
||||
* path_parent_dir:
|
||||
* @path : path
|
||||
*
|
||||
* Extracts parent directory by mutating path.
|
||||
* Assumes that path is a directory. Keeps trailing '/'.
|
||||
* If the path was already at the root directory, returns empty string
|
||||
**/
|
||||
void path_parent_dir(char *path);
|
||||
|
||||
/**
|
||||
* path_resolve_realpath:
|
||||
* @buf : input and output buffer for path
|
||||
* @size : size of buffer
|
||||
* @resolve_symlinks : whether to resolve symlinks or not
|
||||
*
|
||||
* Resolves use of ".", "..", multiple slashes etc in absolute paths.
|
||||
*
|
||||
* Relative paths are rebased on the current working dir.
|
||||
*
|
||||
* Returns: @buf if successful, NULL otherwise.
|
||||
* Note: Not implemented on consoles
|
||||
* Note: Symlinks are only resolved on Unix-likes
|
||||
* Note: The current working dir might not be what you expect,
|
||||
* e.g. on Android it is "/"
|
||||
* Use of fill_pathname_resolve_relative() should be prefered
|
||||
**/
|
||||
char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks);
|
||||
|
||||
/**
|
||||
* path_relative_to:
|
||||
* @out : buffer to write the relative path to
|
||||
* @path : path to be expressed relatively
|
||||
* @base : relative to this
|
||||
* @size : size of output buffer
|
||||
*
|
||||
* Turns @path into a path relative to @base and writes it to @out.
|
||||
*
|
||||
* @base is assumed to be a base directory, i.e. a path ending with '/' or '\'.
|
||||
* Both @path and @base are assumed to be absolute paths without "." or "..".
|
||||
*
|
||||
* E.g. path /a/b/e/f.cgp with base /a/b/c/d/ turns into ../../e/f.cgp
|
||||
**/
|
||||
size_t path_relative_to(char *out, const char *path, const char *base, size_t size);
|
||||
|
||||
/**
|
||||
* path_is_absolute:
|
||||
* @path : path
|
||||
*
|
||||
* Checks if @path is an absolute path or a relative path.
|
||||
*
|
||||
* Returns: true if path is absolute, false if path is relative.
|
||||
**/
|
||||
bool path_is_absolute(const char *path);
|
||||
|
||||
/**
|
||||
* fill_pathname:
|
||||
* @out_path : output path
|
||||
* @in_path : input path
|
||||
* @replace : what to replace
|
||||
* @size : buffer size of output path
|
||||
*
|
||||
* FIXME: Verify
|
||||
*
|
||||
* Replaces filename extension with 'replace' and outputs result to out_path.
|
||||
* The extension here is considered to be the string from the last '.'
|
||||
* to the end.
|
||||
*
|
||||
* Only '.'s after the last slash are considered as extensions.
|
||||
* If no '.' is present, in_path and replace will simply be concatenated.
|
||||
* 'size' is buffer size of 'out_path'.
|
||||
* E.g.: in_path = "/foo/bar/baz/boo.c", replace = ".asm" =>
|
||||
* out_path = "/foo/bar/baz/boo.asm"
|
||||
* E.g.: in_path = "/foo/bar/baz/boo.c", replace = "" =>
|
||||
* out_path = "/foo/bar/baz/boo"
|
||||
*/
|
||||
void fill_pathname(char *out_path, const char *in_path,
|
||||
const char *replace, size_t size);
|
||||
|
||||
/**
|
||||
* fill_dated_filename:
|
||||
* @out_filename : output filename
|
||||
* @ext : extension of output filename
|
||||
* @size : buffer size of output filename
|
||||
*
|
||||
* Creates a 'dated' filename prefixed by 'RetroArch', and
|
||||
* concatenates extension (@ext) to it.
|
||||
*
|
||||
* E.g.:
|
||||
* out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
|
||||
**/
|
||||
size_t fill_dated_filename(char *out_filename,
|
||||
const char *ext, size_t size);
|
||||
|
||||
/**
|
||||
* fill_str_dated_filename:
|
||||
* @out_filename : output filename
|
||||
* @in_str : input string
|
||||
* @ext : extension of output filename
|
||||
* @size : buffer size of output filename
|
||||
*
|
||||
* Creates a 'dated' filename prefixed by the string @in_str, and
|
||||
* concatenates extension (@ext) to it.
|
||||
*
|
||||
* E.g.:
|
||||
* out_filename = "RetroArch-{year}{month}{day}-{Hour}{Minute}{Second}.{@ext}"
|
||||
**/
|
||||
void fill_str_dated_filename(char *out_filename,
|
||||
const char *in_str, const char *ext, size_t size);
|
||||
|
||||
/**
|
||||
* fill_pathname_noext:
|
||||
* @out_path : output path
|
||||
* @in_path : input path
|
||||
* @replace : what to replace
|
||||
* @size : buffer size of output path
|
||||
*
|
||||
* Appends a filename extension 'replace' to 'in_path', and outputs
|
||||
* result in 'out_path'.
|
||||
*
|
||||
* Assumes in_path has no extension. If an extension is still
|
||||
* present in 'in_path', it will be ignored.
|
||||
*
|
||||
*/
|
||||
size_t fill_pathname_noext(char *out_path, const char *in_path,
|
||||
const char *replace, size_t size);
|
||||
|
||||
/**
|
||||
* find_last_slash:
|
||||
* @str : input path
|
||||
*
|
||||
* Gets a pointer to the last slash in the input path.
|
||||
*
|
||||
* Returns: a pointer to the last slash in the input path.
|
||||
**/
|
||||
char *find_last_slash(const char *str);
|
||||
|
||||
/**
|
||||
* fill_pathname_dir:
|
||||
* @in_dir : input directory path
|
||||
* @in_basename : input basename to be appended to @in_dir
|
||||
* @replace : replacement to be appended to @in_basename
|
||||
* @size : size of buffer
|
||||
*
|
||||
* Appends basename of 'in_basename', to 'in_dir', along with 'replace'.
|
||||
* Basename of in_basename is the string after the last '/' or '\\',
|
||||
* i.e the filename without directories.
|
||||
*
|
||||
* If in_basename has no '/' or '\\', the whole 'in_basename' will be used.
|
||||
* 'size' is buffer size of 'in_dir'.
|
||||
*
|
||||
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
|
||||
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
|
||||
**/
|
||||
size_t fill_pathname_dir(char *in_dir, const char *in_basename,
|
||||
const char *replace, size_t size);
|
||||
|
||||
/**
|
||||
* fill_pathname_base:
|
||||
* @out : output path
|
||||
* @in_path : input path
|
||||
* @size : size of output path
|
||||
*
|
||||
* Copies basename of @in_path into @out_path.
|
||||
**/
|
||||
size_t fill_pathname_base(char *out_path, const char *in_path, size_t size);
|
||||
|
||||
void fill_pathname_base_noext(char *out_dir,
|
||||
const char *in_path, size_t size);
|
||||
|
||||
size_t fill_pathname_base_ext(char *out,
|
||||
const char *in_path, const char *ext,
|
||||
size_t size);
|
||||
|
||||
/**
|
||||
* fill_pathname_basedir:
|
||||
* @out_dir : output directory
|
||||
* @in_path : input path
|
||||
* @size : size of output directory
|
||||
*
|
||||
* Copies base directory of @in_path into @out_path.
|
||||
* If in_path is a path without any slashes (relative current directory),
|
||||
* @out_path will get path "./".
|
||||
**/
|
||||
void fill_pathname_basedir(char *out_path, const char *in_path, size_t size);
|
||||
|
||||
void fill_pathname_basedir_noext(char *out_dir,
|
||||
const char *in_path, size_t size);
|
||||
|
||||
/**
|
||||
* fill_pathname_parent_dir_name:
|
||||
* @out_dir : output directory
|
||||
* @in_dir : input directory
|
||||
* @size : size of output directory
|
||||
*
|
||||
* Copies only the parent directory name of @in_dir into @out_dir.
|
||||
* The two buffers must not overlap. Removes trailing '/'.
|
||||
* Returns true on success, false if a slash was not found in the path.
|
||||
**/
|
||||
bool fill_pathname_parent_dir_name(char *out_dir,
|
||||
const char *in_dir, size_t size);
|
||||
|
||||
/**
|
||||
* fill_pathname_parent_dir:
|
||||
* @out_dir : output directory
|
||||
* @in_dir : input directory
|
||||
* @size : size of output directory
|
||||
*
|
||||
* Copies parent directory of @in_dir into @out_dir.
|
||||
* Assumes @in_dir is a directory. Keeps trailing '/'.
|
||||
* If the path was already at the root directory, @out_dir will be an empty string.
|
||||
**/
|
||||
void fill_pathname_parent_dir(char *out_dir,
|
||||
const char *in_dir, size_t size);
|
||||
|
||||
/**
|
||||
* fill_pathname_resolve_relative:
|
||||
* @out_path : output path
|
||||
* @in_refpath : input reference path
|
||||
* @in_path : input path
|
||||
* @size : size of @out_path
|
||||
*
|
||||
* Joins basedir of @in_refpath together with @in_path.
|
||||
* If @in_path is an absolute path, out_path = in_path.
|
||||
* E.g.: in_refpath = "/foo/bar/baz.a", in_path = "foobar.cg",
|
||||
* out_path = "/foo/bar/foobar.cg".
|
||||
**/
|
||||
void fill_pathname_resolve_relative(char *out_path, const char *in_refpath,
|
||||
const char *in_path, size_t size);
|
||||
|
||||
/**
|
||||
* fill_pathname_join:
|
||||
* @out_path : output path
|
||||
* @dir : directory
|
||||
* @path : path
|
||||
* @size : size of output path
|
||||
*
|
||||
* Joins a directory (@dir) and path (@path) together.
|
||||
* Makes sure not to get two consecutive slashes
|
||||
* between directory and path.
|
||||
**/
|
||||
size_t fill_pathname_join(char *out_path, const char *dir,
|
||||
const char *path, size_t size);
|
||||
|
||||
size_t fill_pathname_join_special_ext(char *out_path,
|
||||
const char *dir, const char *path,
|
||||
const char *last, const char *ext,
|
||||
size_t size);
|
||||
|
||||
size_t fill_pathname_join_concat_noext(char *out_path,
|
||||
const char *dir, const char *path,
|
||||
const char *concat,
|
||||
size_t size);
|
||||
|
||||
size_t fill_pathname_join_concat(char *out_path,
|
||||
const char *dir, const char *path,
|
||||
const char *concat,
|
||||
size_t size);
|
||||
|
||||
void fill_pathname_join_noext(char *out_path,
|
||||
const char *dir, const char *path, size_t size);
|
||||
|
||||
/**
|
||||
* fill_pathname_join_delim:
|
||||
* @out_path : output path
|
||||
* @dir : directory
|
||||
* @path : path
|
||||
* @delim : delimiter
|
||||
* @size : size of output path
|
||||
*
|
||||
* Joins a directory (@dir) and path (@path) together
|
||||
* using the given delimiter (@delim).
|
||||
**/
|
||||
size_t fill_pathname_join_delim(char *out_path, const char *dir,
|
||||
const char *path, const char delim, size_t size);
|
||||
|
||||
size_t fill_pathname_join_delim_concat(char *out_path, const char *dir,
|
||||
const char *path, const char delim, const char *concat,
|
||||
size_t size);
|
||||
|
||||
/**
|
||||
* fill_short_pathname_representation:
|
||||
* @out_rep : output representation
|
||||
* @in_path : input path
|
||||
* @size : size of output representation
|
||||
*
|
||||
* Generates a short representation of path. It should only
|
||||
* be used for displaying the result; the output representation is not
|
||||
* binding in any meaningful way (for a normal path, this is the same as basename)
|
||||
* In case of more complex URLs, this should cut everything except for
|
||||
* the main image file.
|
||||
*
|
||||
* E.g.: "/path/to/game.img" -> game.img
|
||||
* "/path/to/myarchive.7z#folder/to/game.img" -> game.img
|
||||
*/
|
||||
size_t fill_short_pathname_representation(char* out_rep,
|
||||
const char *in_path, size_t size);
|
||||
|
||||
void fill_short_pathname_representation_noext(char* out_rep,
|
||||
const char *in_path, size_t size);
|
||||
|
||||
void fill_pathname_expand_special(char *out_path,
|
||||
const char *in_path, size_t size);
|
||||
|
||||
void fill_pathname_abbreviate_special(char *out_path,
|
||||
const char *in_path, size_t size);
|
||||
|
||||
/**
|
||||
* path_basedir:
|
||||
* @path : path
|
||||
*
|
||||
* Extracts base directory by mutating path.
|
||||
* Keeps trailing '/'.
|
||||
**/
|
||||
void path_basedir_wrapper(char *path);
|
||||
|
||||
/**
|
||||
* path_char_is_slash:
|
||||
* @c : character
|
||||
*
|
||||
* Checks if character (@c) is a slash.
|
||||
*
|
||||
* Returns: true (1) if character is a slash, otherwise false (0).
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#define PATH_CHAR_IS_SLASH(c) (((c) == '/') || ((c) == '\\'))
|
||||
#else
|
||||
#define PATH_CHAR_IS_SLASH(c) ((c) == '/')
|
||||
#endif
|
||||
|
||||
/**
|
||||
* path_default_slash and path_default_slash_c:
|
||||
*
|
||||
* Gets the default slash separator.
|
||||
*
|
||||
* Returns: default slash separator.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
#define PATH_DEFAULT_SLASH() "\\"
|
||||
#define PATH_DEFAULT_SLASH_C() '\\'
|
||||
#else
|
||||
#define PATH_DEFAULT_SLASH() "/"
|
||||
#define PATH_DEFAULT_SLASH_C() '/'
|
||||
#endif
|
||||
|
||||
/**
|
||||
* fill_pathname_slash:
|
||||
* @path : path
|
||||
* @size : size of path
|
||||
*
|
||||
* Assumes path is a directory. Appends a slash
|
||||
* if not already there.
|
||||
**/
|
||||
void fill_pathname_slash(char *path, size_t size);
|
||||
|
||||
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
|
||||
void fill_pathname_application_path(char *buf, size_t size);
|
||||
void fill_pathname_application_dir(char *buf, size_t size);
|
||||
void fill_pathname_home_dir(char *buf, size_t size);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* path_mkdir:
|
||||
* @dir : directory
|
||||
*
|
||||
* Create directory on filesystem.
|
||||
*
|
||||
* Returns: true (1) if directory could be created, otherwise false (0).
|
||||
**/
|
||||
bool path_mkdir(const char *dir);
|
||||
|
||||
/**
|
||||
* path_is_directory:
|
||||
* @path : path
|
||||
*
|
||||
* Checks if path is a directory.
|
||||
*
|
||||
* Returns: true (1) if path is a directory, otherwise false (0).
|
||||
*/
|
||||
bool path_is_directory(const char *path);
|
||||
|
||||
bool path_is_character_special(const char *path);
|
||||
|
||||
int path_stat(const char *path);
|
||||
|
||||
bool path_is_valid(const char *path);
|
||||
|
||||
int32_t path_get_size(const char *path);
|
||||
|
||||
bool is_path_accessible_using_standard_io(const char *path);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
52
libretro/libretro-common/include/memmap.h
Normal file
52
libretro/libretro-common/include/memmap.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (memmap.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _LIBRETRO_MEMMAP_H
|
||||
#define _LIBRETRO_MEMMAP_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(PSP) || defined(PS2) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH) || defined(HAVE_LIBNX) || defined(__PS3__) || defined(__PSL1GHT__)
|
||||
/* No mman available */
|
||||
#elif defined(_WIN32) && !defined(_XBOX)
|
||||
#include <windows.h>
|
||||
#include <errno.h>
|
||||
#include <io.h>
|
||||
#else
|
||||
#define HAVE_MMAN
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_MMAN) || defined(_WIN32)
|
||||
void* mmap(void *addr, size_t len, int mmap_prot, int mmap_flags, int fildes, size_t off);
|
||||
|
||||
int munmap(void *addr, size_t len);
|
||||
|
||||
int mprotect(void *addr, size_t len, int prot);
|
||||
#endif
|
||||
|
||||
int memsync(void *start, void *end);
|
||||
|
||||
int memprotect(void *addr, size_t len);
|
||||
|
||||
#endif
|
37
libretro/libretro-common/include/retro_assert.h
Normal file
37
libretro/libretro-common/include/retro_assert.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (retro_assert.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __RETRO_ASSERT_H
|
||||
#define __RETRO_ASSERT_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#include <stdio.h>
|
||||
#define retro_assert(cond) do { \
|
||||
if (!(cond)) { printf("Assertion failed at %s:%d.\n", __FILE__, __LINE__); abort(); } \
|
||||
} while(0)
|
||||
#else
|
||||
#define retro_assert(cond) assert(cond)
|
||||
#endif
|
||||
|
||||
#endif
|
114
libretro/libretro-common/include/retro_environment.h
Normal file
114
libretro/libretro-common/include/retro_environment.h
Normal file
@ -0,0 +1,114 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (retro_environment.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_ENVIRONMENT_H
|
||||
#define __LIBRETRO_SDK_ENVIRONMENT_H
|
||||
|
||||
/*
|
||||
This file is designed to create a normalized environment for compiling
|
||||
libretro-common's private implementations, or any other sources which might
|
||||
enjoy use of it's environment (RetroArch for instance).
|
||||
This should be an elaborately crafted environment so that sources don't
|
||||
need to be full of platform-specific workarounds.
|
||||
*/
|
||||
|
||||
#if defined (__cplusplus)
|
||||
#if 0
|
||||
printf("This is C++, version %d.\n", __cplusplus);
|
||||
#endif
|
||||
/* The expected values would be
|
||||
* 199711L, for ISO/IEC 14882:1998 or 14882:2003
|
||||
*/
|
||||
|
||||
#elif defined(__STDC__)
|
||||
/* This is standard C. */
|
||||
|
||||
#if (__STDC__ == 1)
|
||||
/* The implementation is ISO-conforming. */
|
||||
#define __STDC_ISO__
|
||||
#else
|
||||
/* The implementation is not ISO-conforming. */
|
||||
#endif
|
||||
|
||||
#if defined(__STDC_VERSION__)
|
||||
#if (__STDC_VERSION__ >= 201112L)
|
||||
/* This is C11. */
|
||||
#define __STDC_C11__
|
||||
#elif (__STDC_VERSION__ >= 199901L)
|
||||
/* This is C99. */
|
||||
#define __STDC_C99__
|
||||
#elif (__STDC_VERSION__ >= 199409L)
|
||||
/* This is C89 with amendment 1. */
|
||||
#define __STDC_C89__
|
||||
#define __STDC_C89_AMENDMENT_1__
|
||||
#else
|
||||
/* This is C89 without amendment 1. */
|
||||
#define __STDC_C89__
|
||||
#endif
|
||||
#else /* !defined(__STDC_VERSION__) */
|
||||
/* This is C89. __STDC_VERSION__ is not defined. */
|
||||
#define __STDC_C89__
|
||||
#endif
|
||||
|
||||
#else /* !defined(__STDC__) */
|
||||
/* 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
|
39
libretro/libretro-common/include/retro_inline.h
Normal file
39
libretro/libretro-common/include/retro_inline.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (retro_inline.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_INLINE_H
|
||||
#define __LIBRETRO_SDK_INLINE_H
|
||||
|
||||
#ifndef INLINE
|
||||
|
||||
#if defined(_WIN32) || defined(__INTEL_COMPILER)
|
||||
#define INLINE __inline
|
||||
#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
|
||||
#define INLINE inline
|
||||
#elif defined(__GNUC__)
|
||||
#define INLINE __inline__
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
180
libretro/libretro-common/include/retro_miscellaneous.h
Normal file
180
libretro/libretro-common/include/retro_miscellaneous.h
Normal file
@ -0,0 +1,180 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (retro_miscellaneous.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_MISCELLANEOUS_H
|
||||
#define __RARCH_MISCELLANEOUS_H
|
||||
|
||||
#define RARCH_MAX_SUBSYSTEMS 10
|
||||
#define RARCH_MAX_SUBSYSTEM_ROMS 10
|
||||
|
||||
#include <stdint.h>
|
||||
#include <boolean.h>
|
||||
#include <retro_inline.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#if defined(_XBOX)
|
||||
#include <Xtl.h>
|
||||
#else
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <compat/msvc.h>
|
||||
#endif
|
||||
|
||||
static INLINE void bits_or_bits(uint32_t *a, uint32_t *b, uint32_t count)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < count;i++)
|
||||
a[i] |= b[i];
|
||||
}
|
||||
|
||||
static INLINE void bits_clear_bits(uint32_t *a, uint32_t *b, uint32_t count)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < count;i++)
|
||||
a[i] &= ~b[i];
|
||||
}
|
||||
|
||||
static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (ptr[i] != 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef PATH_MAX_LENGTH
|
||||
#if 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
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
#define BITS_GET_ELEM(a, i) ((a).data[i])
|
||||
#define BITS_GET_ELEM_PTR(a, i) ((a)->data[i])
|
||||
|
||||
#define BIT_SET(a, bit) ((a)[(bit) >> 3] |= (1 << ((bit) & 7)))
|
||||
#define BIT_CLEAR(a, bit) ((a)[(bit) >> 3] &= ~(1 << ((bit) & 7)))
|
||||
#define BIT_GET(a, bit) (((a)[(bit) >> 3] >> ((bit) & 7)) & 1)
|
||||
|
||||
#define BIT16_SET(a, bit) ((a) |= (1 << ((bit) & 15)))
|
||||
#define BIT16_CLEAR(a, bit) ((a) &= ~(1 << ((bit) & 15)))
|
||||
#define BIT16_GET(a, bit) (((a) >> ((bit) & 15)) & 1)
|
||||
#define BIT16_CLEAR_ALL(a) ((a) = 0)
|
||||
|
||||
#define BIT32_SET(a, bit) ((a) |= (UINT32_C(1) << ((bit) & 31)))
|
||||
#define BIT32_CLEAR(a, bit) ((a) &= ~(UINT32_C(1) << ((bit) & 31)))
|
||||
#define BIT32_GET(a, bit) (((a) >> ((bit) & 31)) & 1)
|
||||
#define BIT32_CLEAR_ALL(a) ((a) = 0)
|
||||
|
||||
#define BIT64_SET(a, bit) ((a) |= (UINT64_C(1) << ((bit) & 63)))
|
||||
#define BIT64_CLEAR(a, bit) ((a) &= ~(UINT64_C(1) << ((bit) & 63)))
|
||||
#define BIT64_GET(a, bit) (((a) >> ((bit) & 63)) & 1)
|
||||
#define BIT64_CLEAR_ALL(a) ((a) = 0)
|
||||
|
||||
#define BIT128_SET(a, bit) ((a).data[(bit) >> 5] |= (UINT32_C(1) << ((bit) & 31)))
|
||||
#define BIT128_CLEAR(a, bit) ((a).data[(bit) >> 5] &= ~(UINT32_C(1) << ((bit) & 31)))
|
||||
#define BIT128_GET(a, bit) (((a).data[(bit) >> 5] >> ((bit) & 31)) & 1)
|
||||
#define BIT128_CLEAR_ALL(a) memset(&(a), 0, sizeof(a))
|
||||
|
||||
#define BIT128_SET_PTR(a, bit) BIT128_SET(*a, bit)
|
||||
#define BIT128_CLEAR_PTR(a, bit) BIT128_CLEAR(*a, bit)
|
||||
#define BIT128_GET_PTR(a, bit) BIT128_GET(*a, bit)
|
||||
#define BIT128_CLEAR_ALL_PTR(a) BIT128_CLEAR_ALL(*a)
|
||||
|
||||
#define BIT256_SET(a, bit) BIT128_SET(a, bit)
|
||||
#define BIT256_CLEAR(a, bit) BIT128_CLEAR(a, bit)
|
||||
#define BIT256_GET(a, bit) BIT128_GET(a, bit)
|
||||
#define BIT256_CLEAR_ALL(a) BIT128_CLEAR_ALL(a)
|
||||
|
||||
#define BIT256_SET_PTR(a, bit) BIT256_SET(*a, bit)
|
||||
#define BIT256_CLEAR_PTR(a, bit) BIT256_CLEAR(*a, bit)
|
||||
#define BIT256_GET_PTR(a, bit) BIT256_GET(*a, bit)
|
||||
#define BIT256_CLEAR_ALL_PTR(a) BIT256_CLEAR_ALL(*a)
|
||||
|
||||
#define BITS_COPY16_PTR(a,bits) \
|
||||
{ \
|
||||
BIT128_CLEAR_ALL_PTR(a); \
|
||||
BITS_GET_ELEM_PTR(a, 0) = (bits) & 0xffff; \
|
||||
}
|
||||
|
||||
#define BITS_COPY32_PTR(a,bits) \
|
||||
{ \
|
||||
BIT128_CLEAR_ALL_PTR(a); \
|
||||
BITS_GET_ELEM_PTR(a, 0) = (bits); \
|
||||
}
|
||||
|
||||
/* Helper macros and struct to keep track of many booleans. */
|
||||
/* This struct has 256 bits. */
|
||||
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 defined(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
|
198
libretro/libretro-common/include/string/stdstring.h
Normal file
198
libretro/libretro-common/include/string/stdstring.h
Normal file
@ -0,0 +1,198 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (stdstring.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_STDSTRING_H
|
||||
#define __LIBRETRO_SDK_STDSTRING_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <boolean.h>
|
||||
|
||||
#include <retro_common_api.h>
|
||||
#include <retro_inline.h>
|
||||
#include <compat/strl.h>
|
||||
|
||||
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)
|
||||
{
|
||||
return !data || (*data == '\0');
|
||||
}
|
||||
|
||||
static INLINE bool string_is_equal(const char *a, const char *b)
|
||||
{
|
||||
return (a && b) ? !strcmp(a, b) : false;
|
||||
}
|
||||
|
||||
static INLINE bool string_starts_with_size(const char *str, const char *prefix,
|
||||
size_t size)
|
||||
{
|
||||
return (str && prefix) ? !strncmp(prefix, str, size) : false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static INLINE bool string_is_equal_case_insensitive(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 true;
|
||||
|
||||
while ((result = tolower (*p1) - tolower (*p2++)) == 0)
|
||||
if (*p1++ == '\0')
|
||||
break;
|
||||
|
||||
return (result == 0);
|
||||
}
|
||||
|
||||
char *string_to_upper(char *s);
|
||||
|
||||
char *string_to_lower(char *s);
|
||||
|
||||
char *string_ucwords(char *s);
|
||||
|
||||
char *string_replace_substring(const char *in, const char *pattern,
|
||||
const char *by);
|
||||
|
||||
/* Remove leading whitespaces */
|
||||
char *string_trim_whitespace_left(char *const s);
|
||||
|
||||
/* Remove trailing whitespaces */
|
||||
char *string_trim_whitespace_right(char *const s);
|
||||
|
||||
/* Remove leading and trailing whitespaces */
|
||||
char *string_trim_whitespace(char *const s);
|
||||
|
||||
/* 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);
|
||||
|
||||
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
|
||||
|
||||
#endif
|
48
libretro/libretro-common/include/time/rtime.h
Normal file
48
libretro/libretro-common/include/time/rtime.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (rtime.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_RTIME_H__
|
||||
#define __LIBRETRO_SDK_RTIME_H__
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <time.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/* TODO/FIXME: Move all generic time handling functions
|
||||
* to this file */
|
||||
|
||||
/* Must be called before using rtime_localtime() */
|
||||
void rtime_init(void);
|
||||
|
||||
/* Must be called upon program termination */
|
||||
void rtime_deinit(void);
|
||||
|
||||
/* Thread-safe wrapper for localtime() */
|
||||
struct tm *rtime_localtime(const time_t *timep, struct tm *result);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
111
libretro/libretro-common/include/vfs/vfs.h
Normal file
111
libretro/libretro-common/include/vfs/vfs.h
Normal file
@ -0,0 +1,111 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (vfs_implementation.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_VFS_H
|
||||
#define __LIBRETRO_SDK_VFS_H
|
||||
|
||||
#include <retro_common_api.h>
|
||||
#include <boolean.h>
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#ifndef VFS_FRONTEND
|
||||
#define VFS_FRONTEND
|
||||
#endif
|
||||
#endif
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef void* HANDLE;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CDROM
|
||||
typedef struct
|
||||
{
|
||||
int64_t byte_pos;
|
||||
char *cue_buf;
|
||||
size_t cue_len;
|
||||
unsigned cur_lba;
|
||||
unsigned last_frame_lba;
|
||||
unsigned char cur_min;
|
||||
unsigned char cur_sec;
|
||||
unsigned char cur_frame;
|
||||
unsigned char cur_track;
|
||||
unsigned char last_frame[2352];
|
||||
char drive;
|
||||
bool last_frame_valid;
|
||||
} vfs_cdrom_t;
|
||||
#endif
|
||||
|
||||
enum vfs_scheme
|
||||
{
|
||||
VFS_SCHEME_NONE = 0,
|
||||
VFS_SCHEME_CDROM
|
||||
};
|
||||
|
||||
#ifndef __WINRT__
|
||||
#ifdef VFS_FRONTEND
|
||||
struct retro_vfs_file_handle
|
||||
#else
|
||||
struct libretro_vfs_implementation_file
|
||||
#endif
|
||||
{
|
||||
#ifdef HAVE_CDROM
|
||||
vfs_cdrom_t cdrom; /* int64_t alignment */
|
||||
#endif
|
||||
int64_t size;
|
||||
uint64_t mappos;
|
||||
uint64_t mapsize;
|
||||
FILE *fp;
|
||||
#ifdef _WIN32
|
||||
HANDLE fh;
|
||||
#endif
|
||||
char *buf;
|
||||
char* orig_path;
|
||||
uint8_t *mapped;
|
||||
int fd;
|
||||
unsigned hints;
|
||||
enum vfs_scheme scheme;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Replace the following symbol with something appropriate
|
||||
* to signify the file is being compiled for a front end instead of a core.
|
||||
* This allows the same code to act as reference implementation
|
||||
* for VFS and as fallbacks for when the front end does not provide VFS functionality.
|
||||
*/
|
||||
|
||||
#ifdef VFS_FRONTEND
|
||||
typedef struct retro_vfs_file_handle libretro_vfs_implementation_file;
|
||||
#else
|
||||
typedef struct libretro_vfs_implementation_file libretro_vfs_implementation_file;
|
||||
#endif
|
||||
|
||||
#ifdef VFS_FRONTEND
|
||||
typedef struct retro_vfs_dir_handle libretro_vfs_implementation_dir;
|
||||
#else
|
||||
typedef struct libretro_vfs_implementation_dir libretro_vfs_implementation_dir;
|
||||
#endif
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
76
libretro/libretro-common/include/vfs/vfs_implementation.h
Normal file
76
libretro/libretro-common/include/vfs/vfs_implementation.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (vfs_implementation.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_VFS_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>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints);
|
||||
|
||||
int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream);
|
||||
|
||||
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);
|
||||
|
||||
int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file *stream, void *s, uint64_t len);
|
||||
|
||||
int64_t retro_vfs_file_write_impl(libretro_vfs_implementation_file *stream, const void *s, uint64_t len);
|
||||
|
||||
int retro_vfs_file_flush_impl(libretro_vfs_implementation_file *stream);
|
||||
|
||||
int retro_vfs_file_remove_impl(const char *path);
|
||||
|
||||
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
|
416
libretro/libretro-common/string/stdstring.c
Normal file
416
libretro/libretro-common/string/stdstring.c
Normal file
@ -0,0 +1,416 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (stdstring.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <string/stdstring.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 *cs = (char *)s;
|
||||
for ( ; *cs != '\0'; cs++)
|
||||
*cs = toupper((unsigned char)*cs);
|
||||
return s;
|
||||
}
|
||||
|
||||
char *string_to_lower(char *s)
|
||||
{
|
||||
char *cs = (char *)s;
|
||||
for ( ; *cs != '\0'; cs++)
|
||||
*cs = tolower((unsigned char)*cs);
|
||||
return s;
|
||||
}
|
||||
|
||||
char *string_ucwords(char *s)
|
||||
{
|
||||
char *cs = (char *)s;
|
||||
for ( ; *cs != '\0'; cs++)
|
||||
{
|
||||
if (*cs == ' ')
|
||||
*(cs+1) = toupper((unsigned char)*(cs+1));
|
||||
}
|
||||
|
||||
s[0] = toupper((unsigned char)s[0]);
|
||||
return s;
|
||||
}
|
||||
|
||||
char *string_replace_substring(const char *in,
|
||||
const char *pattern, const char *replacement)
|
||||
{
|
||||
size_t numhits, pattern_len, replacement_len, outlen;
|
||||
const char *inat = NULL;
|
||||
const char *inprev = NULL;
|
||||
char *out = NULL;
|
||||
char *outat = NULL;
|
||||
|
||||
/* if either pattern or replacement is NULL,
|
||||
* duplicate in and let caller handle it. */
|
||||
if (!pattern || !replacement)
|
||||
return strdup(in);
|
||||
|
||||
pattern_len = strlen(pattern);
|
||||
replacement_len = strlen(replacement);
|
||||
numhits = 0;
|
||||
inat = in;
|
||||
|
||||
while ((inat = strstr(inat, pattern)))
|
||||
{
|
||||
inat += pattern_len;
|
||||
numhits++;
|
||||
}
|
||||
|
||||
outlen = strlen(in) - pattern_len*numhits + replacement_len*numhits;
|
||||
out = (char *)malloc(outlen+1);
|
||||
|
||||
if (!out)
|
||||
return NULL;
|
||||
|
||||
outat = out;
|
||||
inat = in;
|
||||
inprev = in;
|
||||
|
||||
while ((inat = strstr(inat, pattern)))
|
||||
{
|
||||
memcpy(outat, inprev, inat-inprev);
|
||||
outat += inat-inprev;
|
||||
memcpy(outat, replacement, replacement_len);
|
||||
outat += replacement_len;
|
||||
inat += pattern_len;
|
||||
inprev = inat;
|
||||
}
|
||||
strcpy(outat, inprev);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Remove leading whitespaces */
|
||||
char *string_trim_whitespace_left(char *const s)
|
||||
{
|
||||
if (s && *s)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
char *current = s;
|
||||
|
||||
while (*current && ISSPACE((unsigned char)*current))
|
||||
{
|
||||
++current;
|
||||
--len;
|
||||
}
|
||||
|
||||
if (s != current)
|
||||
memmove(s, current, len + 1);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Remove trailing whitespaces */
|
||||
char *string_trim_whitespace_right(char *const s)
|
||||
{
|
||||
if (s && *s)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
char *current = s + len - 1;
|
||||
|
||||
while (current != s && ISSPACE((unsigned char)*current))
|
||||
{
|
||||
--current;
|
||||
--len;
|
||||
}
|
||||
|
||||
current[ISSPACE((unsigned char)*current) ? 0 : 1] = '\0';
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Remove leading and trailing whitespaces */
|
||||
char *string_trim_whitespace(char *const s)
|
||||
{
|
||||
string_trim_whitespace_right(s); /* order matters */
|
||||
string_trim_whitespace_left(s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
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 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++)
|
||||
{
|
||||
const char *character;
|
||||
unsigned char_len;
|
||||
unsigned j = i;
|
||||
|
||||
/* check if end of string reached */
|
||||
if (i == len)
|
||||
{
|
||||
buffer[i] = 0;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
character = utf8skip(&string[i], 1);
|
||||
char_len = (unsigned)(character - &string[i]);
|
||||
|
||||
if (!unicode)
|
||||
counter += char_len - 1;
|
||||
|
||||
do
|
||||
{
|
||||
buffer[i] = string[i];
|
||||
char_len--;
|
||||
i++;
|
||||
} while (char_len);
|
||||
|
||||
/* 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] == ' ')
|
||||
{
|
||||
if ((max_lines == 0 || lines < max_lines))
|
||||
{
|
||||
buffer[i] = '\n';
|
||||
i++;
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int k;
|
||||
|
||||
/* check for nearest whitespace back in string */
|
||||
for (k = i; k > 0; 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;
|
||||
}
|
||||
}
|
||||
|
||||
buffer[i] = 0;
|
||||
|
||||
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)))
|
||||
*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((unsigned char)*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((unsigned char)*ptr))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (unsigned)strtoul(hex_str, NULL, 16);
|
||||
}
|
81
libretro/libretro-common/time/rtime.c
Normal file
81
libretro/libretro-common/time/rtime.c
Normal file
@ -0,0 +1,81 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (rtime.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#include <rthreads/rthreads.h>
|
||||
#include <retro_assert.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <time/rtime.h>
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
/* TODO/FIXME - global */
|
||||
slock_t *rtime_localtime_lock = NULL;
|
||||
#endif
|
||||
|
||||
/* Must be called before using rtime_localtime() */
|
||||
void rtime_init(void)
|
||||
{
|
||||
rtime_deinit();
|
||||
#ifdef HAVE_THREADS
|
||||
if (!rtime_localtime_lock)
|
||||
rtime_localtime_lock = slock_new();
|
||||
|
||||
retro_assert(rtime_localtime_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Must be called upon program termination */
|
||||
void rtime_deinit(void)
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
if (rtime_localtime_lock)
|
||||
{
|
||||
slock_free(rtime_localtime_lock);
|
||||
rtime_localtime_lock = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Thread-safe wrapper for localtime() */
|
||||
struct tm *rtime_localtime(const time_t *timep, struct tm *result)
|
||||
{
|
||||
struct tm *time_info = NULL;
|
||||
|
||||
/* Lock mutex */
|
||||
#ifdef HAVE_THREADS
|
||||
slock_lock(rtime_localtime_lock);
|
||||
#endif
|
||||
|
||||
time_info = localtime(timep);
|
||||
if (time_info)
|
||||
memcpy(result, time_info, sizeof(struct tm));
|
||||
|
||||
/* Unlock mutex */
|
||||
#ifdef HAVE_THREADS
|
||||
slock_unlock(rtime_localtime_lock);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
1315
libretro/libretro-common/vfs/vfs_implementation.c
Normal file
1315
libretro/libretro-common/vfs/vfs_implementation.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <string/stdstring.h>
|
||||
#include "libretro.h"
|
||||
#include "libretro_core_options.h"
|
||||
|
||||
#include "libretro-hatari.h"
|
||||
|
||||
@ -8,10 +11,12 @@
|
||||
#include "retro_strings.h"
|
||||
#include "retro_files.h"
|
||||
#include "retro_disk_control.h"
|
||||
|
||||
static dc_storage* dc;
|
||||
|
||||
// LOG
|
||||
retro_log_printf_t log_cb;
|
||||
static void fallback_log(enum retro_log_level level, const char* fmt, ...);
|
||||
retro_log_printf_t log_cb = fallback_log;
|
||||
|
||||
cothread_t mainThread;
|
||||
cothread_t emuThread;
|
||||
@ -102,8 +107,11 @@ static struct retro_input_descriptor input_descriptors[] = {
|
||||
|
||||
void retro_set_environment(retro_environment_t cb)
|
||||
{
|
||||
environ_cb = cb;
|
||||
bool option_cats_supported;
|
||||
|
||||
environ_cb = cb;
|
||||
|
||||
#if 0
|
||||
static struct retro_core_option_definition core_options[] =
|
||||
{
|
||||
// Input
|
||||
@ -239,6 +247,10 @@ void retro_set_environment(retro_environment_t cb)
|
||||
variables[i].value = NULL;
|
||||
cb( RETRO_ENVIRONMENT_SET_VARIABLES, variables);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialise core options */
|
||||
libretro_set_core_options(environ_cb, &option_cats_supported);
|
||||
}
|
||||
|
||||
static void update_variables(void)
|
||||
@ -433,21 +445,98 @@ extern bool Floppy_EjectDiskFromDrive(int Drive);
|
||||
extern const char* Floppy_SetDiskFileName(int Drive, const char *pszFileName, const char *pszZipPath);
|
||||
extern bool Floppy_InsertDiskIntoDrive(int Drive);
|
||||
|
||||
static bool disk_set_eject_state(bool ejected)
|
||||
{
|
||||
if (dc)
|
||||
{
|
||||
dc->eject_state = ejected;
|
||||
|
||||
if(dc->eject_state)
|
||||
return Floppy_EjectDiskFromDrive(0);
|
||||
else
|
||||
return Floppy_InsertDiskIntoDrive(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
void retro_message(const char* text, unsigned int frames, int alt) {
|
||||
struct retro_message msg;
|
||||
struct retro_message_ext msg_ext;
|
||||
|
||||
char msg_local[256];
|
||||
unsigned int message_interface_version;
|
||||
|
||||
snprintf(msg_local, sizeof(msg_local), "Atari800: %s", text);
|
||||
msg.msg = msg_local;
|
||||
msg.frames = frames;
|
||||
|
||||
msg_ext.msg = msg_local;
|
||||
msg_ext.duration = frames;
|
||||
msg_ext.priority = 3;
|
||||
msg_ext.level = RETRO_LOG_INFO;
|
||||
msg_ext.target = RETRO_MESSAGE_TYPE_NOTIFICATION_ALT;
|
||||
msg_ext.type = -1;
|
||||
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION, &message_interface_version) && (message_interface_version >= 1))
|
||||
{
|
||||
if (alt)
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE_EXT, (void*)&msg_ext);
|
||||
else
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE_EXT, (void*)&msg);
|
||||
}
|
||||
else
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, (void*)&msg);
|
||||
}
|
||||
|
||||
// might not need this if floppy image is the only type we are going to worry about.
|
||||
static int get_image_unit()
|
||||
{
|
||||
int unit = dc->unit;
|
||||
if (dc->index < dc->count)
|
||||
{
|
||||
if (dc_get_image_type(dc->files[dc->index]) == DC_IMAGE_TYPE_FLOPPY)
|
||||
dc->unit = DC_IMAGE_TYPE_FLOPPY;
|
||||
else
|
||||
dc->unit = DC_IMAGE_TYPE_FLOPPY;
|
||||
}
|
||||
else
|
||||
unit = DC_IMAGE_TYPE_FLOPPY;
|
||||
|
||||
return unit;
|
||||
}
|
||||
|
||||
static void disk_insert_image()
|
||||
{
|
||||
if (dc->unit == DC_IMAGE_TYPE_FLOPPY)
|
||||
{
|
||||
int error = Floppy_SetDiskFileName(0, dc->files[dc->index], NULL);
|
||||
|
||||
if (error)
|
||||
{
|
||||
log_cb(RETRO_LOG_INFO, "[disk_insert_image] Disk (%d) Error : %s\n", dc->index + 1, dc->files[dc->index]);
|
||||
return;
|
||||
}
|
||||
|
||||
log_cb(RETRO_LOG_INFO, "[disk_insert_image] Disk (%d) inserted into drive 1 : %s\n", dc->index + 1, dc->files[dc->index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_cb(RETRO_LOG_INFO, "[disk_insert_image] unsupported image-type : %u\n", dc->unit);
|
||||
}
|
||||
}
|
||||
|
||||
static bool disk_set_eject_state(bool ejected)
|
||||
{
|
||||
if (dc)
|
||||
{
|
||||
int unit = get_image_unit();
|
||||
|
||||
if (dc->eject_state == ejected)
|
||||
return true;
|
||||
|
||||
if (ejected && dc->index <= dc->count && dc->files[dc->index] != NULL)
|
||||
Floppy_EjectDiskFromDrive(0);
|
||||
else if (!ejected && dc->index < dc->count && dc->files[dc->index] != NULL)
|
||||
{
|
||||
disk_insert_image();
|
||||
Floppy_InsertDiskIntoDrive(0);
|
||||
}
|
||||
|
||||
dc->eject_state = ejected;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Gets current eject state. The initial state is 'not ejected'. */
|
||||
static bool disk_get_eject_state(void)
|
||||
{
|
||||
if (dc)
|
||||
@ -464,26 +553,34 @@ static unsigned disk_get_image_index(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sets image index. Can only be called when disk is ejected.
|
||||
* The implementation supports setting "no disk" by using an
|
||||
* index >= get_num_images().
|
||||
*/
|
||||
static bool disk_set_image_index(unsigned index)
|
||||
{
|
||||
// Insert disk
|
||||
if (dc)
|
||||
{
|
||||
// Same disk...
|
||||
// This can mess things in the emu
|
||||
if(index == dc->index)
|
||||
return true;
|
||||
|
||||
if ((index < dc->count) && (dc->files[index]))
|
||||
{
|
||||
dc->index = index;
|
||||
Floppy_SetDiskFileName(0, dc->files[index], NULL);
|
||||
log_cb(RETRO_LOG_INFO, "Disk (%d) inserted into drive A : %s\n", dc->index+1, dc->files[dc->index]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
// Insert image
|
||||
if (dc)
|
||||
{
|
||||
if (index == dc->index)
|
||||
return true;
|
||||
|
||||
if (dc->replace)
|
||||
{
|
||||
dc->replace = false;
|
||||
index = 0;
|
||||
}
|
||||
|
||||
if (index < dc->count && dc->files[index])
|
||||
{
|
||||
dc->index = index;
|
||||
int unit = get_image_unit();
|
||||
log_cb(RETRO_LOG_INFO, "[retro_set_image_index] Unit (%d) image (%d/%d) inserted: %s\n", dc->index + 1, unit, dc->count, dc->files[dc->index]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static unsigned disk_get_num_images(void)
|
||||
@ -494,39 +591,86 @@ static unsigned disk_get_num_images(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool disk_replace_image_index(unsigned index, const struct retro_game_info *info)
|
||||
/* Adds a new valid index (get_num_images()) to the internal disk list.
|
||||
* This will increment subsequent return values from get_num_images() by 1.
|
||||
* This image index cannot be used until a disk image has been set
|
||||
* with replace_image_index.
|
||||
*/
|
||||
static bool disk_add_image_index(void)
|
||||
{
|
||||
if (dc)
|
||||
{
|
||||
if (index >= dc->count)
|
||||
return false;
|
||||
|
||||
if(dc->files[index])
|
||||
{
|
||||
free(dc->files[index]);
|
||||
dc->files[index] = NULL;
|
||||
}
|
||||
|
||||
// TODO : Handling removing of a disk image when info = NULL
|
||||
|
||||
if(info != NULL)
|
||||
dc->files[index] = strdup(info->path);
|
||||
}
|
||||
if (dc)
|
||||
{
|
||||
if (dc->count <= DC_MAX_SIZE)
|
||||
{
|
||||
dc->files[dc->count] = NULL;
|
||||
dc->names[dc->count] = NULL;
|
||||
dc->types[dc->count] = DC_IMAGE_TYPE_NONE;
|
||||
dc->count++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool disk_add_image_index(void)
|
||||
static bool disk_replace_image_index(unsigned index, const struct retro_game_info* info)
|
||||
{
|
||||
if (dc)
|
||||
{
|
||||
if(dc->count <= DC_MAX_SIZE)
|
||||
{
|
||||
dc->files[dc->count] = NULL;
|
||||
dc->count++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (dc)
|
||||
{
|
||||
if (info != NULL)
|
||||
{
|
||||
int error = dc_replace_file(dc, index, info->path);
|
||||
|
||||
if (error == 2)
|
||||
retro_message("Duplicate Disk selected. Use Index", 6000, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc_remove_file(dc, index);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool disk_get_image_path(unsigned index, char* path, size_t len)
|
||||
{
|
||||
if (len < 1)
|
||||
return false;
|
||||
|
||||
if (dc)
|
||||
{
|
||||
if (index < dc->count)
|
||||
{
|
||||
if (!string_is_empty(dc->files[index]))
|
||||
{
|
||||
strncpy(path, dc->files[index], len);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool disk_get_image_label(unsigned index, char* label, size_t len)
|
||||
{
|
||||
if (len < 1)
|
||||
return false;
|
||||
|
||||
if (dc)
|
||||
{
|
||||
if (index < dc->count)
|
||||
{
|
||||
if (!string_is_empty(dc->names[index]))
|
||||
{
|
||||
strncpy(label, dc->names[index], len);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -541,24 +685,44 @@ static struct retro_disk_control_callback disk_interface = {
|
||||
disk_add_image_index,
|
||||
};
|
||||
|
||||
static struct retro_disk_control_ext_callback disk_interface_ext = {
|
||||
disk_set_eject_state,
|
||||
disk_get_eject_state,
|
||||
disk_get_image_index,
|
||||
disk_set_image_index,
|
||||
disk_get_num_images,
|
||||
disk_replace_image_index,
|
||||
disk_add_image_index,
|
||||
NULL, /* disk_set_initial_image, not even sure if I want to use this */
|
||||
disk_get_image_path,
|
||||
disk_get_image_label,
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
//*****************************************************************************
|
||||
// Init
|
||||
static void fallback_log(enum retro_log_level level, const char *fmt, ...)
|
||||
static void fallback_log(enum retro_log_level level, const char* fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
(void)level;
|
||||
|
||||
va_start(va, fmt);
|
||||
vfprintf(stderr, fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
void retro_init(void)
|
||||
{
|
||||
struct retro_log_callback log;
|
||||
const char *system_dir = NULL;
|
||||
unsigned dci_version = 0;
|
||||
|
||||
dc = dc_create();
|
||||
|
||||
// Init log
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log))
|
||||
log_cb = log.log;
|
||||
else
|
||||
log_cb = fallback_log;
|
||||
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &system_dir) && system_dir)
|
||||
{
|
||||
@ -611,7 +775,10 @@ void retro_init(void)
|
||||
MidiRetroInterface = NULL;
|
||||
|
||||
// Disk control interface
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &disk_interface);
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION, &dci_version) && (dci_version >= 1))
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE, &disk_interface_ext);
|
||||
else
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &disk_interface);
|
||||
|
||||
// Savestates
|
||||
static uint32_t quirks = RETRO_SERIALIZATION_QUIRK_INCOMPLETE | RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE | RETRO_SERIALIZATION_QUIRK_CORE_VARIABLE_SIZE;
|
||||
|
518
libretro/libretro_core_options.h
Normal file
518
libretro/libretro_core_options.h
Normal file
@ -0,0 +1,518 @@
|
||||
#ifndef LIBRETRO_CORE_OPTIONS_H__
|
||||
#define LIBRETRO_CORE_OPTIONS_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libretro.h>
|
||||
#include <retro_inline.h>
|
||||
|
||||
#ifndef HAVE_NO_LANGEXTRA
|
||||
#include "libretro_core_options_intl.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
********************************
|
||||
* VERSION: 1.0
|
||||
********************************
|
||||
*
|
||||
* - 1.0: First commit. Support for core options v2 interfaec.
|
||||
* - libretro_core_options_intl.h includes BOM and utf-8
|
||||
* fix for MSVC 2010-2013
|
||||
* - Contains HAVE_NO_LANGEXTRA flag to disable translations
|
||||
* on platforms/compilers without BOM support
|
||||
* - Uses core options v1 interface when
|
||||
* RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION is >= 1
|
||||
* (previously required RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION == 1)
|
||||
* - Support for generation of core options v0 retro_core_option_value
|
||||
* arrays containing options with a single value
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
********************************
|
||||
* Core Option Definitions
|
||||
********************************
|
||||
*/
|
||||
|
||||
/* RETRO_LANGUAGE_ENGLISH */
|
||||
|
||||
/* Default language:
|
||||
* - All other languages must include the same keys and values
|
||||
* - Will be used as a fallback in the event that frontend language
|
||||
* is not available
|
||||
* - Will be used as a fallback for any missing entries in
|
||||
* frontend language definition */
|
||||
|
||||
//struct retro_core_option_v2_category option_cats_us[] = {
|
||||
// { NULL, NULL, NULL },
|
||||
//};
|
||||
|
||||
struct retro_core_option_v2_category option_cats_us[] = {
|
||||
{
|
||||
"video",
|
||||
"Video",
|
||||
"Enable/Disable high resolution or overscan cropping. Set Frameskip."
|
||||
},
|
||||
{
|
||||
"input",
|
||||
"Input",
|
||||
"Enable/Disable second joystick, system mouse or system keyboard."
|
||||
},
|
||||
{ NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
struct retro_core_option_v2_definition option_defs_us[] = {
|
||||
//video
|
||||
{
|
||||
"hatari_video_hires",
|
||||
"High resolution. (Needs Restart)",
|
||||
NULL,
|
||||
"Enable Hi-Resolution.",
|
||||
NULL,
|
||||
"video",
|
||||
{
|
||||
{ "true", "enabled" },
|
||||
{ "false", "disabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"true"
|
||||
},
|
||||
{
|
||||
"hatari_video_crop_overscan",
|
||||
"Crop overscan. (Needs Restart)",
|
||||
NULL,
|
||||
"Enable for games. Disable for low/med resolution overscan demos",
|
||||
NULL,
|
||||
"video",
|
||||
{
|
||||
{ "true", "enabled" },
|
||||
{ "false", "disabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"true"
|
||||
},
|
||||
{
|
||||
"hatari_frameskips",
|
||||
"Set frameskip. (Needs Restart)",
|
||||
NULL,
|
||||
"Set emulated systems internal resolution.\n \nDisabled, 1-4, Auto (Max 5), Auto (Max 10).",
|
||||
NULL,
|
||||
"video",
|
||||
{
|
||||
{ "0", "disabled" },
|
||||
{ "1", NULL },
|
||||
{ "2", NULL },
|
||||
{ "3", NULL },
|
||||
{ "4", NULL },
|
||||
{ "5", "Auto (Max 5)" },
|
||||
{ "10", "Auto (Max 10)" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"0"
|
||||
},
|
||||
//input
|
||||
{
|
||||
"hatari_twojoy",
|
||||
"Enable second joystick",
|
||||
NULL,
|
||||
"Enables a second joystick on port 2, may conflict with mouse.",
|
||||
NULL,
|
||||
"input",
|
||||
{
|
||||
{ "true", "enabled" },
|
||||
{ "false", "disabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"true"
|
||||
},
|
||||
{
|
||||
"hatari_nomouse",
|
||||
"Disable mouse",
|
||||
NULL,
|
||||
"Prevents input from your sytem mouse device. Gamepad mouse mode (select) is not disabled.",
|
||||
NULL,
|
||||
"input",
|
||||
{
|
||||
{ "false", "disabled" },
|
||||
{ "true", "enabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"false"
|
||||
},
|
||||
{
|
||||
"hatari_nokeys",
|
||||
"Disable keyboard",
|
||||
NULL,
|
||||
"Prevents input from your system keyboard. Virtual keyboard is not disabled.",
|
||||
NULL,
|
||||
"input",
|
||||
{
|
||||
{ "false", "disabled" },
|
||||
{ "true", "enabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"false"
|
||||
},
|
||||
// Floppy speed
|
||||
{
|
||||
"hatari_fastfdc",
|
||||
"Fast floppy access",
|
||||
NULL,
|
||||
"Decreases the time spent loading from disk.",
|
||||
NULL,
|
||||
NULL,
|
||||
{
|
||||
{ "true", "enabled" },
|
||||
{ "false", "disabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"true"
|
||||
},
|
||||
// Audio
|
||||
{
|
||||
"hatari_polarized_filter",
|
||||
"Polarized audio filter",
|
||||
NULL,
|
||||
"Uses hatari's polarized lowpass filters on audio to simulate distortion.",
|
||||
NULL,
|
||||
NULL,
|
||||
{
|
||||
{ "false", "disabled" },
|
||||
{ "true", "enabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"false"
|
||||
},
|
||||
{ NULL, NULL, NULL, NULL, NULL, NULL, {{0}}, NULL },
|
||||
};
|
||||
|
||||
struct retro_core_options_v2 options_us = {
|
||||
option_cats_us,
|
||||
option_defs_us
|
||||
};
|
||||
|
||||
/*
|
||||
********************************
|
||||
* Language Mapping
|
||||
********************************
|
||||
*/
|
||||
|
||||
#ifndef HAVE_NO_LANGEXTRA
|
||||
struct retro_core_options_v2 *options_intl[RETRO_LANGUAGE_LAST] = {
|
||||
&options_us, /* RETRO_LANGUAGE_ENGLISH */
|
||||
NULL, /* RETRO_LANGUAGE_JAPANESE */
|
||||
NULL, /* RETRO_LANGUAGE_FRENCH */
|
||||
NULL, /* RETRO_LANGUAGE_SPANISH */
|
||||
NULL, /* RETRO_LANGUAGE_GERMAN */
|
||||
NULL, /* RETRO_LANGUAGE_ITALIAN */
|
||||
NULL, /* RETRO_LANGUAGE_DUTCH */
|
||||
NULL, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */
|
||||
NULL, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */
|
||||
NULL, /* RETRO_LANGUAGE_RUSSIAN */
|
||||
NULL, /* RETRO_LANGUAGE_KOREAN */
|
||||
NULL, /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */
|
||||
NULL, /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */
|
||||
NULL, /* RETRO_LANGUAGE_ESPERANTO */
|
||||
NULL, /* RETRO_LANGUAGE_POLISH */
|
||||
NULL, /* RETRO_LANGUAGE_VIETNAMESE */
|
||||
NULL, /* RETRO_LANGUAGE_ARABIC */
|
||||
NULL, /* RETRO_LANGUAGE_GREEK */
|
||||
NULL, /* RETRO_LANGUAGE_TURKISH */
|
||||
NULL, /* RETRO_LANGUAGE_SLOVAK */
|
||||
NULL, /* RETRO_LANGUAGE_PERSIAN */
|
||||
NULL, /* RETRO_LANGUAGE_HEBREW */
|
||||
NULL, /* RETRO_LANGUAGE_ASTURIAN */
|
||||
NULL, /* RETRO_LANGUAGE_FINNISH */
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
********************************
|
||||
* Functions
|
||||
********************************
|
||||
*/
|
||||
|
||||
/* Handles configuration/setting of core options.
|
||||
* Should be called as early as possible - ideally inside
|
||||
* retro_set_environment(), and no later than retro_load_game()
|
||||
* > We place the function body in the header to avoid the
|
||||
* necessity of adding more .c files (i.e. want this to
|
||||
* be as painless as possible for core devs)
|
||||
*/
|
||||
|
||||
static INLINE void libretro_set_core_options(retro_environment_t environ_cb,
|
||||
bool *categories_supported)
|
||||
{
|
||||
unsigned version = 0;
|
||||
#ifndef HAVE_NO_LANGEXTRA
|
||||
unsigned language = 0;
|
||||
#endif
|
||||
|
||||
if (!environ_cb || !categories_supported)
|
||||
return;
|
||||
|
||||
*categories_supported = false;
|
||||
|
||||
if (!environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version))
|
||||
version = 0;
|
||||
|
||||
if (version >= 2)
|
||||
{
|
||||
#ifndef HAVE_NO_LANGEXTRA
|
||||
struct retro_core_options_v2_intl core_options_intl;
|
||||
|
||||
core_options_intl.us = &options_us;
|
||||
core_options_intl.local = NULL;
|
||||
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) &&
|
||||
(language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH))
|
||||
core_options_intl.local = options_intl[language];
|
||||
|
||||
*categories_supported = environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL,
|
||||
&core_options_intl);
|
||||
#else
|
||||
*categories_supported = environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2,
|
||||
&options_us);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t i, j;
|
||||
size_t option_index = 0;
|
||||
size_t num_options = 0;
|
||||
struct retro_core_option_definition
|
||||
*option_v1_defs_us = NULL;
|
||||
#ifndef HAVE_NO_LANGEXTRA
|
||||
size_t num_options_intl = 0;
|
||||
struct retro_core_option_v2_definition
|
||||
*option_defs_intl = NULL;
|
||||
struct retro_core_option_definition
|
||||
*option_v1_defs_intl = NULL;
|
||||
struct retro_core_options_intl
|
||||
core_options_v1_intl;
|
||||
#endif
|
||||
struct retro_variable *variables = NULL;
|
||||
char **values_buf = NULL;
|
||||
|
||||
/* Determine total number of options */
|
||||
while (true)
|
||||
{
|
||||
if (option_defs_us[num_options].key)
|
||||
num_options++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (version >= 1)
|
||||
{
|
||||
/* Allocate US array */
|
||||
option_v1_defs_us = (struct retro_core_option_definition *)
|
||||
calloc(num_options + 1, sizeof(struct retro_core_option_definition));
|
||||
|
||||
/* Copy parameters from option_defs_us array */
|
||||
for (i = 0; i < num_options; i++)
|
||||
{
|
||||
struct retro_core_option_v2_definition *option_def_us = &option_defs_us[i];
|
||||
struct retro_core_option_value *option_values = option_def_us->values;
|
||||
struct retro_core_option_definition *option_v1_def_us = &option_v1_defs_us[i];
|
||||
struct retro_core_option_value *option_v1_values = option_v1_def_us->values;
|
||||
|
||||
option_v1_def_us->key = option_def_us->key;
|
||||
option_v1_def_us->desc = option_def_us->desc;
|
||||
option_v1_def_us->info = option_def_us->info;
|
||||
option_v1_def_us->default_value = option_def_us->default_value;
|
||||
|
||||
/* Values must be copied individually... */
|
||||
while (option_values->value)
|
||||
{
|
||||
option_v1_values->value = option_values->value;
|
||||
option_v1_values->label = option_values->label;
|
||||
|
||||
option_values++;
|
||||
option_v1_values++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HAVE_NO_LANGEXTRA
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) &&
|
||||
(language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH) &&
|
||||
options_intl[language])
|
||||
option_defs_intl = options_intl[language]->definitions;
|
||||
|
||||
if (option_defs_intl)
|
||||
{
|
||||
/* Determine number of intl options */
|
||||
while (true)
|
||||
{
|
||||
if (option_defs_intl[num_options_intl].key)
|
||||
num_options_intl++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* Allocate intl array */
|
||||
option_v1_defs_intl = (struct retro_core_option_definition *)
|
||||
calloc(num_options_intl + 1, sizeof(struct retro_core_option_definition));
|
||||
|
||||
/* Copy parameters from option_defs_intl array */
|
||||
for (i = 0; i < num_options_intl; i++)
|
||||
{
|
||||
struct retro_core_option_v2_definition *option_def_intl = &option_defs_intl[i];
|
||||
struct retro_core_option_value *option_values = option_def_intl->values;
|
||||
struct retro_core_option_definition *option_v1_def_intl = &option_v1_defs_intl[i];
|
||||
struct retro_core_option_value *option_v1_values = option_v1_def_intl->values;
|
||||
|
||||
option_v1_def_intl->key = option_def_intl->key;
|
||||
option_v1_def_intl->desc = option_def_intl->desc;
|
||||
option_v1_def_intl->info = option_def_intl->info;
|
||||
option_v1_def_intl->default_value = option_def_intl->default_value;
|
||||
|
||||
/* Values must be copied individually... */
|
||||
while (option_values->value)
|
||||
{
|
||||
option_v1_values->value = option_values->value;
|
||||
option_v1_values->label = option_values->label;
|
||||
|
||||
option_values++;
|
||||
option_v1_values++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
core_options_v1_intl.us = option_v1_defs_us;
|
||||
core_options_v1_intl.local = option_v1_defs_intl;
|
||||
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_v1_intl);
|
||||
#else
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, option_v1_defs_us);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate arrays */
|
||||
variables = (struct retro_variable *)calloc(num_options + 1,
|
||||
sizeof(struct retro_variable));
|
||||
values_buf = (char **)calloc(num_options, sizeof(char *));
|
||||
|
||||
if (!variables || !values_buf)
|
||||
goto error;
|
||||
|
||||
/* Copy parameters from option_defs_us array */
|
||||
for (i = 0; i < num_options; i++)
|
||||
{
|
||||
const char *key = option_defs_us[i].key;
|
||||
const char *desc = option_defs_us[i].desc;
|
||||
const char *default_value = option_defs_us[i].default_value;
|
||||
struct retro_core_option_value *values = option_defs_us[i].values;
|
||||
size_t buf_len = 3;
|
||||
size_t default_index = 0;
|
||||
|
||||
values_buf[i] = NULL;
|
||||
|
||||
if (desc)
|
||||
{
|
||||
size_t num_values = 0;
|
||||
|
||||
/* Determine number of values */
|
||||
while (true)
|
||||
{
|
||||
if (values[num_values].value)
|
||||
{
|
||||
/* Check if this is the default value */
|
||||
if (default_value)
|
||||
if (strcmp(values[num_values].value, default_value) == 0)
|
||||
default_index = num_values;
|
||||
|
||||
buf_len += strlen(values[num_values].value);
|
||||
num_values++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* Build values string */
|
||||
if (num_values > 0)
|
||||
{
|
||||
buf_len += num_values - 1;
|
||||
buf_len += strlen(desc);
|
||||
|
||||
values_buf[i] = (char *)calloc(buf_len, sizeof(char));
|
||||
if (!values_buf[i])
|
||||
goto error;
|
||||
|
||||
strcpy(values_buf[i], desc);
|
||||
strcat(values_buf[i], "; ");
|
||||
|
||||
/* Default value goes first */
|
||||
strcat(values_buf[i], values[default_index].value);
|
||||
|
||||
/* Add remaining values */
|
||||
for (j = 0; j < num_values; j++)
|
||||
{
|
||||
if (j != default_index)
|
||||
{
|
||||
strcat(values_buf[i], "|");
|
||||
strcat(values_buf[i], values[j].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variables[option_index].key = key;
|
||||
variables[option_index].value = values_buf[i];
|
||||
option_index++;
|
||||
}
|
||||
|
||||
/* Set variables */
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables);
|
||||
}
|
||||
|
||||
error:
|
||||
/* Clean up */
|
||||
|
||||
if (option_v1_defs_us)
|
||||
{
|
||||
free(option_v1_defs_us);
|
||||
option_v1_defs_us = NULL;
|
||||
}
|
||||
|
||||
#ifndef HAVE_NO_LANGEXTRA
|
||||
if (option_v1_defs_intl)
|
||||
{
|
||||
free(option_v1_defs_intl);
|
||||
option_v1_defs_intl = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (values_buf)
|
||||
{
|
||||
for (i = 0; i < num_options; i++)
|
||||
{
|
||||
if (values_buf[i])
|
||||
{
|
||||
free(values_buf[i]);
|
||||
values_buf[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free(values_buf);
|
||||
values_buf = NULL;
|
||||
}
|
||||
|
||||
if (variables)
|
||||
{
|
||||
free(variables);
|
||||
variables = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
91
libretro/libretro_core_options_intl.h
Normal file
91
libretro/libretro_core_options_intl.h
Normal file
@ -0,0 +1,91 @@
|
||||
#ifndef LIBRETRO_CORE_OPTIONS_INTL_H__
|
||||
#define LIBRETRO_CORE_OPTIONS_INTL_H__
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500 && _MSC_VER < 1900)
|
||||
/* https://support.microsoft.com/en-us/kb/980263 */
|
||||
#pragma execution_character_set("utf-8")
|
||||
#pragma warning(disable:4566)
|
||||
#endif
|
||||
|
||||
#include <libretro.h>
|
||||
|
||||
/*
|
||||
********************************
|
||||
* VERSION: 2.0
|
||||
********************************
|
||||
*
|
||||
* - 2.0: Add support for core options v2 interface
|
||||
* - 1.3: Move translations to libretro_core_options_intl.h
|
||||
* - libretro_core_options_intl.h includes BOM and utf-8
|
||||
* fix for MSVC 2010-2013
|
||||
* - Added HAVE_NO_LANGEXTRA flag to disable translations
|
||||
* on platforms/compilers without BOM support
|
||||
* - 1.2: Use core options v1 interface when
|
||||
* RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION is >= 1
|
||||
* (previously required RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION == 1)
|
||||
* - 1.1: Support generation of core options v0 retro_core_option_value
|
||||
* arrays containing options with a single value
|
||||
* - 1.0: First commit
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
********************************
|
||||
* Core Option Definitions
|
||||
********************************
|
||||
*/
|
||||
|
||||
/* RETRO_LANGUAGE_JAPANESE */
|
||||
|
||||
/* RETRO_LANGUAGE_FRENCH */
|
||||
|
||||
/* RETRO_LANGUAGE_SPANISH */
|
||||
|
||||
/* RETRO_LANGUAGE_GERMAN */
|
||||
|
||||
/* RETRO_LANGUAGE_ITALIAN */
|
||||
|
||||
/* RETRO_LANGUAGE_DUTCH */
|
||||
|
||||
/* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */
|
||||
|
||||
/* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */
|
||||
|
||||
/* RETRO_LANGUAGE_RUSSIAN */
|
||||
|
||||
/* RETRO_LANGUAGE_KOREAN */
|
||||
|
||||
/* RETRO_LANGUAGE_CHINESE_TRADITIONAL */
|
||||
|
||||
/* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */
|
||||
|
||||
/* RETRO_LANGUAGE_ESPERANTO */
|
||||
|
||||
/* RETRO_LANGUAGE_POLISH */
|
||||
|
||||
/* RETRO_LANGUAGE_VIETNAMESE */
|
||||
|
||||
/* RETRO_LANGUAGE_ARABIC */
|
||||
|
||||
/* RETRO_LANGUAGE_GREEK */
|
||||
|
||||
/* RETRO_LANGUAGE_TURKISH */
|
||||
|
||||
/* RETRO_LANGUAGE_SLOVAK */
|
||||
|
||||
/* RETRO_LANGUAGE_PERSIAN */
|
||||
|
||||
/* RETRO_LANGUAGE_HEBREW */
|
||||
|
||||
/* RETRO_LANGUAGE_ASTURIAN */
|
||||
|
||||
/* RETRO_LANGUAGE_FINNISH */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -16,13 +16,18 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "libretro.h"
|
||||
#include "retro_disk_control.h"
|
||||
#include "retro_strings.h"
|
||||
#include "retro_files.h"
|
||||
#include "retro_utils.h"
|
||||
#include "file/file_path.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string/stdstring.h>
|
||||
|
||||
/*#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
@ -30,48 +35,45 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>*/
|
||||
|
||||
static void fallback_log(enum retro_log_level level, const char* fmt, ...);
|
||||
static retro_log_printf_t log_cb = fallback_log;
|
||||
|
||||
static void fallback_log(enum retro_log_level level, const char* fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
(void)level;
|
||||
|
||||
va_start(va, fmt);
|
||||
vfprintf(stderr, fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
#define COMMENT "#"
|
||||
#define M3U_SPECIAL_COMMAND "#COMMAND:"
|
||||
|
||||
// Return the directory name of filename 'filename'.
|
||||
char* dirname_int(const char* filename)
|
||||
static char* dirname_int(const char* filename)
|
||||
{
|
||||
if (filename == NULL)
|
||||
return NULL;
|
||||
|
||||
char* right;
|
||||
int len = strlen(filename);
|
||||
|
||||
if ((right = strrchr(filename, RETRO_PATH_SEPARATOR[0])) != NULL)
|
||||
return strleft(filename, len - strlen(right));
|
||||
|
||||
#ifdef _WIN32
|
||||
// Alternative search for windows beceause it also support the UNIX seperator
|
||||
if ((right = strrchr(filename, RETRO_PATH_SEPARATOR_ALT[0])) != NULL)
|
||||
return strleft(filename, len - strlen(right));
|
||||
#endif
|
||||
|
||||
|
||||
// Find last separator
|
||||
char* right = find_last_slash(filename);
|
||||
if (right)
|
||||
return strleft(filename, right - filename);
|
||||
|
||||
// Not found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* m3u_search_file(const char* basedir, const char* dskName)
|
||||
static char* m3u_search_file(const char* basedir, const char* dskName)
|
||||
{
|
||||
// Verify if this item is an absolute pathname (or the file is in working dir)
|
||||
if (file_exists(dskName))
|
||||
{
|
||||
// Copy and return
|
||||
char* result = calloc(strlen(dskName) + 1, sizeof(char));
|
||||
strcpy(result, dskName);
|
||||
return result;
|
||||
}
|
||||
|
||||
// If basedir was provided
|
||||
if(basedir != NULL)
|
||||
if (basedir != NULL && !path_is_absolute(dskName))
|
||||
{
|
||||
// Join basedir and dskName
|
||||
char* dskPath = calloc(RETRO_PATH_MAX, sizeof(char));
|
||||
path_join(dskPath, basedir, dskName);
|
||||
char* dskPath = path_join_dup(basedir, dskName);
|
||||
|
||||
// Verify if this item is a relative filename (append it to the m3u path)
|
||||
if (file_exists(dskPath))
|
||||
@ -81,98 +83,251 @@ char* m3u_search_file(const char* basedir, const char* dskName)
|
||||
}
|
||||
free(dskPath);
|
||||
}
|
||||
|
||||
|
||||
// Verify if this item is an absolute pathname (or the file is in working dir)
|
||||
if (file_exists(dskName))
|
||||
{
|
||||
// Copy and return
|
||||
return strdup(dskName);
|
||||
}
|
||||
|
||||
// File not found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void dc_reset(dc_storage* dc)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
// Verify
|
||||
if(dc == NULL)
|
||||
if (dc == NULL)
|
||||
return;
|
||||
|
||||
|
||||
// Clean the command
|
||||
if(dc->command)
|
||||
if (dc->command)
|
||||
{
|
||||
free(dc->command);
|
||||
dc->command = NULL;
|
||||
}
|
||||
|
||||
// Clean the struct
|
||||
for(unsigned i=0; i < dc->count; i++)
|
||||
for (i = 0; i < dc->count; i++)
|
||||
{
|
||||
free(dc->files[i]);
|
||||
dc->files[i] = NULL;
|
||||
free(dc->names[i]);
|
||||
dc->names[i] = NULL;
|
||||
|
||||
dc->types[i] = DC_IMAGE_TYPE_NONE;
|
||||
}
|
||||
|
||||
dc->unit = DC_IMAGE_TYPE_NONE;
|
||||
dc->count = 0;
|
||||
dc->index = -1;
|
||||
dc->index = 0;
|
||||
dc->index_prev = 0;
|
||||
dc->eject_state = true;
|
||||
dc->replace = false;
|
||||
}
|
||||
|
||||
dc_storage* dc_create(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Initialize the struct
|
||||
dc_storage* dc = NULL;
|
||||
|
||||
if((dc = malloc(sizeof(dc_storage))) != NULL)
|
||||
|
||||
if ((dc = (dc_storage*)malloc(sizeof(dc_storage))) != NULL)
|
||||
{
|
||||
dc->unit = DC_IMAGE_TYPE_NONE;
|
||||
dc->count = 0;
|
||||
dc->index = -1;
|
||||
dc->index = 0;
|
||||
dc->eject_state = true;
|
||||
dc->replace = false;
|
||||
dc->command = NULL;
|
||||
for(int i = 0; i < DC_MAX_SIZE; i++)
|
||||
for (i = 0; i < DC_MAX_SIZE; i++)
|
||||
{
|
||||
dc->files[i] = NULL;
|
||||
dc->names[i] = NULL;
|
||||
dc->types[i] = DC_IMAGE_TYPE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return dc;
|
||||
}
|
||||
|
||||
bool dc_add_file_int(dc_storage* dc, char* filename)
|
||||
bool dc_add_file_int(dc_storage* dc, char* filename, char* name)
|
||||
{
|
||||
// Verify
|
||||
if(dc == NULL)
|
||||
/* Verify */
|
||||
if (dc == NULL)
|
||||
return false;
|
||||
|
||||
if(filename == NULL)
|
||||
if (!filename || (*filename == '\0'))
|
||||
return false;
|
||||
|
||||
// If max size is not
|
||||
if(dc->count < DC_MAX_SIZE)
|
||||
/* If max size is not exceeded */
|
||||
if (dc->count < DC_MAX_SIZE)
|
||||
{
|
||||
// Add the file
|
||||
/* Add the file */
|
||||
dc->count++;
|
||||
dc->files[dc->count-1] = filename;
|
||||
dc->files[dc->count - 1] = strdup(filename);
|
||||
dc->names[dc->count - 1] = !string_is_empty(name) ? strdup(name) : NULL;
|
||||
dc->types[dc->count - 1] = dc_get_image_type(filename);
|
||||
|
||||
log_cb(RETRO_LOG_INFO, ">>> dc added int %s - [%s]\n", filename, name);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dc_add_file(dc_storage* dc, const char* filename)
|
||||
{
|
||||
// Verify
|
||||
if(dc == NULL)
|
||||
unsigned index = 0;
|
||||
|
||||
/* Verify */
|
||||
if (dc == NULL || !filename || (*filename == '\0'))
|
||||
return false;
|
||||
|
||||
if(filename == NULL)
|
||||
/* Dupecheck */
|
||||
for (index = 0; index < dc->count; index++)
|
||||
{
|
||||
if (!strcmp(dc->files[index], filename))
|
||||
{
|
||||
log_cb(RETRO_LOG_INFO,"File '%s' ignored as duplicate!\n", filename);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Get 'name' - just the filename without extension
|
||||
char name[512];
|
||||
name[0] = '\0';
|
||||
fill_pathname(name, path_basename(filename), "", sizeof(name));
|
||||
|
||||
if (!dc_add_file_int(dc, strdup(filename), strdup(name)))
|
||||
return false;
|
||||
|
||||
// Copy and return
|
||||
char* filename_int = calloc(strlen(filename) + 1, sizeof(char));
|
||||
strcpy(filename_int, filename);
|
||||
return dc_add_file_int(dc, filename_int);
|
||||
// if dc unit-type is none, get type from first image
|
||||
if (dc->unit == DC_IMAGE_TYPE_NONE)
|
||||
{
|
||||
if (dc_get_image_type(dc->files[0]) == DC_IMAGE_TYPE_TAPE)
|
||||
dc->unit = DC_IMAGE_TYPE_TAPE;
|
||||
else if (dc_get_image_type(dc->files[0]) == DC_IMAGE_TYPE_FLOPPY)
|
||||
dc->unit = DC_IMAGE_TYPE_FLOPPY;
|
||||
else if (dc_get_image_type(dc->files[0]) == DC_IMAGE_TYPE_MEM)
|
||||
dc->unit = DC_IMAGE_TYPE_MEM;
|
||||
else
|
||||
dc->unit = DC_IMAGE_TYPE_FLOPPY;
|
||||
}
|
||||
|
||||
log_cb(RETRO_LOG_INFO,">>> dc added %s - [%s] [unit %i]\n", filename, name, dc->unit);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_remove_file(dc_storage* dc, int index)
|
||||
{
|
||||
if (dc == NULL)
|
||||
return false;
|
||||
|
||||
if (index < 0 || index >= dc->count)
|
||||
return false;
|
||||
|
||||
// "If ptr is a null pointer, no action occurs"
|
||||
free(dc->files[index]);
|
||||
dc->files[index] = NULL;
|
||||
free(dc->names[index]);
|
||||
dc->names[index] = NULL;
|
||||
dc->types[index] = DC_IMAGE_TYPE_NONE;
|
||||
|
||||
// Shift all entries after index one slot up
|
||||
if (index != dc->count - 1)
|
||||
{
|
||||
memmove(dc->files + index, dc->files + index + 1, (dc->count - 1 - index) * sizeof(dc->files[0]));
|
||||
memmove(dc->names + index, dc->names + index + 1, (dc->count - 1 - index) * sizeof(dc->names[0]));
|
||||
}
|
||||
dc->count--;
|
||||
|
||||
// Reset fliplist unit after removing last entry
|
||||
if (dc->count == 0)
|
||||
{
|
||||
dc->unit = DC_IMAGE_TYPE_NONE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int dc_replace_file(dc_storage* dc, int index, const char* filename)
|
||||
{
|
||||
if (dc == NULL)
|
||||
return false;
|
||||
|
||||
if (index < 0 || index >= dc->count)
|
||||
return false;
|
||||
|
||||
// "If ptr is a null pointer, no action occurs"
|
||||
free(dc->files[index]);
|
||||
dc->files[index] = NULL;
|
||||
free(dc->names[index]);
|
||||
dc->names[index] = NULL;
|
||||
dc->types[index] = DC_IMAGE_TYPE_NONE;
|
||||
|
||||
if (filename == NULL)
|
||||
{
|
||||
dc_remove_file(dc, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc->replace = false;
|
||||
|
||||
char full_path_replace[RETRO_PATH_MAX] = { 0 };
|
||||
strncpy(full_path_replace, (char*)filename, sizeof(full_path_replace));
|
||||
|
||||
/* ZIP/M3U not implemented internally */
|
||||
if (
|
||||
strendswith(full_path_replace, "m3u") ||
|
||||
strendswith(full_path_replace, "zip") ||
|
||||
strendswith(full_path_replace, "7z")
|
||||
)
|
||||
{
|
||||
log_cb(RETRO_LOG_INFO,">>> dc replace %s unsupported type.\n", filename);
|
||||
return false;
|
||||
}
|
||||
/* Single append */
|
||||
else
|
||||
{
|
||||
// Get 'name' - just the filename without extension
|
||||
char name[512];
|
||||
name[0] = '\0';
|
||||
fill_pathname(name, path_basename(filename), "", sizeof(name));
|
||||
|
||||
/* Dupecheck */
|
||||
for (unsigned i = 0; i < dc->count - 1; i++)
|
||||
{
|
||||
if (!strcmp(dc->files[i], full_path_replace))
|
||||
{
|
||||
dc_remove_file(dc, index);
|
||||
return 2; // 2 = duplicate found
|
||||
}
|
||||
}
|
||||
|
||||
dc->files[index] = strdup(filename);
|
||||
dc->names[index] = !string_is_empty(name) ? strdup(name) : NULL;
|
||||
dc->types[index] = dc_get_image_type(filename);
|
||||
|
||||
log_cb(RETRO_LOG_INFO,">>> dc replace %s - %s [%u].\n", filename, name , dc->types[index] );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void dc_parse_m3u(dc_storage* dc, const char* m3u_file)
|
||||
{
|
||||
// Verify
|
||||
if(dc == NULL)
|
||||
if (dc == NULL)
|
||||
return;
|
||||
|
||||
if(m3u_file == NULL)
|
||||
|
||||
if (m3u_file == NULL)
|
||||
return;
|
||||
|
||||
FILE* fp = NULL;
|
||||
@ -183,16 +338,19 @@ void dc_parse_m3u(dc_storage* dc, const char* m3u_file)
|
||||
|
||||
// Reset
|
||||
dc_reset(dc);
|
||||
|
||||
|
||||
// Get the m3u base dir for resolving relative path
|
||||
char* basedir = dirname_int(m3u_file);
|
||||
|
||||
|
||||
// Disk control interface 'name' for the following file
|
||||
char* image_name = NULL;
|
||||
|
||||
// Read the lines while there is line to read and we have enough space
|
||||
char buffer[2048];
|
||||
while ((dc->count <= DC_MAX_SIZE) && (fgets(buffer, sizeof(buffer), fp) != NULL))
|
||||
{
|
||||
char* string = trimwhitespace(buffer);
|
||||
|
||||
|
||||
// If it's a m3u special key or a file
|
||||
if (strstartswith(string, M3U_SPECIAL_COMMAND))
|
||||
{
|
||||
@ -204,19 +362,39 @@ void dc_parse_m3u(dc_storage* dc, const char* m3u_file)
|
||||
char* filename;
|
||||
if ((filename = m3u_search_file(basedir, string)) != NULL)
|
||||
{
|
||||
|
||||
char tmp[512];
|
||||
tmp[0] = '\0';
|
||||
|
||||
fill_pathname(tmp, path_basename(filename), "", sizeof(tmp));
|
||||
image_name = strdup(tmp);
|
||||
|
||||
// Add the file to the struct
|
||||
dc_add_file_int(dc, filename);
|
||||
dc_add_file_int(dc, filename, image_name);
|
||||
image_name = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If basedir was provided
|
||||
if(basedir != NULL)
|
||||
if (basedir != NULL)
|
||||
free(basedir);
|
||||
|
||||
// Close the file
|
||||
// Close the file
|
||||
fclose(fp);
|
||||
|
||||
if (dc->count != 0)
|
||||
{
|
||||
if (dc_get_image_type(dc->files[0]) == DC_IMAGE_TYPE_TAPE)
|
||||
dc->unit = DC_IMAGE_TYPE_TAPE;
|
||||
else if (dc_get_image_type(dc->files[0]) == DC_IMAGE_TYPE_FLOPPY)
|
||||
dc->unit = DC_IMAGE_TYPE_FLOPPY;
|
||||
else
|
||||
dc->unit = DC_IMAGE_TYPE_FLOPPY;
|
||||
|
||||
log_cb(RETRO_LOG_INFO,">>> dc (m3u) unit type: %i\n", dc->unit);
|
||||
}
|
||||
}
|
||||
|
||||
void dc_free(dc_storage* dc)
|
||||
@ -226,4 +404,26 @@ void dc_free(dc_storage* dc)
|
||||
free(dc);
|
||||
dc = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
enum dc_image_type dc_get_image_type(const char* filename)
|
||||
{
|
||||
// Missing file
|
||||
if (!filename || (*filename == '\0'))
|
||||
return DC_IMAGE_TYPE_NONE;
|
||||
|
||||
// Floppy image
|
||||
if (strendswith(filename, "st") ||
|
||||
strendswith(filename, "msa") ||
|
||||
strendswith(filename, "stx") ||
|
||||
strendswith(filename, "dim") ||
|
||||
strendswith(filename, "ipf"))
|
||||
return DC_IMAGE_TYPE_FLOPPY;
|
||||
|
||||
// Place holder for other images types
|
||||
//if (strendswith(filename, "cas"))
|
||||
// return DC_IMAGE_TYPE_TAPE;
|
||||
|
||||
// Fallback
|
||||
return DC_IMAGE_TYPE_UNKNOWN;
|
||||
}
|
||||
|
@ -1,20 +1,41 @@
|
||||
/* Copyright (C) 2018
|
||||
/****************************************************************************
|
||||
* Caprice32 libretro port
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
* Copyright not6 - r-type (2015-2018)
|
||||
* Copyright David Colmenero - D_Skywalk (2019-2021)
|
||||
* Copyright Daniel De Matteis (2012-2021)
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
* Redistribution and use of this code or any derivative works are permitted
|
||||
* provided that the following conditions are met:
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
* - Redistributions may not be sold, nor may they be used in a commercial
|
||||
* product or activity.
|
||||
*
|
||||
* - Redistributions that are modified from the original source must include the
|
||||
* complete source code, including the source code for all components used by a
|
||||
* binary built from the modified sources. However, as a special exception, the
|
||||
* source code distributed need not include anything that is normally distributed
|
||||
* (in either source or binary form) with the major components (compiler, kernel,
|
||||
* and so on) of the operating system on which the executable runs, unless that
|
||||
* component itself accompanies the executable.
|
||||
*
|
||||
* - Redistributions must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef RETRO_DISK_CONTROL_H__
|
||||
#define RETRO_DISK_CONTROL_H__
|
||||
@ -25,18 +46,41 @@
|
||||
// Disk control structure and functions
|
||||
#define DC_MAX_SIZE 20
|
||||
|
||||
//static INLINE bool string_is_empty(const char* data)
|
||||
//{
|
||||
// return !data || (*data == '\0');
|
||||
//}
|
||||
|
||||
enum dc_image_type {
|
||||
DC_IMAGE_TYPE_NONE = 0,
|
||||
DC_IMAGE_TYPE_FLOPPY,
|
||||
DC_IMAGE_TYPE_TAPE,
|
||||
DC_IMAGE_TYPE_MEM,
|
||||
DC_IMAGE_TYPE_UNKNOWN
|
||||
};
|
||||
|
||||
struct dc_storage{
|
||||
char* command;
|
||||
char* files[DC_MAX_SIZE];
|
||||
char* names[DC_MAX_SIZE];
|
||||
enum dc_image_type types[DC_MAX_SIZE];
|
||||
unsigned unit;
|
||||
unsigned count;
|
||||
int index;
|
||||
bool eject_state;
|
||||
bool replace;
|
||||
unsigned index_prev;
|
||||
};
|
||||
|
||||
typedef struct dc_storage dc_storage;
|
||||
dc_storage* dc_create(void);
|
||||
|
||||
void dc_parse_m3u(dc_storage* dc, const char* m3u_file);
|
||||
bool dc_add_file(dc_storage* dc, const char* filename);
|
||||
void dc_free(dc_storage* dc);
|
||||
void dc_reset(dc_storage* dc);
|
||||
int dc_replace_file(dc_storage* dc, int index, const char* filename);
|
||||
bool dc_remove_file(dc_storage* dc, int index);
|
||||
enum dc_image_type dc_get_image_type(const char* filename);
|
||||
|
||||
#endif
|
||||
|
185
libretro/retro_utils.c
Normal file
185
libretro/retro_utils.c
Normal file
@ -0,0 +1,185 @@
|
||||
/****************************************************************************
|
||||
* Caprice32 libretro port
|
||||
*
|
||||
* Copyright not6 - r-type (2015-2018)
|
||||
* Copyright David Colmenero - D_Skywalk (2019-2021)
|
||||
* Copyright Daniel De Matteis (2012-2021)
|
||||
*
|
||||
* Redistribution and use of this code or any derivative works are permitted
|
||||
* provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions may not be sold, nor may they be used in a commercial
|
||||
* product or activity.
|
||||
*
|
||||
* - Redistributions that are modified from the original source must include the
|
||||
* complete source code, including the source code for all components used by a
|
||||
* binary built from the modified sources. However, as a special exception, the
|
||||
* source code distributed need not include anything that is normally distributed
|
||||
* (in either source or binary form) with the major components (compiler, kernel,
|
||||
* and so on) of the operating system on which the executable runs, unless that
|
||||
* component itself accompanies the executable.
|
||||
*
|
||||
* - Redistributions must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "retro_utils.h"
|
||||
#ifdef VITA
|
||||
#include "file/file_path.h"
|
||||
#endif
|
||||
|
||||
extern uint8_t* pbGPBuffer;
|
||||
|
||||
// Verify file extension
|
||||
bool file_check_extension(const char *filename, const size_t filename_size, const char *ext, const size_t ext_size)
|
||||
{
|
||||
#ifndef __PS3__
|
||||
size_t file_len = strnlen(filename, filename_size);
|
||||
size_t ext_len = strnlen(ext, ext_size);
|
||||
#else
|
||||
size_t file_len = strlen(filename) > filename_size ? filename_size : strlen(filename);
|
||||
size_t ext_len = strlen(ext) > ext_size ? ext_size : strlen(ext);
|
||||
#endif
|
||||
|
||||
if( ext_len > file_len || file_len >= filename_size - 1)
|
||||
return false;
|
||||
|
||||
const char * file_ext = &filename[file_len - ext_len];
|
||||
|
||||
return (strncasecmp(file_ext, ext, filename_size) == 0);
|
||||
}
|
||||
|
||||
bool file_check_flag(const char *filename, const size_t filename_size, const char *flag, const size_t flag_size)
|
||||
{
|
||||
#ifndef __PS3__
|
||||
size_t file_len = strnlen(filename, filename_size);
|
||||
size_t flag_len = strnlen(flag, flag_size);
|
||||
#else
|
||||
size_t file_len = strlen(filename) > filename_size ? filename_size : strlen(filename);
|
||||
size_t flag_len = strlen(flag) > flag_size ? flag_size : strlen(flag);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < file_len; i++) {
|
||||
if (i + flag_len > file_len)
|
||||
return false;
|
||||
|
||||
if (strncasecmp(&filename[i], flag, flag_len) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify if file exists
|
||||
bool file_exists(const char *filename)
|
||||
{
|
||||
#ifdef VITA
|
||||
if (path_is_valid(filename) && !path_is_directory(filename))
|
||||
#else
|
||||
struct stat buf;
|
||||
if (stat(filename, &buf) == 0 &&
|
||||
(buf.st_mode & (S_IRUSR|S_IWUSR)) && !(buf.st_mode & S_IFDIR))
|
||||
#endif
|
||||
{
|
||||
/* file points to user readable regular file */
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int file_size (int file_num)
|
||||
{
|
||||
struct stat s;
|
||||
|
||||
if (!fstat(file_num, &s)) {
|
||||
return s.st_size;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void path_join(char* out, const char* basedir, const char* filename)
|
||||
{
|
||||
snprintf(out, RETRO_PATH_MAX, "%s%s%s", basedir, RETRO_PATH_SEPARATOR, filename);
|
||||
}
|
||||
|
||||
char* path_join_dup(const char* basedir, const char* filename)
|
||||
{
|
||||
size_t dirlen = strlen(basedir);
|
||||
size_t seplen = strlen(RETRO_PATH_SEPARATOR);
|
||||
size_t filelen = strlen(filename);
|
||||
char* result = (char*)malloc(dirlen + seplen + filelen + 1);
|
||||
strcpy(result, basedir);
|
||||
strcpy(result + dirlen, RETRO_PATH_SEPARATOR);
|
||||
strcpy(result + dirlen + seplen, filename);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* D_Skywalk: Imported from my 3DS pituka implementation
|
||||
* http://david.dantoine.org/proyecto/26/
|
||||
*/
|
||||
|
||||
#ifdef _3DS
|
||||
void* linearMemAlign(size_t size, size_t alignment);
|
||||
void linearFree(void* mem);
|
||||
#endif
|
||||
|
||||
void *retro_malloc(size_t size) {
|
||||
#ifdef _3DS
|
||||
return linearMemAlign(size, 0x80);
|
||||
#else
|
||||
return malloc(size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void retro_free(void * mem) {
|
||||
#ifdef _3DS
|
||||
linearFree(mem);
|
||||
#else
|
||||
free(mem);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------- crc32b --------------------------------
|
||||
|
||||
/* This is the basic CRC-32 calculation with some optimization but no
|
||||
table lookup. The the byte reversal is avoided by shifting the crc reg
|
||||
right instead of left and by using a reversed 32-bit word to represent
|
||||
the polynomial. */
|
||||
|
||||
uint32_t crc32_calculate(uint8_t * data, uint32_t size) {
|
||||
uint32_t byte, crc, mask;
|
||||
|
||||
crc = 0xFFFFFFFF;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
byte = data[i];
|
||||
crc = crc ^ byte;
|
||||
for (int j = 7; j >= 0; j--) {
|
||||
mask = -(crc & 1);
|
||||
crc = (crc >> 1) ^ (0xedb88320 & mask);
|
||||
}
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
72
libretro/retro_utils.h
Normal file
72
libretro/retro_utils.h
Normal file
@ -0,0 +1,72 @@
|
||||
/****************************************************************************
|
||||
* Caprice32 libretro port
|
||||
*
|
||||
* Copyright not6 - r-type (2015-2018)
|
||||
* Copyright David Colmenero - D_Skywalk (2019-2021)
|
||||
* Copyright Daniel De Matteis (2012-2021)
|
||||
*
|
||||
* Redistribution and use of this code or any derivative works are permitted
|
||||
* provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions may not be sold, nor may they be used in a commercial
|
||||
* product or activity.
|
||||
*
|
||||
* - Redistributions that are modified from the original source must include the
|
||||
* complete source code, including the source code for all components used by a
|
||||
* binary built from the modified sources. However, as a special exception, the
|
||||
* source code distributed need not include anything that is normally distributed
|
||||
* (in either source or binary form) with the major components (compiler, kernel,
|
||||
* and so on) of the operating system on which the executable runs, unless that
|
||||
* component itself accompanies the executable.
|
||||
*
|
||||
* - Redistributions must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
|
||||
#ifndef RETRO_UTILS_H__
|
||||
#define RETRO_UTILS_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
//*****************************************************************************
|
||||
// File helpers functions
|
||||
#define RETRO_PATH_MAX 512
|
||||
|
||||
#ifdef _WIN32
|
||||
#define RETRO_PATH_SEPARATOR "\\"
|
||||
// Windows also support the unix path separator
|
||||
#define RETRO_PATH_SEPARATOR_ALT "/"
|
||||
#else
|
||||
#define RETRO_PATH_SEPARATOR "/"
|
||||
#endif
|
||||
|
||||
bool file_check_extension(const char *filename, const size_t filename_size, const char *ext, const size_t ext_size);
|
||||
bool file_check_flag(const char *filename, const size_t filename_size, const char *flag, const size_t flag_size);
|
||||
void path_join(char* out, const char* basedir, const char* filename);
|
||||
char* path_join_dup(const char* basedir, const char* filename);
|
||||
|
||||
bool file_exists(const char *filename);
|
||||
int file_size (int file_num);
|
||||
uint32_t get_hash(const char *filename);
|
||||
|
||||
void *retro_malloc(size_t size);
|
||||
void retro_free(void * mem);
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user