merge latest libretro-common

This commit is contained in:
zeromus 2016-03-21 01:27:43 +00:00
parent c4d7e476c5
commit 2c127b73b0
77 changed files with 5389 additions and 2278 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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"
};

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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)

View File

@ -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;
}

View File

@ -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. */

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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" {

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -27,6 +27,9 @@
extern "C" {
#endif
#include <stddef.h>
#include <stdlib.h>
#include <boolean.h>
struct item_file

View 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

View File

@ -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
}

View File

@ -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__ */

View File

@ -27,7 +27,7 @@
#include <stddef.h>
#include <boolean.h>
#include <file/file_extract.h>
#include <file/file_archive.h>
#ifdef __cplusplus
extern "C" {

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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.
*

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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__)

View File

@ -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

View File

@ -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)))

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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);

View File

@ -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:

View File

@ -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)

View File

@ -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
}

View File

@ -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);
}

View File

@ -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())

View File

@ -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));

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}
/**

View File

@ -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;
}

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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" />

View File

@ -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">