merge latest libretro-common
This commit is contained in:
parent
c4d7e476c5
commit
2c127b73b0
|
@ -1,7 +1,7 @@
|
|||
/* Copyright (C) 2010-2015 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (compat.c).
|
||||
* The following license statement only applies to this file (compat_getopt.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
|
@ -20,16 +20,15 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef HAVE_GETOPT_LONG
|
||||
#include <string.h>
|
||||
#include <boolean.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <retro_miscellaneous.h>
|
||||
#endif
|
||||
|
||||
#include <compat/getopt.h>
|
||||
#include <compat/strl.h>
|
||||
|
@ -38,7 +37,6 @@
|
|||
|
||||
#include <retro_assert.h>
|
||||
|
||||
#ifndef HAVE_GETOPT_LONG
|
||||
char *optarg;
|
||||
int optind, opterr, optopt;
|
||||
|
||||
|
@ -111,7 +109,8 @@ static int parse_short(const char *optstring, char * const *argv)
|
|||
|
||||
return optarg ? opt[0] : '?';
|
||||
}
|
||||
else if (embedded_arg)
|
||||
|
||||
if (embedded_arg)
|
||||
{
|
||||
/* If we see additional characters,
|
||||
* and they don't take arguments, this
|
||||
|
@ -119,11 +118,9 @@ static int parse_short(const char *optstring, char * const *argv)
|
|||
memmove(&argv[0][1], &argv[0][2], strlen(&argv[0][2]) + 1);
|
||||
return opt[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
optind++;
|
||||
return opt[0];
|
||||
}
|
||||
|
||||
optind++;
|
||||
return opt[0];
|
||||
}
|
||||
|
||||
static int parse_long(const struct option *longopts, char * const *argv)
|
||||
|
@ -168,7 +165,7 @@ static void shuffle_block(char **begin, char **last, char **end)
|
|||
ptrdiff_t len = last - begin;
|
||||
const char **tmp = (const char**)calloc(len, sizeof(const char*));
|
||||
|
||||
rarch_assert(tmp);
|
||||
retro_assert(tmp);
|
||||
|
||||
memcpy(tmp, begin, len * sizeof(const char*));
|
||||
memmove(begin, last, (end - last) * sizeof(const char*));
|
||||
|
@ -211,165 +208,12 @@ int getopt_long(int argc, char *argv[],
|
|||
long_index = 0;
|
||||
}
|
||||
|
||||
rarch_assert(short_index == 0 || long_index == 0);
|
||||
retro_assert(short_index == 0 || long_index == 0);
|
||||
|
||||
if (short_index == 0)
|
||||
return parse_short(optstring, &argv[optind]);
|
||||
else if (long_index == 0)
|
||||
if (long_index == 0)
|
||||
return parse_long(longopts, &argv[optind]);
|
||||
else
|
||||
return '?';
|
||||
|
||||
return '?';
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRCASESTR
|
||||
/* 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_rarch__(const char *haystack, const char *needle)
|
||||
{
|
||||
size_t i, hay_len, needle_len, search_off;
|
||||
|
||||
hay_len = strlen(haystack);
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRL
|
||||
|
||||
/* Implementation of strlcpy()/strlcat() based on OpenBSD. */
|
||||
|
||||
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
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#undef strcasecmp
|
||||
#undef strdup
|
||||
#undef isblank
|
||||
#undef strtok_r
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <compat/strl.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
int rarch_strcasecmp__(const char *a, const char *b)
|
||||
{
|
||||
while (*a && *b)
|
||||
{
|
||||
int a_ = tolower(*a);
|
||||
int b_ = tolower(*b);
|
||||
|
||||
if (a_ != b_)
|
||||
return a_ - b_;
|
||||
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
|
||||
return tolower(*a) - tolower(*b);
|
||||
}
|
||||
|
||||
char *rarch_strdup__(const char *orig)
|
||||
{
|
||||
size_t len = strlen(orig) + 1;
|
||||
char *ret = (char*)malloc(len);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
strlcpy(ret, orig, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rarch_isblank__(int c)
|
||||
{
|
||||
return (c == ' ') || (c == '\t');
|
||||
}
|
||||
|
||||
char *rarch_strtok_r__(char *str, const char *delim, char **saveptr)
|
||||
{
|
||||
char *first = NULL;
|
||||
if (!saveptr || !delim)
|
||||
return NULL;
|
||||
|
||||
if (str)
|
||||
*saveptr = str;
|
||||
|
||||
do
|
||||
{
|
||||
char *ptr = NULL;
|
||||
first = *saveptr;
|
||||
while (*first && strchr(delim, *first))
|
||||
*first++ = '\0';
|
||||
|
||||
if (*first == '\0')
|
||||
return NULL;
|
||||
|
||||
ptr = first + 1;
|
||||
|
||||
while (*ptr && !strchr(delim, *ptr))
|
||||
ptr++;
|
||||
|
||||
*saveptr = ptr + (*ptr ? 1 : 0);
|
||||
*ptr = '\0';
|
||||
} while (strlen(first) == 0);
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,106 @@
|
|||
/* Copyright (C) 2010-2015 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (compat.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/posix_string.h>
|
||||
|
||||
#include <retro_assert.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#undef strcasecmp
|
||||
#undef strdup
|
||||
#undef isblank
|
||||
#undef strtok_r
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <compat/strl.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
int retro_strcasecmp__(const char *a, const char *b)
|
||||
{
|
||||
while (*a && *b)
|
||||
{
|
||||
int a_ = tolower(*a);
|
||||
int b_ = tolower(*b);
|
||||
|
||||
if (a_ != b_)
|
||||
return a_ - b_;
|
||||
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
|
||||
return tolower(*a) - tolower(*b);
|
||||
}
|
||||
|
||||
char *retro_strdup__(const char *orig)
|
||||
{
|
||||
size_t len = strlen(orig) + 1;
|
||||
char *ret = (char*)malloc(len);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
strlcpy(ret, orig, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int retro_isblank__(int c)
|
||||
{
|
||||
return (c == ' ') || (c == '\t');
|
||||
}
|
||||
|
||||
char *retro_strtok_r__(char *str, const char *delim, char **saveptr)
|
||||
{
|
||||
char *first = NULL;
|
||||
if (!saveptr || !delim)
|
||||
return NULL;
|
||||
|
||||
if (str)
|
||||
*saveptr = str;
|
||||
|
||||
do
|
||||
{
|
||||
char *ptr = NULL;
|
||||
first = *saveptr;
|
||||
while (*first && strchr(delim, *first))
|
||||
*first++ = '\0';
|
||||
|
||||
if (*first == '\0')
|
||||
return NULL;
|
||||
|
||||
ptr = first + 1;
|
||||
|
||||
while (*ptr && !strchr(delim, *ptr))
|
||||
ptr++;
|
||||
|
||||
*saveptr = ptr + (*ptr ? 1 : 0);
|
||||
*ptr = '\0';
|
||||
} while (strlen(first) == 0);
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,59 @@
|
|||
/* Copyright (C) 2010-2015 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>
|
||||
#include <retro_assert.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, hay_len, needle_len, search_off;
|
||||
|
||||
hay_len = strlen(haystack);
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/* Copyright (C) 2010-2015 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 <ctype.h>
|
||||
|
||||
#include <compat/strl.h>
|
||||
#include <compat/posix_string.h>
|
||||
|
||||
#include <retro_assert.h>
|
||||
|
||||
/* Implementation of strlcpy()/strlcat() based on OpenBSD. */
|
||||
|
||||
size_t strlcpy_retro__(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_retro__(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);
|
||||
}
|
|
@ -95,7 +95,6 @@ char *dylib_error(void)
|
|||
function_t dylib_proc(dylib_t lib, const char *proc)
|
||||
{
|
||||
function_t sym;
|
||||
void *ptr_sym = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
sym = (function_t)GetProcAddress(lib ?
|
||||
|
@ -107,6 +106,8 @@ function_t dylib_proc(dylib_t lib, const char *proc)
|
|||
}
|
||||
last_dyn_error[0] = 0;
|
||||
#else
|
||||
void *ptr_sym = NULL;
|
||||
|
||||
if (lib)
|
||||
ptr_sym = dlsym(lib, proc);
|
||||
else
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
/* Copyright (C) 2010-2015 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (encodings_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 <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <compat/strl.h>
|
||||
#include <retro_inline.h>
|
||||
|
||||
static INLINE 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)
|
||||
{
|
||||
static uint8_t kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
||||
size_t out_pos = 0;
|
||||
size_t in_pos = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned numAdds;
|
||||
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 (numAdds = 1; numAdds < 5; numAdds++)
|
||||
if (value < (((uint32_t)1) << (numAdds * 5 + 6)))
|
||||
break;
|
||||
if (out)
|
||||
out[out_pos] = (char)(kUtf8Limits[numAdds - 1]
|
||||
+ (value >> (6 * numAdds)));
|
||||
out_pos++;
|
||||
do
|
||||
{
|
||||
numAdds--;
|
||||
if (out)
|
||||
out[out_pos] = (char)(0x80
|
||||
+ ((value >> (6 * numAdds)) & 0x3F));
|
||||
out_pos++;
|
||||
}while (numAdds != 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)
|
||||
{
|
||||
#ifdef HAVE_UTF8
|
||||
char *d_org = d;
|
||||
char *d_end = d+d_len;
|
||||
const uint8_t *sb = (const uint8_t*)s;
|
||||
const uint8_t *sb_org = sb;
|
||||
|
||||
while (*sb && chars-- > 0)
|
||||
{
|
||||
sb++;
|
||||
while ((*sb&0xC0) == 0x80) sb++;
|
||||
}
|
||||
|
||||
if (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;
|
||||
#else
|
||||
return strlcpy(d, s, chars + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *utf8skip(const char *str, size_t chars)
|
||||
{
|
||||
#ifdef HAVE_UTF8
|
||||
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;
|
||||
#else
|
||||
return str + chars;
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t utf8len(const char *string)
|
||||
{
|
||||
#ifdef HAVE_UTF8
|
||||
size_t ret = 0;
|
||||
while (*string)
|
||||
{
|
||||
if ((*string & 0xC0) != 0x80)
|
||||
ret++;
|
||||
string++;
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
return strlen(string);
|
||||
#endif
|
||||
}
|
|
@ -47,6 +47,34 @@
|
|||
|
||||
#define MAX_INCLUDE_DEPTH 16
|
||||
|
||||
struct config_entry_list
|
||||
{
|
||||
/* If we got this from an #include,
|
||||
* do not allow overwrite. */
|
||||
bool readonly;
|
||||
char *key;
|
||||
char *value;
|
||||
uint32_t key_hash;
|
||||
|
||||
struct config_entry_list *next;
|
||||
};
|
||||
|
||||
struct config_include_list
|
||||
{
|
||||
char *path;
|
||||
struct config_include_list *next;
|
||||
};
|
||||
|
||||
struct config_file
|
||||
{
|
||||
char *path;
|
||||
struct config_entry_list *entries;
|
||||
struct config_entry_list *tail;
|
||||
unsigned include_depth;
|
||||
|
||||
struct config_include_list *includes;
|
||||
};
|
||||
|
||||
static config_file_t *config_file_new_internal(const char *path, unsigned depth);
|
||||
void config_file_free(config_file_t *conf);
|
||||
|
||||
|
@ -496,7 +524,7 @@ config_file_t *config_file_new(const char *path)
|
|||
void config_file_free(config_file_t *conf)
|
||||
{
|
||||
struct config_include_list *inc_tmp = NULL;
|
||||
struct config_entry_list *tmp = NULL;
|
||||
struct config_entry_list *tmp = NULL;
|
||||
if (!conf)
|
||||
return;
|
||||
|
||||
|
@ -504,11 +532,19 @@ void config_file_free(config_file_t *conf)
|
|||
while (tmp)
|
||||
{
|
||||
struct config_entry_list *hold = NULL;
|
||||
free(tmp->key);
|
||||
free(tmp->value);
|
||||
hold = tmp;
|
||||
tmp = tmp->next;
|
||||
free(hold);
|
||||
if (tmp->key)
|
||||
free(tmp->key);
|
||||
if (tmp->value)
|
||||
free(tmp->value);
|
||||
|
||||
tmp->value = NULL;
|
||||
tmp->key = NULL;
|
||||
|
||||
hold = tmp;
|
||||
tmp = tmp->next;
|
||||
|
||||
if (hold)
|
||||
free(hold);
|
||||
}
|
||||
|
||||
inc_tmp = (struct config_include_list*)conf->includes;
|
||||
|
@ -521,7 +557,8 @@ void config_file_free(config_file_t *conf)
|
|||
free(hold);
|
||||
}
|
||||
|
||||
free(conf->path);
|
||||
if (conf->path)
|
||||
free(conf->path);
|
||||
free(conf);
|
||||
}
|
||||
|
||||
|
@ -589,6 +626,7 @@ bool config_get_int(config_file_t *conf, const char *key, int *in)
|
|||
return entry != NULL && errno == 0;
|
||||
}
|
||||
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
|
||||
bool config_get_uint64(config_file_t *conf, const char *key, uint64_t *in)
|
||||
{
|
||||
const struct config_entry_list *entry = config_get_entry(conf, key, NULL);
|
||||
|
@ -604,6 +642,7 @@ bool config_get_uint64(config_file_t *conf, const char *key, uint64_t *in)
|
|||
|
||||
return entry != NULL && errno == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool config_get_uint(config_file_t *conf, const char *key, unsigned *in)
|
||||
{
|
||||
|
@ -662,6 +701,14 @@ bool config_get_string(config_file_t *conf, const char *key, char **str)
|
|||
return entry != NULL;
|
||||
}
|
||||
|
||||
bool config_get_config_path(config_file_t *conf, char *s, size_t len)
|
||||
{
|
||||
if (!conf)
|
||||
return false;
|
||||
|
||||
return strlcpy(s, conf->path, len);
|
||||
}
|
||||
|
||||
bool config_get_array(config_file_t *conf, const char *key,
|
||||
char *buf, size_t size)
|
||||
{
|
||||
|
@ -735,6 +782,20 @@ void config_set_string(config_file_t *conf, const char *key, const char *val)
|
|||
conf->entries = entry;
|
||||
}
|
||||
|
||||
void config_unset(config_file_t *conf, const char *key)
|
||||
{
|
||||
struct config_entry_list *last = conf->entries;
|
||||
struct config_entry_list *entry = config_get_entry(conf, key, &last);
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
entry->key = NULL;
|
||||
entry->value = NULL;
|
||||
free(entry->key);
|
||||
free(entry->value);
|
||||
}
|
||||
|
||||
void config_set_path(config_file_t *conf, const char *entry, const char *val)
|
||||
{
|
||||
#if defined(RARCH_CONSOLE)
|
||||
|
@ -751,8 +812,10 @@ void config_set_double(config_file_t *conf, const char *key, double val)
|
|||
char buf[128] = {0};
|
||||
#ifdef __cplusplus
|
||||
snprintf(buf, sizeof(buf), "%f", (float)val);
|
||||
#else
|
||||
#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
|
||||
snprintf(buf, sizeof(buf), "%lf", val);
|
||||
#else
|
||||
snprintf(buf, sizeof(buf), "%f", (float)val);
|
||||
#endif
|
||||
config_set_string(conf, key, buf);
|
||||
}
|
||||
|
@ -835,7 +898,10 @@ void config_file_dump(config_file_t *conf, FILE *file)
|
|||
list = (struct config_entry_list*)conf->entries;
|
||||
while (list)
|
||||
{
|
||||
if (!list->readonly)
|
||||
if (!list)
|
||||
break;
|
||||
|
||||
if (!list->readonly && list->key)
|
||||
fprintf(file, "%s = \"%s\"\n", list->key, list->value);
|
||||
list = list->next;
|
||||
}
|
||||
|
|
|
@ -33,16 +33,16 @@
|
|||
|
||||
static int qstrcmp_plain(const void *a_, const void *b_)
|
||||
{
|
||||
const struct string_list_elem *a = (const struct string_list_elem*)a_;
|
||||
const struct string_list_elem *b = (const struct string_list_elem*)b_;
|
||||
const struct string_list_elem *a = (const struct string_list_elem*)a_;
|
||||
const struct string_list_elem *b = (const struct string_list_elem*)b_;
|
||||
|
||||
return strcasecmp(a->data, b->data);
|
||||
}
|
||||
|
||||
static int qstrcmp_dir(const void *a_, const void *b_)
|
||||
{
|
||||
const struct string_list_elem *a = (const struct string_list_elem*)a_;
|
||||
const struct string_list_elem *b = (const struct string_list_elem*)b_;
|
||||
const struct string_list_elem *a = (const struct string_list_elem*)a_;
|
||||
const struct string_list_elem *b = (const struct string_list_elem*)b_;
|
||||
int a_type = a->attr.i;
|
||||
int b_type = b->attr.i;
|
||||
|
||||
|
@ -182,12 +182,13 @@ struct string_list *dir_list_new(const char *dir,
|
|||
while (retro_readdir(entry))
|
||||
{
|
||||
char file_path[PATH_MAX_LENGTH];
|
||||
bool is_dir;
|
||||
int ret = 0;
|
||||
const char *name = retro_dirent_get_name(entry);
|
||||
bool is_dir = retro_dirent_is_dir(entry, file_path);
|
||||
const char *file_ext = path_get_extension(name);
|
||||
|
||||
fill_pathname_join(file_path, dir, name, sizeof(file_path));
|
||||
is_dir = retro_dirent_is_dir(entry, file_path);
|
||||
|
||||
ret = parse_dir_entry(name, file_path, is_dir,
|
||||
include_dirs, include_compressed, list, ext_list, file_ext);
|
||||
|
|
|
@ -1,230 +0,0 @@
|
|||
/* Copyright (C) 2010-2015 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (dir_list.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 <file/dir_list.h>
|
||||
#include <file/file_path.h>
|
||||
#include <compat/strl.h>
|
||||
#include <compat/posix_string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
static int qstrcmp_plain(const void *a_, const void *b_)
|
||||
{
|
||||
const struct string_list_elem *a = (const struct string_list_elem*)a_;
|
||||
const struct string_list_elem *b = (const struct string_list_elem*)b_;
|
||||
|
||||
return strcasecmp(a->data, b->data);
|
||||
}
|
||||
|
||||
static int qstrcmp_dir(const void *a_, const void *b_)
|
||||
{
|
||||
const struct string_list_elem *a = (const struct string_list_elem*)a_;
|
||||
const struct string_list_elem *b = (const struct string_list_elem*)b_;
|
||||
int a_type = a->attr.i;
|
||||
int b_type = b->attr.i;
|
||||
|
||||
|
||||
/* Sort directories before files. */
|
||||
if (a_type != b_type)
|
||||
return b_type - a_type;
|
||||
return strcasecmp(a->data, b->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* dir_list_sort:
|
||||
* @list : pointer to the directory listing.
|
||||
* @dir_first : move the directories in the listing to the top?
|
||||
*
|
||||
* Sorts a directory listing.
|
||||
*
|
||||
**/
|
||||
void dir_list_sort(struct string_list *list, bool dir_first)
|
||||
{
|
||||
if (list)
|
||||
qsort(list->elems, list->size, sizeof(struct string_list_elem),
|
||||
dir_first ? qstrcmp_dir : qstrcmp_plain);
|
||||
}
|
||||
|
||||
/**
|
||||
* dir_list_free:
|
||||
* @list : pointer to the directory listing
|
||||
*
|
||||
* Frees a directory listing.
|
||||
*
|
||||
**/
|
||||
void dir_list_free(struct string_list *list)
|
||||
{
|
||||
string_list_free(list);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* dirent_is_directory:
|
||||
* @path : path to the directory entry.
|
||||
* @entry : pointer to the directory entry.
|
||||
*
|
||||
* Is the directory listing entry a directory?
|
||||
*
|
||||
* Returns: true if directory listing entry is
|
||||
* a directory, false if not.
|
||||
*/
|
||||
|
||||
static bool dirent_is_directory(const char *path)
|
||||
{
|
||||
BOOL is_directory;
|
||||
BOOL file_exists_at_path = [[NSFileManager defaultManager] fileExistsAtPath:@(path) isDirectory:&is_directory];
|
||||
|
||||
(void)file_exists_at_path;
|
||||
|
||||
return is_directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* parse_dir_entry:
|
||||
* @name : name of the directory listing entry.
|
||||
* @file_path : file path of the directory listing entry.
|
||||
* @is_dir : is the directory listing a directory?
|
||||
* @include_dirs : include directories as part of the finished directory listing?
|
||||
* @include_compressed : include compressed files, even when not part of ext_list.
|
||||
* @list : pointer to directory listing.
|
||||
* @ext_list : pointer to allowed file extensions listing.
|
||||
* @file_ext : file extension of the directory listing entry.
|
||||
*
|
||||
* Parses a directory listing.
|
||||
*
|
||||
* Returns: zero on success, -1 on error, 1 if we should
|
||||
* continue to the next entry in the directory listing.
|
||||
**/
|
||||
static int parse_dir_entry(const char *name, char *file_path,
|
||||
bool is_dir, bool include_dirs, bool include_compressed,
|
||||
struct string_list *list, struct string_list *ext_list,
|
||||
const char *file_ext)
|
||||
{
|
||||
union string_list_elem_attr attr;
|
||||
bool is_compressed_file = false;
|
||||
bool supported_by_core = false;
|
||||
|
||||
attr.i = RARCH_FILETYPE_UNSET;
|
||||
|
||||
if (!is_dir)
|
||||
{
|
||||
is_compressed_file = path_is_compressed_file(file_path);
|
||||
if (string_list_find_elem_prefix(ext_list, ".", file_ext))
|
||||
supported_by_core = true;
|
||||
}
|
||||
|
||||
if (!include_dirs && is_dir)
|
||||
return 1;
|
||||
|
||||
if (!strcmp(name, ".") || !strcmp(name, ".."))
|
||||
return 1;
|
||||
|
||||
if (!is_dir && ext_list &&
|
||||
((!is_compressed_file && !supported_by_core) ||
|
||||
(!supported_by_core && !include_compressed)))
|
||||
return 1;
|
||||
|
||||
if (is_dir)
|
||||
attr.i = RARCH_DIRECTORY;
|
||||
if (is_compressed_file)
|
||||
attr.i = RARCH_COMPRESSED_ARCHIVE;
|
||||
/* The order of these ifs is important.
|
||||
* If the file format is explicitly supported by the libretro-core, we
|
||||
* need to immediately load it and not designate it as a compressed file.
|
||||
*
|
||||
* Example: .zip could be supported as a image by the core and as a
|
||||
* compressed_file. In that case, we have to interpret it as a image.
|
||||
*
|
||||
* */
|
||||
if (supported_by_core)
|
||||
attr.i = RARCH_PLAIN_FILE;
|
||||
|
||||
if (!string_list_append(list, file_path, attr))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dir_list_new:
|
||||
* @dir : directory path.
|
||||
* @ext : allowed extensions of file directory entries to include.
|
||||
* @include_dirs : include directories as part of the finished directory listing?
|
||||
* @include_compressed : Include compressed files, even if not part of ext.
|
||||
*
|
||||
* Create a directory listing.
|
||||
*
|
||||
* Returns: pointer to a directory listing of type 'struct string_list *' on success,
|
||||
* NULL in case of error. Has to be freed manually.
|
||||
**/
|
||||
struct string_list *dir_list_new(const char *dir,
|
||||
const char *ext, bool include_dirs, bool include_compressed)
|
||||
{
|
||||
NSArray *entries = NULL;
|
||||
char path_buf[PATH_MAX_LENGTH] = {0};
|
||||
struct string_list *ext_list = NULL;
|
||||
struct string_list *list = NULL;
|
||||
|
||||
(void)path_buf;
|
||||
|
||||
if (!(list = string_list_new()))
|
||||
return NULL;
|
||||
|
||||
if (ext)
|
||||
ext_list = string_split(ext, "|");
|
||||
|
||||
entries = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@(dir) error:nil];
|
||||
|
||||
for (NSString *name in entries)
|
||||
{
|
||||
int ret = 0;
|
||||
char file_path[PATH_MAX_LENGTH] = {0};
|
||||
const char *file_ext = path_get_extension([name UTF8String]);
|
||||
bool is_dir = false;
|
||||
|
||||
fill_pathname_join(file_path, dir, [name UTF8String], sizeof(file_path));
|
||||
|
||||
is_dir = dirent_is_directory(file_path);
|
||||
|
||||
ret = parse_dir_entry([name UTF8String], file_path, is_dir,
|
||||
include_dirs, include_compressed, list, ext_list, file_ext);
|
||||
|
||||
if (ret == -1)
|
||||
goto error;
|
||||
|
||||
if (ret == 1)
|
||||
continue;
|
||||
}
|
||||
|
||||
string_list_free(ext_list);
|
||||
return list;
|
||||
|
||||
error:
|
||||
string_list_free(list);
|
||||
string_list_free(ext_list);
|
||||
return NULL;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,213 @@
|
|||
/* Copyright (C) 2010-2015 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (file_archive_zlib.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 <compat/zlib.h>
|
||||
#include <file/file_archive.h>
|
||||
#include <retro_file.h>
|
||||
|
||||
static void *zlib_stream_new(void)
|
||||
{
|
||||
return (z_stream*)calloc(1, sizeof(z_stream));
|
||||
}
|
||||
|
||||
static void zlib_stream_free(void *data)
|
||||
{
|
||||
z_stream *ret = (z_stream*)data;
|
||||
if (ret)
|
||||
inflateEnd(ret);
|
||||
}
|
||||
|
||||
static void zlib_stream_set(void *data,
|
||||
uint32_t avail_in,
|
||||
uint32_t avail_out,
|
||||
const uint8_t *next_in,
|
||||
uint8_t *next_out
|
||||
)
|
||||
{
|
||||
z_stream *stream = (z_stream*)data;
|
||||
|
||||
if (!stream)
|
||||
return;
|
||||
|
||||
stream->avail_in = avail_in;
|
||||
stream->avail_out = avail_out;
|
||||
|
||||
stream->next_in = (uint8_t*)next_in;
|
||||
stream->next_out = next_out;
|
||||
}
|
||||
|
||||
static uint32_t zlib_stream_get_avail_in(void *data)
|
||||
{
|
||||
z_stream *stream = (z_stream*)data;
|
||||
|
||||
if (!stream)
|
||||
return 0;
|
||||
|
||||
return stream->avail_in;
|
||||
}
|
||||
|
||||
static uint32_t zlib_stream_get_avail_out(void *data)
|
||||
{
|
||||
z_stream *stream = (z_stream*)data;
|
||||
|
||||
if (!stream)
|
||||
return 0;
|
||||
|
||||
return stream->avail_out;
|
||||
}
|
||||
|
||||
static uint64_t zlib_stream_get_total_out(void *data)
|
||||
{
|
||||
z_stream *stream = (z_stream*)data;
|
||||
|
||||
if (!stream)
|
||||
return 0;
|
||||
|
||||
return stream->total_out;
|
||||
}
|
||||
|
||||
static void zlib_stream_decrement_total_out(void *data, unsigned subtraction)
|
||||
{
|
||||
z_stream *stream = (z_stream*)data;
|
||||
|
||||
if (stream)
|
||||
stream->total_out -= subtraction;
|
||||
}
|
||||
|
||||
static void zlib_stream_compress_free(void *data)
|
||||
{
|
||||
z_stream *ret = (z_stream*)data;
|
||||
if (ret)
|
||||
deflateEnd(ret);
|
||||
}
|
||||
|
||||
static int zlib_stream_compress_data_to_file(void *data)
|
||||
{
|
||||
int zstatus;
|
||||
z_stream *stream = (z_stream*)data;
|
||||
|
||||
if (!stream)
|
||||
return -1;
|
||||
|
||||
zstatus = deflate(stream, Z_FINISH);
|
||||
|
||||
if (zstatus == Z_STREAM_END)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool zlib_stream_decompress_init(void *data)
|
||||
{
|
||||
z_stream *stream = (z_stream*)data;
|
||||
|
||||
if (!stream)
|
||||
return false;
|
||||
if (inflateInit(stream) != Z_OK)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool zlib_stream_decompress_data_to_file_init(
|
||||
file_archive_file_handle_t *handle,
|
||||
const uint8_t *cdata, uint32_t csize, uint32_t size)
|
||||
{
|
||||
if (!handle)
|
||||
return false;
|
||||
|
||||
if (!(handle->stream = (z_stream*)zlib_stream_new()))
|
||||
goto error;
|
||||
|
||||
if (inflateInit2((z_streamp)handle->stream, -MAX_WBITS) != Z_OK)
|
||||
goto error;
|
||||
|
||||
handle->data = (uint8_t*)malloc(size);
|
||||
|
||||
if (!handle->data)
|
||||
goto error;
|
||||
|
||||
zlib_stream_set(handle->stream, csize, size,
|
||||
(const uint8_t*)cdata, handle->data);
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
zlib_stream_free(handle->stream);
|
||||
free(handle->stream);
|
||||
if (handle->data)
|
||||
free(handle->data);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int zlib_stream_decompress_data_to_file_iterate(void *data)
|
||||
{
|
||||
int zstatus;
|
||||
z_stream *stream = (z_stream*)data;
|
||||
|
||||
if (!stream)
|
||||
return -1;
|
||||
|
||||
zstatus = inflate(stream, Z_NO_FLUSH);
|
||||
|
||||
if (zstatus == Z_STREAM_END)
|
||||
return 1;
|
||||
|
||||
if (zstatus != Z_OK && zstatus != Z_BUF_ERROR)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void zlib_stream_compress_init(void *data, int level)
|
||||
{
|
||||
z_stream *stream = (z_stream*)data;
|
||||
|
||||
if (stream)
|
||||
deflateInit(stream, level);
|
||||
}
|
||||
|
||||
static uint32_t zlib_stream_crc32_calculate(uint32_t crc,
|
||||
const uint8_t *data, size_t length)
|
||||
{
|
||||
return crc32(crc, data, length);
|
||||
}
|
||||
|
||||
const struct file_archive_file_backend zlib_backend = {
|
||||
zlib_stream_new,
|
||||
zlib_stream_free,
|
||||
zlib_stream_set,
|
||||
zlib_stream_get_avail_in,
|
||||
zlib_stream_get_avail_out,
|
||||
zlib_stream_get_total_out,
|
||||
zlib_stream_decrement_total_out,
|
||||
zlib_stream_decompress_init,
|
||||
zlib_stream_decompress_data_to_file_init,
|
||||
zlib_stream_decompress_data_to_file_iterate,
|
||||
zlib_stream_compress_init,
|
||||
zlib_stream_compress_free,
|
||||
zlib_stream_compress_data_to_file,
|
||||
zlib_stream_crc32_calculate,
|
||||
"zlib"
|
||||
};
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include <file/file_list.h>
|
||||
#include <compat/strcasestr.h>
|
||||
#include <compat/posix_string.h>
|
||||
#include <compat/strl.h>
|
||||
|
||||
void file_list_push(file_list_t *list,
|
||||
const char *path, const char *label,
|
||||
|
@ -131,8 +133,7 @@ void file_list_free(file_list_t *list)
|
|||
if (list->list)
|
||||
free(list->list);
|
||||
list->list = NULL;
|
||||
if (list)
|
||||
free(list);
|
||||
free(list);
|
||||
}
|
||||
|
||||
void file_list_clear(file_list_t *list)
|
||||
|
@ -236,7 +237,7 @@ void file_list_get_label_at_offset(const file_list_t *list, size_t idx,
|
|||
void file_list_set_alt_at_offset(file_list_t *list, size_t idx,
|
||||
const char *alt)
|
||||
{
|
||||
if (!list)
|
||||
if (!list || !alt)
|
||||
return;
|
||||
|
||||
if (list->list[idx].alt)
|
||||
|
|
|
@ -35,13 +35,14 @@
|
|||
|
||||
#include <file/file_path.h>
|
||||
|
||||
#ifndef __MACH__
|
||||
#include <compat/strl.h>
|
||||
#include <compat/posix_string.h>
|
||||
#endif
|
||||
#include <retro_assert.h>
|
||||
#include <retro_stat.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
|
||||
/**
|
||||
* path_mkdir:
|
||||
* @dir : directory
|
||||
|
@ -154,7 +155,7 @@ bool path_contains_compressed_file(const char *path)
|
|||
**/
|
||||
bool path_is_compressed_file(const char* path)
|
||||
{
|
||||
#ifdef HAVE_COMPRESSION
|
||||
#if defined(HAVE_COMPRESSION) && (defined(HAVE_ZLIB) || defined(HAVE_7ZIP))
|
||||
const char* file_ext = path_get_extension(path);
|
||||
|
||||
#ifdef HAVE_ZLIB
|
||||
|
@ -217,13 +218,13 @@ void fill_pathname(char *out_path, const char *in_path,
|
|||
char tmp_path[PATH_MAX_LENGTH] = {0};
|
||||
char *tok = NULL;
|
||||
|
||||
rarch_assert(strlcpy(tmp_path, in_path,
|
||||
retro_assert(strlcpy(tmp_path, in_path,
|
||||
sizeof(tmp_path)) < sizeof(tmp_path));
|
||||
if ((tok = (char*)strrchr(path_basename(tmp_path), '.')))
|
||||
*tok = '\0';
|
||||
|
||||
rarch_assert(strlcpy(out_path, tmp_path, size) < size);
|
||||
rarch_assert(strlcat(out_path, replace, size) < size);
|
||||
retro_assert(strlcpy(out_path, tmp_path, size) < size);
|
||||
retro_assert(strlcat(out_path, replace, size) < size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -243,8 +244,8 @@ void fill_pathname(char *out_path, const char *in_path,
|
|||
void fill_pathname_noext(char *out_path, const char *in_path,
|
||||
const char *replace, size_t size)
|
||||
{
|
||||
rarch_assert(strlcpy(out_path, in_path, size) < size);
|
||||
rarch_assert(strlcat(out_path, replace, size) < size);
|
||||
retro_assert(strlcpy(out_path, in_path, size) < size);
|
||||
retro_assert(strlcat(out_path, replace, size) < size);
|
||||
}
|
||||
|
||||
static char *find_last_slash(const char *str)
|
||||
|
@ -278,10 +279,10 @@ void fill_pathname_slash(char *path, size_t size)
|
|||
{
|
||||
char join_str[2];
|
||||
strlcpy(join_str, last_slash, sizeof(join_str));
|
||||
rarch_assert(strlcat(path, join_str, size) < size);
|
||||
retro_assert(strlcat(path, join_str, size) < size);
|
||||
}
|
||||
else if (!last_slash)
|
||||
rarch_assert(strlcat(path, path_default_slash(), size) < size);
|
||||
retro_assert(strlcat(path, path_default_slash(), size) < size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -308,8 +309,8 @@ void fill_pathname_dir(char *in_dir, const char *in_basename,
|
|||
|
||||
fill_pathname_slash(in_dir, size);
|
||||
base = path_basename(in_basename);
|
||||
rarch_assert(strlcat(in_dir, base, size) < size);
|
||||
rarch_assert(strlcat(in_dir, replace, size) < size);
|
||||
retro_assert(strlcat(in_dir, base, size) < size);
|
||||
retro_assert(strlcat(in_dir, replace, size) < size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -347,7 +348,7 @@ void fill_pathname_base(char *out, const char *in_path, size_t size)
|
|||
ptr = ptr_bak;
|
||||
#endif
|
||||
|
||||
rarch_assert(strlcpy(out, ptr, size) < size);
|
||||
retro_assert(strlcpy(out, ptr, size) < size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -363,7 +364,8 @@ void fill_pathname_base(char *out, const char *in_path, size_t size)
|
|||
void fill_pathname_basedir(char *out_dir,
|
||||
const char *in_path, size_t size)
|
||||
{
|
||||
rarch_assert(strlcpy(out_dir, in_path, size) < size);
|
||||
if (out_dir != in_path)
|
||||
retro_assert(strlcpy(out_dir, in_path, size) < size);
|
||||
path_basedir(out_dir);
|
||||
}
|
||||
|
||||
|
@ -379,7 +381,8 @@ void fill_pathname_basedir(char *out_dir,
|
|||
void fill_pathname_parent_dir(char *out_dir,
|
||||
const char *in_dir, size_t size)
|
||||
{
|
||||
rarch_assert(strlcpy(out_dir, in_dir, size) < size);
|
||||
if (out_dir != in_dir)
|
||||
retro_assert(strlcpy(out_dir, in_dir, size) < size);
|
||||
path_parent_dir(out_dir);
|
||||
}
|
||||
|
||||
|
@ -459,12 +462,10 @@ void path_parent_dir(char *path)
|
|||
**/
|
||||
const char *path_basename(const char *path)
|
||||
{
|
||||
const char *last_hash = NULL;
|
||||
const char *last = find_last_slash(path);
|
||||
|
||||
(void)last_hash;
|
||||
|
||||
#ifdef HAVE_COMPRESSION
|
||||
const char *last_hash = NULL;
|
||||
|
||||
/* We cut either at the last hash or the last slash; whichever comes last */
|
||||
last_hash = strchr(path,'#');
|
||||
|
||||
|
@ -517,7 +518,7 @@ void path_resolve_realpath(char *buf, size_t size)
|
|||
if (!_fullpath(buf, tmp, size))
|
||||
strlcpy(buf, tmp, size);
|
||||
#else
|
||||
rarch_assert(size >= PATH_MAX_LENGTH);
|
||||
retro_assert(size >= PATH_MAX_LENGTH);
|
||||
|
||||
/* NOTE: realpath() expects at least PATH_MAX_LENGTH bytes in buf.
|
||||
* Technically, PATH_MAX_LENGTH needn't be defined, but we rely on it anyways.
|
||||
|
@ -546,13 +547,13 @@ void fill_pathname_resolve_relative(char *out_path,
|
|||
{
|
||||
if (path_is_absolute(in_path))
|
||||
{
|
||||
rarch_assert(strlcpy(out_path, in_path, size) < size);
|
||||
retro_assert(strlcpy(out_path, in_path, size) < size);
|
||||
return;
|
||||
}
|
||||
|
||||
rarch_assert(strlcpy(out_path, in_refpath, size) < size);
|
||||
retro_assert(strlcpy(out_path, in_refpath, size) < size);
|
||||
path_basedir(out_path);
|
||||
rarch_assert(strlcat(out_path, in_path, size) < size);
|
||||
retro_assert(strlcat(out_path, in_path, size) < size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -569,12 +570,22 @@ void fill_pathname_resolve_relative(char *out_path,
|
|||
void fill_pathname_join(char *out_path,
|
||||
const char *dir, const char *path, size_t size)
|
||||
{
|
||||
rarch_assert(strlcpy(out_path, dir, size) < size);
|
||||
if (out_path != dir)
|
||||
retro_assert(strlcpy(out_path, dir, size) < size);
|
||||
|
||||
if (*out_path)
|
||||
fill_pathname_slash(out_path, size);
|
||||
|
||||
rarch_assert(strlcat(out_path, path, size) < size);
|
||||
retro_assert(strlcat(out_path, path, size) < size);
|
||||
}
|
||||
|
||||
void fill_string_join(char *out_path,
|
||||
const char *append, size_t size)
|
||||
{
|
||||
if (*out_path)
|
||||
fill_pathname_slash(out_path, size);
|
||||
|
||||
retro_assert(strlcat(out_path, append, size) < size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -592,12 +603,12 @@ void fill_pathname_join_delim(char *out_path, const char *dir,
|
|||
const char *path, const char delim, size_t size)
|
||||
{
|
||||
size_t copied = strlcpy(out_path, dir, size);
|
||||
rarch_assert(copied < size+1);
|
||||
retro_assert(copied < size+1);
|
||||
|
||||
out_path[copied] = delim;
|
||||
out_path[copied+1] = '\0';
|
||||
|
||||
rarch_assert(strlcat(out_path, path, size) < size);
|
||||
retro_assert(strlcat(out_path, path, size) < size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -634,7 +645,7 @@ void fill_short_pathname_representation(char* out_rep,
|
|||
* We check whether something is actually
|
||||
* after the hash to avoid going over the buffer.
|
||||
*/
|
||||
rarch_assert(strlen(last_hash) > 1);
|
||||
retro_assert(strlen(last_hash) > 1);
|
||||
strlcpy(out_rep, last_hash + 1, size);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <compat/posix_string.h>
|
||||
# ifdef _MSC_VER
|
||||
# define setmode _setmode
|
||||
# endif
|
||||
|
@ -78,14 +77,14 @@ struct RDIR
|
|||
|
||||
struct RDIR *retro_opendir(const char *name)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
char path_buf[1024];
|
||||
#endif
|
||||
struct RDIR *rdir = (struct RDIR*)calloc(1, sizeof(*rdir));
|
||||
|
||||
if (!rdir)
|
||||
return NULL;
|
||||
|
||||
(void)path_buf;
|
||||
|
||||
#if defined(_WIN32)
|
||||
snprintf(path_buf, sizeof(path_buf), "%s\\*", name);
|
||||
rdir->directory = FindFirstFile(path_buf, &rdir->entry);
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <errno.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <compat/posix_string.h>
|
||||
# ifdef _MSC_VER
|
||||
# define setmode _setmode
|
||||
# endif
|
||||
|
@ -64,11 +63,8 @@
|
|||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#include <retro_log.h>
|
||||
#endif
|
||||
|
||||
#include <retro_file.h>
|
||||
#include <memmap.h>
|
||||
|
||||
#if 1
|
||||
#define HAVE_BUFFERED_IO 1
|
||||
|
@ -76,13 +72,20 @@
|
|||
|
||||
struct RFILE
|
||||
{
|
||||
unsigned hints;
|
||||
#if defined(PSP) || defined(VITA)
|
||||
SceUID fd;
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
int fd;
|
||||
#elif defined(HAVE_BUFFERED_IO)
|
||||
FILE *fd;
|
||||
#else
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
FILE *fp;
|
||||
#endif
|
||||
#if defined(HAVE_MMAP)
|
||||
uint8_t *mapped;
|
||||
uint64_t mappos;
|
||||
uint64_t mapsize;
|
||||
#endif
|
||||
int fd;
|
||||
#endif
|
||||
};
|
||||
|
@ -93,9 +96,11 @@ int retro_get_fd(RFILE *stream)
|
|||
return -1;
|
||||
#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__)
|
||||
return stream->fd;
|
||||
#elif defined(HAVE_BUFFERED_IO)
|
||||
return fileno(stream->fd);
|
||||
#else
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
return fileno(stream->fp);
|
||||
#endif
|
||||
return stream->fd;
|
||||
#endif
|
||||
}
|
||||
|
@ -114,7 +119,16 @@ RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len)
|
|||
(void)mode_int;
|
||||
(void)flags;
|
||||
|
||||
switch (mode)
|
||||
stream->hints = mode;
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
if (stream->hints & RFILE_HINT_MMAP && (stream->hints & 0xff) == RFILE_MODE_READ)
|
||||
stream->hints |= RFILE_HINT_UNBUFFERED;
|
||||
else
|
||||
#endif
|
||||
stream->hints &= ~RFILE_HINT_MMAP;
|
||||
|
||||
switch (mode & 0xff)
|
||||
{
|
||||
case RFILE_MODE_READ:
|
||||
#if defined(VITA) || defined(PSP)
|
||||
|
@ -123,9 +137,12 @@ RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len)
|
|||
#elif defined(__CELLOS_LV2__)
|
||||
mode_int = 0777;
|
||||
flags = CELL_FS_O_RDONLY;
|
||||
#elif defined(HAVE_BUFFERED_IO)
|
||||
mode_str = "rb";
|
||||
#else
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
mode_str = "rb";
|
||||
#endif
|
||||
/* No "else" here */
|
||||
flags = O_RDONLY;
|
||||
#endif
|
||||
break;
|
||||
|
@ -136,10 +153,18 @@ RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len)
|
|||
#elif defined(__CELLOS_LV2__)
|
||||
mode_int = 0777;
|
||||
flags = CELL_FS_O_CREAT | CELL_FS_O_WRONLY | CELL_FS_O_TRUNC;
|
||||
#elif defined(HAVE_BUFFERED_IO)
|
||||
mode_str = "wb";
|
||||
#else
|
||||
flags = O_WRONLY | O_CREAT | O_TRUNC | S_IRUSR | S_IWUSR;
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
mode_str = "wb";
|
||||
#endif
|
||||
else
|
||||
{
|
||||
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
#ifndef _WIN32
|
||||
flags |= S_IRUSR | S_IWUSR;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case RFILE_MODE_READ_WRITE:
|
||||
|
@ -149,13 +174,18 @@ RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len)
|
|||
#elif defined(__CELLOS_LV2__)
|
||||
mode_int = 0777;
|
||||
flags = CELL_FS_O_RDWR;
|
||||
#elif defined(HAVE_BUFFERED_IO)
|
||||
mode_str = "w+";
|
||||
#else
|
||||
flags = O_RDWR;
|
||||
#ifdef _WIN32
|
||||
flags |= O_BINARY;
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
mode_str = "w+";
|
||||
#endif
|
||||
else
|
||||
{
|
||||
flags = O_RDWR;
|
||||
#ifdef _WIN32
|
||||
flags |= O_BINARY;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -164,16 +194,42 @@ RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len)
|
|||
stream->fd = sceIoOpen(path, flags, mode_int);
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
cellFsOpen(path, flags, &stream->fd, NULL, 0);
|
||||
#elif defined(HAVE_BUFFERED_IO)
|
||||
stream->fd = fopen(path, mode_str);
|
||||
#else
|
||||
stream->fd = open(path, flags);
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
{
|
||||
stream->fp = fopen(path, mode_str);
|
||||
if (!stream->fp)
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
stream->fd = open(path, flags);
|
||||
if (stream->fd == -1)
|
||||
goto error;
|
||||
#ifdef HAVE_MMAP
|
||||
if (stream->hints & RFILE_HINT_MMAP)
|
||||
{
|
||||
stream->mappos = 0;
|
||||
stream->mapped = NULL;
|
||||
stream->mapsize = retro_fseek(stream, 0, SEEK_END);
|
||||
|
||||
if (stream->mapsize == (uint64_t)-1)
|
||||
goto error;
|
||||
|
||||
retro_frewind(stream);
|
||||
|
||||
stream->mapped = (uint8_t*)mmap((void*)0, stream->mapsize, PROT_READ, MAP_SHARED, stream->fd, 0);
|
||||
|
||||
if (stream->mapped == MAP_FAILED)
|
||||
stream->hints &= ~RFILE_HINT_MMAP;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if (!stream->fd)
|
||||
goto error;
|
||||
#else
|
||||
#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__)
|
||||
if (stream->fd == -1)
|
||||
goto error;
|
||||
#endif
|
||||
|
@ -203,13 +259,52 @@ ssize_t retro_fseek(RFILE *stream, ssize_t offset, int whence)
|
|||
if (cellFsLseek(stream->fd, offset, whence, &pos) != CELL_FS_SUCCEEDED)
|
||||
return -1;
|
||||
return 0;
|
||||
#elif defined(HAVE_BUFFERED_IO)
|
||||
return fseek(stream->fd, (long)offset, whence);
|
||||
#else
|
||||
ret = lseek(stream->fd, offset, whence);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
return fseek(stream->fp, (long)offset, whence);
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_MMAP
|
||||
/* Need to check stream->mapped because this function is called in retro_fopen() */
|
||||
if (stream->mapped && stream->hints & RFILE_HINT_MMAP)
|
||||
{
|
||||
/* fseek() returns error on under/overflow but allows cursor > EOF for
|
||||
read-only file descriptors. */
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
if (offset < 0)
|
||||
return -1;
|
||||
|
||||
stream->mappos = offset;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
if ((offset < 0 && stream->mappos + offset > stream->mappos) ||
|
||||
(offset > 0 && stream->mappos + offset < stream->mappos))
|
||||
return -1;
|
||||
|
||||
stream->mappos += offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
if (stream->mapsize + offset < stream->mapsize)
|
||||
return -1;
|
||||
|
||||
stream->mappos = stream->mapsize + offset;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return stream->mappos;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = lseek(stream->fd, offset, whence);
|
||||
return ret < 0 ? -1 : ret;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -224,10 +319,19 @@ ssize_t retro_ftell(RFILE *stream)
|
|||
if (cellFsLseek(stream->fd, 0, CELL_FS_SEEK_CUR, &pos) != CELL_FS_SUCCEEDED)
|
||||
return -1;
|
||||
return 0;
|
||||
#elif defined(HAVE_BUFFERED_IO)
|
||||
return ftell(stream->fd);
|
||||
#else
|
||||
return lseek(stream->fd, 0, SEEK_CUR);
|
||||
#else
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
return ftell(stream->fp);
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_MMAP
|
||||
/* Need to check stream->mapped because this function is called in retro_fopen() */
|
||||
if (stream->mapped && stream->hints & RFILE_HINT_MMAP)
|
||||
return stream->mappos;
|
||||
else
|
||||
#endif
|
||||
return lseek(stream->fd, 0, SEEK_CUR);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -238,7 +342,7 @@ void retro_frewind(RFILE *stream)
|
|||
|
||||
ssize_t retro_fread(RFILE *stream, void *s, size_t len)
|
||||
{
|
||||
if (!stream)
|
||||
if (!stream || !s)
|
||||
return -1;
|
||||
#if defined(VITA) || defined(PSP)
|
||||
return sceIoRead(stream->fd, s, len);
|
||||
|
@ -247,10 +351,29 @@ ssize_t retro_fread(RFILE *stream, void *s, size_t len)
|
|||
if (cellFsRead(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED)
|
||||
return -1;
|
||||
return bytes_written;
|
||||
#elif defined(HAVE_BUFFERED_IO)
|
||||
return fread(s, 1, len, stream->fd);
|
||||
#else
|
||||
return read(stream->fd, s, len);
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
return fread(s, 1, len, stream->fp);
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_MMAP
|
||||
if (stream->hints & RFILE_HINT_MMAP)
|
||||
{
|
||||
if (stream->mappos > stream->mapsize)
|
||||
return -1;
|
||||
|
||||
if (stream->mappos + len > stream->mapsize)
|
||||
len = stream->mapsize - stream->mappos;
|
||||
|
||||
memcpy(s, &stream->mapped[stream->mappos], len);
|
||||
stream->mappos += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return read(stream->fd, s, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -265,10 +388,18 @@ ssize_t retro_fwrite(RFILE *stream, const void *s, size_t len)
|
|||
if (cellFsWrite(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED)
|
||||
return -1;
|
||||
return bytes_written;
|
||||
#elif defined(HAVE_BUFFERED_IO)
|
||||
return fwrite(s, 1, len, stream->fd);
|
||||
#else
|
||||
return write(stream->fd, s, len);
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
return fwrite(s, 1, len, stream->fp);
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_MMAP
|
||||
if (stream->hints & RFILE_HINT_MMAP)
|
||||
return -1;
|
||||
else
|
||||
#endif
|
||||
return write(stream->fd, s, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -283,12 +414,22 @@ int retro_fclose(RFILE *stream)
|
|||
#elif defined(__CELLOS_LV2__)
|
||||
if (stream->fd > 0)
|
||||
cellFsClose(stream->fd);
|
||||
#elif defined(HAVE_BUFFERED_IO)
|
||||
if (stream->fd)
|
||||
fclose(stream->fd);
|
||||
#else
|
||||
if (stream->fd > 0)
|
||||
close(stream->fd);
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||
{
|
||||
if (stream->fp)
|
||||
fclose(stream->fp);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_MMAP
|
||||
if (stream->hints & RFILE_HINT_MMAP)
|
||||
munmap(stream->mapped, stream->mapsize);
|
||||
#endif
|
||||
|
||||
if (stream->fd > 0)
|
||||
close(stream->fd);
|
||||
#endif
|
||||
free(stream);
|
||||
|
||||
|
@ -313,7 +454,14 @@ int retro_read_file(const char *path, void **buf, ssize_t *len)
|
|||
RFILE *file = retro_fopen(path, RFILE_MODE_READ, -1);
|
||||
|
||||
if (!file)
|
||||
{
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
fprintf(stderr, "%s: Failed to open %s: %s\n", __FUNCTION__, path, strerror(errno));
|
||||
#else
|
||||
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
||||
#endif
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (retro_fseek(file, 0, SEEK_END) != 0)
|
||||
goto error;
|
||||
|
@ -329,17 +477,18 @@ int retro_read_file(const char *path, void **buf, ssize_t *len)
|
|||
if (!content_buf)
|
||||
goto error;
|
||||
|
||||
if ((ret = retro_fread(file, content_buf, content_buf_size)) < content_buf_size)
|
||||
ret = retro_fread(file, content_buf, content_buf_size);
|
||||
if (ret < 0)
|
||||
{
|
||||
#ifdef RARCH_INTERNAL
|
||||
RARCH_WARN("Didn't read whole file: %s.\n", path);
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
fprintf(stderr, "%s: Failed to read %s: %s\n", __FUNCTION__, path, strerror(errno));
|
||||
#else
|
||||
printf("Didn't read whole file: %s.\n", path);
|
||||
fprintf(stderr, "Failed to read %s: %s\n", path, strerror(errno));
|
||||
#endif
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!content_buf)
|
||||
goto error;
|
||||
retro_fclose(file);
|
||||
|
||||
*buf = content_buf;
|
||||
|
||||
|
@ -347,16 +496,14 @@ int retro_read_file(const char *path, void **buf, ssize_t *len)
|
|||
* Will only work with sane character formatting (Unix). */
|
||||
((char*)content_buf)[content_buf_size] = '\0';
|
||||
|
||||
if (retro_fclose(file) != 0)
|
||||
printf("Failed to close file stream.\n");
|
||||
|
||||
if (len)
|
||||
*len = ret;
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
retro_fclose(file);
|
||||
if (file)
|
||||
retro_fclose(file);
|
||||
if (content_buf)
|
||||
free(content_buf);
|
||||
if (len)
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
#endif
|
||||
|
||||
#if defined(VITA)
|
||||
#define FIO_SO_ISDIR PSP2_S_ISDIR
|
||||
#define FIO_S_ISDIR PSP2_S_ISDIR
|
||||
#endif
|
||||
|
||||
#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP)
|
||||
|
@ -79,19 +79,31 @@ enum stat_mode
|
|||
IS_VALID
|
||||
};
|
||||
|
||||
static bool path_stat(const char *path, enum stat_mode mode)
|
||||
static bool path_stat(const char *path, enum stat_mode mode, int32_t *size)
|
||||
{
|
||||
#if defined(VITA) || defined(PSP)
|
||||
SceIoStat buf;
|
||||
if (sceIoGetstat(path, &buf) < 0)
|
||||
char *tmp = strdup(path);
|
||||
size_t len = strlen(tmp);
|
||||
if (tmp[len-1] == '/')
|
||||
tmp[len-1]='\0';
|
||||
|
||||
if (sceIoGetstat(tmp, &buf) < 0)
|
||||
{
|
||||
free(tmp);
|
||||
return false;
|
||||
}
|
||||
free(tmp);
|
||||
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
CellFsStat buf;
|
||||
if (cellFsStat(path, &buf) < 0)
|
||||
return false;
|
||||
#elif defined(_WIN32)
|
||||
DWORD ret = GetFileAttributes(path);
|
||||
if (ret == INVALID_FILE_ATTRIBUTES)
|
||||
WIN32_FILE_ATTRIBUTE_DATA file_info;
|
||||
GET_FILEEX_INFO_LEVELS fInfoLevelId = GetFileExInfoStandard;
|
||||
DWORD ret = GetFileAttributesEx(path, fInfoLevelId, &file_info);
|
||||
if (ret == 0)
|
||||
return false;
|
||||
#else
|
||||
struct stat buf;
|
||||
|
@ -99,15 +111,23 @@ static bool path_stat(const char *path, enum stat_mode mode)
|
|||
return false;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (size)
|
||||
*size = file_info.nFileSizeLow;
|
||||
#else
|
||||
if (size)
|
||||
*size = buf.st_size;
|
||||
#endif
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case IS_DIRECTORY:
|
||||
#if defined(VITA) || defined(PSP)
|
||||
return FIO_SO_ISDIR(buf.st_mode);
|
||||
return FIO_S_ISDIR(buf.st_mode);
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
return ((buf.st_mode & S_IFMT) == S_IFDIR);
|
||||
#elif defined(_WIN32)
|
||||
return (ret & FILE_ATTRIBUTE_DIRECTORY);
|
||||
return (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||
#else
|
||||
return S_ISDIR(buf.st_mode);
|
||||
#endif
|
||||
|
@ -134,17 +154,26 @@ static bool path_stat(const char *path, enum stat_mode mode)
|
|||
*/
|
||||
bool path_is_directory(const char *path)
|
||||
{
|
||||
return path_stat(path, IS_DIRECTORY);
|
||||
return path_stat(path, IS_DIRECTORY, NULL);
|
||||
}
|
||||
|
||||
bool path_is_character_special(const char *path)
|
||||
{
|
||||
return path_stat(path, IS_CHARACTER_SPECIAL);
|
||||
return path_stat(path, IS_CHARACTER_SPECIAL, NULL);
|
||||
}
|
||||
|
||||
bool stat_is_valid(const char *path)
|
||||
bool path_is_valid(const char *path)
|
||||
{
|
||||
return path_stat(path, IS_VALID);
|
||||
return path_stat(path, IS_VALID, NULL);
|
||||
}
|
||||
|
||||
int32_t path_get_size(const char *path)
|
||||
{
|
||||
int32_t filesize = 0;
|
||||
if (path_stat(path, IS_VALID, &filesize))
|
||||
return filesize;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -171,6 +200,9 @@ bool mkdir_norecurse(const char *dir)
|
|||
#if defined(VITA)
|
||||
if ((ret == SCE_ERROR_ERRNO_EEXIST) && path_is_directory(dir))
|
||||
ret = 0;
|
||||
#elif defined(PSP) || defined(_3DS)
|
||||
if ((ret == -1) && path_is_directory(dir))
|
||||
ret = 0;
|
||||
#else
|
||||
if (ret < 0 && errno == EEXIST && path_is_directory(dir))
|
||||
ret = 0;
|
||||
|
|
|
@ -0,0 +1,316 @@
|
|||
/* Copyright (C) 2010-2015 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (jsonsax.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 <setjmp.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <retro_inline.h>
|
||||
#include <formats/jsonsax.h>
|
||||
|
||||
#ifdef JSONSAX_ERRORS
|
||||
const char* jsonsax_errors[] =
|
||||
{
|
||||
"Ok",
|
||||
"Interrupted",
|
||||
"Missing key",
|
||||
"Unterminated key",
|
||||
"Missing value",
|
||||
"Unterminated object",
|
||||
"Unterminated array",
|
||||
"Unterminated string",
|
||||
"Invalid value"
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const jsonsax_handlers_t* handlers;
|
||||
|
||||
const char* json;
|
||||
void* ud;
|
||||
jmp_buf env;
|
||||
}
|
||||
state_t;
|
||||
|
||||
static INLINE void skip_spaces( state_t* state )
|
||||
{
|
||||
while ( isspace( *state->json ) )
|
||||
state->json++;
|
||||
}
|
||||
|
||||
static INLINE void skip_digits( state_t* state )
|
||||
{
|
||||
while ( isdigit( *state->json ) )
|
||||
state->json++;
|
||||
}
|
||||
|
||||
#define HANDLE_0( event ) \
|
||||
do { \
|
||||
if ( state->handlers->event && state->handlers->event( state->ud ) ) \
|
||||
longjmp( state->env, JSONSAX_INTERRUPTED ); \
|
||||
} while ( 0 )
|
||||
|
||||
#define HANDLE_1( event, arg1 ) \
|
||||
do { \
|
||||
if ( state->handlers->event && state->handlers->event( state->ud, arg1 ) ) \
|
||||
longjmp( state->env, JSONSAX_INTERRUPTED ); \
|
||||
} while ( 0 )
|
||||
|
||||
#define HANDLE_2( event, arg1, arg2 ) \
|
||||
do { \
|
||||
if ( state->handlers->event && state->handlers->event( state->ud, arg1, arg2 ) ) \
|
||||
longjmp( state->env, JSONSAX_INTERRUPTED ); \
|
||||
} while ( 0 )
|
||||
|
||||
static void jsonx_parse_value(state_t* state);
|
||||
|
||||
static void jsonx_parse_object( state_t* state )
|
||||
{
|
||||
state->json++; /* we're sure the current character is a '{' */
|
||||
skip_spaces( state );
|
||||
HANDLE_0( start_object );
|
||||
|
||||
while ( *state->json != '}' )
|
||||
{
|
||||
const char *name = NULL;
|
||||
if ( *state->json != '"' )
|
||||
longjmp( state->env, JSONSAX_MISSING_KEY );
|
||||
|
||||
name = ++state->json;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
const char* quote = strchr( state->json, '"' );
|
||||
|
||||
if ( !quote )
|
||||
longjmp( state->env, JSONSAX_UNTERMINATED_KEY );
|
||||
|
||||
state->json = quote + 1;
|
||||
|
||||
if ( quote[ -1 ] != '\\' )
|
||||
break;
|
||||
}
|
||||
|
||||
HANDLE_2( key, name, state->json - name - 1 );
|
||||
skip_spaces( state );
|
||||
|
||||
if ( *state->json != ':' )
|
||||
longjmp( state->env, JSONSAX_MISSING_VALUE );
|
||||
|
||||
state->json++;
|
||||
skip_spaces( state );
|
||||
jsonx_parse_value( state );
|
||||
skip_spaces( state );
|
||||
|
||||
if ( *state->json != ',' )
|
||||
break;
|
||||
|
||||
state->json++;
|
||||
skip_spaces( state );
|
||||
}
|
||||
|
||||
if ( *state->json != '}' )
|
||||
longjmp( state->env, JSONSAX_UNTERMINATED_OBJECT );
|
||||
|
||||
state->json++;
|
||||
HANDLE_0( end_object );
|
||||
}
|
||||
|
||||
static void jsonx_parse_array(state_t* state)
|
||||
{
|
||||
unsigned int ndx = 0;
|
||||
|
||||
state->json++; /* we're sure the current character is a '[' */
|
||||
skip_spaces( state );
|
||||
HANDLE_0( start_array );
|
||||
|
||||
while ( *state->json != ']' )
|
||||
{
|
||||
HANDLE_1( index, ndx++ );
|
||||
jsonx_parse_value( state );
|
||||
skip_spaces( state );
|
||||
|
||||
if ( *state->json != ',' )
|
||||
break;
|
||||
|
||||
state->json++;
|
||||
skip_spaces( state );
|
||||
}
|
||||
|
||||
if ( *state->json != ']' )
|
||||
longjmp( state->env, JSONSAX_UNTERMINATED_ARRAY );
|
||||
|
||||
state->json++;
|
||||
HANDLE_0( end_array );
|
||||
}
|
||||
|
||||
static void jsonx_parse_string(state_t* state)
|
||||
{
|
||||
const char* string = ++state->json;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
const char* quote = strchr( state->json, '"' );
|
||||
|
||||
if ( !quote )
|
||||
longjmp( state->env, JSONSAX_UNTERMINATED_STRING );
|
||||
|
||||
state->json = quote + 1;
|
||||
|
||||
if ( quote[ -1 ] != '\\' )
|
||||
break;
|
||||
}
|
||||
|
||||
HANDLE_2( string, string, state->json - string - 1 );
|
||||
}
|
||||
|
||||
static void jsonx_parse_boolean(state_t* state)
|
||||
{
|
||||
if ( !strncmp( state->json, "true", 4 ) )
|
||||
{
|
||||
state->json += 4;
|
||||
HANDLE_1( boolean, 1 );
|
||||
}
|
||||
else if ( !strncmp( state->json, "false", 5 ) )
|
||||
{
|
||||
state->json += 5;
|
||||
HANDLE_1( boolean, 0 );
|
||||
}
|
||||
else
|
||||
longjmp( state->env, JSONSAX_INVALID_VALUE );
|
||||
}
|
||||
|
||||
static void jsonx_parse_null(state_t* state)
|
||||
{
|
||||
if ( !strncmp( state->json + 1, "ull", 3 ) ) /* we're sure the current character is a 'n' */
|
||||
{
|
||||
state->json += 4;
|
||||
HANDLE_0( null );
|
||||
}
|
||||
else
|
||||
longjmp( state->env, JSONSAX_INVALID_VALUE );
|
||||
}
|
||||
|
||||
static void jsonx_parse_number(state_t* state)
|
||||
{
|
||||
const char* number = state->json;
|
||||
|
||||
if ( *state->json == '-' )
|
||||
state->json++;
|
||||
|
||||
if ( !isdigit( *state->json ) )
|
||||
longjmp( state->env, JSONSAX_INVALID_VALUE );
|
||||
|
||||
skip_digits( state );
|
||||
|
||||
if ( *state->json == '.' )
|
||||
{
|
||||
state->json++;
|
||||
|
||||
if ( !isdigit( *state->json ) )
|
||||
longjmp( state->env, JSONSAX_INVALID_VALUE );
|
||||
|
||||
skip_digits( state );
|
||||
}
|
||||
|
||||
if ( *state->json == 'e' || *state->json == 'E' )
|
||||
{
|
||||
state->json++;
|
||||
|
||||
if ( *state->json == '-' || *state->json == '+' )
|
||||
state->json++;
|
||||
|
||||
if ( !isdigit( *state->json ) )
|
||||
longjmp( state->env, JSONSAX_INVALID_VALUE );
|
||||
|
||||
skip_digits( state );
|
||||
}
|
||||
|
||||
HANDLE_2( number, number, state->json - number );
|
||||
}
|
||||
|
||||
static void jsonx_parse_value(state_t* state)
|
||||
{
|
||||
skip_spaces( state );
|
||||
|
||||
switch ( *state->json )
|
||||
{
|
||||
case '{':
|
||||
jsonx_parse_object(state);
|
||||
break;
|
||||
case '[':
|
||||
jsonx_parse_array( state );
|
||||
break;
|
||||
case '"':
|
||||
jsonx_parse_string( state );
|
||||
break;
|
||||
case 't':
|
||||
case 'f':
|
||||
jsonx_parse_boolean( state );
|
||||
break;
|
||||
case 'n':
|
||||
jsonx_parse_null( state );
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '-':
|
||||
jsonx_parse_number( state );
|
||||
break;
|
||||
|
||||
default:
|
||||
longjmp( state->env, JSONSAX_INVALID_VALUE );
|
||||
}
|
||||
}
|
||||
|
||||
int jsonsax_parse( const char* json, const jsonsax_handlers_t* handlers, void* userdata )
|
||||
{
|
||||
state_t state;
|
||||
int res;
|
||||
|
||||
state.json = json;
|
||||
state.handlers = handlers;
|
||||
state.ud = userdata;
|
||||
|
||||
if ( ( res = setjmp( state.env ) ) == 0 )
|
||||
{
|
||||
if ( handlers->start_document )
|
||||
handlers->start_document( userdata );
|
||||
|
||||
jsonx_parse_value(&state);
|
||||
|
||||
if ( handlers->end_document )
|
||||
handlers->end_document( userdata );
|
||||
|
||||
res = JSONSAX_OK;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
|
@ -11,9 +11,10 @@ endif
|
|||
SOURCES_C := rpng.c \
|
||||
rpng_encode.c \
|
||||
rpng_test.c \
|
||||
../../compat/compat.c \
|
||||
../../compat/compat_strl.c \
|
||||
../../file/nbio/nbio_stdio.c \
|
||||
../../file/file_extract.c \
|
||||
../../file/file_archive.c \
|
||||
../../file/file_archive_zlib.c \
|
||||
../../file/file_path.c \
|
||||
../../file/retro_file.c \
|
||||
../../string/string_list.c
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <boolean.h>
|
||||
#include <file/nbio.h>
|
||||
#include <formats/rpng.h>
|
||||
#include <file/file_extract.h>
|
||||
#include <file/file_archive.h>
|
||||
|
||||
#include "rpng_internal.h"
|
||||
|
||||
|
@ -112,7 +112,7 @@ struct rpng_process_t
|
|||
unsigned pos;
|
||||
} pass;
|
||||
void *stream;
|
||||
zlib_file_handle_t handle;
|
||||
const struct file_archive_file_backend *stream_backend;
|
||||
};
|
||||
|
||||
struct rpng
|
||||
|
@ -220,9 +220,9 @@ static bool png_process_ihdr(struct png_ihdr *ihdr)
|
|||
#ifdef RPNG_TEST
|
||||
fprintf(stderr, "IHDR: (%u x %u), bpc = %u, palette = %s, color = %s, alpha = %s, adam7 = %s.\n",
|
||||
ihdr->width, ihdr->height,
|
||||
ihdr->depth, ihdr->color_type == PNG_IHDR_COLOR_PLT ? "yes" : "no",
|
||||
ihdr->color_type & PNG_IHDR_COLOR_RGB ? "yes" : "no",
|
||||
ihdr->color_type & PNG_IHDR_COLOR_GRAY_ALPHA ? "yes" : "no",
|
||||
ihdr->depth, (ihdr->color_type == PNG_IHDR_COLOR_PLT) ? "yes" : "no",
|
||||
(ihdr->color_type & PNG_IHDR_COLOR_RGB) ? "yes" : "no",
|
||||
(ihdr->color_type & PNG_IHDR_COLOR_GRAY_ALPHA) ? "yes" : "no",
|
||||
ihdr->interlace == 1 ? "yes" : "no");
|
||||
#endif
|
||||
|
||||
|
@ -462,7 +462,7 @@ static int png_reverse_filter_init(const struct png_ihdr *ihdr,
|
|||
png_pass_geom(&pngp->ihdr, pngp->pass.width,
|
||||
pngp->pass.height, NULL, NULL, &pngp->pass.size);
|
||||
|
||||
if (pngp->pass.size > zlib_stream_get_total_out(pngp->stream))
|
||||
if (pngp->pass.size > pngp->stream_backend->stream_get_total_out(pngp->stream))
|
||||
{
|
||||
free(pngp->data);
|
||||
return -1;
|
||||
|
@ -478,7 +478,7 @@ static int png_reverse_filter_init(const struct png_ihdr *ihdr,
|
|||
|
||||
png_pass_geom(ihdr, ihdr->width, ihdr->height, &pngp->bpp, &pngp->pitch, &pass_size);
|
||||
|
||||
if (zlib_stream_get_total_out(pngp->stream) < pass_size)
|
||||
if (pngp->stream_backend->stream_get_total_out(pngp->stream) < pass_size)
|
||||
return -1;
|
||||
|
||||
pngp->restore_buf_size = 0;
|
||||
|
@ -635,7 +635,7 @@ static int png_reverse_filter_adam7_iterate(uint32_t **data_,
|
|||
pngp->inflate_buf += pngp->pass.size;
|
||||
pngp->adam7_restore_buf_size += pngp->pass.size;
|
||||
|
||||
zlib_stream_decrement_total_out(pngp->stream, pngp->pass.size);
|
||||
pngp->stream_backend->stream_decrement_total_out(pngp->stream, pngp->pass.size);
|
||||
|
||||
png_reverse_filter_adam7_deinterlace_pass(data,
|
||||
ihdr, pngp->data, pngp->pass.width, pngp->pass.height, &passes[pngp->pass.pos]);
|
||||
|
@ -693,13 +693,13 @@ static int rpng_load_image_argb_process_inflate_init(rpng_t *rpng,
|
|||
uint32_t **data, unsigned *width, unsigned *height)
|
||||
{
|
||||
int zstatus;
|
||||
bool to_continue = (zlib_stream_get_avail_in(rpng->process.stream) > 0
|
||||
&& zlib_stream_get_avail_out(rpng->process.stream) > 0);
|
||||
bool to_continue = (rpng->process.stream_backend->stream_get_avail_in(rpng->process.stream) > 0
|
||||
&& rpng->process.stream_backend->stream_get_avail_out(rpng->process.stream) > 0);
|
||||
|
||||
if (!to_continue)
|
||||
goto end;
|
||||
|
||||
zstatus = zlib_inflate_data_to_file_iterate(rpng->process.stream);
|
||||
zstatus = rpng->process.stream_backend->stream_decompress_data_to_file_iterate(rpng->process.stream);
|
||||
|
||||
switch (zstatus)
|
||||
{
|
||||
|
@ -714,7 +714,7 @@ static int rpng_load_image_argb_process_inflate_init(rpng_t *rpng,
|
|||
return 0;
|
||||
|
||||
end:
|
||||
zlib_stream_free(rpng->process.stream);
|
||||
rpng->process.stream_backend->stream_free(rpng->process.stream);
|
||||
|
||||
*width = rpng->ihdr.width;
|
||||
*height = rpng->ihdr.height;
|
||||
|
@ -741,7 +741,7 @@ end:
|
|||
return 1;
|
||||
|
||||
error:
|
||||
zlib_stream_free(rpng->process.stream);
|
||||
rpng->process.stream_backend->stream_free(rpng->process.stream);
|
||||
|
||||
false_end:
|
||||
rpng->process.inflate_initialized = false;
|
||||
|
@ -786,19 +786,19 @@ static bool rpng_load_image_argb_process_init(rpng_t *rpng,
|
|||
if (rpng->ihdr.interlace == 1) /* To be sure. */
|
||||
rpng->process.inflate_buf_size *= 2;
|
||||
|
||||
rpng->process.stream = zlib_stream_new();
|
||||
rpng->process.stream = rpng->process.stream_backend->stream_new();
|
||||
|
||||
if (!rpng->process.stream)
|
||||
return false;
|
||||
|
||||
if (!zlib_inflate_init(rpng->process.stream))
|
||||
if (!rpng->process.stream_backend->stream_decompress_init(rpng->process.stream))
|
||||
return false;
|
||||
|
||||
rpng->process.inflate_buf = (uint8_t*)malloc(rpng->process.inflate_buf_size);
|
||||
if (!rpng->process.inflate_buf)
|
||||
return false;
|
||||
|
||||
zlib_set_stream(
|
||||
rpng->process.stream_backend->stream_set(
|
||||
rpng->process.stream,
|
||||
rpng->idat_buf.size,
|
||||
rpng->process.inflate_buf_size,
|
||||
|
@ -953,6 +953,9 @@ int rpng_nbio_load_image_argb_process(rpng_t *rpng,
|
|||
{
|
||||
if (!rpng->process.initialized)
|
||||
{
|
||||
if (!rpng->process.stream_backend)
|
||||
rpng->process.stream_backend = file_archive_get_default_file_backend();
|
||||
|
||||
if (!rpng_load_image_argb_process_init(rpng, data, width,
|
||||
height))
|
||||
return PNG_PROCESS_ERROR;
|
||||
|
@ -982,7 +985,7 @@ void rpng_nbio_load_image_free(rpng_t *rpng)
|
|||
free(rpng->process.inflate_buf);
|
||||
if (rpng->process.stream)
|
||||
{
|
||||
zlib_stream_free(rpng->process.stream);
|
||||
rpng->process.stream_backend->stream_free(rpng->process.stream);
|
||||
free(rpng->process.stream);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,9 @@ static void dword_write_be(uint8_t *buf, uint32_t val)
|
|||
static bool png_write_crc(RFILE *file, const uint8_t *data, size_t size)
|
||||
{
|
||||
uint8_t crc_raw[4] = {0};
|
||||
uint32_t crc = zlib_crc32_calculate(data, size);
|
||||
const struct file_archive_file_backend *stream_backend =
|
||||
file_archive_get_default_file_backend();
|
||||
uint32_t crc = stream_backend->stream_crc_calculate(0, data, size);
|
||||
|
||||
dword_write_be(crc_raw, crc);
|
||||
return retro_fwrite(file, crc_raw, sizeof(crc_raw)) == sizeof(crc_raw);
|
||||
|
@ -213,6 +215,7 @@ static bool rpng_save_image(const char *path,
|
|||
bool ret = true;
|
||||
struct png_ihdr ihdr = {0};
|
||||
|
||||
const struct file_archive_file_backend *stream_backend = NULL;
|
||||
size_t encode_buf_size = 0;
|
||||
uint8_t *encode_buf = NULL;
|
||||
uint8_t *deflate_buf = NULL;
|
||||
|
@ -224,11 +227,12 @@ static bool rpng_save_image(const char *path,
|
|||
uint8_t *prev_encoded = NULL;
|
||||
uint8_t *encode_target = NULL;
|
||||
void *stream = NULL;
|
||||
|
||||
RFILE *file = retro_fopen(path, RFILE_MODE_WRITE, -1);
|
||||
RFILE *file = retro_fopen(path, RFILE_MODE_WRITE, -1);
|
||||
if (!file)
|
||||
GOTO_END_ERROR();
|
||||
|
||||
stream_backend = file_archive_get_default_file_backend();
|
||||
|
||||
if (retro_fwrite(file, png_magic, sizeof(png_magic)) != sizeof(png_magic))
|
||||
GOTO_END_ERROR();
|
||||
|
||||
|
@ -321,31 +325,31 @@ static bool rpng_save_image(const char *path,
|
|||
if (!deflate_buf)
|
||||
GOTO_END_ERROR();
|
||||
|
||||
stream = zlib_stream_new();
|
||||
stream = stream_backend->stream_new();
|
||||
|
||||
if (!stream)
|
||||
GOTO_END_ERROR();
|
||||
|
||||
zlib_set_stream(
|
||||
stream_backend->stream_set(
|
||||
stream,
|
||||
encode_buf_size,
|
||||
encode_buf_size * 2,
|
||||
encode_buf,
|
||||
deflate_buf + 8);
|
||||
|
||||
zlib_deflate_init(stream, 9);
|
||||
stream_backend->stream_compress_init(stream, 9);
|
||||
|
||||
if (zlib_deflate_data_to_file(stream) != 1)
|
||||
if (stream_backend->stream_compress_data_to_file(stream) != 1)
|
||||
{
|
||||
zlib_stream_deflate_free(stream);
|
||||
stream_backend->stream_compress_free(stream);
|
||||
GOTO_END_ERROR();
|
||||
}
|
||||
|
||||
zlib_stream_deflate_free(stream);
|
||||
stream_backend->stream_compress_free(stream);
|
||||
|
||||
memcpy(deflate_buf + 4, "IDAT", 4);
|
||||
dword_write_be(deflate_buf + 0, zlib_stream_get_total_out(stream));
|
||||
if (!png_write_idat(file, deflate_buf, zlib_stream_get_total_out(stream) + 8))
|
||||
dword_write_be(deflate_buf + 0, stream_backend->stream_get_total_out(stream));
|
||||
if (!png_write_idat(file, deflate_buf, stream_backend->stream_get_total_out(stream) + 8))
|
||||
GOTO_END_ERROR();
|
||||
|
||||
if (!png_write_iend(file))
|
||||
|
@ -362,7 +366,7 @@ end:
|
|||
free(avg_filtered);
|
||||
free(paeth_filtered);
|
||||
|
||||
zlib_stream_free(stream);
|
||||
stream_backend->stream_free(stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ bool rtga_image_load_shift(uint8_t *buf,
|
|||
const uint8_t *tmp = NULL;
|
||||
struct texture_image *out_img = (struct texture_image*)data;
|
||||
|
||||
if (buf[2] != 2)
|
||||
if (!buf || buf[2] != 2)
|
||||
{
|
||||
fprintf(stderr, "TGA image is not uncompressed RGB.\n");
|
||||
goto error;
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
TARGET := rxml
|
||||
|
||||
SOURCES := $(wildcard *.c)
|
||||
LIBRETRO_COMM_DIR := ../..
|
||||
|
||||
SOURCES := \
|
||||
$(wildcard *.c) \
|
||||
$(LIBRETRO_COMM_DIR)/file/retro_file.c
|
||||
|
||||
OBJS := $(SOURCES:.c=.o)
|
||||
|
||||
CFLAGS += -DRXML_TEST -Wall -pedantic -std=gnu99 -O0 -g -I../../include
|
||||
CFLAGS += -DRXML_TEST -Wall -pedantic -std=gnu99 -g -I$(LIBRETRO_COMM_DIR)/include
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
|
|
|
@ -20,16 +20,20 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <formats/rxml.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <retro_file.h>
|
||||
#include <compat/posix_string.h>
|
||||
|
||||
#include <formats/rxml.h>
|
||||
|
||||
struct rxml_document
|
||||
{
|
||||
struct rxml_node *root_node;
|
||||
|
@ -414,8 +418,7 @@ rxml_document_t *rxml_load_document(const char *path)
|
|||
char *new_memory_buffer = NULL;
|
||||
const char *mem_ptr = NULL;
|
||||
long len = 0;
|
||||
|
||||
FILE *file = fopen(path, "r");
|
||||
RFILE *file = retro_fopen(path, RFILE_MODE_READ, -1);
|
||||
if (!file)
|
||||
return NULL;
|
||||
|
||||
|
@ -423,19 +426,19 @@ rxml_document_t *rxml_load_document(const char *path)
|
|||
if (!doc)
|
||||
goto error;
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
len = ftell(file);
|
||||
rewind(file);
|
||||
retro_fseek(file, 0, SEEK_END);
|
||||
len = retro_ftell(file);
|
||||
retro_frewind(file);
|
||||
|
||||
memory_buffer = (char*)malloc(len + 1);
|
||||
if (!memory_buffer)
|
||||
goto error;
|
||||
|
||||
memory_buffer[len] = '\0';
|
||||
if (fread(memory_buffer, 1, len, file) != (size_t)len)
|
||||
if (retro_fread(file, memory_buffer, len) != (size_t)len)
|
||||
goto error;
|
||||
|
||||
fclose(file);
|
||||
retro_fclose(file);
|
||||
file = NULL;
|
||||
|
||||
mem_ptr = memory_buffer;
|
||||
|
@ -459,8 +462,7 @@ rxml_document_t *rxml_load_document(const char *path)
|
|||
|
||||
error:
|
||||
free(memory_buffer);
|
||||
if (file)
|
||||
fclose(file);
|
||||
retro_fclose(file);
|
||||
rxml_free_document(doc);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ void conv_rgb565_0rgb1555(void *output_, const void *input_,
|
|||
int width, int height,
|
||||
int out_stride, int in_stride)
|
||||
{
|
||||
int h, w;
|
||||
int h;
|
||||
const uint16_t *input = (const uint16_t*)input_;
|
||||
uint16_t *output = (uint16_t*)output_;
|
||||
|
||||
|
@ -55,7 +55,7 @@ void conv_rgb565_0rgb1555(void *output_, const void *input_,
|
|||
for (h = 0; h < height;
|
||||
h++, output += out_stride >> 1, input += in_stride >> 1)
|
||||
{
|
||||
w = 0;
|
||||
int w = 0;
|
||||
#if defined(__SSE2_)
|
||||
for (; w < max_width; w += 8)
|
||||
{
|
||||
|
@ -80,7 +80,7 @@ void conv_0rgb1555_rgb565(void *output_, const void *input_,
|
|||
int width, int height,
|
||||
int out_stride, int in_stride)
|
||||
{
|
||||
int h, w;
|
||||
int h;
|
||||
const uint16_t *input = (const uint16_t*)input_;
|
||||
uint16_t *output = (uint16_t*)output_;
|
||||
|
||||
|
@ -96,7 +96,7 @@ void conv_0rgb1555_rgb565(void *output_, const void *input_,
|
|||
for (h = 0; h < height;
|
||||
h++, output += out_stride >> 1, input += in_stride >> 1)
|
||||
{
|
||||
w = 0;
|
||||
int w = 0;
|
||||
#if defined(__SSE2__)
|
||||
for (; w < max_width; w += 8)
|
||||
{
|
||||
|
@ -124,7 +124,7 @@ void conv_0rgb1555_argb8888(void *output_, const void *input_,
|
|||
int width, int height,
|
||||
int out_stride, int in_stride)
|
||||
{
|
||||
int h, w;
|
||||
int h;
|
||||
const uint16_t *input = (const uint16_t*)input_;
|
||||
uint32_t *output = (uint32_t*)output_;
|
||||
|
||||
|
@ -141,7 +141,7 @@ void conv_0rgb1555_argb8888(void *output_, const void *input_,
|
|||
for (h = 0; h < height;
|
||||
h++, output += out_stride >> 2, input += in_stride >> 1)
|
||||
{
|
||||
w = 0;
|
||||
int w = 0;
|
||||
#ifdef __SSE2__
|
||||
for (; w < max_width; w += 8)
|
||||
{
|
||||
|
@ -191,7 +191,7 @@ void conv_rgb565_argb8888(void *output_, const void *input_,
|
|||
int width, int height,
|
||||
int out_stride, int in_stride)
|
||||
{
|
||||
int h, w;
|
||||
int h;
|
||||
const uint16_t *input = (const uint16_t*)input_;
|
||||
uint32_t *output = (uint32_t*)output_;
|
||||
|
||||
|
@ -210,7 +210,7 @@ void conv_rgb565_argb8888(void *output_, const void *input_,
|
|||
for (h = 0; h < height;
|
||||
h++, output += out_stride >> 2, input += in_stride >> 1)
|
||||
{
|
||||
w = 0;
|
||||
int w = 0;
|
||||
#if defined(__SSE2__)
|
||||
for (; w < max_width; w += 8)
|
||||
{
|
||||
|
@ -385,7 +385,7 @@ void conv_0rgb1555_bgr24(void *output_, const void *input_,
|
|||
int width, int height,
|
||||
int out_stride, int in_stride)
|
||||
{
|
||||
int h, w;
|
||||
int h;
|
||||
const uint16_t *input = (const uint16_t*)input_;
|
||||
uint8_t *output = (uint8_t*)output_;
|
||||
|
||||
|
@ -403,8 +403,8 @@ void conv_0rgb1555_bgr24(void *output_, const void *input_,
|
|||
h++, output += out_stride, input += in_stride >> 1)
|
||||
{
|
||||
uint8_t *out = output;
|
||||
int w = 0;
|
||||
|
||||
w = 0;
|
||||
#if defined(__SSE2__)
|
||||
for (; w < max_width; w += 16, out += 48)
|
||||
{
|
||||
|
@ -471,7 +471,7 @@ void conv_rgb565_bgr24(void *output_, const void *input_,
|
|||
int width, int height,
|
||||
int out_stride, int in_stride)
|
||||
{
|
||||
int h, w;
|
||||
int h;
|
||||
const uint16_t *input = (const uint16_t*)input_;
|
||||
uint8_t *output = (uint8_t*)output_;
|
||||
|
||||
|
@ -490,8 +490,7 @@ void conv_rgb565_bgr24(void *output_, const void *input_,
|
|||
for (h = 0; h < height; h++, output += out_stride, input += in_stride >> 1)
|
||||
{
|
||||
uint8_t *out = output;
|
||||
|
||||
w = 0;
|
||||
int w = 0;
|
||||
#if defined(__SSE2__)
|
||||
for (; w < max_width; w += 16, out += 48)
|
||||
{
|
||||
|
@ -601,7 +600,7 @@ void conv_argb8888_bgr24(void *output_, const void *input_,
|
|||
int width, int height,
|
||||
int out_stride, int in_stride)
|
||||
{
|
||||
int h, w;
|
||||
int h;
|
||||
const uint32_t *input = (const uint32_t*)input_;
|
||||
uint8_t *output = (uint8_t*)output_;
|
||||
|
||||
|
@ -613,8 +612,7 @@ void conv_argb8888_bgr24(void *output_, const void *input_,
|
|||
h++, output += out_stride, input += in_stride >> 2)
|
||||
{
|
||||
uint8_t *out = output;
|
||||
|
||||
w = 0;
|
||||
int w = 0;
|
||||
#if defined(__SSE2__)
|
||||
for (; w < max_width; w += 16, out += 48)
|
||||
{
|
||||
|
@ -668,7 +666,7 @@ void conv_yuyv_argb8888(void *output_, const void *input_,
|
|||
int width, int height,
|
||||
int out_stride, int in_stride)
|
||||
{
|
||||
int h, w;
|
||||
int h;
|
||||
const uint8_t *input = (const uint8_t*)input_;
|
||||
uint32_t *output = (uint32_t*)output_;
|
||||
|
||||
|
@ -692,8 +690,7 @@ void conv_yuyv_argb8888(void *output_, const void *input_,
|
|||
{
|
||||
const uint8_t *src = input;
|
||||
uint32_t *dst = output;
|
||||
|
||||
w = 0;
|
||||
int w = 0;
|
||||
|
||||
#if defined(__SSE2__)
|
||||
/* Each loop processes 16 pixels. */
|
||||
|
|
|
@ -30,10 +30,6 @@
|
|||
#include <retro_inline.h>
|
||||
#include <filters.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
static bool allocate_filters(struct scaler_ctx *ctx)
|
||||
{
|
||||
ctx->horiz.filter = (int16_t*)scaler_alloc(sizeof(int16_t), ctx->horiz.filter_stride * ctx->out_width);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -80,7 +80,6 @@ static void sha256_block(struct sha256_ctx *p)
|
|||
unsigned i;
|
||||
uint32_t s0, s1;
|
||||
uint32_t a, b, c, d, e, f, g, h;
|
||||
uint32_t t1, t2, maj, ch;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
p->w[i] = load32be(p->in.u32 + i);
|
||||
|
@ -97,15 +96,23 @@ static void sha256_block(struct sha256_ctx *p)
|
|||
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
uint32_t t1, t2, maj, ch;
|
||||
|
||||
s0 = ROR32(a, 2) ^ ROR32(a, 13) ^ ROR32(a, 22);
|
||||
maj = (a & b) ^ (a & c) ^ (b & c);
|
||||
t2 = s0 + maj;
|
||||
s1 = ROR32(e, 6) ^ ROR32(e, 11) ^ ROR32(e, 25);
|
||||
ch = (e & f) ^ (~e & g);
|
||||
t1 = h + s1 + ch + T_K[i] + p->w[i];
|
||||
t2 = s0 + maj;
|
||||
s1 = ROR32(e, 6) ^ ROR32(e, 11) ^ ROR32(e, 25);
|
||||
ch = (e & f) ^ (~e & g);
|
||||
t1 = h + s1 + ch + T_K[i] + p->w[i];
|
||||
|
||||
h = g; g = f; f = e; e = d + t1;
|
||||
d = c; c = b; b = a; a = t1 + t2;
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + t1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = t1 + t2;
|
||||
}
|
||||
|
||||
p->h[0] += a; p->h[1] += b; p->h[2] += c; p->h[3] += d;
|
||||
|
@ -118,20 +125,20 @@ static void sha256_block(struct sha256_ctx *p)
|
|||
static void sha256_chunk(struct sha256_ctx *p,
|
||||
const uint8_t *s, unsigned len)
|
||||
{
|
||||
unsigned l;
|
||||
|
||||
p->len += len;
|
||||
|
||||
while (len)
|
||||
{
|
||||
l = 64 - p->inlen;
|
||||
l = (len < l) ? len : l;
|
||||
unsigned l = 64 - p->inlen;
|
||||
|
||||
if (len < l)
|
||||
l = len;
|
||||
|
||||
memcpy(p->in.u8 + p->inlen, s, l);
|
||||
|
||||
s += l;
|
||||
p->inlen += l;
|
||||
len -= l;
|
||||
s += l;
|
||||
p->inlen += l;
|
||||
len -= l;
|
||||
|
||||
if (p->inlen == 64)
|
||||
sha256_block(p);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4)
|
||||
typedef int NSInteger;
|
||||
typedef unsigned NSUInteger;
|
||||
typedef float CGFloat;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#else
|
||||
/* Avoid possible naming collisions during link since we
|
||||
* prefer to use the actual name. */
|
||||
#define getopt_long(argc, argv, optstring, longopts, longindex) __getopt_long_rarch(argc, argv, optstring, longopts, longindex)
|
||||
#define getopt_long(argc, argv, optstring, longopts, longindex) __getopt_long_retro(argc, argv, optstring, longopts, longindex)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
#ifndef snprintf
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#ifndef vsnprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef UNICODE /* Do not bother with UNICODE at this time. */
|
||||
|
@ -51,9 +54,9 @@ typedef int ssize_t;
|
|||
#define mkdir(dirname, unused) _mkdir(dirname)
|
||||
#define strtoull _strtoui64
|
||||
#undef strcasecmp
|
||||
#define strcasecmp(x,y) _stricmp(x,y)
|
||||
#define strcasecmp _stricmp
|
||||
#undef strncasecmp
|
||||
#define strncasecmp(x, y, l) _strnicmp(x, y, l)
|
||||
#define strncasecmp _strnicmp
|
||||
|
||||
/* Disable some of the annoying warnings. */
|
||||
#pragma warning(disable : 4800)
|
||||
|
|
|
@ -24,30 +24,34 @@
|
|||
#define __LIBRETRO_SDK_COMPAT_POSIX_STRING_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#include <compat/msvc.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#undef strtok_r
|
||||
#define strtok_r(str, delim, saveptr) retro_strtok_r__(str, delim, saveptr)
|
||||
|
||||
char *strtok_r(char *str, const char *delim, char **saveptr);
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#undef strcasecmp
|
||||
#undef strdup
|
||||
#undef isblank
|
||||
#undef strtok_r
|
||||
#define strcasecmp(a, b) rarch_strcasecmp__(a, b)
|
||||
#define strdup(orig) rarch_strdup__(orig)
|
||||
#define isblank(c) rarch_isblank__(c)
|
||||
#define strtok_r(str, delim, saveptr) rarch_strtok_r__(str, delim, saveptr)
|
||||
#define strcasecmp(a, b) retro_strcasecmp__(a, b)
|
||||
#define strdup(orig) retro_strdup__(orig)
|
||||
#define isblank(c) retro_isblank__(c)
|
||||
int strcasecmp(const char *a, const char *b);
|
||||
char *strdup(const char *orig);
|
||||
int isblank(int c);
|
||||
char *strtok_r(char *str, const char *delim, char **saveptr);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ extern "C" {
|
|||
|
||||
/* Avoid possible naming collisions during link
|
||||
* since we prefer to use the actual name. */
|
||||
#define strcasestr(haystack, needle) strcasestr_rarch__(haystack, needle)
|
||||
#define strcasestr(haystack, needle) strcasestr_retro__(haystack, needle)
|
||||
|
||||
char *strcasestr(const char *haystack, const char *needle);
|
||||
|
||||
|
|
|
@ -34,12 +34,18 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#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_rarch__(dst, src, size)
|
||||
#define strlcpy(dst, src, size) strlcpy_retro__(dst, src, size)
|
||||
|
||||
#define strlcat(dst, src, size) strlcat_rarch__(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);
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/* Copyright (C) 2010-2015 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>
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
|
@ -34,33 +34,23 @@ extern "C" {
|
|||
|
||||
#include <boolean.h>
|
||||
|
||||
struct config_entry_list
|
||||
{
|
||||
/* If we got this from an #include,
|
||||
* do not allow overwrite. */
|
||||
bool readonly;
|
||||
char *key;
|
||||
char *value;
|
||||
uint32_t key_hash;
|
||||
#define CONFIG_GET_BOOL_BASE(conf, base, var, key) do { \
|
||||
bool tmp = false; \
|
||||
if (config_get_bool(conf, key, &tmp)) \
|
||||
base->var = tmp; \
|
||||
} while(0)
|
||||
|
||||
struct config_entry_list *next;
|
||||
};
|
||||
#define CONFIG_GET_INT_BASE(conf, base, var, key) do { \
|
||||
int tmp = 0; \
|
||||
if (config_get_int(conf, key, &tmp)) \
|
||||
base->var = tmp; \
|
||||
} while(0)
|
||||
|
||||
struct config_include_list
|
||||
{
|
||||
char *path;
|
||||
struct config_include_list *next;
|
||||
};
|
||||
|
||||
struct config_file
|
||||
{
|
||||
char *path;
|
||||
struct config_entry_list *entries;
|
||||
struct config_entry_list *tail;
|
||||
unsigned include_depth;
|
||||
|
||||
struct config_include_list *includes;
|
||||
};
|
||||
#define CONFIG_GET_FLOAT_BASE(conf, base, var, key) do { \
|
||||
float tmp = 0.0f; \
|
||||
if (config_get_float(conf, key, &tmp)) \
|
||||
base->var = tmp; \
|
||||
} while(0)
|
||||
|
||||
typedef struct config_file config_file_t;
|
||||
|
||||
|
@ -117,8 +107,10 @@ bool config_get_int(config_file_t *conf, const char *entry, int *in);
|
|||
/* Extracts an uint from config file. */
|
||||
bool config_get_uint(config_file_t *conf, const char *entry, unsigned *in);
|
||||
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
|
||||
/* Extracts an uint64 from config file. */
|
||||
bool config_get_uint64(config_file_t *conf, const char *entry, uint64_t *in);
|
||||
#endif
|
||||
|
||||
/* Extracts an unsigned int from config file treating input as hex. */
|
||||
bool config_get_hex(config_file_t *conf, const char *entry, unsigned *in);
|
||||
|
@ -132,11 +124,14 @@ bool config_get_char(config_file_t *conf, const char *entry, char *in);
|
|||
bool config_get_string(config_file_t *conf, const char *entry, char **in);
|
||||
|
||||
/* Extracts a string to a preallocated buffer. Avoid memory allocation. */
|
||||
bool config_get_array(config_file_t *conf, const char *entry, char *in, size_t size);
|
||||
bool config_get_array(config_file_t *conf, const char *entry, char *s, size_t len);
|
||||
|
||||
/* Extracts a string to a preallocated buffer. Avoid memory allocation.
|
||||
* Recognized magic like ~/. Similar to config_get_array() otherwise. */
|
||||
bool config_get_path(config_file_t *conf, const char *entry, char *in, size_t size);
|
||||
bool config_get_path(config_file_t *conf, const char *entry, char *s, size_t len);
|
||||
|
||||
/* Extracts a string to a preallocated buffer. Avoid memory allocation. */
|
||||
bool config_get_config_path(config_file_t *conf, char *s, size_t len);
|
||||
|
||||
/* Extracts a boolean from config.
|
||||
* Valid boolean true are "true" and "1". Valid false are "false" and "0".
|
||||
|
@ -152,6 +147,7 @@ void config_set_hex(config_file_t *conf, const char *entry, unsigned val);
|
|||
void config_set_uint64(config_file_t *conf, const char *entry, uint64_t val);
|
||||
void config_set_char(config_file_t *conf, const char *entry, char val);
|
||||
void config_set_string(config_file_t *conf, const char *entry, const char *val);
|
||||
void config_unset(config_file_t *conf, const char *key);
|
||||
void config_set_path(config_file_t *conf, const char *entry, const char *val);
|
||||
void config_set_bool(config_file_t *conf, const char *entry, bool val);
|
||||
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
/* Copyright (C) 2010-2015 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (file_archive.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 FILE_ARCHIVE_H__
|
||||
#define FILE_ARCHIVE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
enum file_archive_transfer_type
|
||||
{
|
||||
ZLIB_TRANSFER_NONE = 0,
|
||||
ZLIB_TRANSFER_INIT,
|
||||
ZLIB_TRANSFER_ITERATE,
|
||||
ZLIB_TRANSFER_DEINIT,
|
||||
ZLIB_TRANSFER_DEINIT_ERROR
|
||||
};
|
||||
|
||||
typedef struct file_archive_handle
|
||||
{
|
||||
void *stream;
|
||||
uint8_t *data;
|
||||
uint32_t real_checksum;
|
||||
const struct file_archive_file_backend *backend;
|
||||
} file_archive_file_handle_t;
|
||||
|
||||
struct file_archive_file_backend
|
||||
{
|
||||
void *(*stream_new)(void);
|
||||
void (*stream_free)(void *);
|
||||
void (*stream_set)(void *, uint32_t, uint32_t,
|
||||
const uint8_t *, uint8_t *);
|
||||
uint32_t (*stream_get_avail_in)(void*);
|
||||
uint32_t (*stream_get_avail_out)(void*);
|
||||
uint64_t (*stream_get_total_out)(void*);
|
||||
void (*stream_decrement_total_out)(void *, unsigned);
|
||||
bool (*stream_decompress_init)(void *);
|
||||
bool (*stream_decompress_data_to_file_init)(
|
||||
file_archive_file_handle_t *, const uint8_t *, uint32_t, uint32_t);
|
||||
int (*stream_decompress_data_to_file_iterate)(void *);
|
||||
void (*stream_compress_init)(void *, int);
|
||||
void (*stream_compress_free)(void *);
|
||||
int (*stream_compress_data_to_file)(void *);
|
||||
uint32_t (*stream_crc_calculate)(uint32_t, const uint8_t *, size_t);
|
||||
const char *ident;
|
||||
};
|
||||
|
||||
typedef struct file_archive_transfer
|
||||
{
|
||||
void *handle;
|
||||
const uint8_t *footer;
|
||||
const uint8_t *directory;
|
||||
const uint8_t *data;
|
||||
int32_t zip_size;
|
||||
enum file_archive_transfer_type type;
|
||||
const struct file_archive_file_backend *backend;
|
||||
} file_archive_transfer_t;
|
||||
|
||||
|
||||
/* Returns true when parsing should continue. False to stop. */
|
||||
typedef int (*file_archive_file_cb)(const char *name, const char *valid_exts,
|
||||
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size,
|
||||
uint32_t crc32, void *userdata);
|
||||
|
||||
int file_archive_parse_file_iterate(
|
||||
file_archive_transfer_t *state,
|
||||
bool *returnerr,
|
||||
const char *file,
|
||||
const char *valid_exts,
|
||||
file_archive_file_cb file_cb,
|
||||
void *userdata);
|
||||
|
||||
void file_archive_parse_file_iterate_stop(file_archive_transfer_t *state);
|
||||
|
||||
int file_archive_parse_file_progress(file_archive_transfer_t *state);
|
||||
|
||||
/**
|
||||
* file_archive_extract_first_content_file:
|
||||
* @zip_path : filename path to ZIP archive.
|
||||
* @zip_path_size : size of ZIP archive.
|
||||
* @valid_exts : valid extensions for a content file.
|
||||
* @extraction_directory : the directory to extract temporary
|
||||
* unzipped content to.
|
||||
*
|
||||
* Extract first content file from archive.
|
||||
*
|
||||
* Returns : true (1) on success, otherwise false (0).
|
||||
**/
|
||||
bool file_archive_extract_first_content_file(char *zip_path, size_t zip_path_size,
|
||||
const char *valid_exts, const char *extraction_dir,
|
||||
char *out_path, size_t len);
|
||||
|
||||
/**
|
||||
* file_archive_get_file_list:
|
||||
* @path : filename path of archive
|
||||
* @valid_exts : Valid extensions of archive to be parsed.
|
||||
* If NULL, allow all.
|
||||
*
|
||||
* Returns: string listing of files from archive on success, otherwise NULL.
|
||||
**/
|
||||
struct string_list *file_archive_get_file_list(const char *path, const char *valid_exts);
|
||||
|
||||
bool file_archive_perform_mode(const char *name, const char *valid_exts,
|
||||
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size,
|
||||
uint32_t crc32, void *userdata);
|
||||
|
||||
struct string_list *compressed_file_list_new(const char *filename,
|
||||
const char* ext);
|
||||
|
||||
void file_archive_deflate_init(void *data, int level);
|
||||
|
||||
const struct file_archive_file_backend *file_archive_get_default_file_backend(void);
|
||||
|
||||
extern const struct file_archive_file_backend zlib_backend;
|
||||
|
||||
#endif
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
/* Copyright (C) 2010-2015 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (file_extract.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 FILE_EXTRACT_H__
|
||||
#define FILE_EXTRACT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
typedef struct zlib_handle
|
||||
{
|
||||
void *stream;
|
||||
uint8_t *data;
|
||||
uint32_t real_checksum;
|
||||
} zlib_file_handle_t;
|
||||
|
||||
enum zlib_transfer_type
|
||||
{
|
||||
ZLIB_TRANSFER_NONE = 0,
|
||||
ZLIB_TRANSFER_INIT,
|
||||
ZLIB_TRANSFER_ITERATE,
|
||||
ZLIB_TRANSFER_DEINIT,
|
||||
ZLIB_TRANSFER_DEINIT_ERROR
|
||||
};
|
||||
|
||||
typedef struct zlib_transfer
|
||||
{
|
||||
void *handle;
|
||||
const uint8_t *footer;
|
||||
const uint8_t *directory;
|
||||
const uint8_t *data;
|
||||
int32_t zip_size;
|
||||
enum zlib_transfer_type type;
|
||||
const struct zlib_file_backend *backend;
|
||||
} zlib_transfer_t;
|
||||
|
||||
/* Returns true when parsing should continue. False to stop. */
|
||||
typedef int (*zlib_file_cb)(const char *name, const char *valid_exts,
|
||||
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size,
|
||||
uint32_t crc32, void *userdata);
|
||||
|
||||
uint32_t zlib_crc32_calculate(const uint8_t *data, size_t length);
|
||||
|
||||
uint32_t zlib_crc32_adjust(uint32_t crc, uint8_t data);
|
||||
|
||||
/**
|
||||
* zlib_parse_file:
|
||||
* @file : filename path of archive
|
||||
* @valid_exts : Valid extensions of archive to be parsed.
|
||||
* If NULL, allow all.
|
||||
* @file_cb : file_cb function pointer
|
||||
* @userdata : userdata to pass to file_cb function pointer.
|
||||
*
|
||||
* Low-level file parsing. Enumerates over all files and calls
|
||||
* file_cb with userdata.
|
||||
*
|
||||
* Returns: true (1) on success, otherwise false (0).
|
||||
**/
|
||||
bool zlib_parse_file(const char *file, const char *valid_exts,
|
||||
zlib_file_cb file_cb, void *userdata);
|
||||
|
||||
int zlib_parse_file_iterate(void *data, bool *returnerr,
|
||||
const char *file,
|
||||
const char *valid_exts, zlib_file_cb file_cb, void *userdata);
|
||||
|
||||
void zlib_parse_file_iterate_stop(void *data);
|
||||
|
||||
/**
|
||||
* zlib_extract_first_content_file:
|
||||
* @zip_path : filename path to ZIP archive.
|
||||
* @zip_path_size : size of ZIP archive.
|
||||
* @valid_exts : valid extensions for a content file.
|
||||
* @extraction_directory : the directory to extract temporary
|
||||
* unzipped content to.
|
||||
*
|
||||
* Extract first content file from archive.
|
||||
*
|
||||
* Returns : true (1) on success, otherwise false (0).
|
||||
**/
|
||||
bool zlib_extract_first_content_file(char *zip_path, size_t zip_path_size,
|
||||
const char *valid_exts, const char *extraction_dir);
|
||||
|
||||
/**
|
||||
* zlib_get_file_list:
|
||||
* @path : filename path of archive
|
||||
* @valid_exts : Valid extensions of archive to be parsed.
|
||||
* If NULL, allow all.
|
||||
*
|
||||
* Returns: string listing of files from archive on success, otherwise NULL.
|
||||
**/
|
||||
struct string_list *zlib_get_file_list(const char *path, const char *valid_exts);
|
||||
|
||||
bool zlib_inflate_data_to_file_init(
|
||||
zlib_file_handle_t *handle,
|
||||
const uint8_t *cdata, uint32_t csize, uint32_t size);
|
||||
|
||||
int zlib_inflate_data_to_file_iterate(void *data);
|
||||
|
||||
/**
|
||||
* zlib_inflate_data_to_file:
|
||||
* @path : filename path of archive.
|
||||
* @cdata : input data.
|
||||
* @csize : size of input data.
|
||||
* @size : output file size
|
||||
* @checksum : CRC32 checksum from input data.
|
||||
*
|
||||
* Decompress data to file.
|
||||
*
|
||||
* Returns: true (1) on success, otherwise false (0).
|
||||
**/
|
||||
int zlib_inflate_data_to_file(zlib_file_handle_t *handle,
|
||||
int ret, const char *path, const char *valid_exts,
|
||||
const uint8_t *cdata, uint32_t csize, uint32_t size, uint32_t checksum);
|
||||
|
||||
bool zlib_perform_mode(const char *name, const char *valid_exts,
|
||||
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size,
|
||||
uint32_t crc32, void *userdata);
|
||||
|
||||
struct string_list *compressed_file_list_new(const char *filename,
|
||||
const char* ext);
|
||||
|
||||
void *zlib_stream_new(void);
|
||||
|
||||
void zlib_stream_free(void *data);
|
||||
|
||||
void zlib_deflate_init(void *data, int level);
|
||||
|
||||
int zlib_deflate_data_to_file(void *data);
|
||||
|
||||
void zlib_stream_deflate_free(void *data);
|
||||
|
||||
bool zlib_inflate_init(void *data);
|
||||
|
||||
bool zlib_inflate_init2(void *data);
|
||||
|
||||
void zlib_set_stream(void *data,
|
||||
uint32_t avail_in,
|
||||
uint32_t avail_out,
|
||||
const uint8_t *next_in,
|
||||
uint8_t *next_out
|
||||
);
|
||||
|
||||
uint32_t zlib_stream_get_avail_in(void *data);
|
||||
|
||||
uint32_t zlib_stream_get_avail_out(void *data);
|
||||
|
||||
uint64_t zlib_stream_get_total_out(void *data);
|
||||
|
||||
void zlib_stream_decrement_total_out(void *data,
|
||||
unsigned subtraction);
|
||||
|
||||
#endif
|
||||
|
|
@ -27,6 +27,9 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
struct item_file
|
||||
|
|
|
@ -294,6 +294,19 @@ void fill_pathname_resolve_relative(char *out_path, const char *in_refpath,
|
|||
void fill_pathname_join(char *out_path, const char *dir,
|
||||
const char *path, size_t size);
|
||||
|
||||
/**
|
||||
* fill_string_join:
|
||||
* @out_path : output path
|
||||
* @path : path
|
||||
* @size : size of output path
|
||||
*
|
||||
* Joins a string (@out_path) and path (@append) together.
|
||||
* Makes sure not to get two consecutive slashes
|
||||
* between directory and path.
|
||||
**/
|
||||
void fill_string_join(char *out_path,
|
||||
const char *path, size_t size);
|
||||
|
||||
/**
|
||||
* fill_pathname_join_delim:
|
||||
* @out_path : output path
|
||||
|
|
|
@ -36,24 +36,18 @@ struct texture_image
|
|||
{
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
#ifdef _XBOX1
|
||||
unsigned x;
|
||||
unsigned y;
|
||||
void *texture_buf;
|
||||
void *vertex_buf;
|
||||
#endif
|
||||
uint32_t *pixels;
|
||||
};
|
||||
|
||||
bool texture_image_set_color_shifts(unsigned *r_shift, unsigned *g_shift,
|
||||
bool video_texture_image_set_color_shifts(unsigned *r_shift, unsigned *g_shift,
|
||||
unsigned *b_shift, unsigned *a_shift);
|
||||
|
||||
bool texture_image_color_convert(unsigned r_shift,
|
||||
bool video_texture_image_color_convert(unsigned r_shift,
|
||||
unsigned g_shift, unsigned b_shift, unsigned a_shift,
|
||||
struct texture_image *out_img);
|
||||
|
||||
bool texture_image_load(struct texture_image *img, const char *path);
|
||||
void texture_image_free(struct texture_image *img);
|
||||
bool video_texture_image_load(struct texture_image *img, const char *path);
|
||||
void video_texture_image_free(struct texture_image *img);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/* Copyright (C) 2010-2015 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (jsonsax.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_FORMAT_JSONSAX_H__
|
||||
#define __LIBRETRO_SDK_FORMAT_JSONSAX_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
enum
|
||||
{
|
||||
JSONSAX_OK = 0,
|
||||
JSONSAX_INTERRUPTED,
|
||||
JSONSAX_MISSING_KEY,
|
||||
JSONSAX_UNTERMINATED_KEY,
|
||||
JSONSAX_MISSING_VALUE,
|
||||
JSONSAX_UNTERMINATED_OBJECT,
|
||||
JSONSAX_UNTERMINATED_ARRAY,
|
||||
JSONSAX_UNTERMINATED_STRING,
|
||||
JSONSAX_INVALID_VALUE
|
||||
};
|
||||
|
||||
#ifdef JSONSAX_ERRORS
|
||||
extern const char* jsonsax_errors[];
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int ( *start_document )( void* userdata );
|
||||
int ( *end_document )( void* userdata );
|
||||
int ( *start_object )( void* userdata );
|
||||
int ( *end_object )( void* userdata );
|
||||
int ( *start_array )( void* userdata );
|
||||
int ( *end_array )( void* userdata );
|
||||
int ( *key )( void* userdata, const char* name, size_t length );
|
||||
int ( *index )( void* userdata, unsigned int index );
|
||||
int ( *string )( void* userdata, const char* string, size_t length );
|
||||
int ( *number )( void* userdata, const char* number, size_t length );
|
||||
int ( *boolean )( void* userdata, int istrue );
|
||||
int ( *null )( void* userdata );
|
||||
}
|
||||
jsonsax_handlers_t;
|
||||
|
||||
int jsonsax_parse( const char* json, const jsonsax_handlers_t* handlers, void* userdata );
|
||||
|
||||
#endif /* __LIBRETRO_SDK_FORMAT_JSONSAX_H__ */
|
|
@ -27,7 +27,7 @@
|
|||
#include <stddef.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <file/file_extract.h>
|
||||
#include <file/file_archive.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
/* Copyright (C) 2010-2016 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this libretro SDK code part (glsm.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_GLSM_H
|
||||
#define LIBRETRO_SDK_GLSM_H
|
||||
|
||||
#include <boolean.h>
|
||||
#include <libretro.h>
|
||||
#include <glsym/rglgen_headers.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENGLES2
|
||||
typedef GLfloat GLdouble;
|
||||
typedef GLclampf GLclampd;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_OPENGLES2)
|
||||
#define RARCH_GL_RENDERBUFFER GL_RENDERBUFFER
|
||||
#define RARCH_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
|
||||
#define RARCH_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT
|
||||
#define RARCH_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT
|
||||
#elif defined(OSX_PPC)
|
||||
#define RARCH_GL_RENDERBUFFER GL_RENDERBUFFER_EXT
|
||||
#define RARCH_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_EXT
|
||||
#define RARCH_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT
|
||||
#define RARCH_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_EXT
|
||||
#elif defined(HAVE_PSGL)
|
||||
#define RARCH_GL_RENDERBUFFER GL_RENDERBUFFER_OES
|
||||
#define RARCH_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_SCE
|
||||
#define RARCH_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_OES
|
||||
#define RARCH_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_OES
|
||||
#else
|
||||
#define RARCH_GL_RENDERBUFFER GL_RENDERBUFFER
|
||||
#define RARCH_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8
|
||||
#define RARCH_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT
|
||||
#define RARCH_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PSGL)
|
||||
#define RARCH_GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
|
||||
#define RARCH_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES
|
||||
#define RARCH_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT
|
||||
#elif defined(OSX_PPC)
|
||||
#define RARCH_GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
|
||||
#define RARCH_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT
|
||||
#define RARCH_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT
|
||||
#else
|
||||
#define RARCH_GL_FRAMEBUFFER GL_FRAMEBUFFER
|
||||
#define RARCH_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE
|
||||
#define RARCH_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0
|
||||
#endif
|
||||
|
||||
#ifndef GL_FOG
|
||||
#define GL_FOG 0x0B60
|
||||
#endif
|
||||
|
||||
#ifndef GL_ALPHA_TEST
|
||||
#define GL_ALPHA_TEST 0x0BC0
|
||||
#endif
|
||||
|
||||
#define MAX_ATTRIB 8
|
||||
#define MAX_TEXTURE 32
|
||||
|
||||
enum
|
||||
{
|
||||
SGL_DEPTH_TEST = 0,
|
||||
SGL_BLEND,
|
||||
SGL_POLYGON_OFFSET_FILL,
|
||||
SGL_FOG,
|
||||
SGL_CULL_FACE,
|
||||
SGL_ALPHA_TEST,
|
||||
SGL_SCISSOR_TEST,
|
||||
SGL_STENCIL_TEST,
|
||||
#if !defined(HAVE_OPENGLES)
|
||||
SGL_DEPTH_CLAMP,
|
||||
SGL_CLIP_DISTANCE0,
|
||||
#endif
|
||||
SGL_DITHER,
|
||||
SGL_SAMPLE_ALPHA_TO_COVERAGE,
|
||||
SGL_SAMPLE_COVERAGE,
|
||||
#ifndef HAVE_OPENGLES
|
||||
SGL_COLOR_LOGIC_OP,
|
||||
#endif
|
||||
SGL_CAP_MAX
|
||||
};
|
||||
|
||||
enum glsm_state_ctl
|
||||
{
|
||||
GLSM_CTL_NONE = 0,
|
||||
GLSM_CTL_STATE_SETUP,
|
||||
GLSM_CTL_STATE_BIND,
|
||||
GLSM_CTL_STATE_UNBIND,
|
||||
GLSM_CTL_STATE_CONTEXT_RESET,
|
||||
GLSM_CTL_STATE_CONTEXT_INIT,
|
||||
GLSM_CTL_IS_IMM_VBO,
|
||||
GLSM_CTL_SET_IMM_VBO,
|
||||
GLSM_CTL_UNSET_IMM_VBO,
|
||||
GLSM_CTL_IMM_VBO_DISABLE,
|
||||
GLSM_CTL_IMM_VBO_DRAW,
|
||||
GLSM_CTL_IS_FRAMEBUFFER_LOCKED,
|
||||
GLSM_CTL_PROC_ADDRESS_GET
|
||||
};
|
||||
|
||||
typedef bool (*glsm_imm_vbo_draw)(void *);
|
||||
typedef bool (*glsm_imm_vbo_disable)(void *);
|
||||
typedef bool (*glsm_framebuffer_lock)(void *);
|
||||
|
||||
typedef struct glsm_ctx_proc_address
|
||||
{
|
||||
retro_get_proc_address_t addr;
|
||||
} glsm_ctx_proc_address_t;
|
||||
|
||||
typedef struct glsm_ctx_params
|
||||
{
|
||||
glsm_framebuffer_lock framebuffer_lock;
|
||||
glsm_imm_vbo_draw imm_vbo_draw;
|
||||
glsm_imm_vbo_disable imm_vbo_disable;
|
||||
retro_hw_context_reset_t context_reset;
|
||||
retro_hw_context_reset_t context_destroy;
|
||||
retro_environment_t environ_cb;
|
||||
bool stencil;
|
||||
unsigned major;
|
||||
unsigned minor;
|
||||
} glsm_ctx_params_t;
|
||||
|
||||
bool glsm_ctl(enum glsm_state_ctl state, void *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,222 @@
|
|||
/* Copyright (C) 2010-2016 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this libretro SDK code part (glsmsym.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_GLSM_SYM_H
|
||||
#define LIBRETRO_SDK_GLSM_SYM_H
|
||||
|
||||
#include <glsm/glsm.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* deprecated old FF-style GL symbols */
|
||||
#define glTexCoord2f rglTexCoord2f
|
||||
|
||||
/* more forward-compatible GL subset symbols */
|
||||
#define glBlitFramebuffer rglBlitFramebuffer
|
||||
#define glVertexAttrib4f rglVertexAttrib4f
|
||||
#define glVertexAttrib4fv rglVertexAttrib4fv
|
||||
#define glDrawArrays rglDrawArrays
|
||||
#define glDrawElements rglDrawElements
|
||||
#define glCompressedTexImage2D rglCompressedTexImage2D
|
||||
#define glBindTexture rglBindTexture
|
||||
#define glActiveTexture rglActiveTexture
|
||||
#define glFramebufferTexture2D rglFramebufferTexture2D
|
||||
#define glFramebufferRenderbuffer rglFramebufferRenderbuffer
|
||||
#define glDeleteFramebuffers rglDeleteFramebuffers
|
||||
#define glDeleteTextures rglDeleteTextures
|
||||
#define glDeleteBuffers rglDeleteBuffers
|
||||
#define glRenderbufferStorage rglRenderbufferStorage
|
||||
#define glBindRenderbuffer rglBindRenderbuffer
|
||||
#define glDeleteRenderbuffers rglDeleteRenderbuffers
|
||||
#define glGenRenderbuffers rglGenRenderbuffers
|
||||
#define glGenFramebuffers rglGenFramebuffers
|
||||
#define glGenTextures rglGenTextures
|
||||
#define glBindFramebuffer rglBindFramebuffer
|
||||
#define glGenerateMipmap rglGenerateMipmap
|
||||
#define glCheckFramebufferStatus rglCheckFramebufferStatus
|
||||
#define glBindFragDataLocation rglBindFragDataLocation
|
||||
#define glBindAttribLocation rglBindAttribLocation
|
||||
#define glLinkProgram rglLinkProgram
|
||||
#define glGetProgramiv rglGetProgramiv
|
||||
#define glGetShaderiv rglGetShaderiv
|
||||
#define glAttachShader rglAttachShader
|
||||
#define glDetachShader rglDetachShader
|
||||
#define glShaderSource rglShaderSource
|
||||
#define glCompileShader rglCompileShader
|
||||
#define glCreateProgram rglCreateProgram
|
||||
#define glGetShaderInfoLog rglGetShaderInfoLog
|
||||
#define glGetProgramInfoLog rglGetProgramInfoLog
|
||||
#define glIsProgram rglIsProgram
|
||||
#define glEnableVertexAttribArray rglEnableVertexAttribArray
|
||||
#define glDisableVertexAttribArray rglDisableVertexAttribArray
|
||||
#define glVertexAttribPointer rglVertexAttribPointer
|
||||
#define glGetUniformLocation rglGetUniformLocation
|
||||
#define glGenBuffers rglGenBuffers
|
||||
#define glDisable(T) rglDisable(S##T)
|
||||
#define glEnable(T) rglEnable(S##T)
|
||||
#define glIsEnabled(T) rglIsEnabled(S##T)
|
||||
#define glUseProgram rglUseProgram
|
||||
#define glDepthMask rglDepthMask
|
||||
#define glStencilMask rglStencilMask
|
||||
#define glBufferData rglBufferData
|
||||
#define glBufferSubData rglBufferSubData
|
||||
#define glBindBuffer rglBindBuffer
|
||||
#define glCreateShader rglCreateShader
|
||||
#define glDeleteShader rglDeleteShader
|
||||
#define glDeleteProgram rglDeleteProgram
|
||||
#define glUniform1f rglUniform1f
|
||||
#define glUniform1i rglUniform1i
|
||||
#define glUniform2f rglUniform2f
|
||||
#define glUniform2i rglUniform2i
|
||||
#define glUniform2fv rglUniform2fv
|
||||
#define glUniform3f rglUniform3f
|
||||
#define glUniform3fv rglUniform3fv
|
||||
#define glUniform4f rglUniform4f
|
||||
#define glUniform4fv rglUniform4fv
|
||||
#define glBlendFunc rglBlendFunc
|
||||
#define glBlendFuncSeparate rglBlendFuncSeparate
|
||||
#define glDepthFunc rglDepthFunc
|
||||
#define glColorMask rglColorMask
|
||||
#define glClearColor rglClearColor
|
||||
#define glViewport rglViewport
|
||||
#define glScissor rglScissor
|
||||
#define glStencilFunc rglStencilFunc
|
||||
#define glCullFace rglCullFace
|
||||
#define glStencilOp rglStencilOp
|
||||
#define glFrontFace rglFrontFace
|
||||
#define glDepthRange rglDepthRange
|
||||
#define glClearDepth rglClearDepth
|
||||
#define glPolygonOffset rglPolygonOffset
|
||||
#define glPixelStorei rglPixelStorei
|
||||
#define glReadBuffer rglReadBuffer
|
||||
#define glUniformMatrix4fv rglUniformMatrix4fv
|
||||
#define glGetAttribLocation rglGetAttribLocation
|
||||
|
||||
void rglReadBuffer(GLenum mode);
|
||||
void rglPixelStorei(GLenum pname, GLint param);
|
||||
void rglTexCoord2f(GLfloat s, GLfloat t);
|
||||
void rglDrawElements(GLenum mode, GLsizei count, GLenum type,
|
||||
const GLvoid * indices);
|
||||
void rglCompressedTexImage2D(GLenum target, GLint level,
|
||||
GLenum internalformat, GLsizei width, GLsizei height,
|
||||
GLint border, GLsizei imageSize, const GLvoid *data);
|
||||
void glBindTexture(GLenum target, GLuint texture);
|
||||
void glActiveTexture(GLenum texture);
|
||||
void rglFramebufferTexture2D(GLenum target, GLenum attachment,
|
||||
GLenum textarget, GLuint texture, GLint level);
|
||||
void rglFramebufferRenderbuffer(GLenum target, GLenum attachment,
|
||||
GLenum renderbuffertarget, GLuint renderbuffer);
|
||||
void rglDeleteFramebuffers(GLsizei n, GLuint *framebuffers);
|
||||
void rglRenderbufferStorage(GLenum target, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height);
|
||||
void rglDeleteTextures(GLsizei n, const GLuint *textures);
|
||||
void rglBindRenderbuffer(GLenum target, GLuint renderbuffer);
|
||||
void rglDeleteRenderbuffers(GLsizei n, GLuint *renderbuffers);
|
||||
void rglGenRenderbuffers(GLsizei n, GLuint *renderbuffers);
|
||||
void rglGenFramebuffers(GLsizei n, GLuint *ids);
|
||||
void rglGenTextures(GLsizei n, GLuint *textures);
|
||||
void rglBindFramebuffer(GLenum target, GLuint framebuffer);
|
||||
void rglGenerateMipmap(GLenum target);
|
||||
GLenum rglCheckFramebufferStatus(GLenum target);
|
||||
void rglBindFragDataLocation(GLuint program, GLuint colorNumber,
|
||||
const char * name);
|
||||
void rglBindAttribLocation(GLuint program, GLuint index, const GLchar *name);
|
||||
void rglLinkProgram(GLuint program);
|
||||
void rglGetProgramiv(GLuint shader, GLenum pname, GLint *params);
|
||||
void rglGetShaderiv(GLuint shader, GLenum pname, GLint *params);
|
||||
void rglAttachShader(GLuint program, GLuint shader);
|
||||
void rglShaderSource(GLuint shader, GLsizei count,
|
||||
const GLchar **string, const GLint *length);
|
||||
void rglCompileShader(GLuint shader);
|
||||
GLuint rglCreateProgram(void);
|
||||
void rglGetShaderInfoLog(GLuint shader, GLsizei maxLength,
|
||||
GLsizei *length, GLchar *infoLog);
|
||||
void rglGetProgramInfoLog(GLuint shader, GLsizei maxLength,
|
||||
GLsizei *length, GLchar *infoLog);
|
||||
GLboolean rglIsProgram(GLuint program);
|
||||
void rglEnableVertexAttribArray(GLuint index);
|
||||
void rglDisableVertexAttribArray(GLuint index);
|
||||
void rglVertexAttribPointer(GLuint name, GLint size,
|
||||
GLenum type, GLboolean normalized, GLsizei stride,
|
||||
const GLvoid* pointer);
|
||||
GLint rglGetUniformLocation(GLuint program, const GLchar *name);
|
||||
void rglGenBuffers(GLsizei n, GLuint *buffers);
|
||||
void rglDisable(GLenum cap);
|
||||
void rglEnable(GLenum cap);
|
||||
void rglUseProgram(GLuint program);
|
||||
void rglDepthMask(GLboolean flag);
|
||||
void rglStencilMask(GLenum mask);
|
||||
void rglBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
|
||||
void rglBufferSubData(GLenum target, GLintptr offset,
|
||||
GLsizeiptr size, const GLvoid *data);
|
||||
void rglBindBuffer(GLenum target, GLuint buffer);
|
||||
GLuint rglCreateShader(GLenum shader);
|
||||
void rglDeleteShader(GLuint shader);
|
||||
void rglUniform1f(GLint location, GLfloat v0);
|
||||
void rglUniform1i(GLint location, GLint v0);
|
||||
void rglUniform2f(GLint location, GLfloat v0, GLfloat v1);
|
||||
void rglUniform2i(GLint location, GLint v0, GLint v1);
|
||||
void rglUniform2fv(GLint location, GLsizei count, const GLfloat *value);
|
||||
void rglUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
|
||||
void rglUniform3fv(GLint location, GLsizei count, const GLfloat *value);
|
||||
void rglUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||
void rglUniform4fv(GLint location, GLsizei count, const GLfloat *value);
|
||||
void rglBlendFunc(GLenum sfactor, GLenum dfactor);
|
||||
void rglBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha,
|
||||
GLenum dstAlpha);
|
||||
void rglDepthFunc(GLenum func);
|
||||
void rglColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
|
||||
void rglClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||
void rglViewport(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
void rglScissor(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GLboolean rglIsEnabled(GLenum cap);
|
||||
void rglStencilFunc(GLenum func, GLint ref, GLuint mask);
|
||||
void rglCullFace(GLenum mode);
|
||||
void rglStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass);
|
||||
void rglFrontFace(GLenum mode);
|
||||
void rglDepthRange(GLclampd zNear, GLclampd zFar);
|
||||
void rglClearDepth(GLdouble depth);
|
||||
void rglPolygonOffset(GLfloat factor, GLfloat units);
|
||||
void rglDrawArrays(GLenum mode, GLint first, GLsizei count);
|
||||
void rglVertexAttrib4f(GLuint name, GLfloat x, GLfloat y,
|
||||
GLfloat z, GLfloat w);
|
||||
void rglVertexAttrib4fv(GLuint name, GLfloat* v);
|
||||
void rglDeleteProgram(GLuint program);
|
||||
void rglDeleteBuffers(GLsizei n, const GLuint *buffers);
|
||||
void rglBlitFramebuffer(
|
||||
GLint srcX0, GLint srcY0,
|
||||
GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0,
|
||||
GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter);
|
||||
void rglDetachShader(GLuint program, GLuint shader);
|
||||
void rglUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose,
|
||||
const GLfloat *value);
|
||||
GLint rglGetAttribLocation(GLuint program, const GLchar *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -700,7 +700,7 @@ typedef void (APIENTRYP RGLSYMGLCOPYCOLORTABLEPROC) (GLenum target, GLenum inter
|
|||
typedef void (APIENTRYP RGLSYMGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, void *table);
|
||||
typedef void (APIENTRYP RGLSYMGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
|
||||
typedef void (APIENTRYP RGLSYMGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP RGLSYMGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data);
|
||||
typedef void (APIENTRYP RGLSYMGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
|
||||
typedef void (APIENTRYP RGLSYMGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
|
||||
typedef void (APIENTRYP RGLSYMGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image);
|
||||
typedef void (APIENTRYP RGLSYMGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image);
|
||||
|
|
|
@ -59,7 +59,41 @@
|
|||
#define sockaddr_in SceNetSockaddrIn
|
||||
#define sockaddr SceNetSockaddr
|
||||
#define sendto sceNetSendto
|
||||
#define recvfrom sceNetRecvfrom
|
||||
#define socket(a,b,c) sceNetSocket("unknown",a,b,c)
|
||||
#define bind sceNetBind
|
||||
#define accept sceNetAccept
|
||||
#define setsockopt sceNetSetsockopt
|
||||
#define connect sceNetConnect
|
||||
#define listen sceNetListen
|
||||
#define send sceNetSend
|
||||
#define recv sceNetRecv
|
||||
#define MSG_DONTWAIT PSP2_NET_MSG_DONTWAIT
|
||||
#define AF_INET PSP2_NET_AF_INET
|
||||
#define AF_UNSPEC 0
|
||||
#define INADDR_ANY PSP2_NET_INADDR_ANY
|
||||
#define INADDR_NONE 0xffffffff
|
||||
#define SOCK_STREAM PSP2_NET_SOCK_STREAM
|
||||
#define SOCK_DGRAM PSP2_NET_SOCK_DGRAM
|
||||
#define SOL_SOCKET PSP2_NET_SOL_SOCKET
|
||||
#define SO_REUSEADDR PSP2_NET_SO_REUSEADDR
|
||||
#define SO_SNDBUF PSP2_NET_SO_SNDBUF
|
||||
#define SO_SNDTIMEO PSP2_NET_SO_SNDTIMEO
|
||||
#define SO_NBIO PSP2_NET_SO_NBIO
|
||||
#define htonl sceNetHtonl
|
||||
#define ntohl sceNetNtohl
|
||||
#define htons sceNetHtons
|
||||
#define socklen_t unsigned int
|
||||
|
||||
struct hostent
|
||||
{
|
||||
char *h_name;
|
||||
char **h_aliases;
|
||||
int h_addrtype;
|
||||
int h_length;
|
||||
char **h_addr_list;
|
||||
char *h_addr;
|
||||
};
|
||||
|
||||
#else
|
||||
#include <sys/select.h>
|
||||
|
@ -114,6 +148,8 @@ static INLINE bool isagain(int bytes)
|
|||
if (WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
return false;
|
||||
return true;
|
||||
#elif defined(VITA)
|
||||
return (bytes<0 && (bytes == PSP2_NET_ERROR_EAGAIN || bytes == PSP2_NET_ERROR_EWOULDBLOCK));
|
||||
#else
|
||||
return (bytes < 0 && (errno == EAGAIN || errno == EWOULDBLOCK));
|
||||
#endif
|
||||
|
@ -147,7 +183,7 @@ static INLINE bool isagain(int bytes)
|
|||
#ifdef HAVE_SOCKET_LEGACY
|
||||
|
||||
#define sockaddr_storage sockaddr_in
|
||||
#define addrinfo addrinfo_rarch__
|
||||
#define addrinfo addrinfo_retro__
|
||||
|
||||
struct addrinfo
|
||||
{
|
||||
|
@ -169,11 +205,11 @@ struct addrinfo
|
|||
|
||||
#endif
|
||||
|
||||
int getaddrinfo_rarch(const char *node, const char *service,
|
||||
int getaddrinfo_retro(const char *node, const char *service,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res);
|
||||
|
||||
void freeaddrinfo_rarch(struct addrinfo *res);
|
||||
void freeaddrinfo_retro(struct addrinfo *res);
|
||||
|
||||
bool socket_nonblock(int fd);
|
||||
|
||||
|
@ -203,4 +239,3 @@ bool network_init(void);
|
|||
void network_deinit(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ bool net_http_connection_done(struct http_connection_t *conn);
|
|||
|
||||
void net_http_connection_free(struct http_connection_t *conn);
|
||||
|
||||
const char *net_http_connection_url(struct http_connection_t *conn);
|
||||
|
||||
struct http_t *net_http_new(struct http_connection_t *conn);
|
||||
|
||||
/* You can use this to call net_http_update
|
||||
|
@ -49,6 +51,8 @@ bool net_http_update(struct http_t *state, size_t* progress, size_t* total);
|
|||
/* 200, 404, or whatever. */
|
||||
int net_http_status(struct http_t *state);
|
||||
|
||||
bool net_http_error(struct http_t *state);
|
||||
|
||||
/* Returns the downloaded data. The returned buffer is owned by the
|
||||
* HTTP handler; it's freed by net_http_delete.
|
||||
*
|
||||
|
|
|
@ -30,14 +30,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct fifo_buffer
|
||||
{
|
||||
uint8_t *buffer;
|
||||
size_t bufsize;
|
||||
size_t first;
|
||||
size_t end;
|
||||
};
|
||||
|
||||
typedef struct fifo_buffer fifo_buffer_t;
|
||||
|
||||
fifo_buffer_t *fifo_new(size_t size);
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/* Copyright (C) 2010-2016 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (task_queue.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_TASK_QUEUE_H__
|
||||
#define __LIBRETRO_SDK_TASK_QUEUE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <boolean.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum task_queue_ctl_state
|
||||
{
|
||||
TASK_QUEUE_CTL_NONE = 0,
|
||||
|
||||
/* Deinitializes the task system.
|
||||
* This deinitializes the task system.
|
||||
* The tasks that are running at
|
||||
* the moment will stay on hold
|
||||
* until TASK_QUEUE_CTL_INIT is called again. */
|
||||
TASK_QUEUE_CTL_DEINIT,
|
||||
|
||||
/* Initializes the task system.
|
||||
* This initializes the task system
|
||||
* and chooses an appropriate
|
||||
* implementation according to the settings.
|
||||
*
|
||||
* This must only be called from the main thread. */
|
||||
TASK_QUEUE_CTL_INIT,
|
||||
|
||||
/**
|
||||
* Calls func for every running task
|
||||
* until it returns true.
|
||||
* Returns a task or NULL if not found.
|
||||
*/
|
||||
TASK_QUEUE_CTL_FIND,
|
||||
|
||||
/* Blocks until all tasks have finished.
|
||||
* This must only be called from the main thread. */
|
||||
TASK_QUEUE_CTL_WAIT,
|
||||
|
||||
/* Checks for finished tasks
|
||||
* Takes the finished tasks, if any,
|
||||
* and runs their callbacks.
|
||||
* This must only be called from the main thread. */
|
||||
TASK_QUEUE_CTL_CHECK,
|
||||
|
||||
/* Pushes a task
|
||||
* The task will start as soon as possible. */
|
||||
TASK_QUEUE_CTL_PUSH,
|
||||
|
||||
/* Sends a signal to terminate all the tasks.
|
||||
*
|
||||
* This won't terminate the tasks immediately.
|
||||
* They will finish as soon as possible.
|
||||
*
|
||||
* This must only be called from the main thread. */
|
||||
TASK_QUEUE_CTL_RESET,
|
||||
|
||||
TASK_QUEUE_CTL_SET_THREADED,
|
||||
|
||||
TASK_QUEUE_CTL_UNSET_THREADED,
|
||||
|
||||
TASK_QUEUE_CTL_IS_THREADED
|
||||
};
|
||||
|
||||
typedef struct retro_task retro_task_t;
|
||||
typedef void (*retro_task_callback_t)(void *task_data,
|
||||
void *user_data, const char *error);
|
||||
|
||||
typedef void (*retro_task_handler_t)(retro_task_t *task);
|
||||
|
||||
typedef bool (*retro_task_finder_t)(retro_task_t *task,
|
||||
void *userdata);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *source_file;
|
||||
} decompress_task_data_t;
|
||||
|
||||
struct retro_task
|
||||
{
|
||||
retro_task_handler_t handler;
|
||||
|
||||
/* always called from the main loop */
|
||||
retro_task_callback_t callback;
|
||||
|
||||
/* set to true by the handler to signal
|
||||
* the task has finished executing. */
|
||||
bool finished;
|
||||
|
||||
/* set to true by the task system
|
||||
* to signal the task *must* end. */
|
||||
bool cancelled;
|
||||
|
||||
/* created by the handler, destroyed by the user */
|
||||
void *task_data;
|
||||
|
||||
/* owned by the user */
|
||||
void *user_data;
|
||||
|
||||
/* created and destroyed by the code related to the handler */
|
||||
void *state;
|
||||
|
||||
/* created by task handler; destroyed by main loop
|
||||
* (after calling the callback) */
|
||||
char *error;
|
||||
|
||||
/* -1 = unmettered, 0-100 progress value */
|
||||
int8_t progress;
|
||||
|
||||
/* handler can modify but will be
|
||||
* free()d automatically if non-NULL. */
|
||||
char *title;
|
||||
|
||||
/* don't touch this. */
|
||||
retro_task_t *next;
|
||||
};
|
||||
|
||||
typedef struct task_finder_data
|
||||
{
|
||||
retro_task_finder_t func;
|
||||
void *userdata;
|
||||
} task_finder_data_t;
|
||||
|
||||
void task_queue_push_progress(retro_task_t *task);
|
||||
|
||||
bool task_queue_ctl(enum task_queue_ctl_state state, void *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -23,18 +23,14 @@
|
|||
#ifndef __RETRO_ASSERT_H
|
||||
#define __RETRO_ASSERT_H
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#include <retro_log.h>
|
||||
#else
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#define rarch_assert(cond) do { \
|
||||
if (!(cond)) { RARCH_ERR("Assertion failed at %s:%d.\n", __FILE__, __LINE__); abort(); } \
|
||||
#define retro_assert(cond) do { \
|
||||
if (!(cond)) { printf("Assertion failed at %s:%d.\n", __FILE__, __LINE__); abort(); } \
|
||||
} while(0)
|
||||
#else
|
||||
#define rarch_assert(cond) assert(cond)
|
||||
#define retro_assert(cond) assert(cond)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,10 +28,6 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <compat/msvc.h>
|
||||
#endif
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -44,7 +40,11 @@ enum
|
|||
{
|
||||
RFILE_MODE_READ = 0,
|
||||
RFILE_MODE_WRITE,
|
||||
RFILE_MODE_READ_WRITE
|
||||
RFILE_MODE_READ_WRITE,
|
||||
|
||||
/* There is no garantee these requests will be attended. */
|
||||
RFILE_HINT_UNBUFFERED = 1<<8,
|
||||
RFILE_HINT_MMAP = 1<<9 /* requires RFILE_MODE_READ */
|
||||
};
|
||||
|
||||
RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len);
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
#ifndef INLINE
|
||||
|
||||
#if !defined(__cplusplus) && defined(_WIN32)
|
||||
#define INLINE _inline
|
||||
#if defined(_WIN32)
|
||||
#define INLINE __inline
|
||||
#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
|
||||
#define INLINE inline
|
||||
#elif defined(__GNUC__)
|
||||
|
|
|
@ -1,278 +0,0 @@
|
|||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2015 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_LOGGER_H
|
||||
#define __RARCH_LOGGER_H
|
||||
|
||||
#ifdef _XBOX1
|
||||
#include <xtl.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __MACH__
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
#include <stdio.h>
|
||||
#else
|
||||
#include <asl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
#include <retro_inline.h>
|
||||
#include <boolean.h>
|
||||
#include <compat/posix_string.h>
|
||||
#include <compat/strl.h>
|
||||
|
||||
#if defined(HAVE_FILE_LOGGER) && defined(RARCH_INTERNAL) && !defined(IS_JOYCONFIG)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
|
||||
FILE *rarch_main_log_file(void);
|
||||
|
||||
#define LOG_FILE (rarch_main_log_file())
|
||||
|
||||
#else
|
||||
#define LOG_FILE (stderr)
|
||||
#endif
|
||||
|
||||
#if defined(IS_SALAMANDER)
|
||||
#define PROGRAM_NAME "RetroArch Salamander"
|
||||
#elif defined(RARCH_INTERNAL)
|
||||
#define PROGRAM_NAME "RetroArch"
|
||||
#elif defined(MARCH_INTERNAL)
|
||||
#define PROGRAM_NAME "MicroArch"
|
||||
#else
|
||||
#define PROGRAM_NAME "N/A"
|
||||
#endif
|
||||
|
||||
#if defined(RARCH_INTERNAL) && !defined(ANDROID)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
bool rarch_main_verbosity(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define RARCH_LOG_VERBOSE (rarch_main_verbosity())
|
||||
#else
|
||||
#define RARCH_LOG_VERBOSE (true)
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_IPHONE && defined(RARCH_INTERNAL) && !TARGET_IPHONE_SIMULATOR
|
||||
static aslclient asl_client;
|
||||
static int asl_inited = 0;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LOGGER) && defined(RARCH_INTERNAL)
|
||||
|
||||
#define BUFSIZE (64 * 1024)
|
||||
#define TCPDUMP_STACKSIZE (16 * 1024)
|
||||
#define TCPDUMP_PRIO (2048)
|
||||
|
||||
void logger_init (void);
|
||||
void logger_shutdown (void);
|
||||
void logger_send (const char *__format,...);
|
||||
void logger_send_v(const char *__format, va_list args);
|
||||
|
||||
#ifdef IS_SALAMANDER
|
||||
|
||||
#define RARCH_LOG(...) do { \
|
||||
logger_send("RetroArch Salamander: " __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define RARCH_LOG_V(tag, fmt, vp) do { \
|
||||
logger_send("RetroArch Salamander: " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_LOG_OUTPUT(...) do { \
|
||||
logger_send("RetroArch Salamander [OUTPUT] :: " __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define RARCH_LOG_OUTPUT_V(tag, fmt, vp) do { \
|
||||
logger_send("RetroArch Salamander [OUTPUT] :: " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_ERR(...) do { \
|
||||
logger_send("RetroArch Salamander [ERROR] :: " __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define RARCH_ERR_V(tag, fmt, vp) do { \
|
||||
logger_send("RetroArch Salamander [ERROR] :: " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_WARN(...) do { \
|
||||
logger_send("RetroArch Salamander [WARN] :: " __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define RARCH_WARN_V(tag, fmt, vp) do { \
|
||||
logger_send("RetroArch Salamander [WARN] :: " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define RARCH_LOG(...) do { \
|
||||
logger_send("RetroArch: " __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define RARCH_LOG_V(tag, fmt, vp) do { \
|
||||
logger_send("RetroArch: " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_ERR(...) do { \
|
||||
logger_send("RetroArch [ERROR] :: " __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define RARCH_ERR_V(tag, fmt, vp) do { \
|
||||
logger_send("RetroArch [ERROR] :: " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_WARN(...) do { \
|
||||
logger_send("RetroArch [WARN] :: " __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define RARCH_WARN_V(tag, fmt, vp) do { \
|
||||
logger_send("RetroArch [WARN] :: " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_LOG_OUTPUT(...) do { \
|
||||
logger_send("RetroArch [OUTPUT] :: " __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define RARCH_LOG_OUTPUT_V(tag, fmt, vp) do { \
|
||||
logger_send("RetroArch [OUTPUT] :: " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
static INLINE void RARCH_LOG_V(const char *tag, const char *fmt, va_list ap)
|
||||
{
|
||||
if (!RARCH_LOG_VERBOSE)
|
||||
return;
|
||||
#if TARGET_OS_IPHONE && defined(RARCH_INTERNAL)
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
vprintf(fmt, ap);
|
||||
#else
|
||||
if (!asl_inited)
|
||||
{
|
||||
asl_client = asl_open("RetroArch", "com.apple.console", ASL_OPT_STDERR | ASL_OPT_NO_DELAY);
|
||||
asl_inited = 1;
|
||||
}
|
||||
aslmsg msg = asl_new(ASL_TYPE_MSG);
|
||||
asl_set(msg, ASL_KEY_READ_UID, "-1");
|
||||
if (tag)
|
||||
asl_log(asl_client, msg, ASL_LEVEL_NOTICE, "%s", tag);
|
||||
asl_vlog(asl_client, msg, ASL_LEVEL_NOTICE, fmt, ap);
|
||||
asl_free(msg);
|
||||
#endif
|
||||
#elif defined(_XBOX1)
|
||||
/* FIXME: Using arbitrary string as fmt argument is unsafe. */
|
||||
char msg_new[1024], buffer[1024];
|
||||
snprintf(msg_new, sizeof(msg_new), "%s: %s %s",
|
||||
PROGRAM_NAME,
|
||||
tag ? tag : "",
|
||||
fmt);
|
||||
wvsprintf(buffer, msg_new, ap);
|
||||
OutputDebugStringA(buffer);
|
||||
#elif defined(ANDROID) && defined(HAVE_LOGGER) && defined(RARCH_INTERNAL)
|
||||
int prio = ANDROID_LOG_INFO;
|
||||
if (tag)
|
||||
{
|
||||
if (!strcmp("[WARN]", tag))
|
||||
prio = ANDROID_LOG_WARN;
|
||||
else if (!strcmp("[ERROR]", tag))
|
||||
prio = ANDROID_LOG_ERROR;
|
||||
}
|
||||
__android_log_vprint(prio, PROGRAM_NAME, fmt, ap);
|
||||
#else
|
||||
fprintf(LOG_FILE, "%s %s :: ", PROGRAM_NAME, tag ? tag : "[INFO]");
|
||||
vfprintf(LOG_FILE, fmt, ap);
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE void RARCH_LOG(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (!RARCH_LOG_VERBOSE)
|
||||
return;
|
||||
|
||||
va_start(ap, fmt);
|
||||
RARCH_LOG_V("[INFO]", fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static INLINE void RARCH_LOG_OUTPUT_V(const char *tag,
|
||||
const char *msg, va_list ap)
|
||||
{
|
||||
RARCH_LOG_V(tag, msg, ap);
|
||||
}
|
||||
|
||||
static INLINE void RARCH_LOG_OUTPUT(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
RARCH_LOG_OUTPUT_V("[INFO]", msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static INLINE void RARCH_WARN_V(const char *tag, const char *fmt, va_list ap)
|
||||
{
|
||||
RARCH_LOG_V(tag, fmt, ap);
|
||||
}
|
||||
|
||||
static INLINE void RARCH_WARN(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
RARCH_WARN_V("[WARN]", fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static INLINE void RARCH_ERR_V(const char *tag, const char *fmt, va_list ap)
|
||||
{
|
||||
RARCH_LOG_V(tag, fmt, ap);
|
||||
}
|
||||
|
||||
static INLINE void RARCH_ERR(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
RARCH_ERR_V("[ERROR]", fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
#define __RARCH_MISCELLANEOUS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
#include <sys/timer.h>
|
||||
|
@ -56,15 +57,23 @@
|
|||
#include <retro_inline.h>
|
||||
|
||||
#ifndef PATH_MAX_LENGTH
|
||||
#if defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(GEKKO)
|
||||
#define PATH_MAX_LENGTH 512
|
||||
#else
|
||||
#define PATH_MAX_LENGTH 4096
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef min
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846264338327
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
@ -136,13 +145,26 @@ static INLINE uint32_t prev_pow2(uint32_t v)
|
|||
return v - (v >> 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* db_to_gain:
|
||||
* @db : Decibels.
|
||||
*
|
||||
* Converts decibels to voltage gain.
|
||||
*
|
||||
* Returns: voltage gain value.
|
||||
**/
|
||||
static INLINE float db_to_gain(float db)
|
||||
{
|
||||
return powf(10.0f, db / 20.0f);
|
||||
}
|
||||
|
||||
/* Helper macros and struct to keep track of many booleans.
|
||||
* To check for multiple bits, use &&, not &.
|
||||
* For OR, | can be used. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t data[8];
|
||||
} rarch_bits_t;
|
||||
} retro_bits_t;
|
||||
|
||||
#define BIT_SET(a, bit) ((a)[(bit) >> 3] |= (1 << ((bit) & 7)))
|
||||
#define BIT_CLEAR(a, bit) ((a)[(bit) >> 3] &= ~(1 << ((bit) & 7)))
|
||||
|
|
|
@ -42,6 +42,8 @@ bool path_is_character_special(const char *path);
|
|||
|
||||
bool path_is_valid(const char *path);
|
||||
|
||||
int32_t path_get_size(const char *path);
|
||||
|
||||
/**
|
||||
* path_mkdir_norecurse:
|
||||
* @dir : directory
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
|
||||
#include <retro_inline.h>
|
||||
|
||||
/**
|
||||
/**
|
||||
* sha256_hash:
|
||||
* @out : Output.
|
||||
* @in : Input.
|
||||
|
@ -84,5 +84,43 @@ int sha1_calculate(const char *path, char *result);
|
|||
|
||||
uint32_t djb2_calculate(const char *str);
|
||||
|
||||
#endif
|
||||
/* Any 32-bit or wider unsigned integer data type will do */
|
||||
typedef unsigned int MD5_u32plus;
|
||||
|
||||
typedef struct {
|
||||
MD5_u32plus lo, hi;
|
||||
MD5_u32plus a, b, c, d;
|
||||
unsigned char buffer[64];
|
||||
MD5_u32plus block[16];
|
||||
} MD5_CTX;
|
||||
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See md5.c for more information.
|
||||
*/
|
||||
|
||||
void MD5_Init(MD5_CTX *ctx);
|
||||
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
|
||||
void MD5_Final(unsigned char *result, MD5_CTX *ctx);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/* Copyright (C) 2010-2015 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (async_job.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_ASYNC_JOB_H
|
||||
#define __LIBRETRO_SDK_ASYNC_JOB_H
|
||||
|
||||
typedef struct async_job async_job_t;
|
||||
typedef void (*async_task_t)(void *payload);
|
||||
|
||||
async_job_t *async_job_new(void);
|
||||
|
||||
void async_job_free(async_job_t *ajob);
|
||||
|
||||
int async_job_add(async_job_t *ajob, async_task_t task, void *payload);
|
||||
|
||||
#endif /* __LIBRETRO_SDK_ASYNC_JOB_H */
|
|
@ -0,0 +1,44 @@
|
|||
/* Copyright (C) 2010-2015 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (rsemaphore.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_SEMAPHORE_H
|
||||
#define __LIBRETRO_SDK_SEMAPHORE_H
|
||||
|
||||
typedef struct ssem ssem_t;
|
||||
|
||||
/**
|
||||
* ssem_create:
|
||||
* @value : initial value for the semaphore
|
||||
*
|
||||
* Create a new semaphore.
|
||||
*
|
||||
* Returns: pointer to new semaphore if successful, otherwise NULL.
|
||||
*/
|
||||
ssem_t *ssem_new(int value);
|
||||
|
||||
void ssem_free(ssem_t *semaphore);
|
||||
|
||||
void ssem_wait(ssem_t *semaphore);
|
||||
|
||||
void ssem_signal(ssem_t *semaphore);
|
||||
|
||||
#endif /* __LIBRETRO_SDK_SEMAPHORE_H */
|
|
@ -28,7 +28,8 @@
|
|||
#include <retro_inline.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#if defined(__cplusplus) && !defined(_MSC_VER)
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
@ -170,7 +171,7 @@ int scond_broadcast(scond_t *cond);
|
|||
**/
|
||||
void scond_signal(scond_t *cond);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#if defined(__cplusplus) && !defined(_MSC_VER)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -34,8 +34,14 @@ extern "C" {
|
|||
|
||||
bool string_is_empty(const char *data);
|
||||
|
||||
bool string_is_equal(const char *a, const char *b);
|
||||
|
||||
bool string_is_equal_noncase(const char *a, const char *b);
|
||||
|
||||
char *string_to_upper(char *s);
|
||||
|
||||
char *string_to_lower(char *s);
|
||||
|
||||
char *string_replace_substring(const char *in, const char *pattern,
|
||||
const char *by);
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ struct string_list
|
|||
*
|
||||
* Returns: true (1) if element could be found, otherwise false (0).
|
||||
*/
|
||||
bool string_list_find_elem(const struct string_list *list, const char *elem);
|
||||
int string_list_find_elem(const struct string_list *list, const char *elem);
|
||||
|
||||
/**
|
||||
* string_list_find_elem_prefix:
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
TARGETS = http_test net_ifinfo
|
||||
|
||||
INCFLAGS = -I../include -I../include/net
|
||||
|
||||
SOURCES := $(wildcard *.c) \
|
||||
../compat/compat.c
|
||||
OBJS := $(SOURCES:.c=.o)
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
CFLAGS += -O0 -g
|
||||
else
|
||||
CFLAGS += -O2
|
||||
endif
|
||||
CFLAGS += -Wall -pedantic -std=gnu99
|
||||
|
||||
HTTP_TEST_C = \
|
||||
net_http.c \
|
||||
net_http_test.c \
|
||||
net_compat.c \
|
||||
../compat/compat_strl.c
|
||||
|
||||
HTTP_TEST_OBJS := $(HTTP_TEST_C:.c=.o)
|
||||
|
||||
NET_IFINFO_C = \
|
||||
net_ifinfo.c \
|
||||
net_ifinfo_test.c
|
||||
|
||||
NET_IFINFO_OBJS := $(NET_IFINFO_C:.c=.o)
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(INCFLAGS) $< -c $(CFLAGS) -o $@
|
||||
|
||||
http_test: $(HTTP_TEST_OBJS)
|
||||
$(CC) $(INCFLAGS) $(HTTP_TEST_OBJS) $(CFLAGS) -o $@
|
||||
|
||||
net_ifinfo: $(NET_IFINFO_OBJS)
|
||||
$(CC) $(INCFLAGS) $(NET_IFINFO_OBJS) $(CFLAGS) -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(TARGETS) $(HTTP_TEST_OBJS) $(NET_IFINFO_OBJS)
|
|
@ -1,17 +1,23 @@
|
|||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2015 - Daniel De Matteis
|
||||
/* Copyright (C) 2010-2016 The RetroArch team
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (net_compat.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
@ -20,8 +26,77 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <net/net_compat.h>
|
||||
#include <compat/strl.h>
|
||||
|
||||
int getaddrinfo_rarch(const char *node, const char *service,
|
||||
#if defined(VITA)
|
||||
static void *_net_compat_net_memory = NULL;
|
||||
#define COMPAT_NET_INIT_SIZE 512*1024
|
||||
#define INET_ADDRSTRLEN sizeof(struct sockaddr_in)
|
||||
#define MAX_NAME 512
|
||||
|
||||
typedef uint32_t in_addr_t;
|
||||
|
||||
struct in_addr
|
||||
{
|
||||
in_addr_t s_addr;
|
||||
};
|
||||
|
||||
char *inet_ntoa(struct SceNetInAddr in)
|
||||
{
|
||||
static char ip_addr[INET_ADDRSTRLEN + 1];
|
||||
|
||||
if(sceNetInetNtop(AF_INET, &in, ip_addr, INET_ADDRSTRLEN) == NULL)
|
||||
strlcpy(ip_addr, "Invalid", sizeof(ip_addr));
|
||||
|
||||
return ip_addr;
|
||||
}
|
||||
|
||||
struct SceNetInAddr inet_aton(const char *ip_addr)
|
||||
{
|
||||
SceNetInAddr inaddr;
|
||||
|
||||
sceNetInetPton(AF_INET, ip_addr, &inaddr);
|
||||
return inaddr;
|
||||
}
|
||||
|
||||
unsigned int inet_addr(const char *cp)
|
||||
{
|
||||
return inet_aton(cp).s_addr;
|
||||
}
|
||||
|
||||
struct hostent *gethostbyname(const char *name)
|
||||
{
|
||||
int err;
|
||||
static struct hostent ent;
|
||||
static char sname[MAX_NAME] = "";
|
||||
static struct SceNetInAddr saddr = { 0 };
|
||||
static char *addrlist[2] = { (char *) &saddr, NULL };
|
||||
int rid = sceNetResolverCreate("resolver", NULL, 0);
|
||||
|
||||
if(rid < 0)
|
||||
return NULL;
|
||||
|
||||
err = sceNetResolverStartNtoa(rid, name, &saddr, 0,0,0);
|
||||
sceNetResolverDestroy(rid);
|
||||
if(err < 0)
|
||||
return NULL;
|
||||
|
||||
addrlist[0] = inet_ntoa(saddr);
|
||||
ent.h_name = sname;
|
||||
ent.h_aliases = 0;
|
||||
ent.h_addrtype = AF_INET;
|
||||
ent.h_length = sizeof(struct in_addr);
|
||||
ent.h_addr_list = addrlist;
|
||||
ent.h_addr = addrlist[0];
|
||||
|
||||
return &ent;
|
||||
}
|
||||
|
||||
int retro_epoll_fd;
|
||||
|
||||
#endif
|
||||
|
||||
int getaddrinfo_retro(const char *node, const char *service,
|
||||
const struct addrinfo *hints,
|
||||
struct addrinfo **res)
|
||||
{
|
||||
|
@ -75,7 +150,7 @@ error:
|
|||
#endif
|
||||
}
|
||||
|
||||
void freeaddrinfo_rarch(struct addrinfo *res)
|
||||
void freeaddrinfo_retro(struct addrinfo *res)
|
||||
{
|
||||
#ifdef HAVE_SOCKET_LEGACY
|
||||
free(res->ai_addr);
|
||||
|
@ -87,7 +162,7 @@ void freeaddrinfo_rarch(struct addrinfo *res)
|
|||
|
||||
bool socket_nonblock(int fd)
|
||||
{
|
||||
#if defined(__CELLOS_LV2__)
|
||||
#if defined(__CELLOS_LV2__) || defined(VITA)
|
||||
int i = 1;
|
||||
setsockopt(fd, SOL_SOCKET, SO_NBIO, &i, sizeof(int));
|
||||
return true;
|
||||
|
@ -106,6 +181,8 @@ int socket_close(int fd)
|
|||
return closesocket(fd);
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
return socketclose(fd);
|
||||
#elif defined(VITA)
|
||||
return sceNetSocketClose(fd);
|
||||
#else
|
||||
return close(fd);
|
||||
#endif
|
||||
|
@ -116,6 +193,19 @@ int socket_select(int nfds, fd_set *readfs, fd_set *writefds,
|
|||
{
|
||||
#if defined(__CELLOS_LV2__)
|
||||
return socketselect(nfds, readfs, writefds, errorfds, timeout);
|
||||
#elif defined(VITA)
|
||||
SceNetEpollEvent ev = {0};
|
||||
|
||||
ev.events = PSP2_NET_EPOLLIN | PSP2_NET_EPOLLHUP;
|
||||
ev.data.fd = nfds;
|
||||
|
||||
if((sceNetEpollControl(retro_epoll_fd, PSP2_NET_EPOLL_CTL_ADD, nfds, &ev)))
|
||||
{
|
||||
int ret = sceNetEpollWait(retro_epoll_fd, &ev, 1, 0);
|
||||
sceNetEpollControl(retro_epoll_fd, PSP2_NET_EPOLL_CTL_DEL, nfds, NULL);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return select(nfds, readfs, writefds, errorfds, timeout);
|
||||
#endif
|
||||
|
@ -180,6 +270,30 @@ bool network_init(void)
|
|||
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
cellSysmoduleLoadModule(CELL_SYSMODULE_NET);
|
||||
sys_net_initialize_network();
|
||||
#elif defined(VITA)
|
||||
SceNetInitParam initparam;
|
||||
/* Init Net */
|
||||
if (sceNetShowNetstat() == PSP2_NET_ERROR_ENOTINIT)
|
||||
{
|
||||
_net_compat_net_memory = malloc(COMPAT_NET_INIT_SIZE);
|
||||
|
||||
initparam.memory = _net_compat_net_memory;
|
||||
initparam.size = COMPAT_NET_INIT_SIZE;
|
||||
initparam.flags = 0;
|
||||
|
||||
sceNetInit(&initparam);
|
||||
//printf("sceNetInit(): 0x%08X\n", ret);
|
||||
|
||||
/* Init NetCtl */
|
||||
sceNetCtlInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("Net is already initialized.\n");
|
||||
}
|
||||
|
||||
retro_epoll_fd = sceNetEpollCreate("epoll", 0);
|
||||
//printf("Epoll %x\n",retro_epoll_fd);
|
||||
#else
|
||||
signal(SIGPIPE, SIG_IGN); /* Do not like SIGPIPE killing our app. */
|
||||
#endif
|
||||
|
@ -200,5 +314,14 @@ void network_deinit(void)
|
|||
#elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
sys_net_finalize_network();
|
||||
cellSysmoduleUnloadModule(CELL_SYSMODULE_NET);
|
||||
#elif defined(VITA)
|
||||
sceNetCtlTerm();
|
||||
sceNetTerm();
|
||||
|
||||
if (_net_compat_net_memory)
|
||||
{
|
||||
free(_net_compat_net_memory);
|
||||
_net_compat_net_memory = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2011-2015 - Daniel De Matteis
|
||||
* Copyright (C) 2014-2015 - Alfred Agrell
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
/* Copyright (C) 2010-2016 The RetroArch team
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (net_http.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
* 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>
|
||||
|
@ -68,10 +74,16 @@ static int net_http_new_socket(const char *domain, int port)
|
|||
{
|
||||
int fd;
|
||||
#ifndef _WIN32
|
||||
#ifndef VITA
|
||||
struct timeval timeout;
|
||||
#endif
|
||||
#endif
|
||||
struct addrinfo hints, *addr = NULL;
|
||||
char portstr[16] = {0};
|
||||
|
||||
/* Initialize the network. */
|
||||
if (!network_init())
|
||||
return -1;
|
||||
|
||||
snprintf(portstr, sizeof(portstr), "%i", port);
|
||||
|
||||
|
@ -79,8 +91,8 @@ static int net_http_new_socket(const char *domain, int port)
|
|||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = 0;
|
||||
|
||||
if (getaddrinfo_rarch(domain, portstr, &hints, &addr) < 0)
|
||||
|
||||
if (getaddrinfo_retro(domain, portstr, &hints, &addr) < 0)
|
||||
return -1;
|
||||
if (!addr)
|
||||
return -1;
|
||||
|
@ -88,19 +100,20 @@ static int net_http_new_socket(const char *domain, int port)
|
|||
fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef VITA
|
||||
timeout.tv_sec=4;
|
||||
timeout.tv_usec=0;
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof timeout);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
if (connect(fd, addr->ai_addr, addr->ai_addrlen) != 0)
|
||||
{
|
||||
freeaddrinfo_rarch(addr);
|
||||
freeaddrinfo_retro(addr);
|
||||
socket_close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
freeaddrinfo_rarch(addr);
|
||||
freeaddrinfo_retro(addr);
|
||||
|
||||
if (!socket_nonblock(fd))
|
||||
{
|
||||
|
@ -194,8 +207,7 @@ error:
|
|||
if (conn->urlcopy)
|
||||
free(conn->urlcopy);
|
||||
conn->urlcopy = NULL;
|
||||
if (conn)
|
||||
free(conn);
|
||||
free(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -254,6 +266,11 @@ void net_http_connection_free(struct http_connection_t *conn)
|
|||
free(conn);
|
||||
}
|
||||
|
||||
const char *net_http_connection_url(struct http_connection_t *conn)
|
||||
{
|
||||
return conn->urlcopy;
|
||||
}
|
||||
|
||||
struct http_t *net_http_new(struct http_connection_t *conn)
|
||||
{
|
||||
bool error;
|
||||
|
@ -517,7 +534,7 @@ fail:
|
|||
state->status = -1;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int net_http_status(struct http_t *state)
|
||||
|
@ -532,8 +549,7 @@ uint8_t* net_http_data(struct http_t *state, size_t* len, bool accept_error)
|
|||
if (!state)
|
||||
return NULL;
|
||||
|
||||
if (!accept_error &&
|
||||
(state->error || state->status<200 || state->status>299))
|
||||
if (!accept_error && net_http_error(state))
|
||||
{
|
||||
if (len)
|
||||
*len=0;
|
||||
|
@ -553,7 +569,10 @@ void net_http_delete(struct http_t *state)
|
|||
|
||||
if (state->fd != -1)
|
||||
socket_close(state->fd);
|
||||
if (state->data)
|
||||
free(state->data);
|
||||
free(state);
|
||||
}
|
||||
|
||||
bool net_http_error(struct http_t *state)
|
||||
{
|
||||
return (state->error || state->status<200 || state->status>299);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,25 @@
|
|||
/* Copyright (C) 2010-2016 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (net_http_test.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 <net/net_http.h>
|
||||
#include <net/net_compat.h>
|
||||
|
@ -9,7 +31,7 @@
|
|||
int main(void)
|
||||
{
|
||||
char *data;
|
||||
http_t *http1, *http2, *http3;
|
||||
struct http_t *http1, *http3;
|
||||
size_t len, pos = 0, tot = 0;
|
||||
|
||||
if (!network_init())
|
||||
|
|
|
@ -25,6 +25,14 @@
|
|||
|
||||
#include <queues/fifo_buffer.h>
|
||||
|
||||
struct fifo_buffer
|
||||
{
|
||||
uint8_t *buffer;
|
||||
size_t bufsize;
|
||||
size_t first;
|
||||
size_t end;
|
||||
};
|
||||
|
||||
fifo_buffer_t *fifo_new(size_t size)
|
||||
{
|
||||
fifo_buffer_t *buf = (fifo_buffer_t*)calloc(1, sizeof(*buf));
|
||||
|
|
|
@ -0,0 +1,461 @@
|
|||
/* Copyright (C) 2010-2016 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (task_queue.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <queues/task_queue.h>
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#include <rthreads/rthreads.h>
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
retro_task_t *front;
|
||||
retro_task_t *back;
|
||||
} task_queue_t;
|
||||
|
||||
struct retro_task_impl
|
||||
{
|
||||
void (*push_running)(retro_task_t *);
|
||||
void (*reset)(void);
|
||||
void (*wait)(void);
|
||||
void (*gather)(void);
|
||||
bool (*find)(retro_task_finder_t, void*);
|
||||
void (*init)(void);
|
||||
void (*deinit)(void);
|
||||
};
|
||||
|
||||
static task_queue_t tasks_running = {NULL, NULL};
|
||||
static task_queue_t tasks_finished = {NULL, NULL};
|
||||
|
||||
#ifndef RARCH_INTERNAL
|
||||
static void task_queue_msg_push(unsigned prio, unsigned duration,
|
||||
bool flush, const char *fmt, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* print something here */
|
||||
}
|
||||
|
||||
void task_queue_push_progress(retro_task_t *task)
|
||||
{
|
||||
if (task->title)
|
||||
{
|
||||
if (task->finished)
|
||||
{
|
||||
if (task->error)
|
||||
task_queue_msg_push(1, 60, true, "%s: %s",
|
||||
"Task failed\n", task->title);
|
||||
else
|
||||
task_queue_msg_push(1, 60, true, "100%%: %s", task->title);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (task->progress >= 0 && task->progress <= 100)
|
||||
task_queue_msg_push(1, 60, true, "%i%%: %s",
|
||||
task->progress, task->title);
|
||||
else
|
||||
task_queue_msg_push(1, 60, true, "%s...", task->title);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void task_queue_put(task_queue_t *queue, retro_task_t *task)
|
||||
{
|
||||
task->next = NULL;
|
||||
|
||||
if (queue->front)
|
||||
queue->back->next = task;
|
||||
else
|
||||
queue->front = task;
|
||||
|
||||
queue->back = task;
|
||||
}
|
||||
|
||||
static retro_task_t *task_queue_get(task_queue_t *queue)
|
||||
{
|
||||
retro_task_t *task = queue->front;
|
||||
|
||||
if (task)
|
||||
{
|
||||
queue->front = task->next;
|
||||
task->next = NULL;
|
||||
}
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
static void retro_task_internal_gather(void)
|
||||
{
|
||||
retro_task_t *task = NULL;
|
||||
while ((task = task_queue_get(&tasks_finished)) != NULL)
|
||||
{
|
||||
task_queue_push_progress(task);
|
||||
|
||||
if (task->callback)
|
||||
task->callback(task->task_data, task->user_data, task->error);
|
||||
|
||||
if (task->error)
|
||||
free(task->error);
|
||||
|
||||
if (task->title)
|
||||
free(task->title);
|
||||
|
||||
free(task);
|
||||
}
|
||||
}
|
||||
|
||||
static void retro_task_regular_push_running(retro_task_t *task)
|
||||
{
|
||||
task_queue_put(&tasks_running, task);
|
||||
}
|
||||
|
||||
static void retro_task_regular_gather(void)
|
||||
{
|
||||
retro_task_t *task = NULL;
|
||||
retro_task_t *queue = NULL;
|
||||
retro_task_t *next = NULL;
|
||||
|
||||
while ((task = task_queue_get(&tasks_running)) != NULL)
|
||||
{
|
||||
task->next = queue;
|
||||
queue = task;
|
||||
}
|
||||
|
||||
for (task = queue; task; task = next)
|
||||
{
|
||||
next = task->next;
|
||||
task->handler(task);
|
||||
|
||||
task_queue_push_progress(task);
|
||||
|
||||
if (task->finished)
|
||||
task_queue_put(&tasks_finished, task);
|
||||
else
|
||||
retro_task_regular_push_running(task);
|
||||
}
|
||||
|
||||
retro_task_internal_gather();
|
||||
}
|
||||
|
||||
static void retro_task_regular_wait(void)
|
||||
{
|
||||
while (tasks_running.front)
|
||||
retro_task_regular_gather();
|
||||
}
|
||||
|
||||
static void retro_task_regular_reset(void)
|
||||
{
|
||||
retro_task_t *task = tasks_running.front;
|
||||
|
||||
for (; task; task = task->next)
|
||||
task->cancelled = true;
|
||||
}
|
||||
|
||||
static void retro_task_regular_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void retro_task_regular_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
static bool retro_task_regular_find(retro_task_finder_t func, void *user_data)
|
||||
{
|
||||
retro_task_t *task = tasks_running.front;
|
||||
|
||||
for (; task; task = task->next)
|
||||
{
|
||||
if (func(task, user_data))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct retro_task_impl impl_regular = {
|
||||
retro_task_regular_push_running,
|
||||
retro_task_regular_reset,
|
||||
retro_task_regular_wait,
|
||||
retro_task_regular_gather,
|
||||
retro_task_regular_find,
|
||||
retro_task_regular_init,
|
||||
retro_task_regular_deinit
|
||||
};
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
static slock_t *running_lock = NULL;
|
||||
static slock_t *finished_lock = NULL;
|
||||
static scond_t *worker_cond = NULL;
|
||||
static sthread_t *worker_thread = NULL;
|
||||
static bool worker_continue = true; /* use running_lock when touching it */
|
||||
|
||||
static void retro_task_threaded_push_running(retro_task_t *task)
|
||||
{
|
||||
slock_lock(running_lock);
|
||||
task_queue_put(&tasks_running, task);
|
||||
scond_signal(worker_cond);
|
||||
slock_unlock(running_lock);
|
||||
}
|
||||
|
||||
static void retro_task_threaded_gather(void)
|
||||
{
|
||||
retro_task_t *task = NULL;
|
||||
|
||||
slock_lock(running_lock);
|
||||
for (task = tasks_running.front; task; task = task->next)
|
||||
task_queue_push_progress(task);
|
||||
|
||||
slock_unlock(running_lock);
|
||||
|
||||
slock_lock(finished_lock);
|
||||
retro_task_internal_gather();
|
||||
slock_unlock(finished_lock);
|
||||
}
|
||||
|
||||
static void retro_task_threaded_wait(void)
|
||||
{
|
||||
bool wait = false;
|
||||
|
||||
do
|
||||
{
|
||||
retro_task_threaded_gather();
|
||||
|
||||
slock_lock(running_lock);
|
||||
wait = (tasks_running.front != NULL);
|
||||
slock_unlock(running_lock);
|
||||
} while (wait);
|
||||
}
|
||||
|
||||
static void retro_task_threaded_reset(void)
|
||||
{
|
||||
retro_task_t *task = NULL;
|
||||
|
||||
slock_lock(running_lock);
|
||||
for (task = tasks_running.front; task; task = task->next)
|
||||
task->cancelled = true;
|
||||
slock_unlock(running_lock);
|
||||
}
|
||||
|
||||
|
||||
static bool retro_task_threaded_find(
|
||||
retro_task_finder_t func, void *user_data)
|
||||
{
|
||||
retro_task_t *task = NULL;
|
||||
|
||||
slock_lock(running_lock);
|
||||
for (task = tasks_running.front; task; task = task->next)
|
||||
{
|
||||
if (func(task, user_data))
|
||||
return true;
|
||||
}
|
||||
slock_unlock(running_lock);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void threaded_worker(void *userdata)
|
||||
{
|
||||
(void)userdata;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
retro_task_t *queue = NULL;
|
||||
retro_task_t *task = NULL;
|
||||
retro_task_t *next = NULL;
|
||||
|
||||
/* pop all into a local queue,
|
||||
* tasks are in the reverse order here. */
|
||||
slock_lock(running_lock);
|
||||
|
||||
if (!worker_continue)
|
||||
break; /* should we keep running until all tasks finished? */
|
||||
|
||||
while ((task = task_queue_get(&tasks_running)) != NULL)
|
||||
{
|
||||
task->next = queue;
|
||||
queue = task;
|
||||
}
|
||||
|
||||
if (queue == NULL) /* no tasks running, lets wait a bit */
|
||||
{
|
||||
scond_wait(worker_cond, running_lock);
|
||||
slock_unlock(running_lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
slock_unlock(running_lock);
|
||||
|
||||
for (task = queue; task; task = next)
|
||||
{
|
||||
next = task->next;
|
||||
task->handler(task);
|
||||
|
||||
if (task->finished)
|
||||
{
|
||||
slock_lock(finished_lock);
|
||||
task_queue_put(&tasks_finished, task);
|
||||
slock_unlock(finished_lock);
|
||||
}
|
||||
else
|
||||
retro_task_threaded_push_running(task);
|
||||
}
|
||||
}
|
||||
|
||||
slock_unlock(running_lock);
|
||||
}
|
||||
|
||||
static void retro_task_threaded_init(void)
|
||||
{
|
||||
running_lock = slock_new();
|
||||
finished_lock = slock_new();
|
||||
worker_cond = scond_new();
|
||||
|
||||
slock_lock(running_lock);
|
||||
worker_continue = true;
|
||||
slock_unlock(running_lock);
|
||||
|
||||
worker_thread = sthread_create(threaded_worker, NULL);
|
||||
}
|
||||
|
||||
static void retro_task_threaded_deinit(void)
|
||||
{
|
||||
slock_lock(running_lock);
|
||||
worker_continue = false;
|
||||
scond_signal(worker_cond);
|
||||
slock_unlock(running_lock);
|
||||
|
||||
sthread_join(worker_thread);
|
||||
|
||||
scond_free(worker_cond);
|
||||
slock_free(running_lock);
|
||||
slock_free(finished_lock);
|
||||
|
||||
worker_thread = NULL;
|
||||
worker_cond = NULL;
|
||||
running_lock = NULL;
|
||||
finished_lock = NULL;
|
||||
}
|
||||
|
||||
static struct retro_task_impl impl_threaded = {
|
||||
retro_task_threaded_push_running,
|
||||
retro_task_threaded_reset,
|
||||
retro_task_threaded_wait,
|
||||
retro_task_threaded_gather,
|
||||
retro_task_threaded_find,
|
||||
retro_task_threaded_init,
|
||||
retro_task_threaded_deinit
|
||||
};
|
||||
#endif
|
||||
|
||||
bool task_queue_ctl(enum task_queue_ctl_state state, void *data)
|
||||
{
|
||||
static struct retro_task_impl *impl_current = NULL;
|
||||
static bool task_threaded_enable = false;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case TASK_QUEUE_CTL_DEINIT:
|
||||
if (impl_current)
|
||||
impl_current->deinit();
|
||||
impl_current = NULL;
|
||||
break;
|
||||
case TASK_QUEUE_CTL_SET_THREADED:
|
||||
task_threaded_enable = true;
|
||||
break;
|
||||
case TASK_QUEUE_CTL_UNSET_THREADED:
|
||||
task_threaded_enable = false;
|
||||
break;
|
||||
case TASK_QUEUE_CTL_IS_THREADED:
|
||||
return task_threaded_enable;
|
||||
case TASK_QUEUE_CTL_INIT:
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
bool *boolean_val = (bool*)data;
|
||||
#endif
|
||||
|
||||
impl_current = &impl_regular;
|
||||
#ifdef HAVE_THREADS
|
||||
if (*boolean_val)
|
||||
{
|
||||
task_queue_ctl(TASK_QUEUE_CTL_SET_THREADED, NULL);
|
||||
impl_current = &impl_threaded;
|
||||
}
|
||||
#endif
|
||||
|
||||
impl_current->init();
|
||||
}
|
||||
break;
|
||||
case TASK_QUEUE_CTL_FIND:
|
||||
{
|
||||
task_finder_data_t *find_data = (task_finder_data_t*)data;
|
||||
if (!impl_current->find(find_data->func, find_data->userdata))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case TASK_QUEUE_CTL_CHECK:
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
bool current_threaded = (impl_current == &impl_threaded);
|
||||
bool want_threaded =
|
||||
task_queue_ctl(TASK_QUEUE_CTL_IS_THREADED, NULL);
|
||||
|
||||
if (want_threaded != current_threaded)
|
||||
task_queue_ctl(TASK_QUEUE_CTL_DEINIT, NULL);
|
||||
|
||||
if (!impl_current)
|
||||
task_queue_ctl(TASK_QUEUE_CTL_INIT, NULL);
|
||||
#endif
|
||||
|
||||
impl_current->gather();
|
||||
}
|
||||
break;
|
||||
case TASK_QUEUE_CTL_PUSH:
|
||||
{
|
||||
/* The lack of NULL checks in the following functions
|
||||
* is proposital to ensure correct control flow by the users. */
|
||||
retro_task_t *task = (retro_task_t*)data;
|
||||
impl_current->push_running(task);
|
||||
break;
|
||||
}
|
||||
case TASK_QUEUE_CTL_RESET:
|
||||
impl_current->reset();
|
||||
break;
|
||||
case TASK_QUEUE_CTL_WAIT:
|
||||
impl_current->wait();
|
||||
break;
|
||||
case TASK_QUEUE_CTL_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
/* Copyright (C) 2010-2015 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (async_job.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rthreads/rthreads.h>
|
||||
#include <rthreads/rsemaphore.h>
|
||||
#include <rthreads/async_job.h>
|
||||
|
||||
typedef struct async_job_node async_job_node_t;
|
||||
|
||||
struct async_job_node
|
||||
{
|
||||
async_task_t task;
|
||||
void *payload;
|
||||
async_job_node_t *next;
|
||||
};
|
||||
|
||||
struct async_job
|
||||
{
|
||||
async_job_node_t *first;
|
||||
async_job_node_t *last;
|
||||
volatile int finish;
|
||||
slock_t *lock;
|
||||
ssem_t *sem;
|
||||
sthread_t* thread;
|
||||
};
|
||||
|
||||
static void async_job_processor(void *userdata)
|
||||
{
|
||||
async_job_node_t *node = NULL;
|
||||
async_job_t *ajob = (async_job_t*)userdata;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ssem_wait(ajob->sem);
|
||||
|
||||
if (ajob->finish)
|
||||
return;
|
||||
|
||||
slock_lock(ajob->lock);
|
||||
|
||||
node = ajob->first;
|
||||
ajob->first = node->next;
|
||||
|
||||
slock_unlock(ajob->lock);
|
||||
|
||||
node->task(node->payload);
|
||||
free((void*)node);
|
||||
}
|
||||
}
|
||||
|
||||
async_job_t *async_job_new(void)
|
||||
{
|
||||
async_job_t *ajob = (async_job_t*)calloc(1, sizeof(*ajob));
|
||||
|
||||
if (!ajob)
|
||||
return NULL;
|
||||
|
||||
ajob->lock = slock_new();
|
||||
|
||||
if (!ajob->lock)
|
||||
goto error;
|
||||
|
||||
ajob->sem = ssem_new(0);
|
||||
|
||||
if (!ajob->sem)
|
||||
goto error;
|
||||
|
||||
ajob->thread = sthread_create(async_job_processor, (void*)ajob);
|
||||
|
||||
if (!ajob->thread)
|
||||
goto error;
|
||||
|
||||
return ajob;
|
||||
|
||||
error:
|
||||
if (ajob->lock)
|
||||
slock_free(ajob->lock);
|
||||
ajob->lock = NULL;
|
||||
if (ajob->sem)
|
||||
ssem_free(ajob->sem);
|
||||
if (ajob)
|
||||
free((void*)ajob);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void async_job_free(async_job_t *ajob)
|
||||
{
|
||||
if (!ajob)
|
||||
return;
|
||||
|
||||
ajob->finish = 1;
|
||||
ssem_signal(ajob->sem);
|
||||
sthread_join(ajob->thread);
|
||||
ssem_free(ajob->sem);
|
||||
|
||||
free((void*)ajob);
|
||||
}
|
||||
|
||||
int async_job_add(async_job_t *ajob, async_task_t task, void *payload)
|
||||
{
|
||||
async_job_node_t *node;
|
||||
|
||||
if (!ajob)
|
||||
return -1;
|
||||
|
||||
node = (async_job_node_t*)calloc(1, sizeof(*node));
|
||||
|
||||
if (!node)
|
||||
return -1;
|
||||
|
||||
node->task = task;
|
||||
node->payload = payload;
|
||||
|
||||
slock_lock(ajob->lock);
|
||||
|
||||
if (ajob->first)
|
||||
{
|
||||
ajob->last->next = node;
|
||||
ajob->last = node;
|
||||
}
|
||||
else
|
||||
ajob->first = ajob->last = node;
|
||||
|
||||
slock_unlock(ajob->lock);
|
||||
ssem_signal(ajob->sem);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
Copyright 2005 Allen B. Downey
|
||||
|
||||
This file contains an example program from The Little Book of
|
||||
Semaphores, available from Green Tea Press, greenteapress.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see http://www.gnu.org/licenses/gpl.html
|
||||
or write to the Free Software Foundation, Inc., 51 Franklin St,
|
||||
Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* Code taken from http://greenteapress.com/semaphores/semaphore.c
|
||||
* and changed to use libretro-common's mutexes and conditions.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rthreads/rthreads.h>
|
||||
#include <rthreads/rsemaphore.h>
|
||||
|
||||
struct ssem
|
||||
{
|
||||
int value;
|
||||
int wakeups;
|
||||
slock_t *mutex;
|
||||
scond_t *cond;
|
||||
};
|
||||
|
||||
ssem_t *ssem_new(int value)
|
||||
{
|
||||
ssem_t *semaphore = (ssem_t*)calloc(1, sizeof(*semaphore));
|
||||
|
||||
if (!semaphore)
|
||||
goto error;
|
||||
|
||||
semaphore->value = value;
|
||||
semaphore->wakeups = 0;
|
||||
semaphore->mutex = slock_new();
|
||||
|
||||
if (!semaphore->mutex)
|
||||
goto error;
|
||||
|
||||
semaphore->cond = scond_new();
|
||||
|
||||
if (!semaphore->cond)
|
||||
goto error;
|
||||
|
||||
return semaphore;
|
||||
|
||||
error:
|
||||
if (semaphore->mutex)
|
||||
slock_free(semaphore->mutex);
|
||||
semaphore->mutex = NULL;
|
||||
if (semaphore)
|
||||
free((void*)semaphore);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ssem_free(ssem_t *semaphore)
|
||||
{
|
||||
if (!semaphore)
|
||||
return;
|
||||
|
||||
scond_free(semaphore->cond);
|
||||
slock_free(semaphore->mutex);
|
||||
free((void*)semaphore);
|
||||
}
|
||||
|
||||
void ssem_wait(ssem_t *semaphore)
|
||||
{
|
||||
if (!semaphore)
|
||||
return;
|
||||
|
||||
slock_lock(semaphore->mutex);
|
||||
semaphore->value--;
|
||||
|
||||
if (semaphore->value < 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
scond_wait(semaphore->cond, semaphore->mutex);
|
||||
}while (semaphore->wakeups < 1);
|
||||
|
||||
semaphore->wakeups--;
|
||||
}
|
||||
|
||||
slock_unlock(semaphore->mutex);
|
||||
}
|
||||
|
||||
void ssem_signal(ssem_t *semaphore)
|
||||
{
|
||||
if (!semaphore)
|
||||
return;
|
||||
|
||||
slock_lock(semaphore->mutex);
|
||||
semaphore->value++;
|
||||
|
||||
if (semaphore->value <= 0)
|
||||
{
|
||||
semaphore->wakeups++;
|
||||
scond_signal(semaphore->cond);
|
||||
}
|
||||
|
||||
slock_unlock(semaphore->mutex);
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <rthreads/rthreads.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
@ -104,34 +105,37 @@ static void *thread_wrap(void *data_)
|
|||
*/
|
||||
sthread_t *sthread_create(void (*thread_func)(void*), void *userdata)
|
||||
{
|
||||
sthread_t *thread = (sthread_t*)calloc(1, sizeof(*thread));
|
||||
struct thread_data *data;
|
||||
bool thread_created = false;
|
||||
struct thread_data *data = NULL;
|
||||
sthread_t *thread = (sthread_t*)calloc(1, sizeof(*thread));
|
||||
|
||||
if (!thread)
|
||||
return NULL;
|
||||
|
||||
data = (struct thread_data*)calloc(1, sizeof(*data));
|
||||
data = (struct thread_data*)calloc(1, sizeof(*data));
|
||||
if (!data)
|
||||
{
|
||||
free(thread);
|
||||
return NULL;
|
||||
}
|
||||
goto error;
|
||||
|
||||
data->func = thread_func;
|
||||
data->userdata = userdata;
|
||||
|
||||
#ifdef _WIN32
|
||||
thread->thread = CreateThread(NULL, 0, thread_wrap, data, 0, NULL);
|
||||
if (!thread->thread)
|
||||
thread_created = thread->thread;
|
||||
#else
|
||||
if (pthread_create(&thread->id, NULL, thread_wrap, data) < 0)
|
||||
thread_created = pthread_create(&thread->id, NULL, thread_wrap, data) == 0;
|
||||
#endif
|
||||
{
|
||||
free(data);
|
||||
free(thread);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!thread_created)
|
||||
goto error;
|
||||
|
||||
return thread;
|
||||
|
||||
error:
|
||||
if (data)
|
||||
free(data);
|
||||
free(thread);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -188,22 +192,26 @@ void sthread_join(sthread_t *thread)
|
|||
**/
|
||||
slock_t *slock_new(void)
|
||||
{
|
||||
slock_t *lock = (slock_t*)calloc(1, sizeof(*lock));
|
||||
bool mutex_created = false;
|
||||
slock_t *lock = (slock_t*)calloc(1, sizeof(*lock));
|
||||
if (!lock)
|
||||
return NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
lock->lock = CreateMutex(NULL, FALSE, NULL);
|
||||
if (!lock->lock)
|
||||
lock->lock = CreateMutex(NULL, FALSE, NULL);
|
||||
mutex_created = lock->lock;
|
||||
#else
|
||||
if (pthread_mutex_init(&lock->lock, NULL) < 0)
|
||||
mutex_created = (pthread_mutex_init(&lock->lock, NULL) == 0);
|
||||
#endif
|
||||
{
|
||||
free(lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!mutex_created)
|
||||
goto error;
|
||||
|
||||
return lock;
|
||||
|
||||
error:
|
||||
free(lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -268,22 +276,27 @@ void slock_unlock(slock_t *lock)
|
|||
**/
|
||||
scond_t *scond_new(void)
|
||||
{
|
||||
scond_t *cond = (scond_t*)calloc(1, sizeof(*cond));
|
||||
bool event_created = false;
|
||||
scond_t *cond = (scond_t*)calloc(1, sizeof(*cond));
|
||||
|
||||
if (!cond)
|
||||
return NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
cond->event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (!cond->event)
|
||||
cond->event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
event_created = cond->event;
|
||||
#else
|
||||
if (pthread_cond_init(&cond->cond, NULL) < 0)
|
||||
event_created = (pthread_cond_init(&cond->cond, NULL) == 0);
|
||||
#endif
|
||||
{
|
||||
free(cond);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!event_created)
|
||||
goto error;
|
||||
|
||||
return cond;
|
||||
|
||||
error:
|
||||
free(cond);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,70 +26,79 @@
|
|||
|
||||
bool string_is_empty(const char *data)
|
||||
{
|
||||
char **str = NULL;
|
||||
return data==NULL || *data=='\0';
|
||||
}
|
||||
|
||||
if (!data)
|
||||
return true;
|
||||
bool string_is_equal(const char *a, const char *b)
|
||||
{
|
||||
if (!a || !b)
|
||||
return false;
|
||||
return (strcmp(a, b) == 0);
|
||||
}
|
||||
|
||||
str = (char**)&data;
|
||||
if (**str == '\0')
|
||||
return true;
|
||||
return false;
|
||||
bool string_is_equal_noncase(const char *a, const char *b)
|
||||
{
|
||||
if (!a || !b)
|
||||
return false;
|
||||
return (strcasecmp(a, b) == 0);
|
||||
}
|
||||
|
||||
char *string_to_upper(char *s)
|
||||
{
|
||||
unsigned char *ucs = (unsigned char *)s;
|
||||
for ( ; *ucs != '\0'; ucs++)
|
||||
*ucs = toupper(*ucs);
|
||||
char *cs = (char *)s;
|
||||
for ( ; *cs != '\0'; cs++)
|
||||
*cs = toupper(*cs);
|
||||
return s;
|
||||
}
|
||||
|
||||
char *string_replace_substring(const char *in, const char *pattern, const char *replacement)
|
||||
char *string_to_lower(char *s)
|
||||
{
|
||||
char *needle = NULL;
|
||||
char *newstr = NULL;
|
||||
char *head = NULL;
|
||||
size_t pattern_len = 0;
|
||||
size_t replacement_len = 0;
|
||||
char *cs = (char *)s;
|
||||
for ( ; *cs != '\0'; cs++)
|
||||
*cs = tolower(*cs);
|
||||
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;
|
||||
const char *inprev;
|
||||
char *out, *outat;
|
||||
|
||||
/* 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;
|
||||
|
||||
newstr = strdup(in);
|
||||
head = newstr;
|
||||
|
||||
while ((needle = strstr(head, pattern)))
|
||||
while ((inat = strstr(inat, pattern)))
|
||||
{
|
||||
char *oldstr = newstr;
|
||||
size_t oldstr_len = strlen(oldstr);
|
||||
|
||||
newstr = (char*)malloc(oldstr_len - pattern_len + replacement_len + 1);
|
||||
|
||||
if (!newstr)
|
||||
{
|
||||
/* Failed to allocate memory,
|
||||
* free old string and return NULL. */
|
||||
free(oldstr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(newstr, oldstr, needle - oldstr);
|
||||
memcpy(newstr + (needle - oldstr), replacement, replacement_len);
|
||||
memcpy(newstr + (needle - oldstr) + replacement_len,
|
||||
needle + pattern_len,
|
||||
oldstr_len - pattern_len - (needle - oldstr));
|
||||
newstr[oldstr_len - pattern_len + replacement_len] = '\0';
|
||||
|
||||
/* Move back head right after the last replacement. */
|
||||
head = newstr + (needle - oldstr) + replacement_len;
|
||||
free(oldstr);
|
||||
inat += pattern_len;
|
||||
numhits++;
|
||||
}
|
||||
|
||||
outlen = strlen(in) - pattern_len*numhits + replacement_len*numhits;
|
||||
out = (char *)malloc(outlen+1);
|
||||
outat = out;
|
||||
inat = in;
|
||||
inprev = in;
|
||||
|
||||
return newstr;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ void string_list_free(struct string_list *list)
|
|||
static bool string_list_capacity(struct string_list *list, size_t cap)
|
||||
{
|
||||
struct string_list_elem *new_data = NULL;
|
||||
rarch_assert(cap > list->size);
|
||||
retro_assert(cap > list->size);
|
||||
|
||||
new_data = (struct string_list_elem*)
|
||||
realloc(list->elems, cap * sizeof(*new_data));
|
||||
|
@ -142,7 +142,7 @@ void string_list_set(struct string_list *list,
|
|||
unsigned idx, const char *str)
|
||||
{
|
||||
free(list->elems[idx].data);
|
||||
rarch_assert(list->elems[idx].data = strdup(str));
|
||||
retro_assert(list->elems[idx].data = strdup(str));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -160,9 +160,9 @@ void string_list_join_concat(char *buffer, size_t size,
|
|||
{
|
||||
size_t i, len = strlen(buffer);
|
||||
|
||||
rarch_assert(len < size);
|
||||
retro_assert(len < size);
|
||||
buffer += len;
|
||||
size -= len;
|
||||
size -= len;
|
||||
|
||||
for (i = 0; i < list->size; i++)
|
||||
{
|
||||
|
@ -225,7 +225,7 @@ error:
|
|||
*
|
||||
* Returns: true (1) if element could be found, otherwise false (0).
|
||||
*/
|
||||
bool string_list_find_elem(const struct string_list *list, const char *elem)
|
||||
int string_list_find_elem(const struct string_list *list, const char *elem)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
|
@ -235,7 +235,7 @@ bool string_list_find_elem(const struct string_list *list, const char *elem)
|
|||
for (i = 0; i < list->size; i++)
|
||||
{
|
||||
if (strcasecmp(list->elems[i].data, elem) == 0)
|
||||
return true;
|
||||
return i+1;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -2,7 +2,7 @@ compiler := gcc
|
|||
extra_flags :=
|
||||
use_neon := 0
|
||||
release := release
|
||||
DYLIB :=
|
||||
DYLIB :=
|
||||
|
||||
ifeq ($(platform),)
|
||||
platform = unix
|
||||
|
@ -48,7 +48,7 @@ ifeq ($(platform), unix)
|
|||
DYLIB =
|
||||
else ifeq ($(platform), osx)
|
||||
compiler := $(CC)
|
||||
DYLIB =
|
||||
DYLIB =
|
||||
ldflags := -dynamiclib
|
||||
else
|
||||
extra_flags += -static-libgcc -static-libstdc++
|
||||
|
@ -59,19 +59,27 @@ CC := $(compiler)
|
|||
CXX := $(subst CC,++,$(compiler))
|
||||
flags := -fPIC $(extra_flags) -I../../libretro-common/include
|
||||
asflags := -fPIC $(extra_flags)
|
||||
objects :=
|
||||
LDFLAGS := -lz
|
||||
flags += -std=c99
|
||||
flags += -std=c99 -DMD5_BUILD_UTILITY
|
||||
|
||||
|
||||
ifeq (1,$(use_neon))
|
||||
ASMFLAGS := -INEON/asm
|
||||
asflags += -mfpu=neon
|
||||
endif
|
||||
|
||||
objects += crc32$(DYLIB) djb2$(DYLIB) md5$(DYLIB) sha1$(DYLIB)
|
||||
|
||||
all: build;
|
||||
OBJS += djb2.o md5.o sha1.o crc32.o
|
||||
UTILS += djb2$(DYLIB) md5$(DYLIB) sha1$(DYLIB) crc32$(DYLIB)
|
||||
|
||||
all: djb2$(DYLIB) md5$(DYLIB) sha1$(DYLIB) crc32$(DYLIB)
|
||||
|
||||
djb2$(DYLIB): djb2.o
|
||||
|
||||
md5$(DYLIB): md5.o
|
||||
|
||||
sha1$(DYLIB): sha1.o
|
||||
|
||||
crc32$(DYLIB): crc32.o
|
||||
|
||||
%.o: %.S
|
||||
$(CC) -c -o $@ $(asflags) $(LDFLAGS) $(ASMFLAGS) $<
|
||||
|
@ -82,11 +90,9 @@ all: build;
|
|||
%.$(DYLIB): %.o
|
||||
$(CC) -o $@ $(ldflags) $(flags) $^
|
||||
|
||||
build: $(objects)
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
rm -f *.$(DYLIB)
|
||||
rm -f djb2$(DYLIB) md5$(DYLIB) sha1$(DYLIB) crc32$(DYLIB)
|
||||
|
||||
strip:
|
||||
strip -s *.$(DYLIB)
|
||||
|
|
|
@ -1,523 +1,343 @@
|
|||
/*
|
||||
**********************************************************************
|
||||
** md5.h -- Header file for implementation of MD5 **
|
||||
** RSA Data Security, Inc. MD5 Message Digest Algorithm **
|
||||
** Created: 2/17/90 RLR **
|
||||
** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
|
||||
** Revised (for MD5): RLR 4/27/91 **
|
||||
** -- G modified to have y&~z instead of y&z **
|
||||
** -- FF, GG, HH modified to add in last register done **
|
||||
** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
|
||||
** -- distinct additive constant for each step **
|
||||
** -- round 4 added, working mod 7 **
|
||||
**********************************************************************
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* (This is a heavily cut-down "BSD license".)
|
||||
*
|
||||
* This differs from Colin Plumb's older public domain implementation in that
|
||||
* no exactly 32-bit integer data type is required (any 32-bit or wider
|
||||
* unsigned integer data type will do), there's no compile-time endianness
|
||||
* configuration, and the function prototypes match OpenSSL's. No code from
|
||||
* Colin Plumb's implementation has been reused; this comment merely compares
|
||||
* the properties of the two independent implementations.
|
||||
*
|
||||
* The primary goals of this implementation are portability and ease of use.
|
||||
* It is meant to be fast, but not as fast as possible. Some known
|
||||
* optimizations are not included to reduce source code size and avoid
|
||||
* compile-time configuration.
|
||||
*/
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
|
||||
** **
|
||||
** License to copy and use this software is granted provided that **
|
||||
** it is identified as the "RSA Data Security, Inc. MD5 Message **
|
||||
** Digest Algorithm" in all material mentioning or referencing this **
|
||||
** software or this function. **
|
||||
** **
|
||||
** License is also granted to make and use derivative works **
|
||||
** provided that such works are identified as "derived from the RSA **
|
||||
** Data Security, Inc. MD5 Message Digest Algorithm" in all **
|
||||
** material mentioning or referencing the derived work. **
|
||||
** **
|
||||
** RSA Data Security, Inc. makes no representations concerning **
|
||||
** either the merchantability of this software or the suitability **
|
||||
** of this software for any particular purpose. It is provided "as **
|
||||
** is" without express or implied warranty of any kind. **
|
||||
** **
|
||||
** These notices must be retained in any copies of any part of this **
|
||||
** documentation and/or software. **
|
||||
**********************************************************************
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
/* Data structure for MD5 (Message Digest) computation */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t i[2]; /* number of _bits_ handled mod 2^64 */
|
||||
uint32_t buf[4]; /* scratch buffer */
|
||||
unsigned char in[64]; /* input buffer */
|
||||
unsigned char digest[16]; /* actual digest after MD5Final call */
|
||||
} MD5_CTX;
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
** End of md5.h **
|
||||
******************************* (cut) ********************************
|
||||
*/
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
** md5.c **
|
||||
** RSA Data Security, Inc. MD5 Message Digest Algorithm **
|
||||
** Created: 2/17/90 RLR **
|
||||
** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version **
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
|
||||
** **
|
||||
** License to copy and use this software is granted provided that **
|
||||
** it is identified as the "RSA Data Security, Inc. MD5 Message **
|
||||
** Digest Algorithm" in all material mentioning or referencing this **
|
||||
** software or this function. **
|
||||
** **
|
||||
** License is also granted to make and use derivative works **
|
||||
** provided that such works are identified as "derived from the RSA **
|
||||
** Data Security, Inc. MD5 Message Digest Algorithm" in all **
|
||||
** material mentioning or referencing the derived work. **
|
||||
** **
|
||||
** RSA Data Security, Inc. makes no representations concerning **
|
||||
** either the merchantability of this software or the suitability **
|
||||
** of this software for any particular purpose. It is provided "as **
|
||||
** is" without express or implied warranty of any kind. **
|
||||
** **
|
||||
** These notices must be retained in any copies of any part of this **
|
||||
** documentation and/or software. **
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/* -- include the following line if the md5.h header file is separate -- */
|
||||
/* #include "md5.h" */
|
||||
|
||||
static unsigned char PADDING[64] = {
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* F, G and H are basic MD5 functions: selection, majority, parity */
|
||||
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
|
||||
/* ROTATE_LEFT rotates x left n bits */
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
|
||||
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
|
||||
/* Rotation is separate from addition to prevent recomputation */
|
||||
#define FF(a, b, c, d, x, s, ac) \
|
||||
{(a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define GG(a, b, c, d, x, s, ac) \
|
||||
{(a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define HH(a, b, c, d, x, s, ac) \
|
||||
{(a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define II(a, b, c, d, x, s, ac) \
|
||||
{(a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
void MD5Init(MD5_CTX *mdContext)
|
||||
{
|
||||
mdContext->i[0] = mdContext->i[1] = (uint32_t)0;
|
||||
|
||||
/* Load magic initialization constants.
|
||||
*/
|
||||
mdContext->buf[0] = (uint32_t)0x67452301;
|
||||
mdContext->buf[1] = (uint32_t)0xefcdab89;
|
||||
mdContext->buf[2] = (uint32_t)0x98badcfe;
|
||||
mdContext->buf[3] = (uint32_t)0x10325476;
|
||||
}
|
||||
|
||||
/* Basic MD5 step. Transform buf based on in.
|
||||
*/
|
||||
static void Transform (uint32_t *buf, uint32_t *in)
|
||||
{
|
||||
uint32_t a = buf[0], b = buf[1], c = buf[2], d = buf[3];
|
||||
|
||||
/* Round 1 */
|
||||
#define S11 7
|
||||
#define S12 12
|
||||
#define S13 17
|
||||
#define S14 22
|
||||
FF ( a, b, c, d, in[ 0], S11, 3614090360); /* 1 */
|
||||
FF ( d, a, b, c, in[ 1], S12, 3905402710); /* 2 */
|
||||
FF ( c, d, a, b, in[ 2], S13, 606105819); /* 3 */
|
||||
FF ( b, c, d, a, in[ 3], S14, 3250441966); /* 4 */
|
||||
FF ( a, b, c, d, in[ 4], S11, 4118548399); /* 5 */
|
||||
FF ( d, a, b, c, in[ 5], S12, 1200080426); /* 6 */
|
||||
FF ( c, d, a, b, in[ 6], S13, 2821735955); /* 7 */
|
||||
FF ( b, c, d, a, in[ 7], S14, 4249261313); /* 8 */
|
||||
FF ( a, b, c, d, in[ 8], S11, 1770035416); /* 9 */
|
||||
FF ( d, a, b, c, in[ 9], S12, 2336552879); /* 10 */
|
||||
FF ( c, d, a, b, in[10], S13, 4294925233); /* 11 */
|
||||
FF ( b, c, d, a, in[11], S14, 2304563134); /* 12 */
|
||||
FF ( a, b, c, d, in[12], S11, 1804603682); /* 13 */
|
||||
FF ( d, a, b, c, in[13], S12, 4254626195); /* 14 */
|
||||
FF ( c, d, a, b, in[14], S13, 2792965006); /* 15 */
|
||||
FF ( b, c, d, a, in[15], S14, 1236535329); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
#define S21 5
|
||||
#define S22 9
|
||||
#define S23 14
|
||||
#define S24 20
|
||||
GG ( a, b, c, d, in[ 1], S21, 4129170786); /* 17 */
|
||||
GG ( d, a, b, c, in[ 6], S22, 3225465664); /* 18 */
|
||||
GG ( c, d, a, b, in[11], S23, 643717713); /* 19 */
|
||||
GG ( b, c, d, a, in[ 0], S24, 3921069994); /* 20 */
|
||||
GG ( a, b, c, d, in[ 5], S21, 3593408605); /* 21 */
|
||||
GG ( d, a, b, c, in[10], S22, 38016083); /* 22 */
|
||||
GG ( c, d, a, b, in[15], S23, 3634488961); /* 23 */
|
||||
GG ( b, c, d, a, in[ 4], S24, 3889429448); /* 24 */
|
||||
GG ( a, b, c, d, in[ 9], S21, 568446438); /* 25 */
|
||||
GG ( d, a, b, c, in[14], S22, 3275163606); /* 26 */
|
||||
GG ( c, d, a, b, in[ 3], S23, 4107603335); /* 27 */
|
||||
GG ( b, c, d, a, in[ 8], S24, 1163531501); /* 28 */
|
||||
GG ( a, b, c, d, in[13], S21, 2850285829); /* 29 */
|
||||
GG ( d, a, b, c, in[ 2], S22, 4243563512); /* 30 */
|
||||
GG ( c, d, a, b, in[ 7], S23, 1735328473); /* 31 */
|
||||
GG ( b, c, d, a, in[12], S24, 2368359562); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
#define S31 4
|
||||
#define S32 11
|
||||
#define S33 16
|
||||
#define S34 23
|
||||
HH ( a, b, c, d, in[ 5], S31, 4294588738); /* 33 */
|
||||
HH ( d, a, b, c, in[ 8], S32, 2272392833); /* 34 */
|
||||
HH ( c, d, a, b, in[11], S33, 1839030562); /* 35 */
|
||||
HH ( b, c, d, a, in[14], S34, 4259657740); /* 36 */
|
||||
HH ( a, b, c, d, in[ 1], S31, 2763975236); /* 37 */
|
||||
HH ( d, a, b, c, in[ 4], S32, 1272893353); /* 38 */
|
||||
HH ( c, d, a, b, in[ 7], S33, 4139469664); /* 39 */
|
||||
HH ( b, c, d, a, in[10], S34, 3200236656); /* 40 */
|
||||
HH ( a, b, c, d, in[13], S31, 681279174); /* 41 */
|
||||
HH ( d, a, b, c, in[ 0], S32, 3936430074); /* 42 */
|
||||
HH ( c, d, a, b, in[ 3], S33, 3572445317); /* 43 */
|
||||
HH ( b, c, d, a, in[ 6], S34, 76029189); /* 44 */
|
||||
HH ( a, b, c, d, in[ 9], S31, 3654602809); /* 45 */
|
||||
HH ( d, a, b, c, in[12], S32, 3873151461); /* 46 */
|
||||
HH ( c, d, a, b, in[15], S33, 530742520); /* 47 */
|
||||
HH ( b, c, d, a, in[ 2], S34, 3299628645); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
#define S41 6
|
||||
#define S42 10
|
||||
#define S43 15
|
||||
#define S44 21
|
||||
II ( a, b, c, d, in[ 0], S41, 4096336452); /* 49 */
|
||||
II ( d, a, b, c, in[ 7], S42, 1126891415); /* 50 */
|
||||
II ( c, d, a, b, in[14], S43, 2878612391); /* 51 */
|
||||
II ( b, c, d, a, in[ 5], S44, 4237533241); /* 52 */
|
||||
II ( a, b, c, d, in[12], S41, 1700485571); /* 53 */
|
||||
II ( d, a, b, c, in[ 3], S42, 2399980690); /* 54 */
|
||||
II ( c, d, a, b, in[10], S43, 4293915773); /* 55 */
|
||||
II ( b, c, d, a, in[ 1], S44, 2240044497); /* 56 */
|
||||
II ( a, b, c, d, in[ 8], S41, 1873313359); /* 57 */
|
||||
II ( d, a, b, c, in[15], S42, 4264355552); /* 58 */
|
||||
II ( c, d, a, b, in[ 6], S43, 2734768916); /* 59 */
|
||||
II ( b, c, d, a, in[13], S44, 1309151649); /* 60 */
|
||||
II ( a, b, c, d, in[ 4], S41, 4149444226); /* 61 */
|
||||
II ( d, a, b, c, in[11], S42, 3174756917); /* 62 */
|
||||
II ( c, d, a, b, in[ 2], S43, 718787259); /* 63 */
|
||||
II ( b, c, d, a, in[ 9], S44, 3951481745); /* 64 */
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
||||
void MD5Update (MD5_CTX *mdContext,
|
||||
unsigned char *inBuf, unsigned int inLen)
|
||||
{
|
||||
uint32_t in[16];
|
||||
int mdi;
|
||||
unsigned int i, ii;
|
||||
|
||||
/* compute number of bytes mod 64 */
|
||||
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
|
||||
|
||||
/* update number of bits */
|
||||
if ((mdContext->i[0] + ((uint32_t)inLen << 3)) < mdContext->i[0])
|
||||
mdContext->i[1]++;
|
||||
mdContext->i[0] += ((uint32_t)inLen << 3);
|
||||
mdContext->i[1] += ((uint32_t)inLen >> 29);
|
||||
|
||||
while (inLen--)
|
||||
{
|
||||
/* add new character to buffer, increment mdi */
|
||||
mdContext->in[mdi++] = *inBuf++;
|
||||
|
||||
/* transform if necessary */
|
||||
if (mdi == 0x40)
|
||||
{
|
||||
for (i = 0, ii = 0; i < 16; i++, ii += 4)
|
||||
in[i] = (((uint32_t)mdContext->in[ii+3]) << 24) |
|
||||
(((uint32_t)mdContext->in[ii+2]) << 16) |
|
||||
(((uint32_t)mdContext->in[ii+1]) << 8) |
|
||||
((uint32_t)mdContext->in[ii]);
|
||||
Transform (mdContext->buf, in);
|
||||
mdi = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MD5Final (MD5_CTX *mdContext)
|
||||
{
|
||||
uint32_t in[16];
|
||||
int mdi;
|
||||
unsigned int i, ii;
|
||||
unsigned int padLen;
|
||||
|
||||
/* save number of bits */
|
||||
in[14] = mdContext->i[0];
|
||||
in[15] = mdContext->i[1];
|
||||
|
||||
/* compute number of bytes mod 64 */
|
||||
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
|
||||
|
||||
/* pad out to 56 mod 64 */
|
||||
padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
|
||||
MD5Update (mdContext, PADDING, padLen);
|
||||
|
||||
/* append length in bits and transform */
|
||||
for (i = 0, ii = 0; i < 14; i++, ii += 4)
|
||||
in[i] = (((uint32_t)mdContext->in[ii+3]) << 24) |
|
||||
(((uint32_t)mdContext->in[ii+2]) << 16) |
|
||||
(((uint32_t)mdContext->in[ii+1]) << 8) |
|
||||
((uint32_t)mdContext->in[ii]);
|
||||
Transform (mdContext->buf, in);
|
||||
|
||||
/* store buffer in digest */
|
||||
for (i = 0, ii = 0; i < 4; i++, ii += 4) {
|
||||
mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
|
||||
mdContext->digest[ii+1] =
|
||||
(unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
|
||||
mdContext->digest[ii+2] =
|
||||
(unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
|
||||
mdContext->digest[ii+3] =
|
||||
(unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
** End of md5.c **
|
||||
******************************* (cut) ********************************
|
||||
*/
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
** md5driver.c -- sample routines to test **
|
||||
** RSA Data Security, Inc. MD5 message digest algorithm. **
|
||||
** Created: 2/16/90 RLR **
|
||||
** Updated: 1/91 SRD **
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
|
||||
** **
|
||||
** RSA Data Security, Inc. makes no representations concerning **
|
||||
** either the merchantability of this software or the suitability **
|
||||
** of this software for any particular purpose. It is provided "as **
|
||||
** is" without express or implied warranty of any kind. **
|
||||
** **
|
||||
** These notices must be retained in any copies of any part of this **
|
||||
** documentation and/or software. **
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
/* -- include the following file if the file md5.h is separate -- */
|
||||
/* #include "md5.h" */
|
||||
#include "rhash.h"
|
||||
|
||||
/* Prints message digest buffer in mdContext as 32 hexadecimal digits.
|
||||
Order is from low-order byte to high-order byte of digest.
|
||||
Each byte is printed with high-order hexadecimal digit first.
|
||||
/*
|
||||
* The basic MD5 functions.
|
||||
*
|
||||
* F and G are optimized compared to their RFC 1321 definitions for
|
||||
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
|
||||
* implementation.
|
||||
*/
|
||||
static void MDPrint(MD5_CTX *mdContext)
|
||||
{
|
||||
int i;
|
||||
#define MD5_F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
#define MD5_G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
|
||||
#define MD5_H(x, y, z) (((x) ^ (y)) ^ (z))
|
||||
#define MD5_H2(x, y, z) ((x) ^ ((y) ^ (z)))
|
||||
#define MD5_I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
printf ("%02x", mdContext->digest[i]);
|
||||
/*
|
||||
* The MD5 transformation for all four rounds.
|
||||
*/
|
||||
#define MD5_STEP(f, a, b, c, d, x, t, s) \
|
||||
(a) += f((b), (c), (d)) + (x) + (t); \
|
||||
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
|
||||
(a) += (b);
|
||||
|
||||
/*
|
||||
* MD5_SET reads 4 input bytes in little-endian byte order and stores them
|
||||
* in a properly aligned word in host byte order.
|
||||
*
|
||||
* The check for little-endian architectures that tolerate unaligned
|
||||
* memory accesses is just an optimization. Nothing will break if it
|
||||
* doesn't work.
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
|
||||
#define MD5_SET(n) \
|
||||
(*(MD5_u32plus *)&ptr[(n) * 4])
|
||||
#define MD5_GET(n) \
|
||||
MD5_SET(n)
|
||||
#else
|
||||
#define MD5_SET(n) \
|
||||
(ctx->block[(n)] = \
|
||||
(MD5_u32plus)ptr[(n) * 4] | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
|
||||
#define MD5_GET(n) \
|
||||
(ctx->block[(n)])
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This processes one or more 64-byte data blocks, but does NOT update
|
||||
* the bit counters. There are no alignment requirements.
|
||||
*/
|
||||
static const void *MD5_body(MD5_CTX *ctx, const void *data, unsigned long size)
|
||||
{
|
||||
const unsigned char *ptr;
|
||||
MD5_u32plus a, b, c, d;
|
||||
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
|
||||
|
||||
ptr = (const unsigned char *)data;
|
||||
|
||||
a = ctx->a;
|
||||
b = ctx->b;
|
||||
c = ctx->c;
|
||||
d = ctx->d;
|
||||
|
||||
do {
|
||||
saved_a = a;
|
||||
saved_b = b;
|
||||
saved_c = c;
|
||||
saved_d = d;
|
||||
|
||||
/* Round 1 */
|
||||
MD5_STEP(MD5_F, a, b, c, d, MD5_SET(0), 0xd76aa478, 7)
|
||||
MD5_STEP(MD5_F, d, a, b, c, MD5_SET(1), 0xe8c7b756, 12)
|
||||
MD5_STEP(MD5_F, c, d, a, b, MD5_SET(2), 0x242070db, 17)
|
||||
MD5_STEP(MD5_F, b, c, d, a, MD5_SET(3), 0xc1bdceee, 22)
|
||||
MD5_STEP(MD5_F, a, b, c, d, MD5_SET(4), 0xf57c0faf, 7)
|
||||
MD5_STEP(MD5_F, d, a, b, c, MD5_SET(5), 0x4787c62a, 12)
|
||||
MD5_STEP(MD5_F, c, d, a, b, MD5_SET(6), 0xa8304613, 17)
|
||||
MD5_STEP(MD5_F, b, c, d, a, MD5_SET(7), 0xfd469501, 22)
|
||||
MD5_STEP(MD5_F, a, b, c, d, MD5_SET(8), 0x698098d8, 7)
|
||||
MD5_STEP(MD5_F, d, a, b, c, MD5_SET(9), 0x8b44f7af, 12)
|
||||
MD5_STEP(MD5_F, c, d, a, b, MD5_SET(10), 0xffff5bb1, 17)
|
||||
MD5_STEP(MD5_F, b, c, d, a, MD5_SET(11), 0x895cd7be, 22)
|
||||
MD5_STEP(MD5_F, a, b, c, d, MD5_SET(12), 0x6b901122, 7)
|
||||
MD5_STEP(MD5_F, d, a, b, c, MD5_SET(13), 0xfd987193, 12)
|
||||
MD5_STEP(MD5_F, c, d, a, b, MD5_SET(14), 0xa679438e, 17)
|
||||
MD5_STEP(MD5_F, b, c, d, a, MD5_SET(15), 0x49b40821, 22)
|
||||
|
||||
/* Round 2 */
|
||||
MD5_STEP(MD5_G, a, b, c, d, MD5_GET(1), 0xf61e2562, 5)
|
||||
MD5_STEP(MD5_G, d, a, b, c, MD5_GET(6), 0xc040b340, 9)
|
||||
MD5_STEP(MD5_G, c, d, a, b, MD5_GET(11), 0x265e5a51, 14)
|
||||
MD5_STEP(MD5_G, b, c, d, a, MD5_GET(0), 0xe9b6c7aa, 20)
|
||||
MD5_STEP(MD5_G, a, b, c, d, MD5_GET(5), 0xd62f105d, 5)
|
||||
MD5_STEP(MD5_G, d, a, b, c, MD5_GET(10), 0x02441453, 9)
|
||||
MD5_STEP(MD5_G, c, d, a, b, MD5_GET(15), 0xd8a1e681, 14)
|
||||
MD5_STEP(MD5_G, b, c, d, a, MD5_GET(4), 0xe7d3fbc8, 20)
|
||||
MD5_STEP(MD5_G, a, b, c, d, MD5_GET(9), 0x21e1cde6, 5)
|
||||
MD5_STEP(MD5_G, d, a, b, c, MD5_GET(14), 0xc33707d6, 9)
|
||||
MD5_STEP(MD5_G, c, d, a, b, MD5_GET(3), 0xf4d50d87, 14)
|
||||
MD5_STEP(MD5_G, b, c, d, a, MD5_GET(8), 0x455a14ed, 20)
|
||||
MD5_STEP(MD5_G, a, b, c, d, MD5_GET(13), 0xa9e3e905, 5)
|
||||
MD5_STEP(MD5_G, d, a, b, c, MD5_GET(2), 0xfcefa3f8, 9)
|
||||
MD5_STEP(MD5_G, c, d, a, b, MD5_GET(7), 0x676f02d9, 14)
|
||||
MD5_STEP(MD5_G, b, c, d, a, MD5_GET(12), 0x8d2a4c8a, 20)
|
||||
|
||||
/* Round 3 */
|
||||
MD5_STEP(MD5_H, a, b, c, d, MD5_GET(5), 0xfffa3942, 4)
|
||||
MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(8), 0x8771f681, 11)
|
||||
MD5_STEP(MD5_H, c, d, a, b, MD5_GET(11), 0x6d9d6122, 16)
|
||||
MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(14), 0xfde5380c, 23)
|
||||
MD5_STEP(MD5_H, a, b, c, d, MD5_GET(1), 0xa4beea44, 4)
|
||||
MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(4), 0x4bdecfa9, 11)
|
||||
MD5_STEP(MD5_H, c, d, a, b, MD5_GET(7), 0xf6bb4b60, 16)
|
||||
MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(10), 0xbebfbc70, 23)
|
||||
MD5_STEP(MD5_H, a, b, c, d, MD5_GET(13), 0x289b7ec6, 4)
|
||||
MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(0), 0xeaa127fa, 11)
|
||||
MD5_STEP(MD5_H, c, d, a, b, MD5_GET(3), 0xd4ef3085, 16)
|
||||
MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(6), 0x04881d05, 23)
|
||||
MD5_STEP(MD5_H, a, b, c, d, MD5_GET(9), 0xd9d4d039, 4)
|
||||
MD5_STEP(MD5_H2, d, a, b, c, MD5_GET(12), 0xe6db99e5, 11)
|
||||
MD5_STEP(MD5_H, c, d, a, b, MD5_GET(15), 0x1fa27cf8, 16)
|
||||
MD5_STEP(MD5_H2, b, c, d, a, MD5_GET(2), 0xc4ac5665, 23)
|
||||
|
||||
/* Round 4 */
|
||||
MD5_STEP(MD5_I, a, b, c, d, MD5_GET(0), 0xf4292244, 6)
|
||||
MD5_STEP(MD5_I, d, a, b, c, MD5_GET(7), 0x432aff97, 10)
|
||||
MD5_STEP(MD5_I, c, d, a, b, MD5_GET(14), 0xab9423a7, 15)
|
||||
MD5_STEP(MD5_I, b, c, d, a, MD5_GET(5), 0xfc93a039, 21)
|
||||
MD5_STEP(MD5_I, a, b, c, d, MD5_GET(12), 0x655b59c3, 6)
|
||||
MD5_STEP(MD5_I, d, a, b, c, MD5_GET(3), 0x8f0ccc92, 10)
|
||||
MD5_STEP(MD5_I, c, d, a, b, MD5_GET(10), 0xffeff47d, 15)
|
||||
MD5_STEP(MD5_I, b, c, d, a, MD5_GET(1), 0x85845dd1, 21)
|
||||
MD5_STEP(MD5_I, a, b, c, d, MD5_GET(8), 0x6fa87e4f, 6)
|
||||
MD5_STEP(MD5_I, d, a, b, c, MD5_GET(15), 0xfe2ce6e0, 10)
|
||||
MD5_STEP(MD5_I, c, d, a, b, MD5_GET(6), 0xa3014314, 15)
|
||||
MD5_STEP(MD5_I, b, c, d, a, MD5_GET(13), 0x4e0811a1, 21)
|
||||
MD5_STEP(MD5_I, a, b, c, d, MD5_GET(4), 0xf7537e82, 6)
|
||||
MD5_STEP(MD5_I, d, a, b, c, MD5_GET(11), 0xbd3af235, 10)
|
||||
MD5_STEP(MD5_I, c, d, a, b, MD5_GET(2), 0x2ad7d2bb, 15)
|
||||
MD5_STEP(MD5_I, b, c, d, a, MD5_GET(9), 0xeb86d391, 21)
|
||||
|
||||
a += saved_a;
|
||||
b += saved_b;
|
||||
c += saved_c;
|
||||
d += saved_d;
|
||||
|
||||
ptr += 64;
|
||||
} while (size -= 64);
|
||||
|
||||
ctx->a = a;
|
||||
ctx->b = b;
|
||||
ctx->c = c;
|
||||
ctx->d = d;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* size of test block */
|
||||
#define TEST_BLOCK_SIZE 1000
|
||||
|
||||
/* number of blocks to process */
|
||||
#define TEST_BLOCKS 10000
|
||||
|
||||
/* number of test bytes = TEST_BLOCK_SIZE * TEST_BLOCKS */
|
||||
static long TEST_BYTES = (long)TEST_BLOCK_SIZE * (long)TEST_BLOCKS;
|
||||
|
||||
/* A time trial routine, to measure the speed of MD5.
|
||||
Measures wall time required to digest TEST_BLOCKS * TEST_BLOCK_SIZE
|
||||
characters.
|
||||
*/
|
||||
static void MDTimeTrial(void)
|
||||
void MD5_Init(MD5_CTX *ctx)
|
||||
{
|
||||
MD5_CTX mdContext;
|
||||
time_t endTime, startTime;
|
||||
unsigned char data[TEST_BLOCK_SIZE];
|
||||
unsigned int i;
|
||||
ctx->a = 0x67452301;
|
||||
ctx->b = 0xefcdab89;
|
||||
ctx->c = 0x98badcfe;
|
||||
ctx->d = 0x10325476;
|
||||
|
||||
/* initialize test data */
|
||||
for (i = 0; i < TEST_BLOCK_SIZE; i++)
|
||||
data[i] = (unsigned char)(i & 0xFF);
|
||||
|
||||
/* start timer */
|
||||
printf ("MD5 time trial. Processing %ld characters...\n", TEST_BYTES);
|
||||
time (&startTime);
|
||||
|
||||
/* digest data in TEST_BLOCK_SIZE byte blocks */
|
||||
MD5Init (&mdContext);
|
||||
for (i = TEST_BLOCKS; i > 0; i--)
|
||||
MD5Update (&mdContext, data, TEST_BLOCK_SIZE);
|
||||
MD5Final (&mdContext);
|
||||
|
||||
/* stop timer, get time difference */
|
||||
time (&endTime);
|
||||
MDPrint (&mdContext);
|
||||
printf (" is digest of test input.\n");
|
||||
printf
|
||||
("Seconds to process test input: %ld\n", (long)(endTime-startTime));
|
||||
printf
|
||||
("Characters processed per second: %ld\n",
|
||||
TEST_BYTES/(endTime-startTime));
|
||||
ctx->lo = 0;
|
||||
ctx->hi = 0;
|
||||
}
|
||||
|
||||
/* Computes the message digest for string inString.
|
||||
Prints out message digest, a space, the string (in quotes) and a
|
||||
carriage return.
|
||||
*/
|
||||
static void MDString(char *inString)
|
||||
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
|
||||
{
|
||||
MD5_CTX mdContext;
|
||||
unsigned int len = strlen (inString);
|
||||
MD5_u32plus saved_lo;
|
||||
unsigned long used, available;
|
||||
|
||||
MD5Init (&mdContext);
|
||||
MD5Update (&mdContext, inString, len);
|
||||
MD5Final (&mdContext);
|
||||
MDPrint (&mdContext);
|
||||
printf (" \"%s\"\n\n", inString);
|
||||
saved_lo = ctx->lo;
|
||||
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
|
||||
ctx->hi++;
|
||||
ctx->hi += size >> 29;
|
||||
|
||||
used = saved_lo & 0x3f;
|
||||
|
||||
if (used) {
|
||||
available = 64 - used;
|
||||
|
||||
if (size < available) {
|
||||
memcpy(&ctx->buffer[used], data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&ctx->buffer[used], data, available);
|
||||
data = (const unsigned char *)data + available;
|
||||
size -= available;
|
||||
MD5_body(ctx, ctx->buffer, 64);
|
||||
}
|
||||
|
||||
if (size >= 64) {
|
||||
data = MD5_body(ctx, data, size & ~(unsigned long)0x3f);
|
||||
size &= 0x3f;
|
||||
}
|
||||
|
||||
memcpy(ctx->buffer, data, size);
|
||||
}
|
||||
|
||||
/* Computes the message digest for a specified file.
|
||||
Prints out message digest, a space, the file name, and a carriage
|
||||
return.
|
||||
*/
|
||||
static void MDFile (char *filename)
|
||||
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
|
||||
{
|
||||
FILE *inFile = fopen (filename, "rb");
|
||||
MD5_CTX mdContext;
|
||||
int bytes;
|
||||
unsigned char data[1024];
|
||||
unsigned long used, available;
|
||||
|
||||
if (inFile == NULL)
|
||||
{
|
||||
printf ("%s can't be opened.\n", filename);
|
||||
return;
|
||||
}
|
||||
used = ctx->lo & 0x3f;
|
||||
|
||||
MD5Init (&mdContext);
|
||||
while ((bytes = fread (data, 1, 1024, inFile)) != 0)
|
||||
MD5Update (&mdContext, data, bytes);
|
||||
MD5Final (&mdContext);
|
||||
MDPrint (&mdContext);
|
||||
printf (" %s\n", filename);
|
||||
fclose (inFile);
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
available = 64 - used;
|
||||
|
||||
if (available < 8) {
|
||||
memset(&ctx->buffer[used], 0, available);
|
||||
MD5_body(ctx, ctx->buffer, 64);
|
||||
used = 0;
|
||||
available = 64;
|
||||
}
|
||||
|
||||
memset(&ctx->buffer[used], 0, available - 8);
|
||||
|
||||
ctx->lo <<= 3;
|
||||
ctx->buffer[56] = ctx->lo;
|
||||
ctx->buffer[57] = ctx->lo >> 8;
|
||||
ctx->buffer[58] = ctx->lo >> 16;
|
||||
ctx->buffer[59] = ctx->lo >> 24;
|
||||
ctx->buffer[60] = ctx->hi;
|
||||
ctx->buffer[61] = ctx->hi >> 8;
|
||||
ctx->buffer[62] = ctx->hi >> 16;
|
||||
ctx->buffer[63] = ctx->hi >> 24;
|
||||
|
||||
MD5_body(ctx, ctx->buffer, 64);
|
||||
|
||||
result[0] = ctx->a;
|
||||
result[1] = ctx->a >> 8;
|
||||
result[2] = ctx->a >> 16;
|
||||
result[3] = ctx->a >> 24;
|
||||
result[4] = ctx->b;
|
||||
result[5] = ctx->b >> 8;
|
||||
result[6] = ctx->b >> 16;
|
||||
result[7] = ctx->b >> 24;
|
||||
result[8] = ctx->c;
|
||||
result[9] = ctx->c >> 8;
|
||||
result[10] = ctx->c >> 16;
|
||||
result[11] = ctx->c >> 24;
|
||||
result[12] = ctx->d;
|
||||
result[13] = ctx->d >> 8;
|
||||
result[14] = ctx->d >> 16;
|
||||
result[15] = ctx->d >> 24;
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
/* Writes the message digest of the data from stdin onto stdout,
|
||||
followed by a carriage return.
|
||||
*/
|
||||
static void MDFilter(void)
|
||||
{
|
||||
MD5_CTX mdContext;
|
||||
int bytes;
|
||||
unsigned char data[16];
|
||||
#ifdef MD5_BUILD_UTILITY
|
||||
|
||||
MD5Init (&mdContext);
|
||||
while ((bytes = fread (data, 1, 16, stdin)) != 0)
|
||||
MD5Update (&mdContext, data, bytes);
|
||||
MD5Final (&mdContext);
|
||||
MDPrint (&mdContext);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
/* Runs a standard suite of test data.
|
||||
*/
|
||||
static void MDTestSuite(void)
|
||||
{
|
||||
printf ("MD5 test suite results:\n\n");
|
||||
MDString ("");
|
||||
MDString ("a");
|
||||
MDString ("abc");
|
||||
MDString ("message digest");
|
||||
MDString ("abcdefghijklmnopqrstuvwxyz");
|
||||
MDString
|
||||
("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
|
||||
MDString
|
||||
("1234567890123456789012345678901234567890\
|
||||
1234567890123456789012345678901234567890");
|
||||
/* Contents of file foo are "abc" */
|
||||
MDFile ("foo");
|
||||
}
|
||||
#include <stdio.h>
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
/* For each command line argument in turn:
|
||||
** filename -- prints message digest and name of file
|
||||
** -sstring -- prints message digest and contents of string
|
||||
** -t -- prints time trial statistics for 1M characters
|
||||
** -x -- execute a standard suite of test data
|
||||
** (no args) -- writes messages digest of stdin onto stdout
|
||||
*/
|
||||
if (argc == 1)
|
||||
MDFilter ();
|
||||
else
|
||||
for (i = 1; i < argc; i++)
|
||||
if (argv[i][0] == '-' && argv[i][1] == 's')
|
||||
MDString (argv[i] + 2);
|
||||
else if (!strcmp (argv[i], "-t"))
|
||||
MDTimeTrial ();
|
||||
else if (!strcmp (argv[i], "-x"))
|
||||
MDTestSuite ();
|
||||
else MDFile (argv[i]);
|
||||
int i;
|
||||
MD5_CTX ctx;
|
||||
FILE* file;
|
||||
size_t numread;
|
||||
char buffer[16384];
|
||||
unsigned char result[16];
|
||||
|
||||
return 0;
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
MD5_Init(&ctx);
|
||||
file = fopen(argv[i], "rb");
|
||||
|
||||
if (file)
|
||||
{
|
||||
do
|
||||
{
|
||||
numread = fread((void*)buffer, 1, sizeof(buffer), file);
|
||||
|
||||
if (numread)
|
||||
{
|
||||
MD5_Update(&ctx,(void*)buffer, numread);
|
||||
}
|
||||
}
|
||||
while (numread);
|
||||
|
||||
fclose(file);
|
||||
MD5_Final(result, &ctx);
|
||||
printf("%02x%02x%02x%02x%02x%02x%02x%02x"
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x %s\n",
|
||||
result[ 0 ], result[ 1 ], result[ 2 ], result[ 3 ],
|
||||
result[ 4 ], result[ 5 ], result[ 6 ], result[ 7 ],
|
||||
result[ 8 ], result[ 9 ], result[ 10 ], result[ 11 ],
|
||||
result[ 12 ], result[ 13 ], result[ 14 ], result[ 15 ],
|
||||
argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
** End of md5driver.c **
|
||||
******************************* (cut) ********************************
|
||||
*/
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* public domain */
|
||||
/* gcc -o udptest udp-test.c */
|
||||
|
||||
/*
|
||||
will send "RETROPAD RIGHT" indefinely to player 1
|
||||
to send to player 2 change port to 55401 and so on
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define SERVER "127.0.0.1"
|
||||
#define PORT 55400
|
||||
|
||||
void die(char *s)
|
||||
{
|
||||
perror(s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct sockaddr_in si_other;
|
||||
int s, i, slen=sizeof(si_other);
|
||||
|
||||
if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
||||
{
|
||||
die("socket");
|
||||
}
|
||||
|
||||
memset((char *) &si_other, 0, sizeof(si_other));
|
||||
si_other.sin_family = AF_INET;
|
||||
si_other.sin_port = htons(PORT);
|
||||
|
||||
if (inet_aton(SERVER , &si_other.sin_addr) == 0)
|
||||
{
|
||||
fprintf(stderr, "inet_aton() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
while(1)
|
||||
{
|
||||
|
||||
char message[10]="128";
|
||||
//send the message
|
||||
if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen)==-1)
|
||||
{
|
||||
die("sendto()");
|
||||
}
|
||||
/* sleep for 1 frame (60hz) */
|
||||
usleep(16*1000);
|
||||
|
||||
}
|
||||
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
|
@ -537,15 +537,29 @@
|
|||
<ClCompile Include="..\gfx3d.cpp" />
|
||||
<ClCompile Include="..\GPU.cpp" />
|
||||
<ClCompile Include="..\GPU_OSD.cpp" />
|
||||
<ClCompile Include="..\libretro-common\compat\compat.c" />
|
||||
<ClCompile Include="..\libretro-common\file\file_extract.c" />
|
||||
<ClCompile Include="..\libretro-common\compat\compat_fnmatch.c" />
|
||||
<ClCompile Include="..\libretro-common\compat\compat_getopt.c" />
|
||||
<ClCompile Include="..\libretro-common\compat\compat_posix_string.c" />
|
||||
<ClCompile Include="..\libretro-common\compat\compat_strcasestr.c" />
|
||||
<ClCompile Include="..\libretro-common\compat\compat_strl.c" />
|
||||
<ClCompile Include="..\libretro-common\file\dir_list.c" />
|
||||
<ClCompile Include="..\libretro-common\file\file_archive.c" />
|
||||
<ClCompile Include="..\libretro-common\file\file_archive_zlib.c" />
|
||||
<ClCompile Include="..\libretro-common\file\file_list.c">
|
||||
<PreprocessToFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
</PreprocessToFile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\file\file_path.c" />
|
||||
<ClCompile Include="..\libretro-common\file\memory_stream.c" />
|
||||
<ClCompile Include="..\libretro-common\file\nbio\nbio_stdio.c" />
|
||||
<ClCompile Include="..\libretro-common\file\retro_dirent.c" />
|
||||
<ClCompile Include="..\libretro-common\file\retro_file.c" />
|
||||
<ClCompile Include="..\libretro-common\file\retro_stat.c" />
|
||||
<ClCompile Include="..\libretro-common\formats\bmp\rbmp_encode.c" />
|
||||
<ClCompile Include="..\libretro-common\formats\png\rpng.c" />
|
||||
<ClCompile Include="..\libretro-common\formats\png\rpng_encode.c" />
|
||||
<ClCompile Include="..\libretro-common\hash\rhash.c" />
|
||||
<ClCompile Include="..\libretro-common\rthreads\rsemaphore.c" />
|
||||
<ClCompile Include="..\libretro-common\rthreads\rthreads.c" />
|
||||
<ClCompile Include="..\libretro-common\string\string_list.c" />
|
||||
<ClCompile Include="..\lua-engine.cpp" />
|
||||
|
|
|
@ -112,6 +112,9 @@
|
|||
<Filter Include="Core\libretro-common\compat">
|
||||
<UniqueIdentifier>{334a6ab8-9fe9-4577-983a-10f3b6fa95b9}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Core\libretro-common\hash">
|
||||
<UniqueIdentifier>{23ac753a-66cd-40c8-92c3-90f145eaf022}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\aggdraw.cpp">
|
||||
|
@ -903,27 +906,60 @@
|
|||
<ClCompile Include="..\libretro-common\formats\bmp\rbmp_encode.c">
|
||||
<Filter>Core\libretro-common\formats\bmp</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\file\retro_file.c">
|
||||
<Filter>Core\libretro-common\file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\file\nbio\nbio_stdio.c">
|
||||
<Filter>Core\libretro-common\file\nbio</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\file\file_extract.c">
|
||||
<Filter>Core\libretro-common\file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\string\string_list.c">
|
||||
<Filter>Core\libretro-common\string</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\compat\compat.c">
|
||||
<ClCompile Include="..\libretro-common\compat\compat_posix_string.c">
|
||||
<Filter>Core\libretro-common\compat</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\file\file_path.c">
|
||||
<ClCompile Include="..\libretro-common\compat\compat_strcasestr.c">
|
||||
<Filter>Core\libretro-common\compat</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\compat\compat_strl.c">
|
||||
<Filter>Core\libretro-common\compat</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\compat\compat_getopt.c">
|
||||
<Filter>Core\libretro-common\compat</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\compat\compat_fnmatch.c">
|
||||
<Filter>Core\libretro-common\compat</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\file\retro_file.c">
|
||||
<Filter>Core\libretro-common\file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\file\retro_stat.c">
|
||||
<Filter>Core\libretro-common\file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\file\dir_list.c">
|
||||
<Filter>Core\libretro-common\file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\file\file_archive.c">
|
||||
<Filter>Core\libretro-common\file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\file\file_archive_zlib.c">
|
||||
<Filter>Core\libretro-common\file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\file\file_list.c">
|
||||
<Filter>Core\libretro-common\file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\file\file_path.c">
|
||||
<Filter>Core\libretro-common\file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\file\memory_stream.c">
|
||||
<Filter>Core\libretro-common\file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\file\retro_dirent.c">
|
||||
<Filter>Core\libretro-common\file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\hash\rhash.c">
|
||||
<Filter>Core\libretro-common\hash</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\libretro-common\rthreads\rsemaphore.c">
|
||||
<Filter>Core\libretro-common\rthreads</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\armcpu.h">
|
||||
|
|
Loading…
Reference in New Issue