From 2c127b73b05396d5f63f9f3fc34047fd0aa8af5e Mon Sep 17 00:00:00 2001 From: zeromus Date: Mon, 21 Mar 2016 01:27:43 +0000 Subject: [PATCH] merge latest libretro-common --- .../compat/{compat.c => compat_getopt.c} | 180 +-- .../compat/compat_posix_string.c | 106 ++ .../compat/compat_strcasestr.c | 59 + .../src/libretro-common/compat/compat_strl.c | 61 + desmume/src/libretro-common/dynamic/dylib.c | 3 +- .../libretro-common/encodings/encoding_utf.c | 210 ++++ .../src/libretro-common/file/config_file.c | 84 +- desmume/src/libretro-common/file/dir_list.c | 11 +- .../src/libretro-common/file/dir_list_obj.m | 230 ---- .../file/{file_extract.c => file_archive.c} | 807 +++++-------- .../libretro-common/file/file_archive_zlib.c | 213 ++++ desmume/src/libretro-common/file/file_list.c | 7 +- desmume/src/libretro-common/file/file_path.c | 65 +- .../src/libretro-common/file/retro_dirent.c | 5 +- desmume/src/libretro-common/file/retro_file.c | 265 ++++- desmume/src/libretro-common/file/retro_stat.c | 54 +- .../libretro-common/formats/json/jsonsax.c | 316 +++++ .../src/libretro-common/formats/png/Makefile | 5 +- .../src/libretro-common/formats/png/rpng.c | 37 +- .../libretro-common/formats/png/rpng_encode.c | 28 +- .../src/libretro-common/formats/tga/rtga.c | 2 +- .../src/libretro-common/formats/xml/Makefile | 9 +- .../src/libretro-common/formats/xml/rxml.c | 26 +- .../src/libretro-common/gfx/scaler/pixconv.c | 35 +- .../gfx/scaler/scaler_filter.c | 4 - desmume/src/libretro-common/glsm/glsm.c | 1046 +++++++++++++++++ desmume/src/libretro-common/hash/rhash.c | 35 +- .../include/compat/apple_compat.h | 1 + .../libretro-common/include/compat/getopt.h | 2 +- .../src/libretro-common/include/compat/msvc.h | 7 +- .../include/compat/posix_string.h | 22 +- .../include/compat/strcasestr.h | 2 +- .../src/libretro-common/include/compat/strl.h | 10 +- .../libretro-common/include/encodings/utf.h | 43 + .../include/file/config_file.h | 50 +- .../include/file/file_archive.h | 138 +++ .../include/file/file_extract.h | 174 --- .../libretro-common/include/file/file_list.h | 3 + .../libretro-common/include/file/file_path.h | 13 + .../libretro-common/include/formats/image.h | 14 +- .../libretro-common/include/formats/jsonsax.h | 64 + .../libretro-common/include/formats/rpng.h | 2 +- .../src/libretro-common/include/glsm/glsm.h | 154 +++ .../libretro-common/include/glsm/glsmsym.h | 222 ++++ .../libretro-common/include/glsym/glsym_gl.h | 2 +- .../libretro-common/include/net/net_compat.h | 43 +- .../libretro-common/include/net/net_http.h | 4 + .../include/queues/fifo_buffer.h | 8 - .../include/queues/task_queue.h | 155 +++ .../libretro-common/include/retro_assert.h | 10 +- .../src/libretro-common/include/retro_file.h | 10 +- .../libretro-common/include/retro_inline.h | 4 +- .../src/libretro-common/include/retro_log.h | 278 ----- .../include/retro_miscellaneous.h | 34 +- .../src/libretro-common/include/retro_stat.h | 2 + desmume/src/libretro-common/include/rhash.h | 42 +- .../include/rthreads/async_job.h | 35 + .../include/rthreads/rsemaphore.h | 44 + .../include/rthreads/rthreads.h | 5 +- .../include/string/stdstring.h | 6 + .../include/string/string_list.h | 2 +- desmume/src/libretro-common/net/Makefile | 44 + desmume/src/libretro-common/net/net_compat.c | 151 ++- desmume/src/libretro-common/net/net_http.c | 67 +- .../src/libretro-common/net/net_http_test.c | 24 +- .../src/libretro-common/queues/fifo_buffer.c | 8 + .../src/libretro-common/queues/task_queue.c | 461 ++++++++ .../src/libretro-common/rthreads/async_job.c | 149 +++ .../src/libretro-common/rthreads/rsemaphore.c | 116 ++ .../src/libretro-common/rthreads/rthreads.c | 73 +- .../src/libretro-common/string/stdstring.c | 99 +- .../src/libretro-common/string/string_list.c | 12 +- desmume/src/libretro-common/utils/Makefile | 26 +- desmume/src/libretro-common/utils/md5.c | 800 +++++-------- desmume/src/libretro-common/utils/udp-test.c | 59 + desmume/src/windows/DeSmuME_2010.vcxproj | 18 +- .../src/windows/DeSmuME_2010.vcxproj.filters | 52 +- 77 files changed, 5389 insertions(+), 2278 deletions(-) rename desmume/src/libretro-common/compat/{compat.c => compat_getopt.c} (64%) create mode 100644 desmume/src/libretro-common/compat/compat_posix_string.c create mode 100644 desmume/src/libretro-common/compat/compat_strcasestr.c create mode 100644 desmume/src/libretro-common/compat/compat_strl.c create mode 100644 desmume/src/libretro-common/encodings/encoding_utf.c delete mode 100644 desmume/src/libretro-common/file/dir_list_obj.m rename desmume/src/libretro-common/file/{file_extract.c => file_archive.c} (52%) create mode 100644 desmume/src/libretro-common/file/file_archive_zlib.c create mode 100644 desmume/src/libretro-common/formats/json/jsonsax.c create mode 100644 desmume/src/libretro-common/glsm/glsm.c create mode 100644 desmume/src/libretro-common/include/encodings/utf.h create mode 100644 desmume/src/libretro-common/include/file/file_archive.h delete mode 100644 desmume/src/libretro-common/include/file/file_extract.h create mode 100644 desmume/src/libretro-common/include/formats/jsonsax.h create mode 100644 desmume/src/libretro-common/include/glsm/glsm.h create mode 100644 desmume/src/libretro-common/include/glsm/glsmsym.h create mode 100644 desmume/src/libretro-common/include/queues/task_queue.h delete mode 100644 desmume/src/libretro-common/include/retro_log.h create mode 100644 desmume/src/libretro-common/include/rthreads/async_job.h create mode 100644 desmume/src/libretro-common/include/rthreads/rsemaphore.h create mode 100644 desmume/src/libretro-common/net/Makefile create mode 100644 desmume/src/libretro-common/queues/task_queue.c create mode 100644 desmume/src/libretro-common/rthreads/async_job.c create mode 100644 desmume/src/libretro-common/rthreads/rsemaphore.c create mode 100644 desmume/src/libretro-common/utils/udp-test.c diff --git a/desmume/src/libretro-common/compat/compat.c b/desmume/src/libretro-common/compat/compat_getopt.c similarity index 64% rename from desmume/src/libretro-common/compat/compat.c rename to desmume/src/libretro-common/compat/compat_getopt.c index f2a3c2241..4a0d069dc 100644 --- a/desmume/src/libretro-common/compat/compat.c +++ b/desmume/src/libretro-common/compat/compat_getopt.c @@ -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 #include -#ifndef HAVE_GETOPT_LONG #include #include #include #include #include -#endif #include #include @@ -38,7 +37,6 @@ #include -#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 -#include -#include -#include - -#include - -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 diff --git a/desmume/src/libretro-common/compat/compat_posix_string.c b/desmume/src/libretro-common/compat/compat_posix_string.c new file mode 100644 index 000000000..42b12a7c6 --- /dev/null +++ b/desmume/src/libretro-common/compat/compat_posix_string.c @@ -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 + +#include + +#include + +#ifdef _WIN32 + +#undef strcasecmp +#undef strdup +#undef isblank +#undef strtok_r +#include +#include +#include +#include + +#include + +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 diff --git a/desmume/src/libretro-common/compat/compat_strcasestr.c b/desmume/src/libretro-common/compat/compat_strcasestr.c new file mode 100644 index 000000000..5cefe08f5 --- /dev/null +++ b/desmume/src/libretro-common/compat/compat_strcasestr.c @@ -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 + +#include +#include + +/* 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; +} diff --git a/desmume/src/libretro-common/compat/compat_strl.c b/desmume/src/libretro-common/compat/compat_strl.c new file mode 100644 index 000000000..9253174d4 --- /dev/null +++ b/desmume/src/libretro-common/compat/compat_strl.c @@ -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 + +#include +#include + +#include + +/* 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); +} diff --git a/desmume/src/libretro-common/dynamic/dylib.c b/desmume/src/libretro-common/dynamic/dylib.c index 5bb6ec9c4..2362f5a5f 100644 --- a/desmume/src/libretro-common/dynamic/dylib.c +++ b/desmume/src/libretro-common/dynamic/dylib.c @@ -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 diff --git a/desmume/src/libretro-common/encodings/encoding_utf.c b/desmume/src/libretro-common/encodings/encoding_utf.c new file mode 100644 index 000000000..e6ab4a81f --- /dev/null +++ b/desmume/src/libretro-common/encodings/encoding_utf.c @@ -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 +#include +#include + +#include +#include +#include + +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 +} diff --git a/desmume/src/libretro-common/file/config_file.c b/desmume/src/libretro-common/file/config_file.c index e0903f7c7..8a1b4024e 100644 --- a/desmume/src/libretro-common/file/config_file.c +++ b/desmume/src/libretro-common/file/config_file.c @@ -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; } diff --git a/desmume/src/libretro-common/file/dir_list.c b/desmume/src/libretro-common/file/dir_list.c index 60c12fe37..79fe1d2e2 100644 --- a/desmume/src/libretro-common/file/dir_list.c +++ b/desmume/src/libretro-common/file/dir_list.c @@ -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); diff --git a/desmume/src/libretro-common/file/dir_list_obj.m b/desmume/src/libretro-common/file/dir_list_obj.m deleted file mode 100644 index 1eddbb52e..000000000 --- a/desmume/src/libretro-common/file/dir_list_obj.m +++ /dev/null @@ -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 -#include -#include -#include - -#include -#include -#include -#include - -#include - -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; -} diff --git a/desmume/src/libretro-common/file/file_extract.c b/desmume/src/libretro-common/file/file_archive.c similarity index 52% rename from desmume/src/libretro-common/file/file_extract.c rename to desmume/src/libretro-common/file/file_archive.c index 802c0c8e7..192f0e6e6 100644 --- a/desmume/src/libretro-common/file/file_extract.c +++ b/desmume/src/libretro-common/file/file_archive.c @@ -1,7 +1,7 @@ /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (file_extract.c). + * The following license statement only applies to this file (file_archive.c). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, @@ -20,38 +20,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + #include #include #include -#include -#include - -#include -#include -#include -#include -#include - -/* File backends. Can be fleshed out later, but keep it simple for now. - * The file is mapped to memory directly (via mmap() or just - * plain retro_read_file()). - */ - -struct zlib_file_backend -{ - void *(*open)(const char *path); - const uint8_t *(*data)(void *handle); - size_t (*size)(void *handle); - void (*free)(void *handle); /* Closes, unmaps and frees. */ -}; - -#ifndef CENTRAL_FILE_HEADER_SIGNATURE -#define CENTRAL_FILE_HEADER_SIGNATURE 0x02014b50 -#endif - -#ifndef END_OF_CENTRAL_DIR_SIGNATURE -#define END_OF_CENTRAL_DIR_SIGNATURE 0x06054b50 +#ifdef HAVE_CONFIG_H +#include "config.h" #endif #ifdef HAVE_MMAP @@ -61,17 +36,54 @@ struct zlib_file_backend #include #include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef CENTRAL_FILE_HEADER_SIGNATURE +#define CENTRAL_FILE_HEADER_SIGNATURE 0x02014b50 +#endif + +#ifndef END_OF_CENTRAL_DIR_SIGNATURE +#define END_OF_CENTRAL_DIR_SIGNATURE 0x06054b50 +#endif + +struct zip_extract_userdata +{ + char *zip_path; + char *first_extracted_file_path; + const char *extraction_directory; + size_t zip_path_size; + struct string_list *ext; + bool found_content; +}; + +enum file_archive_compression_mode +{ + ZLIB_MODE_UNCOMPRESSED = 0, + ZLIB_MODE_DEFLATE = 8 +}; typedef struct { +#ifdef HAVE_MMAP int fd; +#endif void *data; size_t size; -} zlib_file_data_t; +} file_archive_file_data_t; -static void zlib_file_free(void *handle) +#ifdef HAVE_MMAP +/* Closes, unmaps and frees. */ +static void file_archive_free(void *handle) { - zlib_file_data_t *data = (zlib_file_data_t*)handle; + file_archive_file_data_t *data = (file_archive_file_data_t*)handle; if (!data) return; @@ -83,42 +95,36 @@ static void zlib_file_free(void *handle) free(data); } -static const uint8_t *zlib_file_data(void *handle) +static const uint8_t *file_archive_data(void *handle) { - zlib_file_data_t *data = (zlib_file_data_t*)handle; + file_archive_file_data_t *data = (file_archive_file_data_t*)handle; if (!data) return NULL; return (const uint8_t*)data->data; } -static size_t zlib_file_size(void *handle) +static size_t file_archive_size(void *handle) { - zlib_file_data_t *data = (zlib_file_data_t*)handle; + file_archive_file_data_t *data = (file_archive_file_data_t*)handle; if (!data) return 0; return data->size; } -static void *zlib_file_open(const char *path) +static void *file_archive_open(const char *path) { - struct stat fds; - zlib_file_data_t *data = (zlib_file_data_t*)calloc(1, sizeof(*data)); + file_archive_file_data_t *data = (file_archive_file_data_t*)calloc(1, sizeof(*data)); if (!data) return NULL; data->fd = open(path, O_RDONLY); + /* Failed to open archive. */ if (data->fd < 0) - { - /* Failed to open archive. */ - goto error; - } - - if (fstat(data->fd, &fds) < 0) goto error; - data->size = fds.st_size; + data->size = path_get_size(path); if (!data->size) return data; @@ -134,85 +140,146 @@ static void *zlib_file_open(const char *path) return data; error: - zlib_file_free(data); + file_archive_free(data); return NULL; } #else -typedef struct -{ - void *data; - size_t size; -} zlib_file_data_t; -static void zlib_file_free(void *handle) +/* Closes, unmaps and frees. */ +static void file_archive_free(void *handle) { - zlib_file_data_t *data = (zlib_file_data_t*)handle; + file_archive_file_data_t *data = (file_archive_file_data_t*)handle; if (!data) return; free(data->data); free(data); } -static const uint8_t *zlib_file_data(void *handle) +static const uint8_t *file_archive_data(void *handle) { - zlib_file_data_t *data = (zlib_file_data_t*)handle; + file_archive_file_data_t *data = (file_archive_file_data_t*)handle; if (!data) return NULL; return (const uint8_t*)data->data; } -static size_t zlib_file_size(void *handle) +static size_t file_archive_size(void *handle) { - zlib_file_data_t *data = (zlib_file_data_t*)handle; + file_archive_file_data_t *data = (file_archive_file_data_t*)handle; if (!data) return 0; return data->size; } -static void *zlib_file_open(const char *path) +static void *file_archive_open(const char *path) { - ssize_t ret = -1; - bool read_from_file = false; - zlib_file_data_t *data = (zlib_file_data_t*)calloc(1, sizeof(*data)); + ssize_t ret = -1; + bool read_from_file = false; + file_archive_file_data_t *data = (file_archive_file_data_t*) + calloc(1, sizeof(*data)); if (!data) return NULL; read_from_file = retro_read_file(path, &data->data, &ret); + /* Failed to open archive? */ if (!read_from_file || ret < 0) - { - /* Failed to open archive. */ goto error; - } data->size = ret; return data; error: - zlib_file_free(data); + file_archive_free(data); return NULL; } #endif -static const struct zlib_file_backend zlib_backend = { - zlib_file_open, - zlib_file_data, - zlib_file_size, - zlib_file_free, -}; - -static const struct zlib_file_backend *zlib_get_default_file_backend(void) +static int file_archive_get_file_list_cb( + const char *path, + const char *valid_exts, + const uint8_t *cdata, + unsigned cmode, + uint32_t csize, + uint32_t size, + uint32_t checksum, + void *userdata) { - return &zlib_backend; + union string_list_elem_attr attr; + struct string_list *ext_list = NULL; + const char *file_ext = NULL; + struct string_list *list = (struct string_list*)userdata; + + (void)cdata; + (void)cmode; + (void)csize; + (void)size; + (void)checksum; + (void)valid_exts; + (void)file_ext; + (void)ext_list; + + memset(&attr, 0, sizeof(attr)); + + if (valid_exts) + ext_list = string_split(valid_exts, "|"); + + if (ext_list) + { + /* Checks if this entry is a directory or a file. */ + char last_char = path[strlen(path)-1]; + + /* Skip if directory. */ + if (last_char == '/' || last_char == '\\' ) + goto error; + + file_ext = path_get_extension(path); + + if (!file_ext || + !string_list_find_elem_prefix(ext_list, ".", file_ext)) + goto error; + + attr.i = RARCH_COMPRESSED_FILE_IN_ARCHIVE; + string_list_free(ext_list); + } + + return string_list_append(list, path, attr); + +error: + string_list_free(ext_list); + return 0; } +static int file_archive_extract_cb(const char *name, const char *valid_exts, + const uint8_t *cdata, + unsigned cmode, uint32_t csize, uint32_t size, + uint32_t checksum, void *userdata) +{ + const char *ext = path_get_extension(name); + struct zip_extract_userdata *data = (struct zip_extract_userdata*)userdata; -#undef GOTO_END_ERROR -#define GOTO_END_ERROR() do { \ - ret = false; \ - goto end; \ -} while(0) + /* Extract first content that matches our list. */ + if (ext && string_list_find_elem(data->ext, ext)) + { + char new_path[PATH_MAX_LENGTH] = {0}; + + if (data->extraction_directory) + fill_pathname_join(new_path, data->extraction_directory, + path_basename(name), sizeof(new_path)); + else + fill_pathname_resolve_relative(new_path, data->zip_path, + path_basename(name), sizeof(new_path)); + + data->first_extracted_file_path = strdup(new_path); + data->found_content = file_archive_perform_mode(new_path, + valid_exts, cdata, cmode, csize, size, + 0, NULL); + return 0; + } + + return 1; +} static uint32_t read_le(const uint8_t *data, unsigned size) { @@ -221,202 +288,13 @@ static uint32_t read_le(const uint8_t *data, unsigned size) size *= 8; for (i = 0; i < size; i += 8) - val |= *data++ << i; + val |= (uint32_t)*data++ << i; return val; } -void *zlib_stream_new(void) -{ - return (z_stream*)calloc(1, sizeof(z_stream)); -} - -bool zlib_inflate_init2(void *data) -{ - z_stream *stream = (z_stream*)data; - - if (!stream) - return false; - if (inflateInit2(stream, -MAX_WBITS) != Z_OK) - return false; - return true; -} - -void zlib_deflate_init(void *data, int level) -{ - z_stream *stream = (z_stream*)data; - - if (stream) - deflateInit(stream, level); -} - -bool zlib_inflate_init(void *data) -{ - z_stream *stream = (z_stream*)data; - - if (!stream) - return false; - if (inflateInit(stream) != Z_OK) - return false; - return true; -} - -void zlib_stream_free(void *data) -{ - z_stream *ret = (z_stream*)data; - if (ret) - inflateEnd(ret); -} - -void zlib_stream_deflate_free(void *data) -{ - z_stream *ret = (z_stream*)data; - if (ret) - deflateEnd(ret); -} - -bool zlib_inflate_data_to_file_init( - zlib_file_handle_t *handle, - const uint8_t *cdata, uint32_t csize, uint32_t size) -{ - z_stream *stream = NULL; - - if (!handle) - return false; - - if (!(handle->stream = (z_stream*)zlib_stream_new())) - goto error; - - if (!(zlib_inflate_init2(handle->stream))) - goto error; - - handle->data = (uint8_t*)malloc(size); - - if (!handle->data) - goto error; - - stream = (z_stream*)handle->stream; - - if (!stream) - goto error; - - zlib_set_stream(stream, - csize, - size, - (const uint8_t*)cdata, - handle->data - ); - - return true; - -error: - if (handle->stream) - zlib_stream_free(handle->stream); - if (handle->data) - free(handle->data); - - return false; -} - -int zlib_deflate_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; -} - -int zlib_inflate_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; -} - -uint32_t zlib_crc32_calculate(const uint8_t *data, size_t length) -{ - return crc32(0, data, length); -} - -uint32_t zlib_crc32_adjust(uint32_t crc, uint8_t data) -{ - /* zlib and nall have different assumptions on "sign" for this - * function. */ - return ~crc32(~crc, &data, 1); -} - -/** - * zlib_inflate_data_to_file: - * @path : filename path of archive. - * @valid_exts : Valid extensions of archive to be parsed. - * If NULL, allow all. - * @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) -{ - if (handle) - { - zlib_stream_free(handle->stream); - free(handle->stream); - } - - if (!handle || ret == -1) - { - ret = 0; - goto end; - } - - handle->real_checksum = zlib_crc32_calculate(handle->data, size); - -#if 0 - if (handle->real_checksum != checksum) - { - /* File CRC difers from ZIP CRC. */ - printf("File CRC differs from ZIP CRC. File: 0x%x, ZIP: 0x%x.\n", - (unsigned)handle->real_checksum, (unsigned)checksum); - } -#endif - - if (!retro_write_file(path, handle->data, size)) - GOTO_END_ERROR(); - -end: - if (handle->data) - free(handle->data); - return ret; -} - -static int zlib_parse_file_iterate_step_internal( - zlib_transfer_t *state, char *filename, +static int file_archive_parse_file_iterate_step_internal( + file_archive_transfer_t *state, char *filename, const uint8_t **cdata, unsigned *cmode, uint32_t *size, uint32_t *csize, uint32_t *checksum, unsigned *payback) @@ -434,28 +312,28 @@ static int zlib_parse_file_iterate_step_internal( *csize = read_le(state->directory + 20, 4); *size = read_le(state->directory + 24, 4); - namelength = read_le(state->directory + 28, 2); - extralength = read_le(state->directory + 30, 2); - commentlength = read_le(state->directory + 32, 2); + namelength = read_le(state->directory + 28, 2); + extralength = read_le(state->directory + 30, 2); + commentlength = read_le(state->directory + 32, 2); if (namelength >= PATH_MAX_LENGTH) return -1; memcpy(filename, state->directory + 46, namelength); - offset = read_le(state->directory + 42, 4); - offsetNL = read_le(state->data + offset + 26, 2); - offsetEL = read_le(state->data + offset + 28, 2); + offset = read_le(state->directory + 42, 4); + offsetNL = read_le(state->data + offset + 26, 2); + offsetEL = read_le(state->data + offset + 28, 2); - *cdata = state->data + offset + 30 + offsetNL + offsetEL; + *cdata = state->data + offset + 30 + offsetNL + offsetEL; - *payback = 46 + namelength + extralength + commentlength; + *payback = 46 + namelength + extralength + commentlength; return 1; } -static int zlib_parse_file_iterate_step(zlib_transfer_t *state, - const char *valid_exts, void *userdata, zlib_file_cb file_cb) +static int file_archive_parse_file_iterate_step(file_archive_transfer_t *state, + const char *valid_exts, void *userdata, file_archive_file_cb file_cb) { const uint8_t *cdata = NULL; uint32_t checksum = 0; @@ -464,7 +342,8 @@ static int zlib_parse_file_iterate_step(zlib_transfer_t *state, unsigned cmode = 0; unsigned payload = 0; char filename[PATH_MAX_LENGTH] = {0}; - int ret = zlib_parse_file_iterate_step_internal(state, filename, &cdata, &cmode, &size, &csize, + int ret = file_archive_parse_file_iterate_step_internal(state, filename, + &cdata, &cmode, &size, &csize, &checksum, &payload); if (ret != 1) @@ -484,23 +363,23 @@ static int zlib_parse_file_iterate_step(zlib_transfer_t *state, return 1; } -static int zlib_parse_file_init(zlib_transfer_t *state, +static int file_archive_parse_file_init(file_archive_transfer_t *state, const char *file) { - state->backend = zlib_get_default_file_backend(); + state->backend = file_archive_get_default_file_backend(); if (!state->backend) return -1; - state->handle = state->backend->open(file); + state->handle = file_archive_open(file); if (!state->handle) return -1; - state->zip_size = state->backend->size(state->handle); + state->zip_size = file_archive_size(state->handle); if (state->zip_size < 22) return -1; - state->data = state->backend->data(state->handle); + state->data = file_archive_data(state->handle); state->footer = state->data + state->zip_size - 22; for (;; state->footer--) @@ -520,11 +399,74 @@ static int zlib_parse_file_init(zlib_transfer_t *state, return 0; } -int zlib_parse_file_iterate(void *data, bool *returnerr, const char *file, - const char *valid_exts, zlib_file_cb file_cb, void *userdata) +/** + * file_archive_decompress_data_to_file: + * @path : filename path of archive. + * @valid_exts : Valid extensions of archive to be parsed. + * If NULL, allow all. + * @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). + **/ +static int file_archive_decompress_data_to_file( + file_archive_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) { - zlib_transfer_t *state = (zlib_transfer_t*)data; + if (handle) + { + handle->backend->stream_free(handle->stream); + free(handle->stream); + } + if (!handle || ret == -1) + { + ret = 0; + goto end; + } + + handle->real_checksum = handle->backend->stream_crc_calculate( + 0, handle->data, size); + +#if 0 + if (handle->real_checksum != checksum) + { + /* File CRC difers from ZIP CRC. */ + printf("File CRC differs from ZIP CRC. File: 0x%x, ZIP: 0x%x.\n", + (unsigned)handle->real_checksum, (unsigned)checksum); + } +#endif + + if (!retro_write_file(path, handle->data, size)) + { + ret = false; + goto end; + } + +end: + if (handle->data) + free(handle->data); + return ret; +} + +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) +{ if (!state) return -1; @@ -533,18 +475,18 @@ int zlib_parse_file_iterate(void *data, bool *returnerr, const char *file, case ZLIB_TRANSFER_NONE: break; case ZLIB_TRANSFER_INIT: - if (zlib_parse_file_init(state, file) == 0) + if (file_archive_parse_file_init(state, file) == 0) state->type = ZLIB_TRANSFER_ITERATE; else state->type = ZLIB_TRANSFER_DEINIT_ERROR; break; case ZLIB_TRANSFER_ITERATE: { - int ret2 = zlib_parse_file_iterate_step(state, + int ret = file_archive_parse_file_iterate_step(state, valid_exts, userdata, file_cb); - if (ret2 != 1) + if (ret != 1) state->type = ZLIB_TRANSFER_DEINIT; - if (ret2 == -1) + if (ret == -1) state->type = ZLIB_TRANSFER_DEINIT_ERROR; } break; @@ -552,10 +494,8 @@ int zlib_parse_file_iterate(void *data, bool *returnerr, const char *file, *returnerr = false; case ZLIB_TRANSFER_DEINIT: if (state->handle) - { - state->backend->free(state->handle); - state->handle = NULL; - } + file_archive_free(state->handle); + state->handle = NULL; break; } @@ -566,18 +506,17 @@ int zlib_parse_file_iterate(void *data, bool *returnerr, const char *file, return 0; } -void zlib_parse_file_iterate_stop(void *data) +void file_archive_parse_file_iterate_stop(file_archive_transfer_t *state) { - zlib_transfer_t *state = (zlib_transfer_t*)data; if (!state || !state->handle) return; state->type = ZLIB_TRANSFER_DEINIT; - zlib_parse_file_iterate(data, NULL, NULL, NULL, NULL, NULL); + file_archive_parse_file_iterate(state, NULL, NULL, NULL, NULL, NULL); } /** - * zlib_parse_file: + * file_archive_parse_file: * @file : filename path of archive * @valid_exts : Valid extensions of archive to be parsed. * If NULL, allow all. @@ -589,17 +528,17 @@ void zlib_parse_file_iterate_stop(void *data) * * 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) +static bool file_archive_parse_file(const char *file, const char *valid_exts, + file_archive_file_cb file_cb, void *userdata) { - zlib_transfer_t state = {0}; - bool returnerr = true; + file_archive_transfer_t state = {0}; + bool returnerr = true; state.type = ZLIB_TRANSFER_INIT; for (;;) { - int ret = zlib_parse_file_iterate(&state, &returnerr, file, + int ret = file_archive_parse_file_iterate(&state, &returnerr, file, valid_exts, file_cb, userdata); if (ret != 0) @@ -609,78 +548,15 @@ bool zlib_parse_file(const char *file, const char *valid_exts, return returnerr; } -struct zip_extract_userdata +int file_archive_parse_file_progress(file_archive_transfer_t *state) { - char *zip_path; - const char *extraction_directory; - size_t zip_path_size; - struct string_list *ext; - bool found_content; -}; - -enum zlib_compression_mode -{ - ZLIB_MODE_UNCOMPRESSED = 0, - ZLIB_MODE_DEFLATE = 8 -}; - -static int zip_extract_cb(const char *name, const char *valid_exts, - const uint8_t *cdata, - unsigned cmode, uint32_t csize, uint32_t size, - uint32_t checksum, void *userdata) -{ - struct zip_extract_userdata *data = (struct zip_extract_userdata*)userdata; - - /* Extract first content that matches our list. */ - const char *ext = path_get_extension(name); - - if (ext && string_list_find_elem(data->ext, ext)) - { - char new_path[PATH_MAX_LENGTH] = {0}; - - if (data->extraction_directory) - fill_pathname_join(new_path, data->extraction_directory, - path_basename(name), sizeof(new_path)); - else - fill_pathname_resolve_relative(new_path, data->zip_path, - path_basename(name), sizeof(new_path)); - - switch (cmode) - { - case ZLIB_MODE_UNCOMPRESSED: - data->found_content = retro_write_file(new_path, cdata, size); - return false; - case ZLIB_MODE_DEFLATE: - { - int ret = 0; - zlib_file_handle_t handle = {0}; - if (!zlib_inflate_data_to_file_init(&handle, cdata, csize, size)) - return 0; - - do{ - ret = zlib_inflate_data_to_file_iterate(handle.stream); - }while(ret == 0); - - if (zlib_inflate_data_to_file(&handle, ret, new_path, valid_exts, - cdata, csize, size, checksum)) - { - strlcpy(data->zip_path, new_path, data->zip_path_size); - data->found_content = true; - return 0; - } - return 0; - } - - default: - return 0; - } - } - - return 1; + /* FIXME: this estimate is worse than before */ + ptrdiff_t delta = state->directory - state->data; + return delta * 100 / state->zip_size; } /** - * zlib_extract_first_content_file: + * 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. @@ -691,11 +567,15 @@ static int zip_extract_cb(const char *name, const char *valid_exts, * * 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_directory) +bool file_archive_extract_first_content_file( + char *zip_path, + size_t zip_path_size, + const char *valid_exts, + const char *extraction_directory, + char *out_path, size_t len) { - struct string_list *list; - bool ret = true; + struct string_list *list = NULL; + bool ret = true; struct zip_extract_userdata userdata = {0}; if (!valid_exts) @@ -707,129 +587,96 @@ bool zlib_extract_first_content_file(char *zip_path, size_t zip_path_size, list = string_split(valid_exts, "|"); if (!list) - GOTO_END_ERROR(); + { + ret = false; + goto end; + } userdata.zip_path = zip_path; userdata.zip_path_size = zip_path_size; userdata.extraction_directory = extraction_directory; userdata.ext = list; - if (!zlib_parse_file(zip_path, valid_exts, zip_extract_cb, &userdata)) + if (!file_archive_parse_file(zip_path, valid_exts, + file_archive_extract_cb, &userdata)) { - /* Parsing ZIP failed. */ - GOTO_END_ERROR(); + /* Parsing file archive failed. */ + ret = false; + goto end; } if (!userdata.found_content) { /* Didn't find any content that matched valid extensions * for libretro implementation. */ - GOTO_END_ERROR(); + ret = false; + goto end; } + if (*userdata.first_extracted_file_path) + strlcpy(out_path, userdata.first_extracted_file_path, len); + end: + if (userdata.first_extracted_file_path) + free(userdata.first_extracted_file_path); if (list) string_list_free(list); return ret; } -static int zlib_get_file_list_cb(const char *path, const char *valid_exts, - const uint8_t *cdata, - unsigned cmode, uint32_t csize, uint32_t size, uint32_t checksum, - void *userdata) -{ - union string_list_elem_attr attr; - struct string_list *ext_list = NULL; - const char *file_ext = NULL; - struct string_list *list = (struct string_list*)userdata; - - (void)cdata; - (void)cmode; - (void)csize; - (void)size; - (void)checksum; - (void)valid_exts; - (void)file_ext; - (void)ext_list; - - memset(&attr, 0, sizeof(attr)); - - if (valid_exts) - ext_list = string_split(valid_exts, "|"); - - if (ext_list) - { - char last_char = ' '; - - /* Checks if this entry is a directory or a file. */ - last_char = path[strlen(path)-1]; - - if (last_char == '/' || last_char == '\\' ) /* Skip if directory. */ - goto error; - - file_ext = path_get_extension(path); - - if (!file_ext || - !string_list_find_elem_prefix(ext_list, ".", file_ext)) - goto error; - - attr.i = RARCH_COMPRESSED_FILE_IN_ARCHIVE; - string_list_free(ext_list); - } - - return string_list_append(list, path, attr); -error: - string_list_free(ext_list); - return 0; -} - /** - * zlib_get_file_list: + * file_archive_get_file_list: * @path : filename path of archive * * 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) +struct string_list *file_archive_get_file_list(const char *path, + const char *valid_exts) { struct string_list *list = string_list_new(); if (!list) - return NULL; + goto error; - if (!zlib_parse_file(path, valid_exts, - zlib_get_file_list_cb, list)) - { - /* Parsing ZIP failed. */ - string_list_free(list); - return NULL; - } + if (!file_archive_parse_file(path, valid_exts, + file_archive_get_file_list_cb, list)) + goto error; return list; + +error: + if (list) + string_list_free(list); + return NULL; } -bool zlib_perform_mode(const char *path, const char *valid_exts, +bool file_archive_perform_mode(const char *path, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, uint32_t crc32, void *userdata) { switch (cmode) { - case 0: /* Uncompressed */ + case ZLIB_MODE_UNCOMPRESSED: if (!retro_write_file(path, cdata, size)) return false; break; - case 8: /* Deflate */ + case ZLIB_MODE_DEFLATE: { int ret = 0; - zlib_file_handle_t handle = {0}; - if (!zlib_inflate_data_to_file_init(&handle, cdata, csize, size)) + file_archive_file_handle_t handle = {0}; + handle.backend = file_archive_get_default_file_backend(); + + if (!handle.backend->stream_decompress_data_to_file_init(&handle, + cdata, csize, size)) return false; do{ - ret = zlib_inflate_data_to_file_iterate(handle.stream); + ret = handle.backend->stream_decompress_data_to_file_iterate(handle.stream); }while(ret == 0); - if (!zlib_inflate_data_to_file(&handle, ret, path, valid_exts, + if (!file_archive_decompress_data_to_file(&handle, + ret, path, valid_exts, cdata, csize, size, crc32)) return false; } @@ -841,59 +688,7 @@ bool zlib_perform_mode(const char *path, const char *valid_exts, return true; } -void zlib_set_stream(void *data, - uint32_t avail_in, - uint32_t avail_out, - const uint8_t *next_in, - uint8_t *next_out - ) +const struct file_archive_file_backend *file_archive_get_default_file_backend(void) { - 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; -} - -uint32_t zlib_stream_get_avail_in(void *data) -{ - z_stream *stream = (z_stream*)data; - - if (!stream) - return 0; - - return stream->avail_in; -} - -uint32_t zlib_stream_get_avail_out(void *data) -{ - z_stream *stream = (z_stream*)data; - - if (!stream) - return 0; - - return stream->avail_out; -} - -uint64_t zlib_stream_get_total_out(void *data) -{ - z_stream *stream = (z_stream*)data; - - if (!stream) - return 0; - - return stream->total_out; -} - -void zlib_stream_decrement_total_out(void *data, unsigned subtraction) -{ - z_stream *stream = (z_stream*)data; - - if (stream) - stream->total_out -= subtraction; + return &zlib_backend; } diff --git a/desmume/src/libretro-common/file/file_archive_zlib.c b/desmume/src/libretro-common/file/file_archive_zlib.c new file mode 100644 index 000000000..8faf97ebc --- /dev/null +++ b/desmume/src/libretro-common/file/file_archive_zlib.c @@ -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 + +#include +#include +#include + +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" +}; diff --git a/desmume/src/libretro-common/file/file_list.c b/desmume/src/libretro-common/file/file_list.c index 49853aee8..9ed5fe6a0 100644 --- a/desmume/src/libretro-common/file/file_list.c +++ b/desmume/src/libretro-common/file/file_list.c @@ -25,6 +25,8 @@ #include #include +#include +#include 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) diff --git a/desmume/src/libretro-common/file/file_path.c b/desmume/src/libretro-common/file/file_path.c index 312944ac6..8c3dbb40c 100644 --- a/desmume/src/libretro-common/file/file_path.c +++ b/desmume/src/libretro-common/file/file_path.c @@ -35,13 +35,14 @@ #include +#ifndef __MACH__ #include #include +#endif #include #include #include - /** * 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 diff --git a/desmume/src/libretro-common/file/retro_dirent.c b/desmume/src/libretro-common/file/retro_dirent.c index 456ebe5f9..5fa0cb4b8 100644 --- a/desmume/src/libretro-common/file/retro_dirent.c +++ b/desmume/src/libretro-common/file/retro_dirent.c @@ -24,7 +24,6 @@ #include #if defined(_WIN32) -# include # 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); diff --git a/desmume/src/libretro-common/file/retro_file.c b/desmume/src/libretro-common/file/retro_file.c index 470e0f76a..d4325b3f6 100644 --- a/desmume/src/libretro-common/file/retro_file.c +++ b/desmume/src/libretro-common/file/retro_file.c @@ -26,7 +26,6 @@ #include #if defined(_WIN32) -# include # ifdef _MSC_VER # define setmode _setmode # endif @@ -64,11 +63,8 @@ #include #endif -#ifdef RARCH_INTERNAL -#include -#endif - #include +#include #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) diff --git a/desmume/src/libretro-common/file/retro_stat.c b/desmume/src/libretro-common/file/retro_stat.c index 2698c9a04..fc7666650 100644 --- a/desmume/src/libretro-common/file/retro_stat.c +++ b/desmume/src/libretro-common/file/retro_stat.c @@ -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; diff --git a/desmume/src/libretro-common/formats/json/jsonsax.c b/desmume/src/libretro-common/formats/json/jsonsax.c new file mode 100644 index 000000000..420c6a590 --- /dev/null +++ b/desmume/src/libretro-common/formats/json/jsonsax.c @@ -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 +#include +#include + +#include +#include + +#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; +} diff --git a/desmume/src/libretro-common/formats/png/Makefile b/desmume/src/libretro-common/formats/png/Makefile index b5d93e0e2..2fbc79dd3 100644 --- a/desmume/src/libretro-common/formats/png/Makefile +++ b/desmume/src/libretro-common/formats/png/Makefile @@ -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 diff --git a/desmume/src/libretro-common/formats/png/rpng.c b/desmume/src/libretro-common/formats/png/rpng.c index 09287d54f..712d234ab 100644 --- a/desmume/src/libretro-common/formats/png/rpng.c +++ b/desmume/src/libretro-common/formats/png/rpng.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #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); } diff --git a/desmume/src/libretro-common/formats/png/rpng_encode.c b/desmume/src/libretro-common/formats/png/rpng_encode.c index b276ff47c..8532e05fd 100644 --- a/desmume/src/libretro-common/formats/png/rpng_encode.c +++ b/desmume/src/libretro-common/formats/png/rpng_encode.c @@ -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; } diff --git a/desmume/src/libretro-common/formats/tga/rtga.c b/desmume/src/libretro-common/formats/tga/rtga.c index fc0348e78..958b5c6e0 100644 --- a/desmume/src/libretro-common/formats/tga/rtga.c +++ b/desmume/src/libretro-common/formats/tga/rtga.c @@ -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; diff --git a/desmume/src/libretro-common/formats/xml/Makefile b/desmume/src/libretro-common/formats/xml/Makefile index 3c2a6e1fc..1186c8e42 100644 --- a/desmume/src/libretro-common/formats/xml/Makefile +++ b/desmume/src/libretro-common/formats/xml/Makefile @@ -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) diff --git a/desmume/src/libretro-common/formats/xml/rxml.c b/desmume/src/libretro-common/formats/xml/rxml.c index 410fbf623..73f03b6ae 100644 --- a/desmume/src/libretro-common/formats/xml/rxml.c +++ b/desmume/src/libretro-common/formats/xml/rxml.c @@ -20,16 +20,20 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include -#include #include +#include #include #include +#include + #include -#include + #include +#include #include +#include + 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; } diff --git a/desmume/src/libretro-common/gfx/scaler/pixconv.c b/desmume/src/libretro-common/gfx/scaler/pixconv.c index 59d35a2cb..78ff6afa0 100644 --- a/desmume/src/libretro-common/gfx/scaler/pixconv.c +++ b/desmume/src/libretro-common/gfx/scaler/pixconv.c @@ -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. */ diff --git a/desmume/src/libretro-common/gfx/scaler/scaler_filter.c b/desmume/src/libretro-common/gfx/scaler/scaler_filter.c index 756161df3..50c290c8c 100644 --- a/desmume/src/libretro-common/gfx/scaler/scaler_filter.c +++ b/desmume/src/libretro-common/gfx/scaler/scaler_filter.c @@ -30,10 +30,6 @@ #include #include -#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); diff --git a/desmume/src/libretro-common/glsm/glsm.c b/desmume/src/libretro-common/glsm/glsm.c new file mode 100644 index 000000000..7e36c4c8c --- /dev/null +++ b/desmume/src/libretro-common/glsm/glsm.c @@ -0,0 +1,1046 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this libretro SDK code part (glsm). + * --------------------------------------------------------------------------------------- + * + * 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 +#include + + +struct gl_cached_state +{ + struct + { + GLuint ids[MAX_TEXTURE]; + } bind_textures; + +#ifndef HAVE_OPENGLES + GLenum colorlogicop; +#endif + + struct + { + bool enabled[MAX_ATTRIB]; + } vertex_attrib_pointer; + + struct + { + GLenum pname; + GLint param; + } pixelstore_i; + + struct + { + GLuint r; + GLuint g; + GLuint b; + GLuint a; + } clear_color; + + struct + { + bool used; + GLint x; + GLint y; + GLsizei w; + GLsizei h; + } scissor; + + struct + { + GLint x; + GLint y; + GLsizei w; + GLsizei h; + } viewport; + + struct + { + bool used; + GLenum sfactor; + GLenum dfactor; + } blendfunc; + + struct + { + bool used; + GLenum srcRGB; + GLenum dstRGB; + GLenum srcAlpha; + GLenum dstAlpha; + } blendfunc_separate; + + struct + { + bool used; + GLboolean red; + GLboolean green; + GLboolean blue; + GLboolean alpha; + } colormask; + + struct + { + bool used; + GLdouble depth; + } cleardepth; + + struct + { + bool used; + GLenum func; + } depthfunc; + + + struct + { + bool used; + GLclampd zNear; + GLclampd zFar; + } depthrange; + + struct + { + bool used; + GLfloat factor; + GLfloat units; + } polygonoffset; + + struct + { + bool used; + GLenum func; + GLint ref; + GLuint mask; + } stencilfunc; + + struct + { + bool used; + GLenum sfail; + GLenum dpfail; + GLenum dppass; + } stencilop; + + struct + { + bool used; + GLenum mode; + } frontface; + + struct + { + bool used; + GLenum mode; + } cullface; + + struct + { + bool used; + GLuint mask; + } stencilmask; + + struct + { + bool used; + GLboolean mask; + } depthmask; + + struct + { + GLenum mode; + } readbuffer; + + GLuint vao; + GLuint framebuf; + GLuint program; + GLenum active_texture; + int cap_state[SGL_CAP_MAX]; + int cap_translate[SGL_CAP_MAX]; +}; + +static glsm_framebuffer_lock glsm_fb_lock = NULL; +static glsm_imm_vbo_draw imm_vbo_draw = NULL; +static glsm_imm_vbo_draw imm_vbo_disable = NULL; +static struct retro_hw_render_callback hw_render; +static struct gl_cached_state gl_state; + +/* GL wrapper-side */ + +void rglBlitFramebuffer( + GLint srcX0, GLint srcY0, + GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, + GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ +#ifndef HAVE_OPENGLES2 + glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, filter); +#endif +} + +void rglReadBuffer(GLenum mode) +{ +#ifndef HAVE_OPENGLES2 + glReadBuffer(mode); +#endif + gl_state.readbuffer.mode = mode; +} + +void rglClearDepth(GLdouble depth) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); +#ifdef HAVE_OPENGLES + glClearDepthf(depth); +#else + glClearDepth(depth); +#endif + gl_state.cleardepth.used = true; + gl_state.cleardepth.depth = depth; +} + +void rglPixelStorei(GLenum pname, GLint param) +{ + glPixelStorei(pname, param); + gl_state.pixelstore_i.pname = pname; + gl_state.pixelstore_i.param = param; +} + +void rglDepthRange(GLclampd zNear, GLclampd zFar) +{ +#ifdef HAVE_OPENGLES + glDepthRangef(zNear, zFar); +#else + glDepthRange(zNear, zFar); +#endif + gl_state.depthrange.used = true; + gl_state.depthrange.zNear = zNear; + gl_state.depthrange.zFar = zFar; +} + +void rglFrontFace(GLenum mode) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glFrontFace(mode); + gl_state.frontface.used = true; + gl_state.frontface.mode = mode; +} + +void rglDepthFunc(GLenum func) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + gl_state.depthfunc.used = true; + gl_state.depthfunc.func = func; + glDepthFunc(func); +} + +void rglColorMask(GLboolean red, GLboolean green, + GLboolean blue, GLboolean alpha) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glColorMask(red, green, blue, alpha); + gl_state.colormask.red = red; + gl_state.colormask.green = green; + gl_state.colormask.blue = blue; + gl_state.colormask.alpha = alpha; + gl_state.colormask.used = true; +} + +void rglCullFace(GLenum mode) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glCullFace(mode); + gl_state.cullface.used = true; + gl_state.cullface.mode = mode; +} + +void rglStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass) +{ + glStencilOp(sfail, dpfail, dppass); + gl_state.stencilop.used = true; + gl_state.stencilop.sfail = sfail; + gl_state.stencilop.dpfail = dpfail; + gl_state.stencilop.dppass = dppass; +} + +void rglStencilFunc(GLenum func, GLint ref, GLuint mask) +{ + glStencilFunc(func, ref, mask); + gl_state.stencilfunc.used = true; + gl_state.stencilfunc.func = func; + gl_state.stencilfunc.ref = ref; + gl_state.stencilfunc.mask = mask; +} + +GLboolean rglIsEnabled(GLenum cap) +{ + return gl_state.cap_state[cap] ? GL_TRUE : GL_FALSE; +} + +void rglClearColor(GLclampf red, GLclampf green, + GLclampf blue, GLclampf alpha) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glClearColor(red, green, blue, alpha); + gl_state.clear_color.r = red; + gl_state.clear_color.g = green; + gl_state.clear_color.b = blue; + gl_state.clear_color.a = alpha; +} + +void rglScissor(GLint x, GLint y, GLsizei width, GLsizei height) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glScissor(x, y, width, height); + gl_state.scissor.used = true; + gl_state.scissor.x = x; + gl_state.scissor.y = y; + gl_state.scissor.w = width; + gl_state.scissor.h = height; +} + +void rglViewport(GLint x, GLint y, GLsizei width, GLsizei height) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glViewport(x, y, width, height); + gl_state.viewport.x = x; + gl_state.viewport.y = y; + gl_state.viewport.w = width; + gl_state.viewport.h = height; +} + +void rglBlendFunc(GLenum sfactor, GLenum dfactor) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + gl_state.blendfunc.used = true; + gl_state.blendfunc.sfactor = sfactor; + gl_state.blendfunc.dfactor = dfactor; + glBlendFunc(sfactor, dfactor); +} + +void rglBlendFuncSeparate(GLenum sfactor, GLenum dfactor) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + gl_state.blendfunc_separate.used = true; + gl_state.blendfunc_separate.srcRGB = sfactor; + gl_state.blendfunc_separate.dstRGB = dfactor; + gl_state.blendfunc_separate.srcAlpha = sfactor; + gl_state.blendfunc_separate.dstAlpha = dfactor; + glBlendFunc(sfactor, dfactor); +} + +void rglActiveTexture(GLenum texture) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glActiveTexture(texture); + gl_state.active_texture = texture - GL_TEXTURE0; +} + +void rglBindTexture(GLenum target, GLuint texture) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glBindTexture(target, texture); + gl_state.bind_textures.ids[gl_state.active_texture] = texture; +} + +void rglDisable(GLenum cap) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glDisable(gl_state.cap_translate[cap]); + gl_state.cap_state[cap] = 0; +} + +void rglEnable(GLenum cap) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glEnable(gl_state.cap_translate[cap]); + gl_state.cap_state[cap] = 1; +} + +void rglUseProgram(GLuint program) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + gl_state.program = program; + glUseProgram(program); +} + +void rglDepthMask(GLboolean flag) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glDepthMask(flag); + gl_state.depthmask.used = true; + gl_state.depthmask.mask = flag; +} + +void rglStencilMask(GLenum mask) +{ + glStencilMask(mask); + gl_state.stencilmask.used = true; + gl_state.stencilmask.mask = mask; +} + +void rglBufferData(GLenum target, GLsizeiptr size, + const GLvoid *data, GLenum usage) +{ + glBufferData(target, size, data, usage); +} + +void rglBufferSubData(GLenum target, GLintptr offset, + GLsizeiptr size, const GLvoid *data) +{ + glBufferSubData(target, offset, size, data); +} + +void rglBindBuffer(GLenum target, GLuint buffer) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glBindBuffer(target, buffer); +} + +void rglLinkProgram(GLuint program) +{ + glLinkProgram(program); +} + +void rglFramebufferTexture2D(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) +{ + glFramebufferTexture2D(target, attachment, textarget, texture, level); +} + +void rglDrawArrays(GLenum mode, GLint first, GLsizei count) +{ + glDrawArrays(mode, first, count); +} + +void rglCompressedTexImage2D(GLenum target, GLint level, + GLenum internalformat, GLsizei width, GLsizei height, + GLint border, GLsizei imageSize, const GLvoid *data) +{ + glCompressedTexImage2D(target, level, internalformat, + width, height, border, imageSize, data); +} + +void rglFramebufferRenderbuffer(GLenum target, GLenum attachment, + GLenum renderbuffertarget, GLuint renderbuffer) +{ + glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); +} + +void rglDeleteFramebuffers(GLsizei n, GLuint *framebuffers) +{ + glDeleteFramebuffers(n, framebuffers); +} + +void rglDeleteTextures(GLsizei n, const GLuint *textures) +{ + glDeleteTextures(n, textures); +} + +void rglRenderbufferStorage(GLenum target, GLenum internalFormat, + GLsizei width, GLsizei height) +{ + glRenderbufferStorage(target, internalFormat, width, height); +} + +void rglBindRenderbuffer(GLenum target, GLuint renderbuffer) +{ + glBindRenderbuffer(target, renderbuffer); +} + +void rglDeleteRenderbuffers(GLsizei n, GLuint *renderbuffers) +{ + glDeleteRenderbuffers(n, renderbuffers); +} + +void rglGenRenderbuffers(GLsizei n, GLuint *renderbuffers) +{ + glGenRenderbuffers(n, renderbuffers); +} + +void rglGenFramebuffers(GLsizei n, GLuint *ids) +{ + glGenFramebuffers(n, ids); +} + +void rglBindFramebuffer(GLenum target, GLuint framebuffer) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + if (!glsm_ctl(GLSM_CTL_IS_FRAMEBUFFER_LOCKED, NULL)) + { + glBindFramebuffer(target, framebuffer); + gl_state.framebuf = framebuffer; + } +} + +void rglGenerateMipmap(GLenum target) +{ + glGenerateMipmap(target); +} + +GLenum rglCheckFramebufferStatus(GLenum target) +{ + return glCheckFramebufferStatus(target); +} + +void rglBindFragDataLocation(GLuint program, GLuint colorNumber, + const char * name) +{ +#if !defined(HAVE_OPENGLES2) + glBindFragDataLocation(program, colorNumber, name); +#endif +} + +void rglBindAttribLocation(GLuint program, GLuint index, const GLchar *name) +{ + glBindAttribLocation(program, index, name); +} + +void rglGetProgramiv(GLuint shader, GLenum pname, GLint *params) +{ + glGetProgramiv(shader, pname, params); +} + +void rglUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value) +{ + glUniformMatrix4fv(location, count, transpose, value); +} + +void rglDetachShader(GLuint program, GLuint shader) +{ + glDetachShader(program, shader); +} + +void rglGetShaderiv(GLuint shader, GLenum pname, GLint *params) +{ + glGetShaderiv(shader, pname, params); +} + +void rglAttachShader(GLuint program, GLuint shader) +{ + glAttachShader(program, shader); +} + +GLint rglGetAttribLocation(GLuint program, const GLchar *name) +{ + return glGetAttribLocation(program, name); +} + +void rglShaderSource(GLuint shader, GLsizei count, + const GLchar **string, const GLint *length) +{ + return glShaderSource(shader, count, string, length); +} + +void rglCompileShader(GLuint shader) +{ + glCompileShader(shader); +} + +GLuint rglCreateProgram(void) +{ + return glCreateProgram(); +} + +void rglGenTextures(GLsizei n, GLuint *textures) +{ + glGenTextures(n, textures); +} + +void rglGetShaderInfoLog(GLuint shader, GLsizei maxLength, + GLsizei *length, GLchar *infoLog) +{ + glGetShaderInfoLog(shader, maxLength, length, infoLog); +} + +void rglGetProgramInfoLog(GLuint shader, GLsizei maxLength, + GLsizei *length, GLchar *infoLog) +{ + glGetProgramInfoLog(shader, maxLength, length, infoLog); +} + +GLboolean rglIsProgram(GLuint program) +{ + return glIsProgram(program); +} + +void rglEnableVertexAttribArray(GLuint index) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + gl_state.vertex_attrib_pointer.enabled[index] = 1; + glEnableVertexAttribArray(index); +} + +void rglDisableVertexAttribArray(GLuint index) +{ + gl_state.vertex_attrib_pointer.enabled[index] = 0; + glDisableVertexAttribArray(index); +} + +void rglDrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid * indices) +{ + glDrawElements(mode, count, type, indices); +} + +void rglTexCoord2f(GLfloat s, GLfloat t) +{ +#ifdef HAVE_LEGACY_GL + glTexCoord2f(s, t); +#endif +} + +void rglVertexAttribPointer(GLuint name, GLint size, + GLenum type, GLboolean normalized, GLsizei stride, + const GLvoid* pointer) +{ + glVertexAttribPointer(name, size, type, normalized, stride, pointer); +} + +void rglVertexAttrib4f(GLuint name, GLfloat x, GLfloat y, + GLfloat z, GLfloat w) +{ + glVertexAttrib4f(name, x, y, z, w); +} + +void rglVertexAttrib4fv(GLuint name, GLfloat* v) +{ + glVertexAttrib4fv(name, v); +} + +GLuint rglCreateShader(GLenum shaderType) +{ + return glCreateShader(shaderType); +} + +void rglDeleteProgram(GLuint program) +{ + glDeleteProgram(program); +} + +void rglDeleteShader(GLuint shader) +{ + glDeleteShader(shader); +} + +GLint rglGetUniformLocation(GLuint program, const GLchar *name) +{ + return glGetUniformLocation(program, name); +} + +void rglDeleteBuffers(GLsizei n, const GLuint *buffers) +{ + glDeleteBuffers(n, buffers); +} + +void rglGenBuffers(GLsizei n, GLuint *buffers) +{ + glGenBuffers(n, buffers); +} + +void rglUniform1f(GLint location, GLfloat v0) +{ + glUniform1f(location, v0); +} + +void rglUniform1i(GLint location, GLint v0) +{ + glUniform1i(location, v0); +} + +void rglUniform2f(GLint location, GLfloat v0, GLfloat v1) +{ + glUniform2f(location, v0, v1); +} + +void rglUniform2i(GLint location, GLint v0, GLint v1) +{ + glUniform2i(location, v0, v1); +} + +void rglUniform2fv(GLint location, GLsizei count, const GLfloat *value) +{ + glUniform2fv(location, count, value); +} + +void rglUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) +{ + glUniform3f(location, v0, v1, v2); +} + +void rglUniform3fv(GLint location, GLsizei count, const GLfloat *value) +{ + glUniform3fv(location, count, value); +} + +void rglUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) +{ + glUniform4f(location, v0, v1, v2, v3); +} + +void rglUniform4fv(GLint location, GLsizei count, const GLfloat *value) +{ + glUniform4fv(location, count, value); +} + +void rglPolygonOffset(GLfloat factor, GLfloat units) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glPolygonOffset(factor, units); + gl_state.polygonoffset.used = true; + gl_state.polygonoffset.factor = factor; + gl_state.polygonoffset.units = units; +} + +/* GLSM-side */ + +static void glsm_state_setup(void) +{ + unsigned i; + + gl_state.cap_translate[SGL_DEPTH_TEST] = GL_DEPTH_TEST; + gl_state.cap_translate[SGL_BLEND] = GL_BLEND; + gl_state.cap_translate[SGL_POLYGON_OFFSET_FILL] = GL_POLYGON_OFFSET_FILL; + gl_state.cap_translate[SGL_FOG] = GL_FOG; + gl_state.cap_translate[SGL_CULL_FACE] = GL_CULL_FACE; + gl_state.cap_translate[SGL_ALPHA_TEST] = GL_ALPHA_TEST; + gl_state.cap_translate[SGL_SCISSOR_TEST] = GL_SCISSOR_TEST; + gl_state.cap_translate[SGL_STENCIL_TEST] = GL_STENCIL_TEST; + +#ifndef HAVE_OPENGLES + gl_state.cap_translate[SGL_COLOR_LOGIC_OP] = GL_COLOR_LOGIC_OP; +#endif + + for (i = 0; i < MAX_ATTRIB; i++) + gl_state.vertex_attrib_pointer.enabled[i] = 0; + + gl_state.framebuf = hw_render.get_current_framebuffer(); + gl_state.cullface.mode = GL_BACK; + gl_state.frontface.mode = GL_CCW; + + gl_state.blendfunc_separate.used = false; + gl_state.blendfunc_separate.srcRGB = GL_ONE; + gl_state.blendfunc_separate.dstRGB = GL_ZERO; + gl_state.blendfunc_separate.srcAlpha = GL_ONE; + gl_state.blendfunc_separate.dstAlpha = GL_ZERO; + + gl_state.depthfunc.used = false; + + gl_state.colormask.used = false; + gl_state.colormask.red = GL_TRUE; + gl_state.colormask.green = GL_TRUE; + gl_state.colormask.blue = GL_TRUE; + gl_state.colormask.alpha = GL_TRUE; + + gl_state.polygonoffset.used = false; + + gl_state.depthfunc.func = GL_LESS; + +#ifndef HAVE_OPENGLES + gl_state.colorlogicop = GL_COPY; +#endif + +#ifdef CORE + glGenVertexArrays(1, &gl_state.vao); +#endif +} + +static void glsm_state_bind(void) +{ + unsigned i; + + for (i = 0; i < MAX_ATTRIB; i++) + { + if (gl_state.vertex_attrib_pointer.enabled[i]) + glEnableVertexAttribArray(i); + else + glDisableVertexAttribArray(i); + } + + glBindFramebuffer(RARCH_GL_FRAMEBUFFER, hw_render.get_current_framebuffer()); + + if (gl_state.blendfunc.used) + glBlendFunc( + gl_state.blendfunc.sfactor, + gl_state.blendfunc.dfactor); + + if (gl_state.blendfunc_separate.used) + glBlendFuncSeparate( + gl_state.blendfunc_separate.srcRGB, + gl_state.blendfunc_separate.dstRGB, + gl_state.blendfunc_separate.srcAlpha, + gl_state.blendfunc_separate.dstAlpha + ); + + glClearColor( + gl_state.clear_color.r, + gl_state.clear_color.g, + gl_state.clear_color.b, + gl_state.clear_color.a); + + if (gl_state.depthfunc.used) + glDepthFunc(gl_state.depthfunc.func); + + if (gl_state.colormask.used) + glColorMask( + gl_state.colormask.red, + gl_state.colormask.green, + gl_state.colormask.blue, + gl_state.colormask.alpha); + + if (gl_state.cullface.used) + glCullFace(gl_state.cullface.mode); + + if (gl_state.depthmask.used) + glDepthMask(gl_state.depthmask.mask); + + if (gl_state.polygonoffset.used) + glPolygonOffset( + gl_state.polygonoffset.factor, + gl_state.polygonoffset.units); + + if (gl_state.scissor.used) + glScissor( + gl_state.scissor.x, + gl_state.scissor.y, + gl_state.scissor.w, + gl_state.scissor.h); + + glUseProgram(gl_state.program); + + glViewport( + gl_state.viewport.x, + gl_state.viewport.y, + gl_state.viewport.w, + gl_state.viewport.h); +#ifdef CORE + glBindVertexArray(gl_state.vao); +#endif + for(i = 0; i < SGL_CAP_MAX; i ++) + { + if (gl_state.cap_state[i]) + glEnable(gl_state.cap_translate[i]); + } + + if (gl_state.frontface.used) + glFrontFace(gl_state.frontface.mode); + + if (gl_state.stencilmask.used) + glStencilMask(gl_state.stencilmask.mask); + + if (gl_state.stencilop.used) + glStencilOp(gl_state.stencilop.sfail, + gl_state.stencilop.dpfail, + gl_state.stencilop.dppass); + + if (gl_state.stencilfunc.used) + glStencilFunc( + gl_state.stencilfunc.func, + gl_state.stencilfunc.ref, + gl_state.stencilfunc.mask); + + for (i = 0; i < MAX_TEXTURE; i ++) + { + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, gl_state.bind_textures.ids[i]); + } + + glActiveTexture(GL_TEXTURE0 + gl_state.active_texture); + + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +static void glsm_state_unbind(void) +{ + unsigned i; +#ifdef CORE + glBindVertexArray(0); +#endif + for (i = 0; i < SGL_CAP_MAX; i ++) + { + if (gl_state.cap_state[i]) + glDisable(gl_state.cap_translate[i]); + } + + glBlendFunc(GL_ONE, GL_ZERO); + + if (gl_state.colormask.used) + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + if (gl_state.blendfunc_separate.used) + glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO); + + if (gl_state.cullface.used) + glCullFace(GL_BACK); + + if (gl_state.depthmask.used) + glDepthMask(GL_TRUE); + + if (gl_state.polygonoffset.used) + glPolygonOffset(0, 0); + + glUseProgram(0); + glClearColor(0,0,0,0.0f); + + if (gl_state.depthrange.used) + rglDepthRange(0, 1); + + glStencilMask(1); + glFrontFace(GL_CCW); + if (gl_state.depthfunc.used) + glDepthFunc(GL_LESS); + + if (gl_state.stencilop.used) + glStencilOp(GL_KEEP,GL_KEEP, GL_KEEP); + + if (gl_state.stencilfunc.used) + glStencilFunc(GL_ALWAYS,0,1); + + /* Clear textures */ + for (i = 0; i < MAX_TEXTURE; i ++) + { + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, 0); + } + glActiveTexture(GL_TEXTURE0); + + for (i = 0; i < MAX_ATTRIB; i ++) + glDisableVertexAttribArray(i); + + glBindFramebuffer(RARCH_GL_FRAMEBUFFER, 0); +} + +static bool dummy_framebuffer_lock(void *data) +{ + (void)data; + return false; +} + +static bool glsm_state_ctx_init(void *data) +{ + glsm_ctx_params_t *params = (glsm_ctx_params_t*)data; + + if (!params || !params->environ_cb) + return false; + +#ifdef HAVE_OPENGLES +#if defined(HAVE_OPENGLES31) + hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES_VERSION; + hw_render.version_major = 3; + hw_render.version_minor = 1; +#elif defined(HAVE_OPENGLES3) + hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES3; +#else + hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES2; +#endif +#else +#ifdef CORE + hw_render.context_type = RETRO_HW_CONTEXT_OPENGL_CORE; + hw_render.version_major = 3; + hw_render.version_minor = 1; +#else + hw_render.context_type = RETRO_HW_CONTEXT_OPENGL; +#endif +#endif + hw_render.context_reset = params->context_reset; + hw_render.context_destroy = params->context_destroy; + hw_render.stencil = params->stencil; + hw_render.depth = true; + hw_render.bottom_left_origin = true; + hw_render.cache_context = true; + + imm_vbo_draw = NULL; + imm_vbo_disable = NULL; + + if (params->imm_vbo_draw != NULL) + imm_vbo_draw = params->imm_vbo_draw; + if (params->imm_vbo_disable != NULL) + imm_vbo_disable = params->imm_vbo_disable; + + glsm_fb_lock = dummy_framebuffer_lock; + if (params->framebuffer_lock != NULL) + glsm_fb_lock = params->framebuffer_lock; + + if (imm_vbo_draw != NULL && imm_vbo_disable != NULL) + glsm_ctl(GLSM_CTL_SET_IMM_VBO, NULL); + + if (!params->environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render)) + return false; + + return true; +} + +bool glsm_ctl(enum glsm_state_ctl state, void *data) +{ + static bool imm_vbo_enable = false; + + switch (state) + { + case GLSM_CTL_IS_FRAMEBUFFER_LOCKED: + return glsm_fb_lock(NULL); + case GLSM_CTL_IMM_VBO_DRAW: + if (imm_vbo_draw == NULL || !imm_vbo_enable) + return false; + imm_vbo_draw(NULL); + break; + case GLSM_CTL_IMM_VBO_DISABLE: + if (imm_vbo_disable == NULL || !imm_vbo_enable) + return false; + imm_vbo_disable(NULL); + break; + case GLSM_CTL_IS_IMM_VBO: + return imm_vbo_enable; + case GLSM_CTL_SET_IMM_VBO: + imm_vbo_enable = true; + break; + case GLSM_CTL_UNSET_IMM_VBO: + imm_vbo_enable = false; + break; + case GLSM_CTL_PROC_ADDRESS_GET: + { + glsm_ctx_proc_address_t *proc = (glsm_ctx_proc_address_t*)data; + if (!hw_render.get_proc_address) + return false; + proc->addr = hw_render.get_proc_address; + } + break; + case GLSM_CTL_STATE_CONTEXT_RESET: + rglgen_resolve_symbols(hw_render.get_proc_address); + break; + case GLSM_CTL_STATE_CONTEXT_INIT: + return glsm_state_ctx_init(data); + case GLSM_CTL_STATE_SETUP: + glsm_state_setup(); + break; + case GLSM_CTL_STATE_UNBIND: + glsm_state_unbind(); + break; + case GLSM_CTL_STATE_BIND: + glsm_state_bind(); + break; + case GLSM_CTL_NONE: + default: + break; + } + + return true; +} diff --git a/desmume/src/libretro-common/hash/rhash.c b/desmume/src/libretro-common/hash/rhash.c index 8effcb226..edf6a06e5 100644 --- a/desmume/src/libretro-common/hash/rhash.c +++ b/desmume/src/libretro-common/hash/rhash.c @@ -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); diff --git a/desmume/src/libretro-common/include/compat/apple_compat.h b/desmume/src/libretro-common/include/compat/apple_compat.h index 7ca1e1592..7e13d90ba 100644 --- a/desmume/src/libretro-common/include/compat/apple_compat.h +++ b/desmume/src/libretro-common/include/compat/apple_compat.h @@ -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 diff --git a/desmume/src/libretro-common/include/compat/getopt.h b/desmume/src/libretro-common/include/compat/getopt.h index ae164e788..94414b54b 100644 --- a/desmume/src/libretro-common/include/compat/getopt.h +++ b/desmume/src/libretro-common/include/compat/getopt.h @@ -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" { diff --git a/desmume/src/libretro-common/include/compat/msvc.h b/desmume/src/libretro-common/include/compat/msvc.h index 91d9ad6ce..5782f9e36 100644 --- a/desmume/src/libretro-common/include/compat/msvc.h +++ b/desmume/src/libretro-common/include/compat/msvc.h @@ -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) diff --git a/desmume/src/libretro-common/include/compat/posix_string.h b/desmume/src/libretro-common/include/compat/posix_string.h index 35c8efce6..bd18f61aa 100644 --- a/desmume/src/libretro-common/include/compat/posix_string.h +++ b/desmume/src/libretro-common/include/compat/posix_string.h @@ -24,30 +24,34 @@ #define __LIBRETRO_SDK_COMPAT_POSIX_STRING_H #ifdef _MSC_VER - #include +#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 - diff --git a/desmume/src/libretro-common/include/compat/strcasestr.h b/desmume/src/libretro-common/include/compat/strcasestr.h index bd36835ee..69814c74f 100644 --- a/desmume/src/libretro-common/include/compat/strcasestr.h +++ b/desmume/src/libretro-common/include/compat/strcasestr.h @@ -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); diff --git a/desmume/src/libretro-common/include/compat/strl.h b/desmume/src/libretro-common/include/compat/strl.h index 14a0c0320..86d2a3993 100644 --- a/desmume/src/libretro-common/include/compat/strl.h +++ b/desmume/src/libretro-common/include/compat/strl.h @@ -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); diff --git a/desmume/src/libretro-common/include/encodings/utf.h b/desmume/src/libretro-common/include/encodings/utf.h new file mode 100644 index 000000000..d6528b0c5 --- /dev/null +++ b/desmume/src/libretro-common/include/encodings/utf.h @@ -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 +#include + +#include + +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 diff --git a/desmume/src/libretro-common/include/file/config_file.h b/desmume/src/libretro-common/include/file/config_file.h index 8a3ad49b6..81baca941 100644 --- a/desmume/src/libretro-common/include/file/config_file.h +++ b/desmume/src/libretro-common/include/file/config_file.h @@ -34,33 +34,23 @@ extern "C" { #include -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); diff --git a/desmume/src/libretro-common/include/file/file_archive.h b/desmume/src/libretro-common/include/file/file_archive.h new file mode 100644 index 000000000..e745430e6 --- /dev/null +++ b/desmume/src/libretro-common/include/file/file_archive.h @@ -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 +#include + +#include + +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 + diff --git a/desmume/src/libretro-common/include/file/file_extract.h b/desmume/src/libretro-common/include/file/file_extract.h deleted file mode 100644 index 6afac0ef7..000000000 --- a/desmume/src/libretro-common/include/file/file_extract.h +++ /dev/null @@ -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 -#include - -#include - -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 - diff --git a/desmume/src/libretro-common/include/file/file_list.h b/desmume/src/libretro-common/include/file/file_list.h index dd8046fd5..4bf13ffc6 100644 --- a/desmume/src/libretro-common/include/file/file_list.h +++ b/desmume/src/libretro-common/include/file/file_list.h @@ -27,6 +27,9 @@ extern "C" { #endif +#include +#include + #include struct item_file diff --git a/desmume/src/libretro-common/include/file/file_path.h b/desmume/src/libretro-common/include/file/file_path.h index 62a4d3ab2..a5bcfe480 100644 --- a/desmume/src/libretro-common/include/file/file_path.h +++ b/desmume/src/libretro-common/include/file/file_path.h @@ -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 diff --git a/desmume/src/libretro-common/include/formats/image.h b/desmume/src/libretro-common/include/formats/image.h index c27381a71..9ca5cd141 100644 --- a/desmume/src/libretro-common/include/formats/image.h +++ b/desmume/src/libretro-common/include/formats/image.h @@ -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 } diff --git a/desmume/src/libretro-common/include/formats/jsonsax.h b/desmume/src/libretro-common/include/formats/jsonsax.h new file mode 100644 index 000000000..76860fe5f --- /dev/null +++ b/desmume/src/libretro-common/include/formats/jsonsax.h @@ -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 + +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__ */ diff --git a/desmume/src/libretro-common/include/formats/rpng.h b/desmume/src/libretro-common/include/formats/rpng.h index b61315bed..ee44b7687 100644 --- a/desmume/src/libretro-common/include/formats/rpng.h +++ b/desmume/src/libretro-common/include/formats/rpng.h @@ -27,7 +27,7 @@ #include #include -#include +#include #ifdef __cplusplus extern "C" { diff --git a/desmume/src/libretro-common/include/glsm/glsm.h b/desmume/src/libretro-common/include/glsm/glsm.h new file mode 100644 index 000000000..940433cd9 --- /dev/null +++ b/desmume/src/libretro-common/include/glsm/glsm.h @@ -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 +#include +#include + +#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 diff --git a/desmume/src/libretro-common/include/glsm/glsmsym.h b/desmume/src/libretro-common/include/glsm/glsmsym.h new file mode 100644 index 000000000..eac9b3627 --- /dev/null +++ b/desmume/src/libretro-common/include/glsm/glsmsym.h @@ -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 + +#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 diff --git a/desmume/src/libretro-common/include/glsym/glsym_gl.h b/desmume/src/libretro-common/include/glsym/glsym_gl.h index 89c27eba2..a3150f08d 100644 --- a/desmume/src/libretro-common/include/glsym/glsym_gl.h +++ b/desmume/src/libretro-common/include/glsym/glsym_gl.h @@ -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); diff --git a/desmume/src/libretro-common/include/net/net_compat.h b/desmume/src/libretro-common/include/net/net_compat.h index dde91f3a5..f7fe042ea 100644 --- a/desmume/src/libretro-common/include/net/net_compat.h +++ b/desmume/src/libretro-common/include/net/net_compat.h @@ -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 @@ -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 - diff --git a/desmume/src/libretro-common/include/net/net_http.h b/desmume/src/libretro-common/include/net/net_http.h index b6b6b3a1e..2c66729ac 100644 --- a/desmume/src/libretro-common/include/net/net_http.h +++ b/desmume/src/libretro-common/include/net/net_http.h @@ -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. * diff --git a/desmume/src/libretro-common/include/queues/fifo_buffer.h b/desmume/src/libretro-common/include/queues/fifo_buffer.h index 3e57372ea..ebcbc6b0e 100644 --- a/desmume/src/libretro-common/include/queues/fifo_buffer.h +++ b/desmume/src/libretro-common/include/queues/fifo_buffer.h @@ -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); diff --git a/desmume/src/libretro-common/include/queues/task_queue.h b/desmume/src/libretro-common/include/queues/task_queue.h new file mode 100644 index 000000000..793eb5403 --- /dev/null +++ b/desmume/src/libretro-common/include/queues/task_queue.h @@ -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 +#include + +#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 diff --git a/desmume/src/libretro-common/include/retro_assert.h b/desmume/src/libretro-common/include/retro_assert.h index 56996acd3..a4173edc0 100644 --- a/desmume/src/libretro-common/include/retro_assert.h +++ b/desmume/src/libretro-common/include/retro_assert.h @@ -23,18 +23,14 @@ #ifndef __RETRO_ASSERT_H #define __RETRO_ASSERT_H -#ifdef RARCH_INTERNAL -#include -#else #include -#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 diff --git a/desmume/src/libretro-common/include/retro_file.h b/desmume/src/libretro-common/include/retro_file.h index e331305d1..8ce8cc175 100644 --- a/desmume/src/libretro-common/include/retro_file.h +++ b/desmume/src/libretro-common/include/retro_file.h @@ -28,10 +28,6 @@ #include -#ifdef _MSC_VER -#include -#endif - #include #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); diff --git a/desmume/src/libretro-common/include/retro_inline.h b/desmume/src/libretro-common/include/retro_inline.h index 8535d8480..3c25b202e 100644 --- a/desmume/src/libretro-common/include/retro_inline.h +++ b/desmume/src/libretro-common/include/retro_inline.h @@ -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__) diff --git a/desmume/src/libretro-common/include/retro_log.h b/desmume/src/libretro-common/include/retro_log.h deleted file mode 100644 index 26454df5d..000000000 --- a/desmume/src/libretro-common/include/retro_log.h +++ /dev/null @@ -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 . - */ - -#ifndef __RARCH_LOGGER_H -#define __RARCH_LOGGER_H - -#ifdef _XBOX1 -#include -#endif -#include -#include - -#ifdef __MACH__ -#include -#if TARGET_IPHONE_SIMULATOR -#include -#else -#include -#endif -#endif - -#ifdef ANDROID -#include -#endif - -#include -#include -#include -#include - -#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 - diff --git a/desmume/src/libretro-common/include/retro_miscellaneous.h b/desmume/src/libretro-common/include/retro_miscellaneous.h index 0209c9bcd..93b673e4e 100644 --- a/desmume/src/libretro-common/include/retro_miscellaneous.h +++ b/desmume/src/libretro-common/include/retro_miscellaneous.h @@ -24,6 +24,7 @@ #define __RARCH_MISCELLANEOUS_H #include +#include #if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__) #include @@ -56,15 +57,23 @@ #include #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))) diff --git a/desmume/src/libretro-common/include/retro_stat.h b/desmume/src/libretro-common/include/retro_stat.h index eaec86889..cd83d003a 100644 --- a/desmume/src/libretro-common/include/retro_stat.h +++ b/desmume/src/libretro-common/include/retro_stat.h @@ -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 diff --git a/desmume/src/libretro-common/include/rhash.h b/desmume/src/libretro-common/include/rhash.h index 4067b22de..5af17e0ea 100644 --- a/desmume/src/libretro-common/include/rhash.h +++ b/desmume/src/libretro-common/include/rhash.h @@ -56,7 +56,7 @@ #include -/** +/** * 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 + * + * 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 diff --git a/desmume/src/libretro-common/include/rthreads/async_job.h b/desmume/src/libretro-common/include/rthreads/async_job.h new file mode 100644 index 000000000..d98742b47 --- /dev/null +++ b/desmume/src/libretro-common/include/rthreads/async_job.h @@ -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 */ diff --git a/desmume/src/libretro-common/include/rthreads/rsemaphore.h b/desmume/src/libretro-common/include/rthreads/rsemaphore.h new file mode 100644 index 000000000..9dbb82155 --- /dev/null +++ b/desmume/src/libretro-common/include/rthreads/rsemaphore.h @@ -0,0 +1,44 @@ +/* Copyright (C) 2010-2015 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (rsemaphore.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __LIBRETRO_SDK_SEMAPHORE_H +#define __LIBRETRO_SDK_SEMAPHORE_H + +typedef struct ssem ssem_t; + +/** + * ssem_create: + * @value : initial value for the semaphore + * + * Create a new semaphore. + * + * Returns: pointer to new semaphore if successful, otherwise NULL. + */ +ssem_t *ssem_new(int value); + +void ssem_free(ssem_t *semaphore); + +void ssem_wait(ssem_t *semaphore); + +void ssem_signal(ssem_t *semaphore); + +#endif /* __LIBRETRO_SDK_SEMAPHORE_H */ diff --git a/desmume/src/libretro-common/include/rthreads/rthreads.h b/desmume/src/libretro-common/include/rthreads/rthreads.h index 90ae90fde..52a4d9b6f 100644 --- a/desmume/src/libretro-common/include/rthreads/rthreads.h +++ b/desmume/src/libretro-common/include/rthreads/rthreads.h @@ -28,7 +28,8 @@ #include #include -#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 diff --git a/desmume/src/libretro-common/include/string/stdstring.h b/desmume/src/libretro-common/include/string/stdstring.h index 1217de9b4..ecc866643 100644 --- a/desmume/src/libretro-common/include/string/stdstring.h +++ b/desmume/src/libretro-common/include/string/stdstring.h @@ -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); diff --git a/desmume/src/libretro-common/include/string/string_list.h b/desmume/src/libretro-common/include/string/string_list.h index 71c3554f2..c6040cc14 100644 --- a/desmume/src/libretro-common/include/string/string_list.h +++ b/desmume/src/libretro-common/include/string/string_list.h @@ -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: diff --git a/desmume/src/libretro-common/net/Makefile b/desmume/src/libretro-common/net/Makefile new file mode 100644 index 000000000..5dfdf3b18 --- /dev/null +++ b/desmume/src/libretro-common/net/Makefile @@ -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) diff --git a/desmume/src/libretro-common/net/net_compat.c b/desmume/src/libretro-common/net/net_compat.c index ec33d7436..db6c64488 100644 --- a/desmume/src/libretro-common/net/net_compat.c +++ b/desmume/src/libretro-common/net/net_compat.c @@ -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 . + * 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 @@ -20,8 +26,77 @@ #include #include +#include -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 } diff --git a/desmume/src/libretro-common/net/net_http.c b/desmume/src/libretro-common/net/net_http.c index ce3482b2a..ecdeccf88 100644 --- a/desmume/src/libretro-common/net/net_http.c +++ b/desmume/src/libretro-common/net/net_http.c @@ -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 . + * 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 @@ -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); +} diff --git a/desmume/src/libretro-common/net/net_http_test.c b/desmume/src/libretro-common/net/net_http_test.c index b32f1bfcf..e6940a537 100644 --- a/desmume/src/libretro-common/net/net_http_test.c +++ b/desmume/src/libretro-common/net/net_http_test.c @@ -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 #include #include @@ -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()) diff --git a/desmume/src/libretro-common/queues/fifo_buffer.c b/desmume/src/libretro-common/queues/fifo_buffer.c index 2a02b68dc..2a0726606 100644 --- a/desmume/src/libretro-common/queues/fifo_buffer.c +++ b/desmume/src/libretro-common/queues/fifo_buffer.c @@ -25,6 +25,14 @@ #include +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)); diff --git a/desmume/src/libretro-common/queues/task_queue.c b/desmume/src/libretro-common/queues/task_queue.c new file mode 100644 index 000000000..40ea3b5d2 --- /dev/null +++ b/desmume/src/libretro-common/queues/task_queue.c @@ -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 +#include +#include + +#include + +#ifdef HAVE_THREADS +#include +#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; +} diff --git a/desmume/src/libretro-common/rthreads/async_job.c b/desmume/src/libretro-common/rthreads/async_job.c new file mode 100644 index 000000000..28548c17a --- /dev/null +++ b/desmume/src/libretro-common/rthreads/async_job.c @@ -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 + +#include +#include +#include + +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; +} diff --git a/desmume/src/libretro-common/rthreads/rsemaphore.c b/desmume/src/libretro-common/rthreads/rsemaphore.c new file mode 100644 index 000000000..eb756318a --- /dev/null +++ b/desmume/src/libretro-common/rthreads/rsemaphore.c @@ -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 + +#include +#include + +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); +} diff --git a/desmume/src/libretro-common/rthreads/rthreads.c b/desmume/src/libretro-common/rthreads/rthreads.c index 9aaa38c93..9f3625c99 100644 --- a/desmume/src/libretro-common/rthreads/rthreads.c +++ b/desmume/src/libretro-common/rthreads/rthreads.c @@ -22,6 +22,7 @@ #include +#include #include #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; } /** diff --git a/desmume/src/libretro-common/string/stdstring.c b/desmume/src/libretro-common/string/stdstring.c index b4a978d01..032836ce8 100644 --- a/desmume/src/libretro-common/string/stdstring.c +++ b/desmume/src/libretro-common/string/stdstring.c @@ -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; } diff --git a/desmume/src/libretro-common/string/string_list.c b/desmume/src/libretro-common/string/string_list.c index 96840dd8d..8e6ecdcdf 100644 --- a/desmume/src/libretro-common/string/string_list.c +++ b/desmume/src/libretro-common/string/string_list.c @@ -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; diff --git a/desmume/src/libretro-common/utils/Makefile b/desmume/src/libretro-common/utils/Makefile index bb2466771..6056f17e8 100644 --- a/desmume/src/libretro-common/utils/Makefile +++ b/desmume/src/libretro-common/utils/Makefile @@ -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) diff --git a/desmume/src/libretro-common/utils/md5.c b/desmume/src/libretro-common/utils/md5.c index b592e27b2..e97d784cc 100644 --- a/desmume/src/libretro-common/utils/md5.c +++ b/desmume/src/libretro-common/utils/md5.c @@ -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 + * + * 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 - -/* 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 -#include -#include #include -/* -- 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 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 diff --git a/desmume/src/libretro-common/utils/udp-test.c b/desmume/src/libretro-common/utils/udp-test.c new file mode 100644 index 000000000..c1cbd77b8 --- /dev/null +++ b/desmume/src/libretro-common/utils/udp-test.c @@ -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 +#include +#include +#include +#include + +#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; +} \ No newline at end of file diff --git a/desmume/src/windows/DeSmuME_2010.vcxproj b/desmume/src/windows/DeSmuME_2010.vcxproj index 4e364e2b8..c78da0fa3 100644 --- a/desmume/src/windows/DeSmuME_2010.vcxproj +++ b/desmume/src/windows/DeSmuME_2010.vcxproj @@ -537,15 +537,29 @@ - - + + + + + + + + + + + + + + + + diff --git a/desmume/src/windows/DeSmuME_2010.vcxproj.filters b/desmume/src/windows/DeSmuME_2010.vcxproj.filters index 40a56eef4..d4b43a2eb 100644 --- a/desmume/src/windows/DeSmuME_2010.vcxproj.filters +++ b/desmume/src/windows/DeSmuME_2010.vcxproj.filters @@ -112,6 +112,9 @@ {334a6ab8-9fe9-4577-983a-10f3b6fa95b9} + + {23ac753a-66cd-40c8-92c3-90f145eaf022} + @@ -903,27 +906,60 @@ Core\libretro-common\formats\bmp - - Core\libretro-common\file - Core\libretro-common\file\nbio - - Core\libretro-common\file - Core\libretro-common\string - + Core\libretro-common\compat - + + Core\libretro-common\compat + + + Core\libretro-common\compat + + + Core\libretro-common\compat + + + Core\libretro-common\compat + + Core\libretro-common\file Core\libretro-common\file + + Core\libretro-common\file + + + Core\libretro-common\file + + + Core\libretro-common\file + + + Core\libretro-common\file + + + Core\libretro-common\file + + + Core\libretro-common\file + + + Core\libretro-common\file + + + Core\libretro-common\hash + + + Core\libretro-common\rthreads +