diff --git a/desmume/src/libretro-common/algorithms/mismatch.c b/desmume/src/libretro-common/algorithms/mismatch.c new file mode 100644 index 000000000..b7997023f --- /dev/null +++ b/desmume/src/libretro-common/algorithms/mismatch.c @@ -0,0 +1,139 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (mismatch.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 + +#if defined(__x86_64__) || defined(__i386__) || defined(__i486__) || defined(__i686__) +#define CPU_X86 +#endif + +/* Other arches SIGBUS (usually) on unaligned accesses. */ +#ifndef CPU_X86 +#define NO_UNALIGNED_MEM +#endif + +#if __SSE2__ +#include +#endif + +/* There's no equivalent in libc, you'd think so ... + * std::mismatch exists, but it's not optimized at all. */ +size_t find_change(const uint16_t *a, const uint16_t *b) +{ +#if __SSE2__ + const __m128i *a128 = (const __m128i*)a; + const __m128i *b128 = (const __m128i*)b; + + for (;;) + { + __m128i v0 = _mm_loadu_si128(a128); + __m128i v1 = _mm_loadu_si128(b128); + __m128i c = _mm_cmpeq_epi32(v0, v1); + uint32_t mask = _mm_movemask_epi8(c); + + if (mask != 0xffff) /* Something has changed, figure out where. */ + { + size_t ret = (((uint8_t*)a128 - (uint8_t*)a) | + (compat_ctz(~mask))) >> 1; + return ret | (a[ret] == b[ret]); + } + + a128++; + b128++; + } +#else + const uint16_t *a_org = a; +#ifdef NO_UNALIGNED_MEM + while (((uintptr_t)a & (sizeof(size_t) - 1)) && *a == *b) + { + a++; + b++; + } + if (*a == *b) +#endif + { + const size_t *a_big = (const size_t*)a; + const size_t *b_big = (const size_t*)b; + + while (*a_big == *b_big) + { + a_big++; + b_big++; + } + a = (const uint16_t*)a_big; + b = (const uint16_t*)b_big; + + while (*a == *b) + { + a++; + b++; + } + } + return a - a_org; +#endif +} + +size_t find_same(const uint16_t *a, const uint16_t *b) +{ + const uint16_t *a_org = a; +#ifdef NO_UNALIGNED_MEM + if (((uintptr_t)a & (sizeof(uint32_t) - 1)) && *a != *b) + { + a++; + b++; + } + if (*a != *b) +#endif + { + /* With this, it's random whether two consecutive identical + * words are caught. + * + * Luckily, compression rate is the same for both cases, and + * three is always caught. + * + * (We prefer to miss two-word blocks, anyways; fewer iterations + * of the outer loop, as well as in the decompressor.) */ + const uint32_t *a_big = (const uint32_t*)a; + const uint32_t *b_big = (const uint32_t*)b; + + while (*a_big != *b_big) + { + a_big++; + b_big++; + } + a = (const uint16_t*)a_big; + b = (const uint16_t*)b_big; + + if (a != a_org && a[-1] == b[-1]) + { + a--; + b--; + } + } + return a - a_org; +} diff --git a/desmume/src/libretro-common/compat/compat_getopt.c b/desmume/src/libretro-common/compat/compat_getopt.c index 4a0d069dc..c7b1c6691 100644 --- a/desmume/src/libretro-common/compat/compat_getopt.c +++ b/desmume/src/libretro-common/compat/compat_getopt.c @@ -167,11 +167,11 @@ static void shuffle_block(char **begin, char **last, char **end) retro_assert(tmp); - memcpy(tmp, begin, len * sizeof(const char*)); + memcpy((void*)tmp, begin, len * sizeof(const char*)); memmove(begin, last, (end - last) * sizeof(const char*)); memcpy(end - len, tmp, len * sizeof(const char*)); - free(tmp); + free((void*)tmp); } int getopt_long(int argc, char *argv[], diff --git a/desmume/src/libretro-common/compat/compat_snprintf.c b/desmume/src/libretro-common/compat/compat_snprintf.c index d068f9c59..336d2b8e7 100644 --- a/desmume/src/libretro-common/compat/compat_snprintf.c +++ b/desmume/src/libretro-common/compat/compat_snprintf.c @@ -34,7 +34,11 @@ int c99_vsnprintf_retro__(char *outBuf, size_t size, const char *format, va_list int count = -1; if (size != 0) +#if (_MSC_VER <= 1310) + count = _vsnprintf(outBuf, size, format, ap); +#else count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); +#endif if (count == -1) count = _vscprintf(format, ap); diff --git a/desmume/src/libretro-common/compat/compat_strl.c b/desmume/src/libretro-common/compat/compat_strl.c index d8d89d2f7..a16df87fb 100644 --- a/desmume/src/libretro-common/compat/compat_strl.c +++ b/desmume/src/libretro-common/compat/compat_strl.c @@ -29,6 +29,8 @@ /* Implementation of strlcpy()/strlcat() based on OpenBSD. */ +#ifndef __MACH__ + size_t strlcpy(char *dest, const char *source, size_t size) { size_t src_size = 0; @@ -59,3 +61,4 @@ size_t strlcat(char *dest, const char *source, size_t size) return len + strlcpy(dest, source, size); } +#endif diff --git a/desmume/src/libretro-common/conversion/float_to_s16.c b/desmume/src/libretro-common/conversion/float_to_s16.c new file mode 100644 index 000000000..9ae0fab4f --- /dev/null +++ b/desmume/src/libretro-common/conversion/float_to_s16.c @@ -0,0 +1,217 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (float_to_s16.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 + +#if defined(__SSE2__) +#include +#elif defined(__ALTIVEC__) +#include +#endif + +#include +#include + +/** + * convert_float_to_s16_C: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * + * Converts floating point + * to signed integer 16-bit. + * + * C implementation callback function. + **/ +void convert_float_to_s16_C(int16_t *out, + const float *in, size_t samples) +{ + size_t i; + for (i = 0; i < samples; i++) + { + int32_t val = (int32_t)(in[i] * 0x8000); + out[i] = (val > 0x7FFF) ? 0x7FFF : + (val < -0x8000 ? -0x8000 : (int16_t)val); + } +} + +#if defined(__SSE2__) +/** + * convert_float_to_s16_SSE2: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * + * Converts floating point + * to signed integer 16-bit. + * + * SSE2 implementation callback function. + **/ +void convert_float_to_s16_SSE2(int16_t *out, + const float *in, size_t samples) +{ + size_t i; + __m128 factor = _mm_set1_ps((float)0x8000); + + for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8) + { + __m128 input_l = _mm_loadu_ps(in + 0); + __m128 input_r = _mm_loadu_ps(in + 4); + __m128 res_l = _mm_mul_ps(input_l, factor); + __m128 res_r = _mm_mul_ps(input_r, factor); + __m128i ints_l = _mm_cvtps_epi32(res_l); + __m128i ints_r = _mm_cvtps_epi32(res_r); + __m128i packed = _mm_packs_epi32(ints_l, ints_r); + + _mm_storeu_si128((__m128i *)out, packed); + } + + convert_float_to_s16_C(out, in, samples - i); +} +#elif defined(__ALTIVEC__) +/** + * convert_float_to_s16_altivec: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * + * Converts floating point + * to signed integer 16-bit. + * + * AltiVec implementation callback function. + **/ +void convert_float_to_s16_altivec(int16_t *out, + const float *in, size_t samples) +{ + int samples_in = samples; + + /* Unaligned loads/store is a bit expensive, + * so we optimize for the good path (very likely). */ + if (((uintptr_t)out & 15) + ((uintptr_t)in & 15) == 0) + { + size_t i; + for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8) + { + vector float input0 = vec_ld( 0, in); + vector float input1 = vec_ld(16, in); + vector signed int result0 = vec_cts(input0, 15); + vector signed int result1 = vec_cts(input1, 15); + vec_st(vec_packs(result0, result1), 0, out); + } + + samples_in -= i; + } + convert_float_to_s16_C(out, in, samples_in); +} +#elif defined(__ARM_NEON__) && !defined(VITA) +void convert_float_s16_asm(int16_t *out, const float *in, size_t samples); +/** + * convert_float_to_s16_neon: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * + * Converts floating point + * to signed integer 16-bit. + * + * ARM NEON implementation callback function. + **/ +static void convert_float_to_s16_neon(int16_t *out, + const float *in, size_t samples) +{ + size_t aligned_samples = samples & ~7; + if (aligned_samples) + convert_float_s16_asm(out, in, aligned_samples); + + convert_float_to_s16_C(out + aligned_samples, in + aligned_samples, + samples - aligned_samples); +} +#elif defined(_MIPS_ARCH_ALLEGREX) +/** + * convert_float_to_s16_ALLEGREX: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * + * Converts floating point + * to signed integer 16-bit. + * + * MIPS ALLEGREX implementation callback function. + **/ +void convert_float_to_s16_ALLEGREX(int16_t *out, + const float *in, size_t samples) +{ + size_t i; + +#ifdef DEBUG + /* Make sure the buffers are 16 byte aligned, this should be + * the default behaviour of malloc in the PSPSDK. + * Assume alignment. */ + retro_assert(((uintptr_t)in & 0xf) == 0); + retro_assert(((uintptr_t)out & 0xf) == 0); +#endif + + for (i = 0; i + 8 <= samples; i += 8) + { + __asm__ ( + ".set push \n" + ".set noreorder \n" + + "lv.q c100, 0(%0) \n" + "lv.q c110, 16(%0) \n" + + "vf2in.q c100, c100, 31 \n" + "vf2in.q c110, c110, 31 \n" + "vi2s.q c100, c100 \n" + "vi2s.q c102, c110 \n" + + "sv.q c100, 0(%1) \n" + + ".set pop \n" + :: "r"(in + i), "r"(out + i)); + } + + for (; i < samples; i++) + { + int32_t val = (int32_t)(in[i] * 0x8000); + out[i] = (val > 0x7FFF) ? 0x7FFF : + (val < -0x8000 ? -0x8000 : (int16_t)val); + } +} +#endif + +/** + * convert_float_to_s16_init_simd: + * + * Sets up function pointers for conversion + * functions based on CPU features. + **/ +void convert_float_to_s16_init_simd(void) +{ + unsigned cpu = cpu_features_get(); + + (void)cpu; +#if defined(__ARM_NEON__) && !defined(VITA) + convert_float_to_s16_arm = (cpu & RETRO_SIMD_NEON) ? + convert_float_to_s16_neon : convert_float_to_s16_C; +#endif +} diff --git a/desmume/src/libretro-common/conversion/float_to_s16_neon.S b/desmume/src/libretro-common/conversion/float_to_s16_neon.S new file mode 100644 index 000000000..b3b5b943e --- /dev/null +++ b/desmume/src/libretro-common/conversion/float_to_s16_neon.S @@ -0,0 +1,56 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * + * 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 . + */ +#if defined(__ARM_NEON__) + +#ifndef __MACH__ +.arm +#endif + +.align 4 +.globl convert_float_s16_asm +.globl _convert_float_s16_asm +# convert_float_s16_asm(int16_t *out, const float *in, size_t samples) +convert_float_s16_asm: +_convert_float_s16_asm: + # Hacky way to get a constant of 2^15. + # ((2^4)^2)^2 * 0.5 = 2^15 + vmov.f32 q8, #16.0 + vmov.f32 q9, #0.5 + vmul.f32 q8, q8, q8 + vmul.f32 q8, q8, q8 + vmul.f32 q8, q8, q9 + +1: + # Preload here? + vld1.f32 {q0-q1}, [r1]! + + vmul.f32 q0, q0, q8 + vmul.f32 q1, q1, q8 + + vcvt.s32.f32 q0, q0 + vcvt.s32.f32 q1, q1 + + vqmovn.s32 d4, q0 + vqmovn.s32 d5, q1 + + vst1.f32 {d4-d5}, [r0]! + + # Guaranteed to get samples in multiples of 8. + subs r2, r2, #8 + bne 1b + + bx lr + +#endif diff --git a/desmume/src/libretro-common/conversion/s16_to_float.c b/desmume/src/libretro-common/conversion/s16_to_float.c new file mode 100644 index 000000000..2bc402b1c --- /dev/null +++ b/desmume/src/libretro-common/conversion/s16_to_float.c @@ -0,0 +1,242 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2014-2016 - Ali Bouhlel ( aliaspider@gmail.com ) + * + * 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 . + */ +#if defined(__SSE2__) +#include +#elif defined(__ALTIVEC__) +#include +#endif + +#include +#include +#include + +/** + * convert_s16_to_float_C: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * @gain : gain applied (.e.g. audio volume) + * + * Converts from signed integer 16-bit + * to floating point. + * + * C implementation callback function. + **/ +void convert_s16_to_float_C(float *out, + const int16_t *in, size_t samples, float gain) +{ + size_t i; + gain = gain / 0x8000; + for (i = 0; i < samples; i++) + out[i] = (float)in[i] * gain; +} + +#if defined(__SSE2__) +/** + * convert_s16_to_float_SSE2: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * @gain : gain applied (e.g. audio volume) + * + * Converts from signed integer 16-bit + * to floating point. + * + * SSE2 implementation callback function. + **/ +void convert_s16_to_float_SSE2(float *out, + const int16_t *in, size_t samples, float gain) +{ + size_t i; + float fgain = gain / UINT32_C(0x80000000); + __m128 factor = _mm_set1_ps(fgain); + + for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8) + { + __m128i input = _mm_loadu_si128((const __m128i *)in); + __m128i regs_l = _mm_unpacklo_epi16(_mm_setzero_si128(), input); + __m128i regs_r = _mm_unpackhi_epi16(_mm_setzero_si128(), input); + __m128 output_l = _mm_mul_ps(_mm_cvtepi32_ps(regs_l), factor); + __m128 output_r = _mm_mul_ps(_mm_cvtepi32_ps(regs_r), factor); + + _mm_storeu_ps(out + 0, output_l); + _mm_storeu_ps(out + 4, output_r); + } + + convert_s16_to_float_C(out, in, samples - i, gain); +} + +#elif defined(__ALTIVEC__) +/** + * convert_s16_to_float_altivec: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * @gain : gain applied (e.g. audio volume) + * + * Converts from signed integer 16-bit + * to floating point. + * + * AltiVec implementation callback function. + **/ +void convert_s16_to_float_altivec(float *out, + const int16_t *in, size_t samples, float gain) +{ + size_t samples_in = samples; + + /* Unaligned loads/store is a bit expensive, so we + * optimize for the good path (very likely). */ + if (((uintptr_t)out & 15) + ((uintptr_t)in & 15) == 0) + { + size_t i; + const vector float gain_vec = { gain, gain , gain, gain }; + const vector float zero_vec = { 0.0f, 0.0f, 0.0f, 0.0f}; + + for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8) + { + vector signed short input = vec_ld(0, in); + vector signed int hi = vec_unpackh(input); + vector signed int lo = vec_unpackl(input); + vector float out_hi = vec_madd(vec_ctf(hi, 15), gain_vec, zero_vec); + vector float out_lo = vec_madd(vec_ctf(lo, 15), gain_vec, zero_vec); + + vec_st(out_hi, 0, out); + vec_st(out_lo, 16, out); + } + + samples_in -= i; + } + convert_s16_to_float_C(out, in, samples_in, gain); +} + +#elif defined(__ARM_NEON__) && !defined(VITA) +/* Avoid potential hard-float/soft-float ABI issues. */ +void convert_s16_float_asm(float *out, const int16_t *in, + size_t samples, const float *gain); + +/** + * convert_s16_to_float_neon: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * @gain : gain applied (.e.g audio volume) + * + * Converts from signed integer 16-bit + * to floating point. + * + * ARM NEON implementation callback function. + **/ +static void convert_s16_to_float_neon(float *out, + const int16_t *in, size_t samples, float gain) +{ + size_t aligned_samples = samples & ~7; + if (aligned_samples) + convert_s16_float_asm(out, in, aligned_samples, &gain); + + /* Could do all conversion in ASM, but keep it simple for now. */ + convert_s16_to_float_C(out + aligned_samples, in + aligned_samples, + samples - aligned_samples, gain); +} +#elif defined(_MIPS_ARCH_ALLEGREX) + +/** + * convert_s16_to_float_ALLEGREX: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * @gain : gain applied (.e.g audio volume) + * + * Converts from signed integer 16-bit + * to floating point. + * + * MIPS ALLEGREX implementation callback function. + **/ +void convert_s16_to_float_ALLEGREX(float *out, + const int16_t *in, size_t samples, float gain) +{ +#ifdef DEBUG + /* Make sure the buffer is 16 byte aligned, this should be the + * default behaviour of malloc in the PSPSDK. + * Only the output buffer can be assumed to be 16-byte aligned. */ + retro_assert(((uintptr_t)out & 0xf) == 0); +#endif + + size_t i; + gain = gain / 0x8000; + __asm__ ( + ".set push \n" + ".set noreorder \n" + "mtv %0, s200 \n" + ".set pop \n" + ::"r"(gain)); + + for (i = 0; i + 16 <= samples; i += 16) + { + __asm__ ( + ".set push \n" + ".set noreorder \n" + + "lv.s s100, 0(%0) \n" + "lv.s s101, 4(%0) \n" + "lv.s s110, 8(%0) \n" + "lv.s s111, 12(%0) \n" + "lv.s s120, 16(%0) \n" + "lv.s s121, 20(%0) \n" + "lv.s s130, 24(%0) \n" + "lv.s s131, 28(%0) \n" + + "vs2i.p c100, c100 \n" + "vs2i.p c110, c110 \n" + "vs2i.p c120, c120 \n" + "vs2i.p c130, c130 \n" + + "vi2f.q c100, c100, 16 \n" + "vi2f.q c110, c110, 16 \n" + "vi2f.q c120, c120, 16 \n" + "vi2f.q c130, c130, 16 \n" + + "vmscl.q e100, e100, s200 \n" + + "sv.q c100, 0(%1) \n" + "sv.q c110, 16(%1) \n" + "sv.q c120, 32(%1) \n" + "sv.q c130, 48(%1) \n" + + ".set pop \n" + :: "r"(in + i), "r"(out + i)); + } + + for (; i < samples; i++) + out[i] = (float)in[i] * gain; +} +#endif + +/** + * convert_s16_to_float_init_simd: + * + * Sets up function pointers for conversion + * functions based on CPU features. + **/ +void convert_s16_to_float_init_simd(void) +{ + unsigned cpu = cpu_features_get(); + + (void)cpu; +#if defined(__ARM_NEON__) && !defined(VITA) + convert_s16_to_float_arm = (cpu & RETRO_SIMD_NEON) ? + convert_s16_to_float_neon : convert_s16_to_float_C; +#endif +} diff --git a/desmume/src/libretro-common/conversion/s16_to_float_neon.S b/desmume/src/libretro-common/conversion/s16_to_float_neon.S new file mode 100644 index 000000000..8891a1032 --- /dev/null +++ b/desmume/src/libretro-common/conversion/s16_to_float_neon.S @@ -0,0 +1,63 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * + * 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 . + */ +#if defined(__ARM_NEON__) + +#ifndef __MACH__ +.arm +#endif + +.align 4 +.globl convert_s16_float_asm +.globl _convert_s16_float_asm +# convert_s16_float_asm(float *out, const int16_t *in, size_t samples, const float *gain) +convert_s16_float_asm: +_convert_s16_float_asm: + # Hacky way to get a constant of 2^-15. + # Might be faster to just load a constant from memory. + # It's just done once however ... + vmov.f32 q8, #0.25 + vmul.f32 q8, q8, q8 + vmul.f32 q8, q8, q8 + vmul.f32 q8, q8, q8 + vadd.f32 q8, q8, q8 + + # Apply gain + vld1.f32 {d6[0]}, [r3] + vmul.f32 q8, q8, d6[0] + +1: + # Preload here? + vld1.s16 {q0}, [r1]! + + # Widen to 32-bit + vmovl.s16 q1, d0 + vmovl.s16 q2, d1 + + # Convert to float + vcvt.f32.s32 q1, q1 + vcvt.f32.s32 q2, q2 + + vmul.f32 q1, q1, q8 + vmul.f32 q2, q2, q8 + + vst1.f32 {q1-q2}, [r0]! + + # Guaranteed to get samples in multiples of 8. + subs r2, r2, #8 + bne 1b + + bx lr + +#endif diff --git a/desmume/src/libretro-common/features/features_cpu.c b/desmume/src/libretro-common/features/features_cpu.c new file mode 100644 index 000000000..01ca84b5c --- /dev/null +++ b/desmume/src/libretro-common/features/features_cpu.c @@ -0,0 +1,731 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (features_cpu.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 + +#if defined(_WIN32) +#include +#else +#include +#endif + +#include +#include +#include +#include + +#if defined(_WIN32) && !defined(_XBOX) +#include +#endif + +#if defined(__CELLOS_LV2__) +#ifndef _PPU_INTRINSICS_H +#include +#endif +#elif defined(_XBOX360) +#include +#elif defined(_POSIX_MONOTONIC_CLOCK) || defined(ANDROID) || defined(__QNX__) +/* POSIX_MONOTONIC_CLOCK is not being defined in Android headers despite support being present. */ +#include +#endif + +#if defined(__QNX__) && !defined(CLOCK_MONOTONIC) +#define CLOCK_MONOTONIC 2 +#endif + +#if defined(PSP) +#include +#include +#endif + +#if defined(VITA) +#include +#include +#endif + +#if defined(__PSL1GHT__) +#include +#elif defined(__CELLOS_LV2__) +#include +#endif + +#ifdef GEKKO +#include +#endif + +/* iOS/OSX specific. Lacks clock_gettime(), so implement it. */ +#ifdef __MACH__ +#include + +#ifndef CLOCK_MONOTONIC +#define CLOCK_MONOTONIC 0 +#endif + +#ifndef CLOCK_REALTIME +#define CLOCK_REALTIME 0 +#endif + +#if __IPHONE_OS_VERSION_MAX_ALLOWED < 100000 +// this function is part of iOS 10 now +static int clock_gettime(int clk_ik, struct timespec *t) +{ + struct timeval now; + int rv = gettimeofday(&now, NULL); + if (rv) + return rv; + t->tv_sec = now.tv_sec; + t->tv_nsec = now.tv_usec * 1000; + return 0; +} +#endif +#endif + +#ifdef EMSCRIPTEN +#include +#endif + +#if defined(BSD) || defined(__APPLE__) +#include +#endif + +#include + +/** + * cpu_features_get_perf_counter: + * + * Gets performance counter. + * + * Returns: performance counter. + **/ +retro_perf_tick_t cpu_features_get_perf_counter(void) +{ + retro_perf_tick_t time_ticks = 0; +#if defined(_WIN32) + long tv_sec, tv_usec; + static const unsigned __int64 epoch = 11644473600000000ULL; + FILETIME file_time; + SYSTEMTIME system_time; + ULARGE_INTEGER ularge; + + GetSystemTime(&system_time); + SystemTimeToFileTime(&system_time, &file_time); + ularge.LowPart = file_time.dwLowDateTime; + ularge.HighPart = file_time.dwHighDateTime; + + tv_sec = (long)((ularge.QuadPart - epoch) / 10000000L); + tv_usec = (long)(system_time.wMilliseconds * 1000); + time_ticks = (1000000 * tv_sec + tv_usec); +#elif defined(__linux__) || defined(__QNX__) || defined(__MACH__) + struct timespec tv; + if (clock_gettime(CLOCK_MONOTONIC, &tv) == 0) + time_ticks = (retro_perf_tick_t)tv.tv_sec * 1000000000 + + (retro_perf_tick_t)tv.tv_nsec; + +#elif defined(__GNUC__) && defined(__i386__) || defined(__i486__) || defined(__i686__) + __asm__ volatile ("rdtsc" : "=A" (time_ticks)); +#elif defined(__GNUC__) && defined(__x86_64__) + unsigned a, d; + __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d)); + time_ticks = (retro_perf_tick_t)a | ((retro_perf_tick_t)d << 32); +#elif defined(__ARM_ARCH_6__) + __asm__ volatile( "mrc p15, 0, %0, c9, c13, 0" : "=r"(time_ticks) ); +#elif defined(__CELLOS_LV2__) || defined(_XBOX360) || defined(__powerpc__) || defined(__ppc__) || defined(__POWERPC__) + time_ticks = __mftb(); +#elif defined(GEKKO) + time_ticks = gettime(); +#elif defined(PSP) || defined(VITA) + sceRtcGetCurrentTick(&time_ticks); +#elif defined(_3DS) + time_ticks = svcGetSystemTick(); +#elif defined(__mips__) + struct timeval tv; + gettimeofday(&tv,NULL); + time_ticks = (1000000 * tv.tv_sec + tv.tv_usec); +#endif + + return time_ticks; +} + +/** + * cpu_features_get_time_usec: + * + * Gets time in microseconds. + * + * Returns: time in microseconds. + **/ +retro_time_t cpu_features_get_time_usec(void) +{ +#if defined(_WIN32) + static LARGE_INTEGER freq; + LARGE_INTEGER count; + + /* Frequency is guaranteed to not change. */ + if (!freq.QuadPart && !QueryPerformanceFrequency(&freq)) + return 0; + + if (!QueryPerformanceCounter(&count)) + return 0; + return count.QuadPart * 1000000 / freq.QuadPart; +#elif defined(__CELLOS_LV2__) + return sys_time_get_system_time(); +#elif defined(GEKKO) + return ticks_to_microsecs(gettime()); +#elif defined(_POSIX_MONOTONIC_CLOCK) || defined(__QNX__) || defined(ANDROID) || defined(__MACH__) + struct timespec tv = {0}; + if (clock_gettime(CLOCK_MONOTONIC, &tv) < 0) + return 0; + return tv.tv_sec * INT64_C(1000000) + (tv.tv_nsec + 500) / 1000; +#elif defined(EMSCRIPTEN) + return emscripten_get_now() * 1000; +#elif defined(__mips__) + struct timeval tv; + gettimeofday(&tv,NULL); + return (1000000 * tv.tv_sec + tv.tv_usec); +#elif defined(_3DS) + return osGetTime() * 1000; +#elif defined(VITA) + return sceKernelGetProcessTimeWide(); +#else +#error "Your platform does not have a timer function implemented in cpu_features_get_time_usec(). Cannot continue." +#endif +} + +#if defined(__x86_64__) || defined(__i386__) || defined(__i486__) || defined(__i686__) +#define CPU_X86 +#endif + +#if defined(_MSC_VER) && !defined(_XBOX) +#if (_MSC_VER > 1310) +#include +#endif +#endif + +#if defined(CPU_X86) && !defined(__MACH__) +void x86_cpuid(int func, int flags[4]) +{ + /* On Android, we compile RetroArch with PIC, and we + * are not allowed to clobber the ebx register. */ +#ifdef __x86_64__ +#define REG_b "rbx" +#define REG_S "rsi" +#else +#define REG_b "ebx" +#define REG_S "esi" +#endif + +#if defined(__GNUC__) + __asm__ volatile ( + "mov %%" REG_b ", %%" REG_S "\n" + "cpuid\n" + "xchg %%" REG_b ", %%" REG_S "\n" + : "=a"(flags[0]), "=S"(flags[1]), "=c"(flags[2]), "=d"(flags[3]) + : "a"(func)); +#elif defined(_MSC_VER) + __cpuid(flags, func); +#else + printf("Unknown compiler. Cannot check CPUID with inline assembly.\n"); + memset(flags, 0, 4 * sizeof(int)); +#endif +} + +/* Only runs on i686 and above. Needs to be conditionally run. */ +static uint64_t xgetbv_x86(uint32_t idx) +{ +#if defined(__GNUC__) + uint32_t eax, edx; + __asm__ volatile ( + /* Older GCC versions (Apple's GCC for example) do + * not understand xgetbv instruction. + * Stamp out the machine code directly. + */ + ".byte 0x0f, 0x01, 0xd0\n" + : "=a"(eax), "=d"(edx) : "c"(idx)); + return ((uint64_t)edx << 32) | eax; +#elif _MSC_FULL_VER >= 160040219 + /* Intrinsic only works on 2010 SP1 and above. */ + return _xgetbv(idx); +#else + printf("Unknown compiler. Cannot check xgetbv bits.\n"); + return 0; +#endif +} +#endif + +#if defined(__ARM_NEON__) +static void arm_enable_runfast_mode(void) +{ + /* RunFast mode. Enables flush-to-zero and some + * floating point optimizations. */ + static const unsigned x = 0x04086060; + static const unsigned y = 0x03000000; + int r; + __asm__ volatile( + "fmrx %0, fpscr \n\t" /* r0 = FPSCR */ + "and %0, %0, %1 \n\t" /* r0 = r0 & 0x04086060 */ + "orr %0, %0, %2 \n\t" /* r0 = r0 | 0x03000000 */ + "fmxr fpscr, %0 \n\t" /* FPSCR = r0 */ + : "=r"(r) + : "r"(x), "r"(y) + ); +} +#endif + +#if defined(__linux__) && !defined(CPU_X86) +static unsigned char check_arm_cpu_feature(const char* feature) +{ + char line[1024]; + unsigned char status = 0; + RFILE *fp = filestream_open("/proc/cpuinfo", RFILE_MODE_READ_TEXT, -1); + + if (!fp) + return 0; + + while (filestream_gets(fp, line, sizeof(line)) != NULL) + { + if (strncmp(line, "Features\t: ", 11)) + continue; + + if (strstr(line + 11, feature) != NULL) + status = 1; + + break; + } + + filestream_close(fp); + + return status; +} + +#if !defined(_SC_NPROCESSORS_ONLN) +/* Parse an decimal integer starting from 'input', but not going further + * than 'limit'. Return the value into '*result'. + * + * NOTE: Does not skip over leading spaces, or deal with sign characters. + * NOTE: Ignores overflows. + * + * The function returns NULL in case of error (bad format), or the new + * position after the decimal number in case of success (which will always + * be <= 'limit'). + */ +static const char *parse_decimal(const char* input, + const char* limit, int* result) +{ + const char* p = input; + int val = 0; + + while (p < limit) + { + int d = (*p - '0'); + if ((unsigned)d >= 10U) + break; + val = val*10 + d; + p++; + } + if (p == input) + return NULL; + + *result = val; + return p; +} + +/* Parse a textual list of cpus and store the result inside a CpuList object. + * Input format is the following: + * - comma-separated list of items (no spaces) + * - each item is either a single decimal number (cpu index), or a range made + * of two numbers separated by a single dash (-). Ranges are inclusive. + * + * Examples: 0 + * 2,4-127,128-143 + * 0-1 + */ +static void cpulist_parse(CpuList* list, char **buf, ssize_t length) +{ + const char* p = (const char*)buf; + const char* end = p + length; + + /* NOTE: the input line coming from sysfs typically contains a + * trailing newline, so take care of it in the code below + */ + while (p < end && *p != '\n') + { + int val, start_value, end_value; + /* Find the end of current item, and put it into 'q' */ + const char *q = (const char*)memchr(p, ',', end-p); + + if (!q) + q = end; + + /* Get first value */ + p = parse_decimal(p, q, &start_value); + if (p == NULL) + return; + + end_value = start_value; + + /* If we're not at the end of the item, expect a dash and + * and integer; extract end value. + */ + if (p < q && *p == '-') + { + p = parse_decimal(p+1, q, &end_value); + if (p == NULL) + return; + } + + /* Set bits CPU list bits */ + for (val = start_value; val <= end_value; val++) + { + if ((unsigned)val < 32) + list->mask |= (uint32_t)(1U << val); + } + + /* Jump to next item */ + p = q; + if (p < end) + p++; + } +} + +/* Read a CPU list from one sysfs file */ +static void cpulist_read_from(CpuList* list, const char* filename) +{ + ssize_t length; + char *buf = NULL; + + list->mask = 0; + + if (filestream_read_file(filename, (void**)&buf, &length) != 1) + return; + + cpulist_parse(list, &buf, length); + if (buf) + free(buf); + buf = NULL; +} +#endif + +#endif + +/** + * cpu_features_get_core_amount: + * + * Gets the amount of available CPU cores. + * + * Returns: amount of CPU cores available. + **/ +unsigned cpu_features_get_core_amount(void) +{ +#if defined(_WIN32) && !defined(_XBOX) + /* Win32 */ + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + return sysinfo.dwNumberOfProcessors; +#elif defined(GEKKO) + return 1; +#elif defined(PSP) + return 1; +#elif defined(VITA) + return 4; +#elif defined(_3DS) + return 1; +#elif defined(_SC_NPROCESSORS_ONLN) + /* Linux, most UNIX-likes. */ + long ret = sysconf(_SC_NPROCESSORS_ONLN); + if (ret <= 0) + return (unsigned)1; + return ret; +#elif defined(BSD) || defined(__APPLE__) + /* BSD */ + /* Copypasta from stackoverflow, dunno if it works. */ + int num_cpu = 0; + int mib[4]; + size_t len = sizeof(num_cpu); + + mib[0] = CTL_HW; + mib[1] = HW_AVAILCPU; + sysctl(mib, 2, &num_cpu, &len, NULL, 0); + if (num_cpu < 1) + { + mib[1] = HW_NCPU; + sysctl(mib, 2, &num_cpu, &len, NULL, 0); + if (num_cpu < 1) + num_cpu = 1; + } + return num_cpu; +#elif defined(__linux__) + CpuList cpus_present[1]; + CpuList cpus_possible[1]; + int amount = 0; + + cpulist_read_from(cpus_present, "/sys/devices/system/cpu/present"); + cpulist_read_from(cpus_possible, "/sys/devices/system/cpu/possible"); + + /* Compute the intersection of both sets to get the actual number of + * CPU cores that can be used on this device by the kernel. + */ + cpus_present->mask &= cpus_possible->mask; + amount = __builtin_popcount(cpus_present->mask); + + if (amount == 0) + return 1; + return amount; +#elif defined(_XBOX360) + return 3; +#else + /* No idea, assume single core. */ + return 1; +#endif +} + +/* According to http://en.wikipedia.org/wiki/CPUID */ +#define VENDOR_INTEL_b 0x756e6547 +#define VENDOR_INTEL_c 0x6c65746e +#define VENDOR_INTEL_d 0x49656e69 + +/** + * cpu_features_get: + * + * Gets CPU features.. + * + * Returns: bitmask of all CPU features available. + **/ +uint64_t cpu_features_get(void) +{ + int flags[4]; + int vendor_shuffle[3]; + char vendor[13] = {0}; + size_t len = 0; + uint64_t cpu_flags = 0; + uint64_t cpu = 0; + unsigned max_flag = 0; +#if defined(CPU_X86) && !defined(__MACH__) + int vendor_is_intel = 0; + const int avx_flags = (1 << 27) | (1 << 28); +#endif + + char buf[sizeof(" MMX MMXEXT SSE SSE2 SSE3 SSSE3 SS4 SSE4.2 AES AVX AVX2 NEON VMX VMX128 VFPU PS")]; + + memset(buf, 0, sizeof(buf)); + + (void)len; + (void)cpu_flags; + (void)flags; + (void)max_flag; + (void)vendor; + (void)vendor_shuffle; + +#if defined(__MACH__) + len = sizeof(size_t); + if (sysctlbyname("hw.optional.mmx", NULL, &len, NULL, 0) == 0) + { + cpu |= RETRO_SIMD_MMX; + cpu |= RETRO_SIMD_MMXEXT; + } + + len = sizeof(size_t); + if (sysctlbyname("hw.optional.sse", NULL, &len, NULL, 0) == 0) + cpu |= RETRO_SIMD_SSE; + + len = sizeof(size_t); + if (sysctlbyname("hw.optional.sse2", NULL, &len, NULL, 0) == 0) + cpu |= RETRO_SIMD_SSE2; + + len = sizeof(size_t); + if (sysctlbyname("hw.optional.sse3", NULL, &len, NULL, 0) == 0) + cpu |= RETRO_SIMD_SSE3; + + len = sizeof(size_t); + if (sysctlbyname("hw.optional.supplementalsse3", NULL, &len, NULL, 0) == 0) + cpu |= RETRO_SIMD_SSSE3; + + len = sizeof(size_t); + if (sysctlbyname("hw.optional.sse4_1", NULL, &len, NULL, 0) == 0) + cpu |= RETRO_SIMD_SSE4; + + len = sizeof(size_t); + if (sysctlbyname("hw.optional.sse4_2", NULL, &len, NULL, 0) == 0) + cpu |= RETRO_SIMD_SSE42; + + len = sizeof(size_t); + if (sysctlbyname("hw.optional.aes", NULL, &len, NULL, 0) == 0) + cpu |= RETRO_SIMD_AES; + + len = sizeof(size_t); + if (sysctlbyname("hw.optional.avx1_0", NULL, &len, NULL, 0) == 0) + cpu |= RETRO_SIMD_AVX; + + len = sizeof(size_t); + if (sysctlbyname("hw.optional.avx2_0", NULL, &len, NULL, 0) == 0) + cpu |= RETRO_SIMD_AVX2; + + len = sizeof(size_t); + if (sysctlbyname("hw.optional.altivec", NULL, &len, NULL, 0) == 0) + cpu |= RETRO_SIMD_VMX; + + len = sizeof(size_t); + if (sysctlbyname("hw.optional.neon", NULL, &len, NULL, 0) == 0) + cpu |= RETRO_SIMD_NEON; + +#elif defined(CPU_X86) + (void)avx_flags; + + x86_cpuid(0, flags); + vendor_shuffle[0] = flags[1]; + vendor_shuffle[1] = flags[3]; + vendor_shuffle[2] = flags[2]; + memcpy(vendor, vendor_shuffle, sizeof(vendor_shuffle)); + + /* printf("[CPUID]: Vendor: %s\n", vendor); */ + + vendor_is_intel = ( + flags[1] == VENDOR_INTEL_b && + flags[2] == VENDOR_INTEL_c && + flags[3] == VENDOR_INTEL_d); + + max_flag = flags[0]; + if (max_flag < 1) /* Does CPUID not support func = 1? (unlikely ...) */ + return 0; + + x86_cpuid(1, flags); + + if (flags[3] & (1 << 23)) + cpu |= RETRO_SIMD_MMX; + + if (flags[3] & (1 << 25)) + { + /* SSE also implies MMXEXT (according to FFmpeg source). */ + cpu |= RETRO_SIMD_SSE; + cpu |= RETRO_SIMD_MMXEXT; + } + + + if (flags[3] & (1 << 26)) + cpu |= RETRO_SIMD_SSE2; + + if (flags[2] & (1 << 0)) + cpu |= RETRO_SIMD_SSE3; + + if (flags[2] & (1 << 9)) + cpu |= RETRO_SIMD_SSSE3; + + if (flags[2] & (1 << 19)) + cpu |= RETRO_SIMD_SSE4; + + if (flags[2] & (1 << 20)) + cpu |= RETRO_SIMD_SSE42; + + if ((flags[2] & (1 << 23))) + cpu |= RETRO_SIMD_POPCNT; + + if (vendor_is_intel && (flags[2] & (1 << 22))) + cpu |= RETRO_SIMD_MOVBE; + + if (flags[2] & (1 << 25)) + cpu |= RETRO_SIMD_AES; + + + /* Must only perform xgetbv check if we have + * AVX CPU support (guaranteed to have at least i686). */ + if (((flags[2] & avx_flags) == avx_flags) + && ((xgetbv_x86(0) & 0x6) == 0x6)) + cpu |= RETRO_SIMD_AVX; + + if (max_flag >= 7) + { + x86_cpuid(7, flags); + if (flags[1] & (1 << 5)) + cpu |= RETRO_SIMD_AVX2; + } + + x86_cpuid(0x80000000, flags); + max_flag = flags[0]; + if (max_flag >= 0x80000001u) + { + x86_cpuid(0x80000001, flags); + if (flags[3] & (1 << 23)) + cpu |= RETRO_SIMD_MMX; + if (flags[3] & (1 << 22)) + cpu |= RETRO_SIMD_MMXEXT; + } +#elif defined(__linux__) + if (check_arm_cpu_feature("neon")) + { + cpu |= RETRO_SIMD_NEON; +#ifdef __ARM_NEON__ + arm_enable_runfast_mode(); +#endif + } + + if (check_arm_cpu_feature("vfpv3")) + cpu |= RETRO_SIMD_VFPV3; + + if (check_arm_cpu_feature("vfpv4")) + cpu |= RETRO_SIMD_VFPV4; + +#if 0 + check_arm_cpu_feature("swp"); + check_arm_cpu_feature("half"); + check_arm_cpu_feature("thumb"); + check_arm_cpu_feature("fastmult"); + check_arm_cpu_feature("vfp"); + check_arm_cpu_feature("edsp"); + check_arm_cpu_feature("thumbee"); + check_arm_cpu_feature("tls"); + check_arm_cpu_feature("idiva"); + check_arm_cpu_feature("idivt"); +#endif + +#elif defined(__ARM_NEON__) + cpu |= RETRO_SIMD_NEON; + arm_enable_runfast_mode(); +#elif defined(__ALTIVEC__) + cpu |= RETRO_SIMD_VMX; +#elif defined(XBOX360) + cpu |= RETRO_SIMD_VMX128; +#elif defined(PSP) + cpu |= RETRO_SIMD_VFPU; +#elif defined(GEKKO) + cpu |= RETRO_SIMD_PS; +#endif + + if (cpu & RETRO_SIMD_MMX) strlcat(buf, " MMX", sizeof(buf)); + if (cpu & RETRO_SIMD_MMXEXT) strlcat(buf, " MMXEXT", sizeof(buf)); + if (cpu & RETRO_SIMD_SSE) strlcat(buf, " SSE", sizeof(buf)); + if (cpu & RETRO_SIMD_SSE2) strlcat(buf, " SSE2", sizeof(buf)); + if (cpu & RETRO_SIMD_SSE3) strlcat(buf, " SSE3", sizeof(buf)); + if (cpu & RETRO_SIMD_SSSE3) strlcat(buf, " SSSE3", sizeof(buf)); + if (cpu & RETRO_SIMD_SSE4) strlcat(buf, " SSE4", sizeof(buf)); + if (cpu & RETRO_SIMD_SSE42) strlcat(buf, " SSE4.2", sizeof(buf)); + if (cpu & RETRO_SIMD_AES) strlcat(buf, " AES", sizeof(buf)); + if (cpu & RETRO_SIMD_AVX) strlcat(buf, " AVX", sizeof(buf)); + if (cpu & RETRO_SIMD_AVX2) strlcat(buf, " AVX2", sizeof(buf)); + if (cpu & RETRO_SIMD_NEON) strlcat(buf, " NEON", sizeof(buf)); + if (cpu & RETRO_SIMD_VFPV3) strlcat(buf, " VFPv3", sizeof(buf)); + if (cpu & RETRO_SIMD_VFPV4) strlcat(buf, " VFPv4", sizeof(buf)); + if (cpu & RETRO_SIMD_VMX) strlcat(buf, " VMX", sizeof(buf)); + if (cpu & RETRO_SIMD_VMX128) strlcat(buf, " VMX128", sizeof(buf)); + if (cpu & RETRO_SIMD_VFPU) strlcat(buf, " VFPU", sizeof(buf)); + if (cpu & RETRO_SIMD_PS) strlcat(buf, " PS", sizeof(buf)); + + return cpu; +} diff --git a/desmume/src/libretro-common/file/.dirstamp b/desmume/src/libretro-common/file/.dirstamp new file mode 100644 index 000000000..e69de29bb diff --git a/desmume/src/libretro-common/file/archive_file.c b/desmume/src/libretro-common/file/archive_file.c index 936f4f374..cbb9e45d4 100644 --- a/desmume/src/libretro-common/file/archive_file.c +++ b/desmume/src/libretro-common/file/archive_file.c @@ -451,7 +451,7 @@ static int file_archive_decompress_data_to_file( } end: - if (handle->data) + if (handle && handle->data) free(handle->data); return ret; } diff --git a/desmume/src/libretro-common/file/config_file.c b/desmume/src/libretro-common/file/config_file.c index ae8281a40..55eccc793 100644 --- a/desmume/src/libretro-common/file/config_file.c +++ b/desmume/src/libretro-common/file/config_file.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #define MAX_INCLUDE_DEPTH 16 @@ -75,12 +76,12 @@ struct config_file 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); +static config_file_t *config_file_new_internal( + const char *path, unsigned depth); static char *getaline(FILE *file) { - char* newline = (char*)malloc(9); + char* newline = (char*)malloc(9); char* newline_tmp = NULL; size_t cur_size = 8; size_t idx = 0; @@ -112,6 +113,45 @@ static char *getaline(FILE *file) return newline; } +static char *strip_comment(char *str) +{ + /* Remove everything after comment. + * Keep #s inside string literals. */ + char *string_end = str + strlen(str); + bool cut_comment = true; + + while (!string_is_empty(str)) + { + char *comment = NULL; + char *literal = strchr(str, '\"'); + if (!literal) + literal = string_end; + comment = (char*)strchr(str, '#'); + if (!comment) + comment = string_end; + + if (cut_comment && literal < comment) + { + cut_comment = false; + str = literal + 1; + } + else if (!cut_comment && literal) + { + cut_comment = true; + str = literal + 1; + } + else if (comment) + { + *comment = '\0'; + str = comment; + } + else + str = string_end; + } + + return str; +} + static char *extract_value(char *line, bool is_value) { char *save = NULL; @@ -152,6 +192,27 @@ static char *extract_value(char *line, bool is_value) return NULL; } +static void add_include_list(config_file_t *conf, const char *path) +{ + struct config_include_list *head = conf->includes; + struct config_include_list *node = (struct config_include_list*)calloc(1, sizeof(*node)); + + if (!node) + return; + + node->path = strdup(path); + + if (head) + { + while (head->next) + head = head->next; + + head->next = node; + } + else + conf->includes = node; +} + static void set_list_readonly(struct config_entry_list *list) { while (list) @@ -195,27 +256,6 @@ static void add_child_list(config_file_t *parent, config_file_t *child) parent->tail = NULL; } -static void add_include_list(config_file_t *conf, const char *path) -{ - struct config_include_list *head = conf->includes; - struct config_include_list *node = (struct config_include_list*)calloc(1, sizeof(*node)); - - if (!node) - return; - - node->path = strdup(path); - - if (head) - { - while (head->next) - head = head->next; - - head->next = node; - } - else - conf->includes = node; -} - static void add_sub_conf(config_file_t *conf, char *line) { char real_path[PATH_MAX_LENGTH] = {0}; @@ -258,53 +298,14 @@ static void add_sub_conf(config_file_t *conf, char *line) free(path); } -static char *strip_comment(char *str) -{ - /* Remove everything after comment. - * Keep #s inside string literals. */ - char *strend = str + strlen(str); - bool cut_comment = true; - - while (*str) - { - char *comment = NULL; - char *literal = strchr(str, '\"'); - if (!literal) - literal = strend; - comment = (char*)strchr(str, '#'); - if (!comment) - comment = strend; - - if (cut_comment && literal < comment) - { - cut_comment = false; - str = literal + 1; - } - else if (!cut_comment && literal) - { - cut_comment = true; - str = literal + 1; - } - else if (comment) - { - *comment = '\0'; - str = comment; - } - else - str = strend; - } - - return str; -} - static bool parse_line(config_file_t *conf, struct config_entry_list *list, char *line) { char *comment = NULL; - char *key = (char*)malloc(9); char *key_tmp = NULL; size_t cur_size = 8; size_t idx = 0; + char *key = (char*)malloc(9); if (!key) return false; @@ -370,23 +371,6 @@ static bool parse_line(config_file_t *conf, return true; } -bool config_append_file(config_file_t *conf, const char *path) -{ - config_file_t *new_conf = config_file_new(path); - if (!new_conf) - return false; - - if (new_conf->tail) - { - new_conf->tail->next = conf->entries; - conf->entries = new_conf->entries; /* Pilfer. */ - new_conf->entries = NULL; - } - - config_file_free(new_conf); - return true; -} - static config_file_t *config_file_new_internal( const char *path, unsigned depth) { @@ -429,26 +413,24 @@ static config_file_t *config_file_new_internal( line = getaline(file); - if (line) - { - if (parse_line(conf, list, line)) - { - if (conf->entries) - conf->tail->next = list; - else - conf->entries = list; - - conf->tail = list; - } - - free(line); - } - else + if (!line) { free(list); continue; } + if (parse_line(conf, list, line)) + { + if (conf->entries) + conf->tail->next = list; + else + conf->entries = list; + + conf->tail = list; + } + + free(line); + if (list != conf->tail) free(list); } @@ -463,6 +445,65 @@ error: return NULL; } +void config_file_free(config_file_t *conf) +{ + struct config_include_list *inc_tmp = NULL; + struct config_entry_list *tmp = NULL; + if (!conf) + return; + + tmp = conf->entries; + while (tmp) + { + struct config_entry_list *hold = NULL; + 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; + while (inc_tmp) + { + struct config_include_list *hold = NULL; + free(inc_tmp->path); + hold = (struct config_include_list*)inc_tmp; + inc_tmp = inc_tmp->next; + free(hold); + } + + if (conf->path) + free(conf->path); + free(conf); +} + +bool config_append_file(config_file_t *conf, const char *path) +{ + config_file_t *new_conf = config_file_new(path); + if (!new_conf) + return false; + + if (new_conf->tail) + { + new_conf->tail->next = conf->entries; + conf->entries = new_conf->entries; /* Pilfer. */ + new_conf->entries = NULL; + } + + config_file_free(new_conf); + return true; +} + + config_file_t *config_file_new_from_string(const char *from_string) { size_t i; @@ -521,46 +562,6 @@ config_file_t *config_file_new(const char *path) return config_file_new_internal(path, 0); } -void config_file_free(config_file_t *conf) -{ - struct config_include_list *inc_tmp = NULL; - struct config_entry_list *tmp = NULL; - if (!conf) - return; - - tmp = conf->entries; - while (tmp) - { - struct config_entry_list *hold = NULL; - 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; - while (inc_tmp) - { - struct config_include_list *hold = NULL; - free(inc_tmp->path); - hold = (struct config_include_list*)inc_tmp; - inc_tmp = inc_tmp->next; - free(hold); - } - - if (conf->path) - free(conf->path); - free(conf); -} static struct config_entry_list *config_get_entry(const config_file_t *conf, const char *key, struct config_entry_list **prev) @@ -887,8 +888,9 @@ bool config_file_write(config_file_t *conf, const char *path) void config_file_dump(config_file_t *conf, FILE *file) { - struct config_entry_list *list = NULL; + struct config_entry_list *list = NULL; struct config_include_list *includes = conf->includes; + while (includes) { fprintf(file, "#include \"%s\"\n", includes->path); @@ -896,11 +898,9 @@ void config_file_dump(config_file_t *conf, FILE *file) } list = (struct config_entry_list*)conf->entries; + while (list) { - 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/file_path.c b/desmume/src/libretro-common/file/file_path.c index cc16645d0..f5814d307 100644 --- a/desmume/src/libretro-common/file/file_path.c +++ b/desmume/src/libretro-common/file/file_path.c @@ -218,8 +218,7 @@ void fill_pathname(char *out_path, const char *in_path, if ((tok = (char*)strrchr(path_basename(tmp_path), '.'))) *tok = '\0'; - retro_assert(strlcpy(out_path, tmp_path, size) < size); - retro_assert(strlcat(out_path, replace, size) < size); + fill_pathname_noext(out_path, tmp_path, replace, size); } /** @@ -243,9 +242,9 @@ void fill_pathname_noext(char *out_path, const char *in_path, retro_assert(strlcat(out_path, replace, size) < size); } -static char *find_last_slash(const char *str) +char *find_last_slash(const char *str) { - const char *slash = strrchr(str, '/'); + const char *slash = strrchr(str, '/'); #ifdef _WIN32 const char *backslash = strrchr(str, '\\'); @@ -346,6 +345,19 @@ void fill_pathname_base(char *out, const char *in_path, size_t size) retro_assert(strlcpy(out, ptr, size) < size); } +void fill_pathname_base_noext(char *out, const char *in_path, size_t size) +{ + fill_pathname_base(out, in_path, size); + path_remove_extension(out); +} + +void fill_pathname_base_ext(char *out, const char *in_path, const char *ext, + size_t size) +{ + fill_pathname_base_noext(out, in_path, size); + strlcat(out, ext, size); +} + /** * fill_pathname_basedir: * @out_dir : output directory @@ -364,6 +376,13 @@ void fill_pathname_basedir(char *out_dir, path_basedir(out_dir); } +void fill_pathname_basedir_noext(char *out_dir, + const char *in_path, size_t size) +{ + fill_pathname_basedir(out_dir, in_path, size); + path_remove_extension(out_dir); +} + /** * fill_pathname_parent_dir: * @out_dir : output directory @@ -505,7 +524,7 @@ bool path_is_absolute(const char *path) void path_resolve_realpath(char *buf, size_t size) { #ifndef RARCH_CONSOLE - char tmp[PATH_MAX_LENGTH]; + char tmp[PATH_MAX_LENGTH] = {0}; strlcpy(tmp, buf, sizeof(tmp)); @@ -546,8 +565,7 @@ void fill_pathname_resolve_relative(char *out_path, return; } - retro_assert(strlcpy(out_path, in_refpath, size) < size); - path_basedir(out_path); + fill_pathname_basedir(out_path, in_refpath, size); retro_assert(strlcat(out_path, in_path, size) < size); } @@ -574,7 +592,7 @@ void fill_pathname_join(char *out_path, retro_assert(strlcat(out_path, path, size) < size); } -void fill_string_join(char *out_path, +static void fill_string_join(char *out_path, const char *append, size_t size) { if (*out_path) @@ -583,6 +601,33 @@ void fill_string_join(char *out_path, retro_assert(strlcat(out_path, append, size) < size); } +void fill_pathname_join_special_ext(char *out_path, + const char *dir, const char *path, + const char *last, const char *ext, + size_t size) +{ + fill_pathname_join(out_path, dir, path, size); + fill_string_join(out_path, last, size); + strlcat(out_path, ext, size); +} + +void fill_pathname_join_concat(char *out_path, + const char *dir, const char *path, + const char *concat, + size_t size) +{ + fill_pathname_join(out_path, dir, path, size); + strlcat(out_path, concat, size); +} + +void fill_pathname_join_noext(char *out_path, + const char *dir, const char *path, size_t size) +{ + fill_pathname_join(out_path, dir, path, size); + path_remove_extension(out_path); +} + + /** * fill_pathname_join_delim: * @out_path : output path @@ -606,6 +651,14 @@ void fill_pathname_join_delim(char *out_path, const char *dir, retro_assert(strlcat(out_path, path, size) < size); } +void fill_pathname_join_delim_concat(char *out_path, const char *dir, + const char *path, const char delim, const char *concat, + size_t size) +{ + fill_pathname_join_delim(out_path, dir, path, delim, size); + strlcat(out_path, concat, size); +} + /** * fill_short_pathname_representation: * @out_rep : output representation @@ -625,11 +678,14 @@ void fill_short_pathname_representation(char* out_rep, const char *in_path, size_t size) { char path_short[PATH_MAX_LENGTH] = {0}; +#ifdef HAVE_COMPRESSION char *last_hash = NULL; +#endif fill_pathname(path_short, path_basename(in_path), "", sizeof(path_short)); +#ifdef HAVE_COMPRESSION last_hash = (char*)strchr(path_short,'#'); if(last_hash != NULL) { @@ -644,5 +700,13 @@ void fill_short_pathname_representation(char* out_rep, strlcpy(out_rep, last_hash + 1, size); } else +#endif strlcpy(out_rep, path_short, size); } + +void fill_short_pathname_representation_noext(char* out_rep, + const char *in_path, size_t size) +{ + fill_short_pathname_representation(out_rep, in_path, size); + path_remove_extension(out_rep); +} diff --git a/desmume/src/libretro-common/file/retro_dirent.c b/desmume/src/libretro-common/file/retro_dirent.c index 0276543b8..ee30c2990 100644 --- a/desmume/src/libretro-common/file/retro_dirent.c +++ b/desmume/src/libretro-common/file/retro_dirent.c @@ -158,7 +158,7 @@ const char *retro_dirent_get_name(struct RDIR *rdir) * Returns: true if directory listing entry is * a directory, false if not. */ -bool retro_dirent_is_dir(struct RDIR *rdir) +bool retro_dirent_is_dir(struct RDIR *rdir, const char *path) { #if defined(_WIN32) const WIN32_FIND_DATA *entry = (const WIN32_FIND_DATA*)&rdir->entry; @@ -168,7 +168,7 @@ bool retro_dirent_is_dir(struct RDIR *rdir) #if defined(PSP) return (entry->d_stat.st_attr & FIO_SO_IFDIR) == FIO_SO_IFDIR; #elif defined(VITA) - return PSP2_S_ISDIR(entry->d_stat.st_mode); + return SCE_S_ISDIR(entry->d_stat.st_mode); #endif #elif defined(__CELLOS_LV2__) CellFsDirent *entry = (CellFsDirent*)&rdir->entry; @@ -178,13 +178,11 @@ bool retro_dirent_is_dir(struct RDIR *rdir) if (entry->d_type == DT_DIR) return true; /* This can happen on certain file systems. */ - const char *path = retro_dirent_get_name(rdir); if (entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK) return path_is_directory(path); return false; #else /* dirent struct doesn't have d_type, do it the slow way ... */ - const char *path = retro_dirent_get_name(rdir); return path_is_directory(path); #endif } diff --git a/desmume/src/libretro-common/file/retro_stat.c b/desmume/src/libretro-common/file/retro_stat.c index 6c3e39051..077a1b7e6 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_S_ISDIR PSP2_S_ISDIR +#define FIO_S_ISDIR SCE_S_ISDIR #endif #if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP) diff --git a/desmume/src/libretro-common/formats/bmp/rbmp.c b/desmume/src/libretro-common/formats/bmp/rbmp.c new file mode 100644 index 000000000..01dd61403 --- /dev/null +++ b/desmume/src/libretro-common/formats/bmp/rbmp.c @@ -0,0 +1,624 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (rbmp.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. + */ + +/* Modified version of stb_image's BMP sources. */ + +#include +#include +#include +#include /* ptrdiff_t on osx */ +#include +#include + +#include +#include + +#include +#include + +typedef struct +{ + int (*read) (void *user,char *data,int size); /* fill 'data' with 'size' bytes. return number of bytes actually read */ + void (*skip) (void *user,int n); /* skip the next 'n' bytes, or 'unget' the last -n bytes if negative */ + int (*eof) (void *user); /* returns nonzero if we are at end of file/data */ +} rbmp_io_callbacks; + +typedef struct +{ + uint32_t img_x, img_y; + int img_n, img_out_n; + + rbmp_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + unsigned char buffer_start[128]; + + unsigned char *img_buffer, *img_buffer_end; + unsigned char *img_buffer_original; +} rbmp__context; + +struct rbmp +{ + uint8_t *buff_data; + uint32_t *output_image; + void *empty; +}; + +static void rbmp__refill_buffer(rbmp__context *s); + +/* initialize a memory-decode context */ +static void rbmp__start_mem(rbmp__context *s, unsigned char const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (unsigned char *) buffer; + s->img_buffer_end = (unsigned char *) buffer+len; +} + +static unsigned char *rbmp__bmp_load(rbmp__context *s, unsigned *x, unsigned *y, int *comp, int req_comp); + +#define rbmp__err(x,y) 0 +#define rbmp__errpf(x,y) ((float *) (rbmp__err(x,y)?NULL:NULL)) +#define rbmp__errpuc(x,y) ((unsigned char *) (rbmp__err(x,y)?NULL:NULL)) + +static unsigned char *rbmp_load_from_memory(unsigned char const *buffer, int len, unsigned *x, unsigned *y, int *comp, int req_comp) +{ + rbmp__context s; + rbmp__start_mem(&s,buffer,len); + return rbmp__bmp_load(&s,x,y,comp,req_comp); +} + +static void rbmp__refill_buffer(rbmp__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + if (n == 0) + { + /* at end of file, treat same as if from memory, but need to handle case + * where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file */ + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } + else + { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +static INLINE unsigned char rbmp__get8(rbmp__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + + if (s->read_from_callbacks) + { + rbmp__refill_buffer(s); + return *s->img_buffer++; + } + + return 0; +} + +static void rbmp__skip(rbmp__context *s, int n) +{ + if (n < 0) + { + s->img_buffer = s->img_buffer_end; + return; + } + + if (s->io.read) + { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) + { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int rbmp__get16le(rbmp__context *s) +{ + int z = rbmp__get8(s); + return z + (rbmp__get8(s) << 8); +} + +static uint32_t rbmp__get32le(rbmp__context *s) +{ + uint32_t z = rbmp__get16le(s); + return z + (rbmp__get16le(s) << 16); +} + +#define RBMP__BYTECAST(x) ((unsigned char) ((x) & 255)) /* truncate int to byte without warnings */ + +static unsigned char rbmp__compute_y(int r, int g, int b) +{ + return (unsigned char) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *rbmp__convert_format( + unsigned char *data, + int img_n, + int req_comp, + unsigned int x, + unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + retro_assert(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) malloc(req_comp * x * y); + if (good == NULL) + { + free(data); + return rbmp__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) + { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + switch (((img_n)*8+(req_comp))) + { + case ((1)*8+(2)): + for(i=x-1; i >= 0; --i, src += 1, dest += 2) + dest[0]=src[0], dest[1]=255; + break; + case ((1)*8+(3)): + for(i=x-1; i >= 0; --i, src += 1, dest += 3) + dest[0]=dest[1]=dest[2]=src[0]; + break; + case ((1)*8+(4)): + for(i=x-1; i >= 0; --i, src += 1, dest += 4) + dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; + break; + case ((2)*8+(1)): + for(i=x-1; i >= 0; --i, src += 2, dest += 1) + dest[0]=src[0]; + break; + case ((2)*8+(3)): + for(i=x-1; i >= 0; --i, src += 2, dest += 3) + dest[0]=dest[1]=dest[2]=src[0]; + break; + case ((2)*8+(4)): + for(i=x-1; i >= 0; --i, src += 2, dest += 4) + dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; + break; + case ((3)*8+(4)): + for(i=x-1; i >= 0; --i, src += 3, dest += 4) + dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; + break; + case ((3)*8+(1)): + for(i=x-1; i >= 0; --i, src += 3, dest += 1) + dest[0]=rbmp__compute_y(src[0],src[1],src[2]); + break; + case ((3)*8+(2)): + for(i=x-1; i >= 0; --i, src += 3, dest += 2) + dest[0]=rbmp__compute_y(src[0],src[1],src[2]), dest[1] = 255; + break; + case ((4)*8+(1)): + for(i=x-1; i >= 0; --i, src += 4, dest += 1) + dest[0]=rbmp__compute_y(src[0],src[1],src[2]); + break; + case ((4)*8+(2)): + for(i=x-1; i >= 0; --i, src += 4, dest += 2) + dest[0]=rbmp__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; + break; + case ((4)*8+(3)): + for(i=x-1; i >= 0; --i, src += 4, dest += 3) + dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; + break; + default: + retro_assert(0); + break; + } + + } + + free(data); + return good; +} + +/* Microsoft/Windows BMP image */ + +/* returns 0..31 for the highest set bit */ +static int rbmp__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) n += 16, z >>= 16; + if (z >= 0x00100) n += 8, z >>= 8; + if (z >= 0x00010) n += 4, z >>= 4; + if (z >= 0x00004) n += 2, z >>= 2; + if (z >= 0x00002) n += 1, z >>= 1; + return n; +} + +static int rbmp__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); /* max 2 */ + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); /* max 4 */ + a = (a + (a >> 4)) & 0x0f0f0f0f; /* max 8 per 4, now 8 bits */ + a = (a + (a >> 8)); /* max 16 per 8 bits */ + a = (a + (a >> 16)); /* max 32 per 8 bits */ + return a & 0xff; +} + +static int rbmp__shiftsigned(int v, int shift, int bits) +{ + int result; + int z=0; + + if (shift < 0) + v <<= -shift; + else + v >>= shift; + + result = v; + z = bits; + + while (z < 8) + { + result += v >> z; + z += bits; + } + return result; +} + +static unsigned char *rbmp__bmp_load(rbmp__context *s, unsigned *x, unsigned *y, int *comp, int req_comp) +{ + unsigned char *out; + unsigned int mr=0,mg=0,mb=0,ma=0; + unsigned char pal[256][4]; + int psize=0,i,j,compress=0,width; + int bpp, flip_vertically, pad, target, offset, hsz; + + if (rbmp__get8(s) != 'B' || rbmp__get8(s) != 'M') + return rbmp__errpuc("not BMP", "Corrupt BMP"); + + rbmp__get32le(s); /* discard filesize */ + rbmp__get16le(s); /* discard reserved */ + rbmp__get16le(s); /* discard reserved */ + offset = rbmp__get32le(s); + hsz = rbmp__get32le(s); + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) + return rbmp__errpuc("unknown BMP", "BMP type not supported: unknown"); + + if (hsz == 12) + { + s->img_x = rbmp__get16le(s); + s->img_y = rbmp__get16le(s); + } + else + { + s->img_x = rbmp__get32le(s); + s->img_y = rbmp__get32le(s); + } + if (rbmp__get16le(s) != 1) + return rbmp__errpuc("bad BMP", "bad BMP"); + bpp = rbmp__get16le(s); + if (bpp == 1) + return rbmp__errpuc("monochrome", "BMP type not supported: 1-bit"); + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + if (hsz == 12) + { + if (bpp < 24) + psize = (offset - 14 - 24) / 3; + } + else + { + compress = rbmp__get32le(s); + + if (compress == 1 || compress == 2) + return rbmp__errpuc("BMP RLE", "BMP type not supported: RLE"); + + rbmp__get32le(s); /* discard sizeof */ + rbmp__get32le(s); /* discard hres */ + rbmp__get32le(s); /* discard vres */ + rbmp__get32le(s); /* discard colors used */ + rbmp__get32le(s); /* discard max important */ + if (hsz == 40 || hsz == 56) + { + if (hsz == 56) + { + rbmp__get32le(s); + rbmp__get32le(s); + rbmp__get32le(s); + rbmp__get32le(s); + } + if (bpp == 16 || bpp == 32) + { + mr = mg = mb = 0; + + switch (compress) + { + case 0: + if (bpp == 32) + { + mr = 0xffu << 16; + mg = 0xffu << 8; + mb = 0xffu << 0; + ma = 0xffu << 24; + } + else + { + mr = 31u << 10; + mg = 31u << 5; + mb = 31u << 0; + } + break; + case 3: + mr = rbmp__get32le(s); + mg = rbmp__get32le(s); + mb = rbmp__get32le(s); + /* not documented, but generated by photoshop and handled by mspaint */ + if (mr == mg && mg == mb) + return rbmp__errpuc("bad BMP", "bad BMP"); + break; + default: + break; + } + return rbmp__errpuc("bad BMP", "bad BMP"); + } + } + else + { + retro_assert(hsz == 108 || hsz == 124); + mr = rbmp__get32le(s); + mg = rbmp__get32le(s); + mb = rbmp__get32le(s); + ma = rbmp__get32le(s); + rbmp__get32le(s); /* discard color space */ + for (i=0; i < 12; ++i) + rbmp__get32le(s); /* discard color space parameters */ + if (hsz == 124) + { + rbmp__get32le(s); /* discard rendering intent */ + rbmp__get32le(s); /* discard offset of profile data */ + rbmp__get32le(s); /* discard size of profile data */ + rbmp__get32le(s); /* discard reserved */ + } + } + if (bpp < 16) + psize = (offset - 14 - hsz) >> 2; + } + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) /* we can directly decode 3 or 4 */ + target = req_comp; + else + target = s->img_n; /* if they want monochrome, we'll post-convert */ + out = (unsigned char *) malloc(target * s->img_x * s->img_y); + if (!out) + return rbmp__errpuc("outofmem", "Out of memory"); + if (bpp < 16) + { + int z=0; + if (psize == 0 || psize > 256) + { + free(out); + return rbmp__errpuc("invalid", "Corrupt BMP"); + } + + for (i=0; i < psize; ++i) + { + pal[i][2] = rbmp__get8(s); + pal[i][1] = rbmp__get8(s); + pal[i][0] = rbmp__get8(s); + if (hsz != 12) rbmp__get8(s); + pal[i][3] = 255; + } + + rbmp__skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4)); + if (bpp == 4) + width = (s->img_x + 1) >> 1; + else if (bpp == 8) + width = s->img_x; + else + { + free(out); + return rbmp__errpuc("bad bpp", "Corrupt BMP"); + } + pad = (-width)&3; + for (j=0; j < (int) s->img_y; ++j) + { + for (i=0; i < (int) s->img_x; i += 2) + { + int v=rbmp__get8(s),v2=0; + if (bpp == 4) + { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (bpp == 8) ? rbmp__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + rbmp__skip(s, pad); + } + } + else + { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + rbmp__skip(s, offset - 14 - hsz); + if (bpp == 24) width = 3 * s->img_x; + else if (bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + + switch (bpp) + { + case 24: + easy = 1; + break; + case 32: + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + break; + default: + break; + } + + if (!easy) + { + if (!mr || !mg || !mb) + { + free(out); + return rbmp__errpuc("bad masks", "Corrupt BMP"); + } + /* right shift amt to put high bit in position #7 */ + rshift = rbmp__high_bit(mr)-7; rcount = rbmp__bitcount(mr); + gshift = rbmp__high_bit(mg)-7; gcount = rbmp__bitcount(mg); + bshift = rbmp__high_bit(mb)-7; bcount = rbmp__bitcount(mb); + ashift = rbmp__high_bit(ma)-7; acount = rbmp__bitcount(ma); + } + for (j=0; j < (int) s->img_y; ++j) + { + if (easy) + { + for (i=0; i < (int) s->img_x; ++i) + { + unsigned char a; + out[z+2] = rbmp__get8(s); + out[z+1] = rbmp__get8(s); + out[z+0] = rbmp__get8(s); + z += 3; + a = (easy == 2 ? rbmp__get8(s) : 255); + if (target == 4) out[z++] = a; + } + } + else + { + for (i=0; i < (int) s->img_x; ++i) + { + uint32_t v = (bpp == 16 ? (uint32_t) rbmp__get16le(s) : rbmp__get32le(s)); + int a; + out[z++] = RBMP__BYTECAST(rbmp__shiftsigned(v & mr, rshift, rcount)); + out[z++] = RBMP__BYTECAST(rbmp__shiftsigned(v & mg, gshift, gcount)); + out[z++] = RBMP__BYTECAST(rbmp__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? rbmp__shiftsigned(v & ma, ashift, acount) : 255); + if (target == 4) out[z++] = RBMP__BYTECAST(a); + } + } + rbmp__skip(s, pad); + } + } + if (flip_vertically) + { + unsigned char t; + for (j=0; j < (int) s->img_y>>1; ++j) + { + unsigned char *p1 = out + j *s->img_x*target; + unsigned char *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) + { + t = p1[i], p1[i] = p2[i], p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) + { + out = rbmp__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) + return out; /* rbmp__convert_format frees input on failure */ + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} + +static void rbmp_convert_frame(uint32_t *frame, unsigned width, unsigned height) +{ + uint32_t *end = frame + (width * height * sizeof(uint32_t))/4; + + while(frame < end) + { + uint32_t pixel = *frame; + *frame = (pixel & 0xff00ff00) | ((pixel << 16) & 0x00ff0000) | ((pixel >> 16) & 0xff); + frame++; + } +} + +int rbmp_process_image(rbmp_t *rbmp, void **buf_data, + size_t size, unsigned *width, unsigned *height) +{ + int comp; + + if (!rbmp) + return IMAGE_PROCESS_ERROR; + + rbmp->output_image = (uint32_t*)rbmp_load_from_memory(rbmp->buff_data, size, width, height, &comp, 4); + *buf_data = rbmp->output_image; + + rbmp_convert_frame(rbmp->output_image, *width, *height); + + return IMAGE_PROCESS_END; +} + +bool rbmp_set_buf_ptr(rbmp_t *rbmp, void *data) +{ + if (!rbmp) + return false; + + rbmp->buff_data = (uint8_t*)data; + + return true; +} + +void rbmp_free(rbmp_t *rbmp) +{ + if (!rbmp) + return; + + free(rbmp); +} + +rbmp_t *rbmp_alloc(void) +{ + rbmp_t *rbmp = (rbmp_t*)calloc(1, sizeof(*rbmp)); + if (!rbmp) + return NULL; + return rbmp; +} diff --git a/desmume/src/libretro-common/formats/bmp/rbmp_encode.c b/desmume/src/libretro-common/formats/bmp/rbmp_encode.c index 0ce5e47a3..0bf59f101 100644 --- a/desmume/src/libretro-common/formats/bmp/rbmp_encode.c +++ b/desmume/src/libretro-common/formats/bmp/rbmp_encode.c @@ -28,10 +28,10 @@ static bool write_header_bmp(RFILE *file, unsigned width, unsigned height, bool is32bpp) { + uint8_t header[54]; unsigned line_size = (width * (is32bpp?4:3) + 3) & ~3; unsigned size = line_size * height + 54; unsigned size_array = line_size * height; - uint8_t header[54]; /* Generic BMP stuff. */ @@ -140,9 +140,9 @@ static void dump_line_32_to_24(uint8_t *line, const uint32_t *src, unsigned widt static void dump_content(RFILE *file, const void *frame, int width, int height, int pitch, enum rbmp_source_type type) { - uint8_t *line; - size_t line_size; int j; + size_t line_size; + uint8_t *line = NULL; int bytes_per_pixel = (type==RBMP_SOURCE_TYPE_ARGB8888?4:3); union { @@ -151,59 +151,70 @@ static void dump_content(RFILE *file, const void *frame, const uint32_t *u32; } u; - u.u8 = (const uint8_t*)frame + (height-1) * pitch; + u.u8 = (const uint8_t*)frame; line_size = (width * bytes_per_pixel + 3) & ~3; - if (type == RBMP_SOURCE_TYPE_BGR24) + switch (type) { - /* BGR24 byte order input matches output. Can directly copy, but... need to make sure we pad it. */ - uint32_t zeros = 0; - int pad = line_size-pitch; - for (j = height-1; j >= 0; j--, u.u8 -= pitch) - { - filestream_write(file, u.u8, pitch); - if(pad != 0) - filestream_write(file, &zeros, pad); - } - return; - } - else if(type == RBMP_SOURCE_TYPE_ARGB8888) - { - /* ARGB8888 byte order input matches output. Can directly copy. */ - for (j = height-1; j >= 0; j--, u.u8 -= pitch) - filestream_write(file, u.u8, line_size); - return; + case RBMP_SOURCE_TYPE_BGR24: + { + /* BGR24 byte order input matches output. Can directly copy, but... need to make sure we pad it. */ + uint32_t zeros = 0; + int pad = line_size-pitch; + for (j = 0; j < height; j++, u.u8 += pitch) + { + filestream_write(file, u.u8, pitch); + if(pad != 0) + filestream_write(file, &zeros, pad); + } + } + break; + case RBMP_SOURCE_TYPE_ARGB8888: + /* ARGB8888 byte order input matches output. Can directly copy. */ + for (j = 0; j < height; j++, u.u8 += pitch) + filestream_write(file, u.u8, line_size); + return; + default: + break; } /* allocate line buffer, and initialize the final four bytes to zero, for deterministic padding */ line = (uint8_t*)malloc(line_size); - if (!line) return; + if (!line) + return; *(uint32_t*)(line + line_size - 4) = 0; - if (type == RBMP_SOURCE_TYPE_XRGB888) + switch (type) { - for (j = height-1; j >= 0; j--, u.u8 -= pitch) - { - dump_line_32_to_24(line, u.u32, width); - filestream_write(file, line, line_size); - } - } - else /* type == RBMP_SOURCE_TYPE_RGB565 */ - { - for (j = height-1; j >= 0; j--, u.u8 -= pitch) - { - dump_line_565_to_24(line, u.u16, width); - filestream_write(file, line, line_size); - } + case RBMP_SOURCE_TYPE_XRGB888: + for (j = 0; j < height; j++, u.u8 += pitch) + { + dump_line_32_to_24(line, u.u32, width); + filestream_write(file, line, line_size); + } + break; + case RBMP_SOURCE_TYPE_RGB565: + for (j = 0; j < height; j++, u.u8 += pitch) + { + dump_line_565_to_24(line, u.u16, width); + filestream_write(file, line, line_size); + } + break; + default: + break; } + /* Free allocated line buffer */ + free(line); } -bool rbmp_save_image(const char *filename, const void *frame, +bool rbmp_save_image( + const char *filename, + const void *frame, unsigned width, unsigned height, unsigned pitch, enum rbmp_source_type type) { - bool ret; + bool ret = false; RFILE *file = filestream_open(filename, RFILE_MODE_WRITE, -1); if (!file) return false; diff --git a/desmume/src/libretro-common/formats/image_texture.c b/desmume/src/libretro-common/formats/image_texture.c new file mode 100644 index 000000000..b1369c06d --- /dev/null +++ b/desmume/src/libretro-common/formats/image_texture.c @@ -0,0 +1,322 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (image_texture.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 + +enum video_image_format +{ + IMAGE_FORMAT_NONE = 0, + IMAGE_FORMAT_TGA, + IMAGE_FORMAT_PNG, + IMAGE_FORMAT_JPEG, + IMAGE_FORMAT_BMP +}; + +static bool image_texture_supports_rgba = false; + +void image_texture_set_rgba(void) +{ + image_texture_supports_rgba = true; +} + +void image_texture_unset_rgba(void) +{ + image_texture_supports_rgba = false; +} + +bool image_texture_set_color_shifts( + unsigned *r_shift, unsigned *g_shift, unsigned *b_shift, + unsigned *a_shift) +{ + *a_shift = 24; + *r_shift = 16; + *g_shift = 8; + *b_shift = 0; + + if (image_texture_supports_rgba) + { + *r_shift = 0; + *b_shift = 16; + return true; + } + + return false; +} + +bool image_texture_color_convert(unsigned r_shift, + unsigned g_shift, unsigned b_shift, unsigned a_shift, + struct texture_image *out_img) +{ + /* This is quite uncommon. */ + if (a_shift != 24 || r_shift != 16 || g_shift != 8 || b_shift != 0) + { + uint32_t i; + uint32_t num_pixels = out_img->width * out_img->height; + uint32_t *pixels = (uint32_t*)out_img->pixels; + + for (i = 0; i < num_pixels; i++) + { + uint32_t col = pixels[i]; + uint8_t a = (uint8_t)(col >> 24); + uint8_t r = (uint8_t)(col >> 16); + uint8_t g = (uint8_t)(col >> 8); + uint8_t b = (uint8_t)(col >> 0); + pixels[i] = (a << a_shift) | + (r << r_shift) | (g << g_shift) | (b << b_shift); + } + + return true; + } + + return false; +} + +#ifdef GEKKO + +#define GX_BLIT_LINE_32(off) \ +{ \ + unsigned x; \ + const uint16_t *tmp_src = src; \ + uint16_t *tmp_dst = dst; \ + for (x = 0; x < width2 >> 3; x++, tmp_src += 8, tmp_dst += 32) \ + { \ + tmp_dst[ 0 + off] = tmp_src[0]; \ + tmp_dst[ 16 + off] = tmp_src[1]; \ + tmp_dst[ 1 + off] = tmp_src[2]; \ + tmp_dst[ 17 + off] = tmp_src[3]; \ + tmp_dst[ 2 + off] = tmp_src[4]; \ + tmp_dst[ 18 + off] = tmp_src[5]; \ + tmp_dst[ 3 + off] = tmp_src[6]; \ + tmp_dst[ 19 + off] = tmp_src[7]; \ + } \ + src += tmp_pitch; \ +} + +static bool image_texture_internal_gx_convert_texture32( + struct texture_image *image) +{ + unsigned tmp_pitch, width2, i; + const uint16_t *src = NULL; + uint16_t *dst = NULL; + /* Memory allocation in libogc is extremely primitive so try + * to avoid gaps in memory when converting by copying over to + * a temporary buffer first, then converting over into + * main buffer again. */ + void *tmp = malloc(image->width + * image->height * sizeof(uint32_t)); + + if (!tmp) + return false; + + memcpy(tmp, image->pixels, image->width + * image->height * sizeof(uint32_t)); + tmp_pitch = (image->width * sizeof(uint32_t)) >> 1; + + image->width &= ~3; + image->height &= ~3; + width2 = image->width << 1; + src = (uint16_t*)tmp; + dst = (uint16_t*)image->pixels; + + for (i = 0; i < image->height; i += 4, dst += 4 * width2) + { + GX_BLIT_LINE_32(0) + GX_BLIT_LINE_32(4) + GX_BLIT_LINE_32(8) + GX_BLIT_LINE_32(12) + } + + free(tmp); + return true; +} +#endif + +static bool image_texture_load_internal( + enum image_type_enum type, + void *ptr, + size_t len, + struct texture_image *out_img, + unsigned a_shift, unsigned r_shift, + unsigned g_shift, unsigned b_shift) +{ + int ret; + bool success = false; + void *img = image_transfer_new(type); + + if (!img) + goto end; + + image_transfer_set_buffer_ptr(img, type, (uint8_t*)ptr); + + if (!image_transfer_start(img, type)) + goto end; + + while (image_transfer_iterate(img, type)); + + if (!image_transfer_is_valid(img, type)) + goto end; + + do + { + ret = image_transfer_process(img, type, + (uint32_t**)&out_img->pixels, len, &out_img->width, + &out_img->height); + }while(ret == IMAGE_PROCESS_NEXT); + + if (ret == IMAGE_PROCESS_ERROR || ret == IMAGE_PROCESS_ERROR_END) + goto end; + + image_texture_color_convert(r_shift, g_shift, b_shift, + a_shift, out_img); + +#ifdef GEKKO + if (!image_texture_internal_gx_convert_texture32(out_img)) + { + image_texture_free(out_img); + goto end; + } +#endif + + success = true; + +end: + if (img) + image_transfer_free(img, type); + + return success; +} + + +void image_texture_free(struct texture_image *img) +{ + if (!img) + return; + + if (img->pixels) + free(img->pixels); + memset(img, 0, sizeof(*img)); +} + +static enum video_image_format image_texture_get_type(const char *path) +{ +#ifdef HAVE_RTGA + if (strstr(path, ".tga")) + return IMAGE_FORMAT_TGA; +#endif +#ifdef HAVE_RPNG + if (strstr(path, ".png")) + return IMAGE_FORMAT_PNG; +#endif +#ifdef HAVE_RJPEG + if (strstr(path, ".jpg") || strstr(path, ".jpeg")) + return IMAGE_FORMAT_JPEG; +#endif +#ifdef HAVE_RBMP + if (strstr(path, ".bmp")) + return IMAGE_FORMAT_BMP; +#endif + return IMAGE_FORMAT_NONE; +} + +static enum image_type_enum image_texture_convert_fmt_to_type(enum video_image_format fmt) +{ + switch (fmt) + { +#ifdef HAVE_RPNG + case IMAGE_FORMAT_PNG: + return IMAGE_TYPE_PNG; +#endif +#ifdef HAVE_RJPEG + case IMAGE_FORMAT_JPEG: + return IMAGE_TYPE_JPEG; +#endif +#ifdef HAVE_RBMP + case IMAGE_FORMAT_BMP: + return IMAGE_TYPE_BMP; +#endif +#ifdef HAVE_RTGA + case IMAGE_FORMAT_TGA: + return IMAGE_TYPE_TGA; +#endif + case IMAGE_FORMAT_NONE: + default: + break; + } + + return IMAGE_TYPE_NONE; +} + +bool image_texture_load(struct texture_image *out_img, + const char *path) +{ + unsigned r_shift, g_shift, b_shift, a_shift; + size_t file_len = 0; + struct nbio_t *handle = NULL; + void *ptr = NULL; + enum video_image_format fmt = image_texture_get_type(path); + + image_texture_set_color_shifts(&r_shift, &g_shift, &b_shift, + &a_shift); + + if (fmt != IMAGE_FORMAT_NONE) + { + handle = (struct nbio_t*)nbio_open(path, NBIO_READ); + if (!handle) + goto error; + nbio_begin_read(handle); + + while (!nbio_iterate(handle)); + + ptr = nbio_get_ptr(handle, &file_len); + + if (!ptr) + goto error; + + if (image_texture_load_internal( + image_texture_convert_fmt_to_type(fmt), + ptr, file_len, out_img, + a_shift, r_shift, g_shift, b_shift)) + goto success; + } + +error: + out_img->pixels = NULL; + out_img->width = 0; + out_img->height = 0; + if (handle) + nbio_free(handle); + + return false; + +success: + if (handle) + nbio_free(handle); + + return true; +} diff --git a/desmume/src/libretro-common/formats/image_transfer.c b/desmume/src/libretro-common/formats/image_transfer.c new file mode 100644 index 000000000..afd3a99fd --- /dev/null +++ b/desmume/src/libretro-common/formats/image_transfer.c @@ -0,0 +1,282 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (image_transfer.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 HAVE_RPNG +#include +#endif +#ifdef HAVE_RJPEG +#include +#endif +#ifdef HAVE_RTGA +#include +#endif +#ifdef HAVE_RBMP +#include +#endif + +#include + +void image_transfer_free(void *data, enum image_type_enum type) +{ + switch (type) + { + case IMAGE_TYPE_TGA: +#ifdef HAVE_RTGA + rtga_free((rtga_t*)data); +#endif + break; + case IMAGE_TYPE_PNG: +#ifdef HAVE_RPNG + rpng_free((rpng_t*)data); +#endif + break; + case IMAGE_TYPE_JPEG: +#ifdef HAVE_RJPEG + rjpeg_free((rjpeg_t*)data); +#endif + break; + case IMAGE_TYPE_BMP: +#ifdef HAVE_RBMP + rbmp_free((rbmp_t*)data); +#endif + break; + case IMAGE_TYPE_NONE: + break; + } +} + +void *image_transfer_new(enum image_type_enum type) +{ + switch (type) + { + case IMAGE_TYPE_PNG: +#ifdef HAVE_RPNG + return rpng_alloc(); +#else + break; +#endif + case IMAGE_TYPE_JPEG: +#ifdef HAVE_RJPEG + return rjpeg_alloc(); +#else + break; +#endif + case IMAGE_TYPE_TGA: +#ifdef HAVE_RTGA + return rtga_alloc(); +#else + break; +#endif + case IMAGE_TYPE_BMP: +#ifdef HAVE_RBMP + return rbmp_alloc(); +#else + break; +#endif + default: + break; + } + + return NULL; +} + +bool image_transfer_start(void *data, enum image_type_enum type) +{ + + switch (type) + { + case IMAGE_TYPE_PNG: +#ifdef HAVE_RPNG + if (!rpng_start((rpng_t*)data)) + break; + return true; +#else + break; +#endif + case IMAGE_TYPE_JPEG: +#ifdef HAVE_RJPEG + return true; +#else + break; +#endif + case IMAGE_TYPE_TGA: +#ifdef HAVE_RTGA + return true; +#else + break; +#endif + case IMAGE_TYPE_BMP: + return true; + case IMAGE_TYPE_NONE: + break; + } + + return false; +} + +bool image_transfer_is_valid( + void *data, + enum image_type_enum type) +{ + switch (type) + { + case IMAGE_TYPE_PNG: +#ifdef HAVE_RPNG + return rpng_is_valid((rpng_t*)data); +#else + break; +#endif + case IMAGE_TYPE_JPEG: +#ifdef HAVE_RJPEG + return true; +#else + break; +#endif + case IMAGE_TYPE_TGA: +#ifdef HAVE_RTGA + return true; +#else + break; +#endif + case IMAGE_TYPE_BMP: + return true; + case IMAGE_TYPE_NONE: + break; + } + + return false; +} + +void image_transfer_set_buffer_ptr( + void *data, + enum image_type_enum type, + void *ptr) +{ + switch (type) + { + case IMAGE_TYPE_PNG: +#ifdef HAVE_RPNG + rpng_set_buf_ptr((rpng_t*)data, (uint8_t*)ptr); +#endif + break; + case IMAGE_TYPE_JPEG: +#ifdef HAVE_RJPEG + rjpeg_set_buf_ptr((rjpeg_t*)data, (uint8_t*)ptr); +#endif + break; + case IMAGE_TYPE_TGA: +#ifdef HAVE_RTGA + rtga_set_buf_ptr((rtga_t*)data, (uint8_t*)ptr); +#endif + break; + case IMAGE_TYPE_BMP: +#ifdef HAVE_RBMP + rbmp_set_buf_ptr((rbmp_t*)data, (uint8_t*)ptr); +#endif + break; + case IMAGE_TYPE_NONE: + break; + } +} + +int image_transfer_process( + void *data, + enum image_type_enum type, + uint32_t **buf, size_t len, + unsigned *width, unsigned *height) +{ + switch (type) + { + case IMAGE_TYPE_PNG: +#ifdef HAVE_RPNG + if (!rpng_is_valid((rpng_t*)data)) + return IMAGE_PROCESS_ERROR; + + return rpng_process_image( + (rpng_t*)data, + (void**)buf, len, width, height); +#else + break; +#endif + case IMAGE_TYPE_JPEG: +#ifdef HAVE_RJPEG + return rjpeg_process_image((rjpeg_t*)data, + (void**)buf, len, width, height); +#else + break; +#endif + case IMAGE_TYPE_TGA: +#ifdef HAVE_RTGA + return rtga_process_image((rtga_t*)data, + (void**)buf, len, width, height); +#else + break; +#endif + case IMAGE_TYPE_BMP: +#ifdef HAVE_RBMP + return rbmp_process_image((rbmp_t*)data, + (void**)buf, len, width, height); +#else + break; +#endif + case IMAGE_TYPE_NONE: + break; + } + + return 0; +} + +bool image_transfer_iterate(void *data, enum image_type_enum type) +{ + + switch (type) + { + case IMAGE_TYPE_PNG: +#ifdef HAVE_RPNG + if (!rpng_iterate_image((rpng_t*)data)) + return false; +#endif + break; + case IMAGE_TYPE_JPEG: +#ifdef HAVE_RJPEG + return false; +#else + break; +#endif + case IMAGE_TYPE_TGA: +#ifdef HAVE_RTGA + return false; +#else + break; +#endif + case IMAGE_TYPE_BMP: + return false; + case IMAGE_TYPE_NONE: + return false; + } + + return true; +} diff --git a/desmume/src/libretro-common/formats/jpeg/rjpeg.c b/desmume/src/libretro-common/formats/jpeg/rjpeg.c new file mode 100644 index 000000000..e3760ba96 --- /dev/null +++ b/desmume/src/libretro-common/formats/jpeg/rjpeg.c @@ -0,0 +1,2570 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (rjpeg.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. + */ + +/* Modified version of stb_image's JPEG sources. */ + +#include +#include +#include /* ptrdiff_t on osx */ +#include +#include + +#include +#include +#include +#include +#include +#include + +enum +{ + RJPEG_DEFAULT = 0, /* only used for req_comp */ + RJPEG_GREY, + RJPEG_GREY_ALPHA, + RJPEG_RGB, + RJPEG_RGB_ALPHA +}; + +typedef struct +{ + int (*read) (void *user,char *data,int size); /* fill 'data' with 'size' bytes. return number of bytes actually read */ + void (*skip) (void *user,int n); /* skip the next 'n' bytes, or 'unget' the last -n bytes if negative */ + int (*eof) (void *user); /* returns nonzero if we are at end of file/data */ +} rjpeg_io_callbacks; + +typedef uint8_t *(*rjpeg_resample_row_func)(uint8_t *out, uint8_t *in0, uint8_t *in1, + int w, int hs); + +typedef struct +{ + rjpeg_resample_row_func resample; + uint8_t *line0,*line1; + int hs,vs; /* expansion factor in each axis */ + int w_lores; /* horizontal pixels pre-expansion */ + int ystep; /* how far through vertical expansion we are */ + int ypos; /* which pre-expansion row we're on */ +} rjpeg__resample; + +struct rjpeg +{ + uint8_t *buff_data; + void *empty; +}; + +#ifdef _MSC_VER +#define RJPEG_HAS_LROTL +#endif + +#ifdef RJPEG_HAS_LROTL + #define rjpeg_lrot(x,y) _lrotl(x,y) +#else + #define rjpeg_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) +#endif + +/* x86/x64 detection */ +#if defined(__x86_64__) || defined(_M_X64) +#define RJPEG__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define RJPEG__X86_TARGET +#endif + +#if defined(__GNUC__) && (defined(RJPEG__X86_TARGET) || defined(RJPEG__X64_TARGET)) && !defined(__SSE2__) && !defined(RJPEG_NO_SIMD) +/* NOTE: not clear do we actually need this for the 64-bit path? + * gcc doesn't support sse2 intrinsics unless you compile with -msse2, + * (but compiling with -msse2 allows the compiler to use SSE2 everywhere; + * this is just broken and gcc are jerks for not fixing it properly + * http://www.virtualdub.org/blog/pivot/entry.php?id=363 ) + */ +#define RJPEG_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(RJPEG__X86_TARGET) && !defined(RJPEG_MINGW_ENABLE_SSE2) && !defined(RJPEG_NO_SIMD) +/* Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid RJPEG__X64_TARGET + * + * 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the + * Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. + * As a result, enabling SSE2 on 32-bit MinGW is dangerous when not + * simultaneously enabling "-mstackrealign". + * + * See https://github.com/nothings/stb/issues/81 for more information. + * + * So default to no SSE2 on 32-bit MinGW. If you've read this far and added + * -mstackrealign to your build settings, feel free to #define RJPEG_MINGW_ENABLE_SSE2. + */ +#define RJPEG_NO_SIMD +#endif + +#if defined(__SSE2__) +#include + +#ifdef _MSC_VER +#define RJPEG_SIMD_ALIGN(type, name) __declspec(align(16)) type name +#else +#define RJPEG_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif + +#endif + +/* ARM NEON */ +#if defined(RJPEG_NO_SIMD) && defined(RJPEG_NEON) +#undef RJPEG_NEON +#endif + +#ifdef RJPEG_NEON +#include +/* assume GCC or Clang on ARM targets */ +#define RJPEG_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif + +#ifndef RJPEG_SIMD_ALIGN +#define RJPEG_SIMD_ALIGN(type, name) type name +#endif + +typedef struct +{ + uint32_t img_x, img_y; + int img_n, img_out_n; + + rjpeg_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + uint8_t buffer_start[128]; + + uint8_t *img_buffer, *img_buffer_end; + uint8_t *img_buffer_original; +} rjpeg__context; + +static uint8_t *rjpeg__jpeg_load(rjpeg__context *s, unsigned *x, unsigned *y, int *comp, int req_comp); + +#define rjpeg__err(x,y) 0 + +#define rjpeg__errpf(x,y) ((float *) (rjpeg__err(x,y)?NULL:NULL)) +#define rjpeg__errpuc(x,y) ((unsigned char *) (rjpeg__err(x,y)?NULL:NULL)) + +static int rjpeg__vertically_flip_on_load = 0; + +static unsigned char *rjpeg__load_flip(rjpeg__context *s, unsigned *x, unsigned *y, int *comp, int req_comp) +{ + unsigned char *result = rjpeg__jpeg_load(s,x,y,comp,req_comp); + + if (rjpeg__vertically_flip_on_load && result != NULL) + { + int row,col,z; + int w = *x, h = *y; + int depth = req_comp ? req_comp : *comp; + + for (row = 0; row < (h>>1); row++) + { + for (col = 0; col < w; col++) + { + for (z = 0; z < depth; z++) + { + uint8_t temp = result[(row * w + col) * depth + z]; + result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; + result[((h - row - 1) * w + col) * depth + z] = temp; + } + } + } + } + + return result; +} + +static uint8_t *rjpeg_load_from_memory(const uint8_t *buffer, int len, unsigned *x, unsigned *y, int *comp, int req_comp) +{ + rjpeg__context s; + s.io.read = NULL; + s.read_from_callbacks = 0; + s.img_buffer = s.img_buffer_original = (uint8_t *) buffer; + s.img_buffer_end = (uint8_t *) buffer+len; + return rjpeg__load_flip(&s,x,y,comp,req_comp); +} + +enum +{ + RJPEG_SCAN_LOAD = 0, + RJPEG_SCAN_TYPE, + RJPEG_SCAN_HEADER +}; + +static void rjpeg__refill_buffer(rjpeg__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + + if (n == 0) + { + /* at end of file, treat same as if from memory, but need to handle case + * where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file */ + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } + else + { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +static INLINE uint8_t rjpeg__get8(rjpeg__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + + if (s->read_from_callbacks) + { + rjpeg__refill_buffer(s); + return *s->img_buffer++; + } + + return 0; +} + +static INLINE int rjpeg__at_eof(rjpeg__context *s) +{ + if (s->io.read) + { + if (!(s->io.eof)(s->io_user_data)) + return 0; + + /* if feof() is true, check if buffer = end + * special case: we've only got the special + * 0 character at the end */ + + if (s->read_from_callbacks == 0) + return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} + +static void rjpeg__skip(rjpeg__context *s, int n) +{ + if (n < 0) + { + s->img_buffer = s->img_buffer_end; + return; + } + + if (s->io.read) + { + int blen = (int) (s->img_buffer_end - s->img_buffer); + + if (blen < n) + { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int rjpeg__get16be(rjpeg__context *s) +{ + int z = rjpeg__get8(s); + return (z << 8) + rjpeg__get8(s); +} + +#define RJPEG__BYTECAST(x) ((uint8_t) ((x) & 255)) /* truncate int to byte without warnings */ + +/* huffman decoding acceleration */ +#define FAST_BITS 9 /* larger handles more cases; smaller stomps less cache */ + +typedef struct +{ + uint8_t fast[1 << FAST_BITS]; + /* weirdly, repacking this into AoS is a 10% speed loss, instead of a win */ + uint16_t code[256]; + uint8_t values[256]; + uint8_t size[257]; + unsigned int maxcode[18]; + int delta[17]; /* old 'firstsymbol' - old 'firstcode' */ +} rjpeg__huffman; + +typedef struct +{ + rjpeg__context *s; + rjpeg__huffman huff_dc[4]; + rjpeg__huffman huff_ac[4]; + uint8_t dequant[4][64]; + int16_t fast_ac[4][1 << FAST_BITS]; + + /* sizes for components, interleaved MCUs */ + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + + /* definition of jpeg image component */ + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + uint8_t *data; + void *raw_data, *raw_coeff; + uint8_t *linebuf; + short *coeff; /* progressive only */ + int coeff_w, coeff_h; /* number of 8x8 coefficient blocks */ + } img_comp[4]; + + uint32_t code_buffer; /* jpeg entropy-coded buffer */ + int code_bits; /* number of valid bits */ + unsigned char marker; /* marker seen while filling entropy buffer */ + int nomore; /* flag if we saw a marker so must stop */ + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + + int scan_n, order[4]; + int restart_interval, todo; + + /* kernels */ + void (*idct_block_kernel)(uint8_t *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(uint8_t *out, const uint8_t *y, const uint8_t *pcb, const uint8_t *pcr, int count, int step); + uint8_t *(*resample_row_hv_2_kernel)(uint8_t *out, uint8_t *in_near, uint8_t *in_far, int w, int hs); +} rjpeg__jpeg; + +#define rjpeg__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define rjpeg__fsh(x) ((x) << 12) + +#define RJPEG__MARKER_none 0xff +/* if there's a pending marker from the entropy stream, return that + * otherwise, fetch from the stream and get a marker. if there's no + * marker, return 0xff, which is never a valid marker value + */ + +/* in each scan, we'll have scan_n components, and the order + * of the components is specified by order[] + */ +#define RJPEG__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +/* use comparisons since in some cases we handle more than one case (e.g. SOF) */ +#define rjpeg__SOI(x) ((x) == 0xd8) +#define rjpeg__EOI(x) ((x) == 0xd9) +#define rjpeg__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define rjpeg__SOS(x) ((x) == 0xda) + +#define rjpeg__SOF_progressive(x) ((x) == 0xc2) +#define rjpeg__div4(x) ((uint8_t) ((x) >> 2)) +#define rjpeg__div16(x) ((uint8_t) ((x) >> 4)) + +static int rjpeg__build_huffman(rjpeg__huffman *h, int *count) +{ + int i,j,k=0,code; + + /* build size list for each symbol (from JPEG spec) */ + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (uint8_t) (i+1); + + h->size[k] = 0; + /* compute actual symbols (from jpeg spec) */ + code = 0; + k = 0; + + for(j=1; j <= 16; ++j) + { + /* compute delta to add to code to compute symbol id */ + h->delta[j] = k - code; + if (h->size[k] == j) + { + while (h->size[k] == j) + h->code[k++] = (uint16_t) (code++); + if (code-1 >= (1 << j)) + return rjpeg__err("bad code lengths","Corrupt JPEG"); + } + /* compute largest code + 1 for this size, preshifted as needed later */ + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + /* build non-spec acceleration table; 255 is flag for not-accelerated */ + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) + { + int s = h->size[i]; + if (s <= FAST_BITS) + { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) + h->fast[c+j] = (uint8_t) i; + } + } + return 1; +} + +/* build a table that decodes both magnitude and value of small ACs in + * one go. */ +static void rjpeg__build_fast_ac(int16_t *fast_ac, rjpeg__huffman *h) +{ + int i; + + for (i=0; i < (1 << FAST_BITS); ++i) + { + uint8_t fast = h->fast[i]; + + fast_ac[i] = 0; + + if (fast < 255) + { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) + { + /* magnitude code followed by receive_extend code */ + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) + k += (-1 << magbits) + 1; + + /* if the result is small enough, we can fit it in fast_ac table */ + if (k >= -128 && k <= 127) + fast_ac[i] = (int16_t) ((k << 8) + (run << 4) + (len + magbits)); + } + } + } +} + +static void rjpeg__grow_buffer_unsafe(rjpeg__jpeg *j) +{ + do + { + int b = j->nomore ? 0 : rjpeg__get8(j->s); + if (b == 0xff) + { + int c = rjpeg__get8(j->s); + + if (c != 0) + { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +/* (1 << n) - 1 */ +static uint32_t rjpeg__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +/* decode a JPEG huffman value from the bitstream */ +static INLINE int rjpeg__jpeg_huff_decode(rjpeg__jpeg *j, rjpeg__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) + rjpeg__grow_buffer_unsafe(j); + + /* look at the top FAST_BITS and determine what symbol ID it is, + * if the code is <= FAST_BITS */ + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + + if (k < 255) + { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + /* naive test is to shift the code_buffer down so k bits are + * valid, then test against maxcode. To speed this up, we've + * preshifted maxcode left so that it has (16-k) 0s at the + * end; in other words, regardless of the number of bits, it + * wants to be compared against something shifted to have 16; + * that way we don't need to shift inside the loop. */ + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + + if (k == 17) + { + /* error! code not found */ + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + /* convert the huffman code to the symbol id */ + c = ((j->code_buffer >> (32 - k)) & rjpeg__bmask[k]) + h->delta[k]; + assert((((j->code_buffer) >> (32 - h->size[c])) & rjpeg__bmask[h->size[c]]) == h->code[c]); + + /* convert the id to a symbol */ + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +/* bias[n] = (-1<code_bits < n) + rjpeg__grow_buffer_unsafe(j); + + sgn = (int32_t)j->code_buffer >> 31; /* sign bit is always in MSB */ + k = rjpeg_lrot(j->code_buffer, n); + assert(n >= 0 && n < (int) (sizeof(rjpeg__bmask)/sizeof(*rjpeg__bmask))); + j->code_buffer = k & ~rjpeg__bmask[n]; + k &= rjpeg__bmask[n]; + j->code_bits -= n; + return k + (rjpeg__jbias[n] & ~sgn); +} + +/* get some unsigned bits */ +static INLINE int rjpeg__jpeg_get_bits(rjpeg__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) rjpeg__grow_buffer_unsafe(j); + k = rjpeg_lrot(j->code_buffer, n); + j->code_buffer = k & ~rjpeg__bmask[n]; + k &= rjpeg__bmask[n]; + j->code_bits -= n; + return k; +} + +static INLINE int rjpeg__jpeg_get_bit(rjpeg__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) rjpeg__grow_buffer_unsafe(j); + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +/* given a value that's at position X in the zigzag stream, + * where does it appear in the 8x8 matrix coded as row-major? */ +static uint8_t rjpeg__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + /* let corrupt input sample past end */ + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +/* decode one 64-entry block-- */ +static int rjpeg__jpeg_decode_block( + rjpeg__jpeg *j, short data[64], + rjpeg__huffman *hdc, + rjpeg__huffman *hac, + int16_t *fac, + int b, + uint8_t *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) + rjpeg__grow_buffer_unsafe(j); + t = rjpeg__jpeg_huff_decode(j, hdc); + if (t < 0) + return rjpeg__err("bad huffman code","Corrupt JPEG"); + + /* 0 all the ac values now so we can do it 32-bits at a time */ + memset(data,0,64*sizeof(data[0])); + + diff = t ? rjpeg__extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc * dequant[0]); + + /* decode AC components, see JPEG spec */ + k = 1; + do + { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) + rjpeg__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) + { + /* fast-AC path */ + k += (r >> 4) & 15; /* run */ + s = r & 15; /* combined length */ + j->code_buffer <<= s; + j->code_bits -= s; + /* decode into unzigzag'd location */ + zig = rjpeg__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } + else + { + int rs = rjpeg__jpeg_huff_decode(j, hac); + if (rs < 0) + return rjpeg__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) + { + if (rs != 0xf0) + break; /* end block */ + k += 16; + } + else + { + k += r; + /* decode into unzigzag'd location */ + zig = rjpeg__jpeg_dezigzag[k++]; + data[zig] = (short) (rjpeg__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int rjpeg__jpeg_decode_block_prog_dc( + rjpeg__jpeg *j, + short data[64], + rjpeg__huffman *hdc, + int b) +{ + if (j->spec_end != 0) + return rjpeg__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) + rjpeg__grow_buffer_unsafe(j); + + if (j->succ_high == 0) + { + int t; + int diff,dc; + + /* first scan for DC coefficient, must be first */ + memset(data,0,64*sizeof(data[0])); /* 0 all the ac values now */ + t = rjpeg__jpeg_huff_decode(j, hdc); + diff = t ? rjpeg__extend_receive(j, t) : 0; + + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc << j->succ_low); + } + else + { + /* refinement scan for DC coefficient */ + if (rjpeg__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +static int rjpeg__jpeg_decode_block_prog_ac( + rjpeg__jpeg *j, + short data[64], + rjpeg__huffman *hac, + int16_t *fac) +{ + int k; + if (j->spec_start == 0) + return rjpeg__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) + { + int shift = j->succ_low; + + if (j->eob_run) + { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) rjpeg__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) + { /* fast-AC path */ + k += (r >> 4) & 15; /* run */ + s = r & 15; /* combined length */ + j->code_buffer <<= s; + j->code_bits -= s; + zig = rjpeg__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) << shift); + } + else + { + int rs = rjpeg__jpeg_huff_decode(j, hac); + if (rs < 0) return rjpeg__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) + { + if (r < 15) + { + j->eob_run = (1 << r); + if (r) + j->eob_run += rjpeg__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = rjpeg__jpeg_dezigzag[k++]; + data[zig] = (short) (rjpeg__extend_receive(j,s) << shift); + } + } + } while (k <= j->spec_end); + } else { + /* refinement scan for these AC coefficients */ + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) + { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) + { + short *p = &data[rjpeg__jpeg_dezigzag[k]]; + if (*p != 0) + if (rjpeg__jpeg_get_bit(j)) + if ((*p & bit)==0) + { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = rjpeg__jpeg_huff_decode(j, hac); + if (rs < 0) return rjpeg__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) + { + if (r < 15) + { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += rjpeg__jpeg_get_bits(j, r); + r = 64; /* force end of block */ + } else { + /* r=15 s=0 should write 16 0s, so we just do + * a run of 15 0s and then write s (which is 0), + * so we don't have to do anything special here */ + } + } else { + if (s != 1) return rjpeg__err("bad huffman code", "Corrupt JPEG"); + /* sign bit */ + if (rjpeg__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + /* advance by r */ + while (k <= j->spec_end) + { + short *p = &data[rjpeg__jpeg_dezigzag[k++]]; + if (*p != 0) + { + if (rjpeg__jpeg_get_bit(j)) + if ((*p & bit)==0) + { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + else + { + if (r == 0) + { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +/* take a -128..127 value and rjpeg__clamp it and convert to 0..255 */ +static INLINE uint8_t rjpeg__clamp(int x) +{ + /* trick to use a single test to catch both cases */ + if ((unsigned int) x > 255) + return 255; + return (uint8_t) x; +} + + +/* derived from jidctint -- DCT_ISLOW */ +#define RJPEG__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * rjpeg__f2f(0.5411961f); \ + t2 = p1 + p3*rjpeg__f2f(-1.847759065f); \ + t3 = p1 + p2*rjpeg__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = rjpeg__fsh(p2+p3); \ + t1 = rjpeg__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*rjpeg__f2f( 1.175875602f); \ + t0 = t0*rjpeg__f2f( 0.298631336f); \ + t1 = t1*rjpeg__f2f( 2.053119869f); \ + t2 = t2*rjpeg__f2f( 3.072711026f); \ + t3 = t3*rjpeg__f2f( 1.501321110f); \ + p1 = p5 + p1*rjpeg__f2f(-0.899976223f); \ + p2 = p5 + p2*rjpeg__f2f(-2.562915447f); \ + p3 = p3*rjpeg__f2f(-1.961570560f); \ + p4 = p4*rjpeg__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void rjpeg__idct_block(uint8_t *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + uint8_t *o = NULL; + int16_t *d = data; + + /* columns */ + for (i=0; i < 8; ++i,++d, ++v) + { + /* if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing */ + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) + { + /* no shortcut 0 seconds + * (1|2|3|4|5|6|7)==0 0 seconds + * all separate -0.047 seconds + * 1 && 2|3 && 4|5 && 6|7: -0.047 seconds */ + int dcterm = d[0] << 2; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } + else + { + RJPEG__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + /* constants scaled things up by 1<<12; let's bring them back + * down, but keep 2 extra bits of precision */ + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) + { + /* no fast case since the first 1D IDCT spread components out */ + RJPEG__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + /* constants scaled things up by 1<<12, plus we had 1<<2 from first + * loop, plus horizontal and vertical each scale by sqrt(8) so together + * we've got an extra 1<<3, so 1<<17 total we need to remove. + * so we want to round that, which means adding 0.5 * 1<<17, + * aka 65536. Also, we'll end up with -128 to 127 that we want + * to encode as 0..255 by adding 128, so we'll add that before the shift */ + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + /* tried computing the shifts into temps, or'ing the temps to see + * if any were out of range, but that was slower */ + o[0] = rjpeg__clamp((x0+t3) >> 17); + o[7] = rjpeg__clamp((x0-t3) >> 17); + o[1] = rjpeg__clamp((x1+t2) >> 17); + o[6] = rjpeg__clamp((x1-t2) >> 17); + o[2] = rjpeg__clamp((x2+t1) >> 17); + o[5] = rjpeg__clamp((x2-t1) >> 17); + o[3] = rjpeg__clamp((x3+t0) >> 17); + o[4] = rjpeg__clamp((x3-t0) >> 17); + } +} + +#if defined(__SSE2__) +/* sse2 integer IDCT. not the fastest possible implementation but it + * produces bit-identical results to the generic C version so it's + * fully "transparent". + */ +static void rjpeg__idct_simd(uint8_t *out, int out_stride, short data[64]) +{ + /* This is constructed to match our regular (generic) integer IDCT exactly. */ + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + /* dot product constant: even elems=x, odd elems=y */ + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + /* out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + * out(1) = c1[even]*x + c1[odd]*y + */ + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + /* out = in << 12 (in 16-bit, out 32-bit) */ + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + /* wide add */ + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + /* wide sub */ + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + /* butterfly a/b, add bias, then shift by "s" and pack */ + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + /* 8-bit interleave step (for transposes) */ + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + /* 16-bit interleave step (for transposes) */ + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(rjpeg__f2f(0.5411961f), rjpeg__f2f(0.5411961f) + rjpeg__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(rjpeg__f2f(0.5411961f) + rjpeg__f2f( 0.765366865f), rjpeg__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(rjpeg__f2f(1.175875602f) + rjpeg__f2f(-0.899976223f), rjpeg__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(rjpeg__f2f(1.175875602f), rjpeg__f2f(1.175875602f) + rjpeg__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(rjpeg__f2f(-1.961570560f) + rjpeg__f2f( 0.298631336f), rjpeg__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(rjpeg__f2f(-1.961570560f), rjpeg__f2f(-1.961570560f) + rjpeg__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(rjpeg__f2f(-0.390180644f) + rjpeg__f2f( 2.053119869f), rjpeg__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(rjpeg__f2f(-0.390180644f), rjpeg__f2f(-0.390180644f) + rjpeg__f2f( 1.501321110f)); + + /* rounding biases in column/row passes, see rjpeg__idct_block for explanation. */ + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + /* load */ + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + /* column pass */ + dct_pass(bias_0, 10); + + { + /* 16bit 8x8 transpose pass 1 */ + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + /* transpose pass 2 */ + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + /* transpose pass 3 */ + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + /* row pass */ + dct_pass(bias_1, 17); + + { + /* pack */ + __m128i p0 = _mm_packus_epi16(row0, row1); /* a0a1a2a3...a7b0b1b2b3...b7 */ + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + /* 8bit 8x8 transpose pass 1 */ + dct_interleave8(p0, p2); /* a0e0a1e1... */ + dct_interleave8(p1, p3); /* c0g0c1g1... */ + + /* transpose pass 2 */ + dct_interleave8(p0, p1); /* a0c0e0g0... */ + dct_interleave8(p2, p3); /* b0d0f0h0... */ + + /* transpose pass 3 */ + dct_interleave8(p0, p2); /* a0b0c0d0... */ + dct_interleave8(p1, p3); /* a4b4c4d4... */ + + /* store */ + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif + +#ifdef RJPEG_NEON + +/* NEON integer IDCT. should produce bit-identical + * results to the generic C version. */ +static void rjpeg__idct_simd(uint8_t *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(rjpeg__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(rjpeg__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(rjpeg__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(rjpeg__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(rjpeg__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(rjpeg__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(rjpeg__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(rjpeg__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(rjpeg__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(rjpeg__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(rjpeg__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(rjpeg__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +/* wide add */ +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +/* wide sub */ +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +/* butterfly a/b, then shift using "shiftop" by "s" and pack */ +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + /* load */ + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + /* add DC bias */ + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + /* column pass */ + dct_pass(vrshrn_n_s32, 10); + + /* 16bit 8x8 transpose */ + { +/* these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. + * whether compilers actually get this is another story, sadly. */ +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + /* pass 1 */ + dct_trn16(row0, row1); /* a0b0a2b2a4b4a6b6 */ + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + /* pass 2 */ + dct_trn32(row0, row2); /* a0b0c0d0a4b4c4d4 */ + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + /* pass 3 */ + dct_trn64(row0, row4); /* a0b0c0d0e0f0g0h0 */ + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + /* row pass + * vrshrn_n_s32 only supports shifts up to 16, we need + * 17. so do a non-rounding shift of 16 first then follow + * up with a rounding shift by 1. */ + dct_pass(vshrn_n_s32, 16); + + { + /* pack and round */ + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + /* again, these can translate into one instruction, but often don't. */ +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + /* sadly can't use interleaved stores here since we only write + * 8 bytes to each scan line! */ + + /* 8x8 8-bit transpose pass 1 */ + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + /* pass 2 */ + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + /* pass 3 */ + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + /* store */ + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif /* RJPEG_NEON */ + +static uint8_t rjpeg__get_marker(rjpeg__jpeg *j) +{ + uint8_t x; + if (j->marker != RJPEG__MARKER_none) + { + x = j->marker; + j->marker = RJPEG__MARKER_none; + return x; + } + + x = rjpeg__get8(j->s); + if (x != 0xff) + return RJPEG__MARKER_none; + while (x == 0xff) + x = rjpeg__get8(j->s); + return x; +} + + +/* after a restart interval, rjpeg__jpeg_reset the entropy decoder and + * the dc prediction + */ +static void rjpeg__jpeg_reset(rjpeg__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; + j->marker = RJPEG__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + /* no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + * since we don't even allow 1<<30 pixels */ +} + +static int rjpeg__parse_entropy_coded_data(rjpeg__jpeg *z) +{ + rjpeg__jpeg_reset(z); + if (!z->progressive) + { + if (z->scan_n == 1) + { + int i,j; + RJPEG_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + /* non-interleaved data, we just need to process one block at a time, + * in trivial scanline order + * number of blocks to do just depends on how many actual "pixels" this + * component has, independent of interleaved MCU blocking and such */ + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + + for (j=0; j < h; ++j) + { + for (i=0; i < w; ++i) + { + int ha = z->img_comp[n].ha; + if (!rjpeg__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + /* every data block is an MCU, so countdown the restart interval */ + if (--z->todo <= 0) + { + if (z->code_bits < 24) rjpeg__grow_buffer_unsafe(z); + /* if it's NOT a restart, then just bail, + * so we get corrupt data rather than no data */ + if (!RJPEG__RESTART(z->marker)) return 1; + rjpeg__jpeg_reset(z); + } + } + } + } + else + { + /* interleaved */ + int i,j,k,x,y; + RJPEG_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) + { + for (i=0; i < z->img_mcu_x; ++i) + { + /* scan an interleaved mcu... + * process scan_n components in order */ + for (k=0; k < z->scan_n; ++k) + { + int n = z->order[k]; + /* scan out an mcu's worth of this component; + * that's just determined by the basic H + * and V specified for the component */ + for (y=0; y < z->img_comp[n].v; ++y) + { + for (x=0; x < z->img_comp[n].h; ++x) + { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!rjpeg__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) + return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + /* after all interleaved components, that's an interleaved MCU, + * so now count down the restart interval */ + if (--z->todo <= 0) + { + if (z->code_bits < 24) rjpeg__grow_buffer_unsafe(z); + if (!RJPEG__RESTART(z->marker)) return 1; + rjpeg__jpeg_reset(z); + } + } + } + } + return 1; + } + else + { + if (z->scan_n == 1) + { + int i,j; + int n = z->order[0]; + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + + /* non-interleaved data, we just need to process one block at a time, + * in trivial scanline order + * number of blocks to do just depends on how many actual "pixels" this + * component has, independent of interleaved MCU blocking and such */ + + for (j=0; j < h; ++j) + { + for (i=0; i < w; ++i) + { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) + { + if (!rjpeg__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!rjpeg__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + + /* every data block is an MCU, so countdown the restart interval */ + if (--z->todo <= 0) + { + if (z->code_bits < 24) rjpeg__grow_buffer_unsafe(z); + if (!RJPEG__RESTART(z->marker)) return 1; + rjpeg__jpeg_reset(z); + } + } + } + } + else + { + /* interleaved */ + int i,j,k,x,y; + + for (j=0; j < z->img_mcu_y; ++j) + { + for (i=0; i < z->img_mcu_x; ++i) + { + /* scan an interleaved MCU... process scan_n components in order */ + for (k=0; k < z->scan_n; ++k) + { + int n = z->order[k]; + /* scan out an MCU's worth of this component; that's just determined + * by the basic H and V specified for the component */ + for (y=0; y < z->img_comp[n].v; ++y) + { + for (x=0; x < z->img_comp[n].h; ++x) + { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!rjpeg__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + /* after all interleaved components, that's an interleaved MCU, + * so now count down the restart interval */ + if (--z->todo <= 0) + { + if (z->code_bits < 24) rjpeg__grow_buffer_unsafe(z); + if (!RJPEG__RESTART(z->marker)) return 1; + rjpeg__jpeg_reset(z); + } + } + } + } + return 1; + } +} + +static void rjpeg__jpeg_dequantize(short *data, uint8_t *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void rjpeg__jpeg_finish(rjpeg__jpeg *z) +{ + if (z->progressive) + { + /* dequantize and IDCT the data */ + int i,j,n; + for (n=0; n < z->s->img_n; ++n) + { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) + { + for (i=0; i < w; ++i) + { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + rjpeg__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int rjpeg__process_marker(rjpeg__jpeg *z, int m) +{ + int L; + switch (m) + { + case RJPEG__MARKER_none: /* no marker found */ + return rjpeg__err("expected marker","Corrupt JPEG"); + + case 0xDD: /* DRI - specify restart interval */ + if (rjpeg__get16be(z->s) != 4) return rjpeg__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = rjpeg__get16be(z->s); + return 1; + + case 0xDB: /* DQT - define quantization table */ + L = rjpeg__get16be(z->s)-2; + while (L > 0) + { + int q = rjpeg__get8(z->s); + int p = q >> 4; + int t = q & 15,i; + if (p != 0) + return rjpeg__err("bad DQT type","Corrupt JPEG"); + if (t > 3) + return rjpeg__err("bad DQT table","Corrupt JPEG"); + for (i=0; i < 64; ++i) + z->dequant[t][rjpeg__jpeg_dezigzag[i]] = rjpeg__get8(z->s); + L -= 65; + } + return L==0; + + case 0xC4: /* DHT - define huffman table */ + L = rjpeg__get16be(z->s)-2; + while (L > 0) + { + int sizes[16],i,n=0; + uint8_t *v = NULL; + int q = rjpeg__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) + return rjpeg__err("bad DHT header","Corrupt JPEG"); + + for (i=0; i < 16; ++i) + { + sizes[i] = rjpeg__get8(z->s); + n += sizes[i]; + } + L -= 17; + + if (tc == 0) + { + if (!rjpeg__build_huffman(z->huff_dc+th, sizes)) + return 0; + v = z->huff_dc[th].values; + } + else + { + if (!rjpeg__build_huffman(z->huff_ac+th, sizes)) + return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = rjpeg__get8(z->s); + if (tc != 0) + rjpeg__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + + /* check for comment block or APP blocks */ + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) + { + rjpeg__skip(z->s, rjpeg__get16be(z->s)-2); + return 1; + } + return 0; +} + +/* after we see SOS */ +static int rjpeg__process_scan_header(rjpeg__jpeg *z) +{ + int i; + int Ls = rjpeg__get16be(z->s); + + z->scan_n = rjpeg__get8(z->s); + + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) + return rjpeg__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) + return rjpeg__err("bad SOS len","Corrupt JPEG"); + + for (i=0; i < z->scan_n; ++i) + { + int id = rjpeg__get8(z->s), which; + int q = rjpeg__get8(z->s); + + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) + return 0; /* no match */ + + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) + return rjpeg__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) + return rjpeg__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = rjpeg__get8(z->s); + z->spec_end = rjpeg__get8(z->s); /* should be 63, but might be 0 */ + aa = rjpeg__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) + { + if ( z->spec_start > 63 || + z->spec_end > 63 || + z->spec_start > z->spec_end || + z->succ_high > 13 || + z->succ_low > 13) + return rjpeg__err("bad SOS", "Corrupt JPEG"); + } + else + { + if (z->spec_start != 0) + return rjpeg__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) + return rjpeg__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int rjpeg__process_frame_header(rjpeg__jpeg *z, int scan) +{ + rjpeg__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = rjpeg__get16be(s); + + /* JPEG */ + if (Lf < 11) + return rjpeg__err("bad SOF len","Corrupt JPEG"); + + p = rjpeg__get8(s); + + /* JPEG baseline */ + if (p != 8) + return rjpeg__err("only 8-bit","JPEG format not supported: 8-bit only"); + + s->img_y = rjpeg__get16be(s); + + /* Legal, but we don't handle it--but neither does IJG */ + if (s->img_y == 0) + return rjpeg__err("no header height", "JPEG format not supported: delayed height"); + + s->img_x = rjpeg__get16be(s); + + if (s->img_x == 0) + return rjpeg__err("0 width","Corrupt JPEG"); /* JPEG requires */ + + c = rjpeg__get8(s); + + /* JFIF requires */ + if (c != 3 && c != 1) + return rjpeg__err("bad component count","Corrupt JPEG"); + + s->img_n = c; + + for (i=0; i < c; ++i) + { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) + return rjpeg__err("bad SOF len","Corrupt JPEG"); + + for (i=0; i < s->img_n; ++i) + { + z->img_comp[i].id = rjpeg__get8(s); + if (z->img_comp[i].id != i+1) /* JFIF requires */ + if (z->img_comp[i].id != i) /* some version of jpegtran outputs non-JFIF-compliant files! */ + return rjpeg__err("bad component ID","Corrupt JPEG"); + q = rjpeg__get8(s); + z->img_comp[i].h = (q >> 4); + if (!z->img_comp[i].h || z->img_comp[i].h > 4) + return rjpeg__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; + if (!z->img_comp[i].v || z->img_comp[i].v > 4) + return rjpeg__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = rjpeg__get8(s); + if (z->img_comp[i].tq > 3) + return rjpeg__err("bad TQ","Corrupt JPEG"); + } + + if (scan != RJPEG_SCAN_LOAD) return 1; + + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return rjpeg__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) + { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + /* compute interleaved MCU info */ + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) + { + /* number of effective pixels (e.g. for non-interleaved MCU) */ + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + /* to simplify generation, we'll allocate enough memory to decode + * the bogus oversized data from using interleaved MCUs and their + * big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + * discard the extra data until colorspace conversion */ + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].raw_data = malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); + + if (z->img_comp[i].raw_data == NULL) + { + for(--i; i >= 0; --i) + { + free(z->img_comp[i].raw_data); + z->img_comp[i].data = NULL; + } + return rjpeg__err("outofmem", "Out of memory"); + } + + /* align blocks for IDCT using MMX/SSE */ + z->img_comp[i].data = (uint8_t*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + z->img_comp[i].linebuf = NULL; + if (z->progressive) + { + z->img_comp[i].coeff_w = (z->img_comp[i].w2 + 7) >> 3; + z->img_comp[i].coeff_h = (z->img_comp[i].h2 + 7) >> 3; + z->img_comp[i].raw_coeff = malloc(z->img_comp[i].coeff_w * z->img_comp[i].coeff_h * 64 * sizeof(short) + 15); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } else { + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + } + } + + return 1; +} + + +static int rjpeg__decode_jpeg_header(rjpeg__jpeg *z, int scan) +{ + int m; + z->marker = RJPEG__MARKER_none; /* initialize cached marker to empty */ + m = rjpeg__get_marker(z); + + if (!rjpeg__SOI(m)) + return rjpeg__err("no SOI","Corrupt JPEG"); + + if (scan == RJPEG_SCAN_TYPE) + return 1; + + m = rjpeg__get_marker(z); + while (!rjpeg__SOF(m)) + { + if (!rjpeg__process_marker(z,m)) + return 0; + m = rjpeg__get_marker(z); + while (m == RJPEG__MARKER_none) + { + /* some files have extra padding after their blocks, so ok, we'll scan */ + if (rjpeg__at_eof(z->s)) + return rjpeg__err("no SOF", "Corrupt JPEG"); + m = rjpeg__get_marker(z); + } + } + z->progressive = rjpeg__SOF_progressive(m); + if (!rjpeg__process_frame_header(z, scan)) return 0; + return 1; +} + +/* decode image to YCbCr format */ +static int rjpeg__decode_jpeg_image(rjpeg__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) + { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!rjpeg__decode_jpeg_header(j, RJPEG_SCAN_LOAD)) + return 0; + m = rjpeg__get_marker(j); + + while (!rjpeg__EOI(m)) + { + if (rjpeg__SOS(m)) + { + if (!rjpeg__process_scan_header(j)) + return 0; + if (!rjpeg__parse_entropy_coded_data(j)) + return 0; + + if (j->marker == RJPEG__MARKER_none ) + { + /* handle 0s at the end of image data from IP Kamera 9060 */ + while (!rjpeg__at_eof(j->s)) + { + int x = rjpeg__get8(j->s); + if (x == 255) + { + j->marker = rjpeg__get8(j->s); + break; + } + else if (x != 0) + return rjpeg__err("junk before marker", "Corrupt JPEG"); + } + /* if we reach eof without hitting a marker, rjpeg__get_marker() below will fail and we'll eventually return 0 */ + } + } + else + { + if (!rjpeg__process_marker(j, m)) + return 0; + } + m = rjpeg__get_marker(j); + } + + if (j->progressive) + rjpeg__jpeg_finish(j); + return 1; +} + +/* static jfif-centered resampling (across block boundaries) */ + +static uint8_t *rjpeg_resample_row_1(uint8_t *out, uint8_t *in_near, uint8_t *in_far, int w, int hs) +{ + (void)out; + (void)in_far; + (void)w; + (void)hs; + return in_near; +} + +static uint8_t* rjpeg__resample_row_v_2(uint8_t *out, uint8_t *in_near, uint8_t *in_far, int w, int hs) +{ + /* need to generate two samples vertically for every one in input */ + int i; + (void)hs; + for (i=0; i < w; ++i) + out[i] = rjpeg__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static uint8_t* rjpeg__resample_row_h_2(uint8_t *out, uint8_t *in_near, uint8_t *in_far, int w, int hs) +{ + /* need to generate two samples horizontally for every one in input */ + int i; + uint8_t *input = in_near; + + if (w == 1) + { + /* if only one sample, can't do any interpolation */ + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = rjpeg__div4(input[0]*3 + input[1] + 2); + + for (i=1; i < w-1; ++i) + { + int n = 3*input[i]+2; + out[i*2+0] = rjpeg__div4(n+input[i-1]); + out[i*2+1] = rjpeg__div4(n+input[i+1]); + } + out[i*2+0] = rjpeg__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + (void)in_far; + (void)hs; + + return out; +} + + +static uint8_t *rjpeg__resample_row_hv_2(uint8_t *out, uint8_t *in_near, uint8_t *in_far, int w, int hs) +{ + /* need to generate 2x2 samples for every one in input */ + int i,t0,t1; + if (w == 1) + { + out[0] = out[1] = rjpeg__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = rjpeg__div4(t1+2); + for (i=1; i < w; ++i) + { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = rjpeg__div16(3*t0 + t1 + 8); + out[i*2 ] = rjpeg__div16(3*t1 + t0 + 8); + } + out[w*2-1] = rjpeg__div4(t1+2); + + (void)hs; + + return out; +} + +#if defined(__SSE2__) || defined(RJPEG_NEON) +static uint8_t *rjpeg__resample_row_hv_2_simd(uint8_t *out, uint8_t *in_near, uint8_t *in_far, int w, int hs) +{ + /* need to generate 2x2 samples for every one in input */ + int i=0,t0,t1; + + if (w == 1) + { + out[0] = out[1] = rjpeg__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + /* process groups of 8 pixels for as long as we can. + * note we can't handle the last pixel in a row in this loop + * because we need to handle the filter boundary conditions. + */ + for (; i < ((w-1) & ~7); i += 8) + { +#if defined(__SSE2__) + /* load and perform the vertical filtering pass + * this uses 3*x + y = 4*x + (y - x) */ + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); /* current row */ + + /* horizontal filter works the same based on shifted vers of current + * row. "prev" is current row shifted right by 1 pixel; we need to + * insert the previous pixel value (from t1). + * "next" is current row shifted left by 1 pixel, with first pixel + * of next block of 8 pixels added in. + */ + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + /* horizontal filter, polyphase implementation since it's convenient: + * even pixels = 3*cur + prev = cur*4 + (prev - cur) + * odd pixels = 3*cur + next = cur*4 + (next - cur) + * note the shared term. */ + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + /* interleave even and odd pixels, then undo scaling. */ + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + /* pack and write output */ + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(RJPEG_NEON) + /* load and perform the vertical filtering pass + * this uses 3*x + y = 4*x + (y - x) */ + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); /* current row */ + + /* horizontal filter works the same based on shifted vers of current + * row. "prev" is current row shifted right by 1 pixel; we need to + * insert the previous pixel value (from t1). + * "next" is current row shifted left by 1 pixel, with first pixel + * of next block of 8 pixels added in. */ + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + /* horizontal filter, polyphase implementation since it's convenient: + * even pixels = 3*cur + prev = cur*4 + (prev - cur) + * odd pixels = 3*cur + next = cur*4 + (next - cur) + * note the shared term. + */ + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + /* undo scaling and round, then store with even/odd phases interleaved */ + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + /* "previous" value for next iteration */ + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = rjpeg__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) + { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = rjpeg__div16(3*t0 + t1 + 8); + out[i*2 ] = rjpeg__div16(3*t1 + t0 + 8); + } + out[w*2-1] = rjpeg__div4(t1+2); + + (void)hs; + + return out; +} +#endif + +static uint8_t *rjpeg__resample_row_generic(uint8_t *out, uint8_t *in_near, uint8_t *in_far, int w, int hs) +{ + /* resample with nearest-neighbor */ + int i,j; + (void)in_far; + + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +/* this is a reduced-precision calculation of YCbCr-to-RGB introduced + * to make sure the code produces the same results in both SIMD and scalar */ +#ifndef float2fixed +#define float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +#endif + +static void rjpeg__YCbCr_to_RGB_row(uint8_t *out, const uint8_t *y, const uint8_t *pcb, const uint8_t *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) + { + int y_fixed = (y[i] << 20) + (1<<19); /* rounding */ + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + int r = y_fixed + cr* float2fixed(1.40200f); + int g = y_fixed + (cr*-float2fixed(0.71414f)) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); + int b = y_fixed + cb* float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) + r = 255; + if ((unsigned) g > 255) + g = 255; + if ((unsigned) b > 255) + b = 255; + out[0] = (uint8_t)r; + out[1] = (uint8_t)g; + out[2] = (uint8_t)b; + out[3] = 255; + out += step; + } +} + +#if defined(__SSE2__) || defined(RJPEG_NEON) +static void rjpeg__YCbCr_to_RGB_simd(uint8_t *out, const uint8_t *y, const uint8_t *pcb, const uint8_t *pcr, int count, int step) +{ + int i = 0; + +#if defined(__SSE2__) + /* step == 3 is pretty ugly on the final interleave, and i'm not convinced + * it's useful in practice (you wouldn't use it for textures, for example). + * so just accelerate step == 4 case. + */ + if (step == 4) + { + /* this is a fairly straightforward implementation and not super-optimized. */ + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); /* alpha channel */ + + for (; i+7 < count; i += 8) + { + /* load */ + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); /* -128 */ + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); /* -128 */ + + /* unpack to short (and left-shift cr, cb by 8) */ + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + /* color transform */ + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + /* descale */ + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + /* back to byte, set up for transpose */ + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + /* transpose to interleave channels */ + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + /* store */ + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef RJPEG_NEON + /* in this version, step=3 support would be easy to add. but is there demand? */ + if (step == 4) + { + /* this is a fairly straightforward implementation and not super-optimized. */ + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) + { + uint8x8x4_t o; + + /* load */ + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + /* expand to s16 */ + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + /* color transform */ + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + /* undo scaling, round, convert to byte */ + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + /* store, interleaving r/g/b/a */ + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) + { + int y_fixed = (y[i] << 20) + (1<<19); /* rounding */ + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + int r = y_fixed + cr* float2fixed(1.40200f); + int g = y_fixed + cr*-float2fixed(0.71414f) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); + int b = y_fixed + cb* float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) + r = 255; + if ((unsigned) g > 255) + g = 255; + if ((unsigned) b > 255) + b = 255; + out[0] = (uint8_t)r; + out[1] = (uint8_t)g; + out[2] = (uint8_t)b; + out[3] = 255; + out += step; + } +} +#endif + +/* set up the kernels */ +static void rjpeg__setup_jpeg(rjpeg__jpeg *j) +{ + uint64_t mask = cpu_features_get(); + + (void)mask; + + j->idct_block_kernel = rjpeg__idct_block; + j->YCbCr_to_RGB_kernel = rjpeg__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = rjpeg__resample_row_hv_2; + + +#if defined(__SSE2__) + if (mask & RETRO_SIMD_SSE2) + { + j->idct_block_kernel = rjpeg__idct_simd; + j->YCbCr_to_RGB_kernel = rjpeg__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = rjpeg__resample_row_hv_2_simd; + } +#endif + +#ifdef RJPEG_NEON + j->idct_block_kernel = rjpeg__idct_simd; + j->YCbCr_to_RGB_kernel = rjpeg__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = rjpeg__resample_row_hv_2_simd; +#endif +} + +/* clean up the temporary component buffers */ +static void rjpeg__cleanup_jpeg(rjpeg__jpeg *j) +{ + int i; + for (i=0; i < j->s->img_n; ++i) + { + if (j->img_comp[i].raw_data) + { + free(j->img_comp[i].raw_data); + j->img_comp[i].raw_data = NULL; + j->img_comp[i].data = NULL; + } + + if (j->img_comp[i].raw_coeff) + { + free(j->img_comp[i].raw_coeff); + j->img_comp[i].raw_coeff = 0; + j->img_comp[i].coeff = 0; + } + + if (j->img_comp[i].linebuf) + { + free(j->img_comp[i].linebuf); + j->img_comp[i].linebuf = NULL; + } + } +} + +static uint8_t *rjpeg_load_jpeg_image(rjpeg__jpeg *z, unsigned *out_x, unsigned *out_y, int *comp, int req_comp) +{ + int n, decode_n; + int k; + unsigned int i,j; + rjpeg__resample res_comp[4]; + uint8_t *coutput[4] = {0}; + uint8_t *output = NULL; + z->s->img_n = 0; /* make rjpeg__cleanup_jpeg safe */ + + /* validate req_comp */ + if (req_comp < 0 || req_comp > 4) + return rjpeg__errpuc("bad req_comp", "Internal error"); + + /* load a jpeg image from whichever source, but leave in YCbCr format */ + if (!rjpeg__decode_jpeg_image(z)) + goto error; + + /* determine actual number of components to generate */ + n = req_comp ? req_comp : z->s->img_n; + + if (z->s->img_n == 3 && n < 3) + decode_n = 1; + else + decode_n = z->s->img_n; + + /* resample and color-convert */ + for (k=0; k < decode_n; ++k) + { + rjpeg__resample *r = &res_comp[k]; + + /* allocate line buffer big enough for upsampling off the edges + * with upsample factor of 4 */ + z->img_comp[k].linebuf = (uint8_t *) malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) + goto error; + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + r->resample = rjpeg__resample_row_generic; + + if (r->hs == 1 && r->vs == 1) + r->resample = rjpeg_resample_row_1; + else if (r->hs == 1 && r->vs == 2) + r->resample = rjpeg__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) + r->resample = rjpeg__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) + r->resample = z->resample_row_hv_2_kernel; + } + + /* can't error after this so, this is safe */ + output = (uint8_t *) malloc(n * z->s->img_x * z->s->img_y + 1); + + if (!output) + goto error; + + /* now go ahead and resample */ + for (j=0; j < z->s->img_y; ++j) + { + uint8_t *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) + { + rjpeg__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + + if (++r->ystep >= r->vs) + { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + + if (n >= 3) + { + uint8_t *y = coutput[0]; + if (z->s->img_n == 3) + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + else + for (i=0; i < z->s->img_x; ++i) + { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; /* not used if n==3 */ + out += n; + } + } + else + { + uint8_t *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) + *out++ = y[i], *out++ = 255; + } + } + + rjpeg__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + + if (comp) + *comp = z->s->img_n; /* report original components, not output */ + return output; + +error: + rjpeg__cleanup_jpeg(z); + return NULL; +} + +static unsigned char *rjpeg__jpeg_load(rjpeg__context *s, unsigned *x, unsigned *y, int *comp, int req_comp) +{ + rjpeg__jpeg j; + j.s = s; + rjpeg__setup_jpeg(&j); + return rjpeg_load_jpeg_image(&j, x,y,comp,req_comp); +} + +int rjpeg_process_image(rjpeg_t *rjpeg, void **buf_data, + size_t size, unsigned *width, unsigned *height) +{ + int comp; + uint32_t *img = NULL; + uint32_t *pixels = NULL; + unsigned size_tex = 0; + + if (!rjpeg) + return IMAGE_PROCESS_ERROR; + + img = (uint32_t*)rjpeg_load_from_memory(rjpeg->buff_data, size, width, height, &comp, 4); + + if (!img) + return IMAGE_PROCESS_ERROR; + + size_tex = (*width) * (*height); + pixels = (uint32_t*)malloc(size_tex * sizeof(uint32_t)); + + if (!pixels) + { + free(img); + return IMAGE_PROCESS_ERROR; + } + + *buf_data = pixels; + + /* Convert RGBA to ARGB */ + while (size_tex--) + { + unsigned int texel = img[size_tex]; + unsigned int A = texel & 0xFF000000; + unsigned int B = texel & 0x00FF0000; + unsigned int G = texel & 0x0000FF00; + unsigned int R = texel & 0x000000FF; + ((unsigned int*)pixels)[size_tex] = A | (R << 16) | G | (B >> 16); + }; + + free(img); + + return IMAGE_PROCESS_END; +} + +bool rjpeg_set_buf_ptr(rjpeg_t *rjpeg, void *data) +{ + if (!rjpeg) + return false; + + rjpeg->buff_data = (uint8_t*)data; + + return true; +} + +void rjpeg_free(rjpeg_t *rjpeg) +{ + if (!rjpeg) + return; + + free(rjpeg); +} + +rjpeg_t *rjpeg_alloc(void) +{ + rjpeg_t *rjpeg = (rjpeg_t*)calloc(1, sizeof(*rjpeg)); + if (!rjpeg) + return NULL; + return rjpeg; +} diff --git a/desmume/src/libretro-common/formats/png/rpng.c b/desmume/src/libretro-common/formats/png/rpng.c index fb15c7e22..47abc04e4 100644 --- a/desmume/src/libretro-common/formats/png/rpng.c +++ b/desmume/src/libretro-common/formats/png/rpng.c @@ -30,7 +30,7 @@ #endif #include -#include +#include #include #include @@ -61,6 +61,7 @@ enum png_chunk_type PNG_CHUNK_IHDR, PNG_CHUNK_IDAT, PNG_CHUNK_PLTE, + PNG_CHUNK_tRNS, PNG_CHUNK_IEND }; @@ -85,9 +86,8 @@ struct png_chunk uint8_t *data; }; -struct rpng_process_t +struct rpng_process { - bool initialized; bool inflate_initialized; bool adam7_pass_initialized; bool pass_initialized; @@ -117,25 +117,18 @@ struct rpng_process_t struct rpng { - struct rpng_process_t process; + struct rpng_process *process; bool has_ihdr; bool has_idat; bool has_iend; bool has_plte; + bool has_trns; struct idat_buffer idat_buf; struct png_ihdr ihdr; uint8_t *buff_data; uint32_t palette[256]; }; -enum png_process_code -{ - PNG_PROCESS_ERROR = -2, - PNG_PROCESS_ERROR_END = -1, - PNG_PROCESS_NEXT = 0, - PNG_PROCESS_END = 1 -}; - static INLINE uint32_t dword_be(const uint8_t *buf) { return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3] << 0); @@ -153,6 +146,7 @@ static enum png_chunk_type png_chunk_type(const struct png_chunk *chunk) { "IDAT", PNG_CHUNK_IDAT }, { "IEND", PNG_CHUNK_IEND }, { "PLTE", PNG_CHUNK_PLTE }, + { "tRNS", PNG_CHUNK_tRNS }, }; for (i = 0; i < ARRAY_SIZE(chunk_map); i++) @@ -333,18 +327,100 @@ static void png_reverse_filter_copy_line_plt(uint32_t *data, const uint8_t *decoded, unsigned width, unsigned depth, const uint32_t *palette) { - unsigned i, bit; - unsigned mask = (1 << depth) - 1; - - bit = 0; - - for (i = 0; i < width; i++, bit += depth) + switch (depth) { - unsigned byte = bit >> 3; - unsigned val = decoded[byte] >> (8 - depth - (bit & 7)); - - val &= mask; - data[i] = palette[val]; + case 1: + { + unsigned w = width / 8; + unsigned i; + + for (i = 0; i < w; i++, decoded++) + { + *data++ = palette[(*decoded >> 7) & 1]; + *data++ = palette[(*decoded >> 6) & 1]; + *data++ = palette[(*decoded >> 5) & 1]; + *data++ = palette[(*decoded >> 4) & 1]; + *data++ = palette[(*decoded >> 3) & 1]; + *data++ = palette[(*decoded >> 2) & 1]; + *data++ = palette[(*decoded >> 1) & 1]; + *data++ = palette[*decoded & 1]; + } + + switch (width & 7) + { + case 7: + data[6] = palette[(*decoded >> 1) & 1]; + case 6: + data[5] = palette[(*decoded >> 2) & 1]; + case 5: + data[4] = palette[(*decoded >> 3) & 1]; + case 4: + data[3] = palette[(*decoded >> 4) & 1]; + case 3: + data[2] = palette[(*decoded >> 5) & 1]; + case 2: + data[1] = palette[(*decoded >> 6) & 1]; + case 1: + data[0] = palette[(*decoded >> 7) & 1]; + break; + } + } + break; + + case 2: + { + unsigned w = width / 4; + unsigned i; + + for (i = 0; i < w; i++, decoded++) + { + *data++ = palette[(*decoded >> 6) & 3]; + *data++ = palette[(*decoded >> 4) & 3]; + *data++ = palette[(*decoded >> 2) & 3]; + *data++ = palette[*decoded & 3]; + } + + switch (width & 3) + { + case 3: + data[2] = palette[(*decoded >> 2) & 3]; + case 2: + data[1] = palette[(*decoded >> 4) & 3]; + case 1: + data[0] = palette[(*decoded >> 6) & 3]; + break; + } + } + break; + + case 4: + { + unsigned w = width / 2; + unsigned i; + + for (i = 0; i < w; i++, decoded++) + { + *data++ = palette[*decoded >> 4]; + *data++ = palette[*decoded & 0x0f]; + } + + if (width & 1) + { + *data = palette[*decoded >> 4]; + } + } + break; + + case 8: + { + unsigned i; + + for (i = 0; i < width; i++, decoded++, data++) + { + *data = palette[*decoded]; + } + } + break; } } @@ -410,7 +486,7 @@ static void png_reverse_filter_adam7_deinterlace_pass(uint32_t *data, } } -static void png_reverse_filter_deinit(struct rpng_process_t *pngp) +static void png_reverse_filter_deinit(struct rpng_process *pngp) { if (pngp->decoded_scanline) free(pngp->decoded_scanline); @@ -434,7 +510,7 @@ static const struct adam7_pass passes[] = { }; static int png_reverse_filter_init(const struct png_ihdr *ihdr, - struct rpng_process_t *pngp) + struct rpng_process *pngp) { size_t pass_size; @@ -500,7 +576,7 @@ error: } static int png_reverse_filter_copy_line(uint32_t *data, const struct png_ihdr *ihdr, - struct rpng_process_t *pngp, unsigned filter) + struct rpng_process *pngp, unsigned filter) { unsigned i; @@ -540,7 +616,7 @@ static int png_reverse_filter_copy_line(uint32_t *data, const struct png_ihdr *i break; default: - return PNG_PROCESS_ERROR_END; + return IMAGE_PROCESS_ERROR_END; } switch (ihdr->color_type) @@ -566,13 +642,13 @@ static int png_reverse_filter_copy_line(uint32_t *data, const struct png_ihdr *i memcpy(pngp->prev_scanline, pngp->decoded_scanline, pngp->pitch); - return PNG_PROCESS_NEXT; + return IMAGE_PROCESS_NEXT; } static int png_reverse_filter_regular_iterate(uint32_t **data, const struct png_ihdr *ihdr, - struct rpng_process_t *pngp) + struct rpng_process *pngp) { - int ret = PNG_PROCESS_END; + int ret = IMAGE_PROCESS_END; if (pngp->h < ihdr->height) { @@ -582,7 +658,7 @@ static int png_reverse_filter_regular_iterate(uint32_t **data, const struct png_ ihdr, pngp, filter); } - if (ret == PNG_PROCESS_END || ret == PNG_PROCESS_ERROR_END) + if (ret == IMAGE_PROCESS_END || ret == IMAGE_PROCESS_ERROR_END) goto end; pngp->h++; @@ -592,7 +668,7 @@ static int png_reverse_filter_regular_iterate(uint32_t **data, const struct png_ *data += ihdr->width; pngp->data_restore_buf_size += ihdr->width; - return PNG_PROCESS_NEXT; + return IMAGE_PROCESS_NEXT; end: png_reverse_filter_deinit(pngp); @@ -605,32 +681,32 @@ end: static int png_reverse_filter_adam7_iterate(uint32_t **data_, const struct png_ihdr *ihdr, - struct rpng_process_t *pngp) + struct rpng_process *pngp) { int ret = 0; bool to_next = pngp->pass.pos < ARRAY_SIZE(passes); uint32_t *data = *data_; if (!to_next) - return PNG_PROCESS_END; + return IMAGE_PROCESS_END; ret = png_reverse_filter_init(ihdr, pngp); if (ret == 1) - return PNG_PROCESS_NEXT; + return IMAGE_PROCESS_NEXT; if (ret == -1) - return PNG_PROCESS_ERROR_END; + return IMAGE_PROCESS_ERROR_END; if (png_reverse_filter_init(&pngp->ihdr, pngp) == -1) - return PNG_PROCESS_ERROR; + return IMAGE_PROCESS_ERROR; do{ ret = png_reverse_filter_regular_iterate(&pngp->data, &pngp->ihdr, pngp); - }while(ret == PNG_PROCESS_NEXT); + }while(ret == IMAGE_PROCESS_NEXT); - if (ret == PNG_PROCESS_ERROR || ret == PNG_PROCESS_ERROR_END) - return PNG_PROCESS_ERROR; + if (ret == IMAGE_PROCESS_ERROR || ret == IMAGE_PROCESS_ERROR_END) + return IMAGE_PROCESS_ERROR; pngp->inflate_buf += pngp->pass.size; pngp->adam7_restore_buf_size += pngp->pass.size; @@ -647,25 +723,25 @@ static int png_reverse_filter_adam7_iterate(uint32_t **data_, pngp->pass.size = 0; pngp->adam7_pass_initialized = false; - return PNG_PROCESS_NEXT; + return IMAGE_PROCESS_NEXT; } static int png_reverse_filter_adam7(uint32_t **data_, const struct png_ihdr *ihdr, - struct rpng_process_t *pngp) + struct rpng_process *pngp) { int ret = png_reverse_filter_adam7_iterate(data_, ihdr, pngp); switch (ret) { - case PNG_PROCESS_ERROR_END: - case PNG_PROCESS_END: + case IMAGE_PROCESS_ERROR_END: + case IMAGE_PROCESS_END: break; - case PNG_PROCESS_NEXT: + case IMAGE_PROCESS_NEXT: pngp->pass.pos++; return 0; - case PNG_PROCESS_ERROR: + case IMAGE_PROCESS_ERROR: if (pngp->data) free(pngp->data); pngp->inflate_buf -= pngp->adam7_restore_buf_size; @@ -684,22 +760,23 @@ static int png_reverse_filter_iterate(rpng_t *rpng, uint32_t **data) return false; if (rpng->ihdr.interlace) - return png_reverse_filter_adam7(data, &rpng->ihdr, &rpng->process); + return png_reverse_filter_adam7(data, &rpng->ihdr, rpng->process); - return png_reverse_filter_regular_iterate(data, &rpng->ihdr, &rpng->process); + return png_reverse_filter_regular_iterate(data, &rpng->ihdr, rpng->process); } static int rpng_load_image_argb_process_inflate_init(rpng_t *rpng, uint32_t **data, unsigned *width, unsigned *height) { int zstatus; - 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); + struct rpng_process *process = (struct rpng_process*)rpng->process; + bool to_continue = (process->stream_backend->stream_get_avail_in(process->stream) > 0 + && process->stream_backend->stream_get_avail_out(process->stream) > 0); if (!to_continue) goto end; - zstatus = rpng->process.stream_backend->stream_decompress_data_to_file_iterate(rpng->process.stream); + zstatus = process->stream_backend->stream_decompress_data_to_file_iterate(process->stream); switch (zstatus) { @@ -714,7 +791,7 @@ static int rpng_load_image_argb_process_inflate_init(rpng_t *rpng, return 0; end: - rpng->process.stream_backend->stream_free(rpng->process.stream); + process->stream_backend->stream_free(process->stream); *width = rpng->ihdr.width; *height = rpng->ihdr.height; @@ -729,22 +806,20 @@ end: if (!*data) goto false_end; - rpng->process.adam7_restore_buf_size = 0; - rpng->process.restore_buf_size = 0; - rpng->process.palette = rpng->palette; + process->adam7_restore_buf_size = 0; + process->restore_buf_size = 0; + process->palette = rpng->palette; if (rpng->ihdr.interlace != 1) - if (png_reverse_filter_init(&rpng->ihdr, &rpng->process) == -1) + if (png_reverse_filter_init(&rpng->ihdr, process) == -1) goto false_end; - rpng->process.inflate_initialized = true; + process->inflate_initialized = true; return 1; error: - rpng->process.stream_backend->stream_free(rpng->process.stream); - false_end: - rpng->process.inflate_initialized = false; + process->inflate_initialized = false; return -1; } @@ -764,6 +839,18 @@ static bool png_read_plte(uint8_t *buf, return true; } +static bool png_read_trns(uint8_t *buf, uint32_t *palette, unsigned entries) +{ + unsigned i; + + for (i = 0; i < entries; i++, buf++, palette++) + { + *palette = (*palette & 0x00ffffff) | *buf << 24; + } + + return true; +} + bool png_realloc_idat(const struct png_chunk *chunk, struct idat_buffer *buf) { uint8_t *new_buffer = (uint8_t*)realloc(buf->data, buf->size + chunk->size); @@ -775,39 +862,57 @@ bool png_realloc_idat(const struct png_chunk *chunk, struct idat_buffer *buf) return true; } -static bool rpng_load_image_argb_process_init(rpng_t *rpng, - uint32_t **data, unsigned *width, unsigned *height) +static struct rpng_process *rpng_process_init(rpng_t *rpng, unsigned *width, unsigned *height) { - rpng->process.inflate_buf_size = 0; - rpng->process.inflate_buf = NULL; + uint8_t *inflate_buf = NULL; + struct rpng_process *process = (struct rpng_process*)calloc(1, sizeof(*process)); + + if (!process) + return NULL; + + process->stream_backend = file_archive_get_default_file_backend(); png_pass_geom(&rpng->ihdr, rpng->ihdr.width, - rpng->ihdr.height, NULL, NULL, &rpng->process.inflate_buf_size); + rpng->ihdr.height, NULL, NULL, &process->inflate_buf_size); if (rpng->ihdr.interlace == 1) /* To be sure. */ - rpng->process.inflate_buf_size *= 2; + process->inflate_buf_size *= 2; - rpng->process.stream = rpng->process.stream_backend->stream_new(); + process->stream = process->stream_backend->stream_new(); - if (!rpng->process.stream) - return false; + if (!process->stream) + { + free(process); + return NULL; + } - if (!rpng->process.stream_backend->stream_decompress_init(rpng->process.stream)) - return false; + if (!process->stream_backend->stream_decompress_init(process->stream)) + { + free(process); + return NULL; + } - rpng->process.inflate_buf = (uint8_t*)malloc(rpng->process.inflate_buf_size); - if (!rpng->process.inflate_buf) - return false; + inflate_buf = (uint8_t*)malloc(process->inflate_buf_size); + if (!inflate_buf) + goto error; - rpng->process.stream_backend->stream_set( - rpng->process.stream, + process->inflate_buf = inflate_buf; + process->stream_backend->stream_set( + process->stream, rpng->idat_buf.size, - rpng->process.inflate_buf_size, + process->inflate_buf_size, rpng->idat_buf.data, - rpng->process.inflate_buf); + process->inflate_buf); - rpng->process.initialized = true; + return process; - return true; +error: + if (process) + { + if (process->stream) + process->stream_backend->stream_free(process->stream); + free(process); + } + return NULL; } static bool read_chunk_header(uint8_t *buf, struct png_chunk *chunk) @@ -818,14 +923,10 @@ static bool read_chunk_header(uint8_t *buf, struct png_chunk *chunk) for (i = 0; i < 4; i++) dword[i] = buf[i]; - buf += 4; - chunk->size = dword_be(dword); for (i = 0; i < 4; i++) - chunk->type[i] = buf[i]; - - buf += 4; + chunk->type[i] = buf[i + 4]; return true; } @@ -849,17 +950,17 @@ static bool png_parse_ihdr(uint8_t *buf, return true; } -bool rpng_nbio_load_image_argb_iterate(rpng_t *rpng) +bool rpng_iterate_image(rpng_t *rpng) { unsigned i; - unsigned ret; - uint8_t *buf = (uint8_t*)rpng->buff_data; - struct png_chunk chunk = {0}; + uint8_t *buf = (uint8_t*)rpng->buff_data; if (!read_chunk_header(buf, &chunk)) return false; + *buf += 8; + #if 0 for (i = 0; i < 4; i++) { @@ -896,7 +997,7 @@ bool rpng_nbio_load_image_argb_iterate(rpng_t *rpng) { unsigned entries = chunk.size / 3; - if (!rpng->has_ihdr || rpng->has_plte || rpng->has_iend || rpng->has_idat) + if (!rpng->has_ihdr || rpng->has_plte || rpng->has_iend || rpng->has_idat || rpng->has_trns) goto error; if (chunk.size % 3) @@ -914,6 +1015,26 @@ bool rpng_nbio_load_image_argb_iterate(rpng_t *rpng) } break; + case PNG_CHUNK_tRNS: + if (rpng->has_idat) + goto error; + + if (rpng->ihdr.color_type == PNG_IHDR_COLOR_PLT) + { + /* we should compare with the number of palette entries */ + if (chunk.size > 256) + goto error; + + buf += 8; + + if (!png_read_trns(buf, rpng->palette, chunk.size)) + goto error; + } + /* TODO: support colorkey in grayscale and truecolor images */ + + rpng->has_trns = true; + break; + case PNG_CHUNK_IDAT: if (!(rpng->has_ihdr) || rpng->has_iend || (rpng->ihdr.color_type == PNG_IHDR_COLOR_PLT && !(rpng->has_plte))) goto error; @@ -939,8 +1060,7 @@ bool rpng_nbio_load_image_argb_iterate(rpng_t *rpng) goto error; } - ret = 4 + 4 + chunk.size + 4; - rpng->buff_data += ret; + rpng->buff_data += chunk.size + 12; return true; @@ -948,51 +1068,71 @@ error: return false; } -int rpng_nbio_load_image_argb_process(rpng_t *rpng, - uint32_t **data, unsigned *width, unsigned *height) +int rpng_process_image(rpng_t *rpng, + void **_data, size_t size, unsigned *width, unsigned *height) { - if (!rpng->process.initialized) - { - if (!rpng->process.stream_backend) - rpng->process.stream_backend = file_archive_get_default_file_backend(); + uint32_t **data = (uint32_t**)_data; - if (!rpng_load_image_argb_process_init(rpng, data, width, - height)) - return PNG_PROCESS_ERROR; - return 0; + (void)size; + + if (!rpng->process) + { + struct rpng_process *process = rpng_process_init( + rpng, width, height); + + if (!process) + goto error; + + rpng->process = process; + return IMAGE_PROCESS_NEXT; } - if (!rpng->process.inflate_initialized) + if (!rpng->process->inflate_initialized) { - int ret = rpng_load_image_argb_process_inflate_init(rpng, data, - width, height); - if (ret == -1) - return PNG_PROCESS_ERROR; - return 0; + if (rpng_load_image_argb_process_inflate_init(rpng, data, + width, height) == -1) + goto error; + return IMAGE_PROCESS_NEXT; } return png_reverse_filter_iterate(rpng, data); + +error: + if (rpng->process) + { + if (rpng->process->inflate_buf) + free(rpng->process->inflate_buf); + if (rpng->process->stream) + rpng->process->stream_backend->stream_free(rpng->process->stream); + free(rpng->process); + } + return IMAGE_PROCESS_ERROR; } -void rpng_nbio_load_image_free(rpng_t *rpng) +void rpng_free(rpng_t *rpng) { if (!rpng) return; if (rpng->idat_buf.data) free(rpng->idat_buf.data); - if (rpng->process.inflate_buf) - free(rpng->process.inflate_buf); - if (rpng->process.stream) + if (rpng->process) { - rpng->process.stream_backend->stream_free(rpng->process.stream); - free(rpng->process.stream); + if (rpng->process->inflate_buf) + free(rpng->process->inflate_buf); + if (rpng->process->stream) + { + if (rpng->process->stream_backend) + rpng->process->stream_backend->stream_free(rpng->process->stream); + free(rpng->process->stream); + } + free(rpng->process); } free(rpng); } -bool rpng_nbio_load_image_argb_start(rpng_t *rpng) +bool rpng_start(rpng_t *rpng) { unsigned i; char header[8] = {0}; @@ -1025,12 +1165,12 @@ bool rpng_is_valid(rpng_t *rpng) return false; } -bool rpng_set_buf_ptr(rpng_t *rpng, uint8_t *data) +bool rpng_set_buf_ptr(rpng_t *rpng, void *data) { if (!rpng) return false; - rpng->buff_data = data; + rpng->buff_data = (uint8_t*)data; return true; } @@ -1042,77 +1182,3 @@ rpng_t *rpng_alloc(void) return NULL; return rpng; } - -bool rpng_load_image_argb(const char *path, uint32_t **data, - unsigned *width, unsigned *height) -{ - int retval; - size_t file_len; - bool ret = true; - rpng_t *rpng = NULL; - void *ptr = NULL; - struct nbio_t* handle = (struct nbio_t*)nbio_open(path, NBIO_READ); - - if (!handle) - goto end; - - ptr = nbio_get_ptr(handle, &file_len); - - nbio_begin_read(handle); - - while (!nbio_iterate(handle)); - - ptr = nbio_get_ptr(handle, &file_len); - - if (!ptr) - { - ret = false; - goto end; - } - - rpng = rpng_alloc(); - - if (!rpng) - { - ret = false; - goto end; - } - - if (!rpng_set_buf_ptr(rpng, (uint8_t*)ptr)) - { - ret = false; - goto end; - } - - if (!rpng_nbio_load_image_argb_start(rpng)) - { - ret = false; - goto end; - } - - while (rpng_nbio_load_image_argb_iterate(rpng)); - - if (!rpng_is_valid(rpng)) - { - ret = false; - goto end; - } - - do - { - retval = rpng_nbio_load_image_argb_process(rpng, data, width, height); - }while(retval == PNG_PROCESS_NEXT); - - if (retval == PNG_PROCESS_ERROR || retval == PNG_PROCESS_ERROR_END) - ret = false; - -end: - if (handle) - nbio_free(handle); - if (rpng) - rpng_nbio_load_image_free(rpng); - rpng = NULL; - if (!ret) - free(*data); - return ret; -} diff --git a/desmume/src/libretro-common/formats/png/rpng_encode.c b/desmume/src/libretro-common/formats/png/rpng_encode.c index 3dccf0d4f..337809af2 100644 --- a/desmume/src/libretro-common/formats/png/rpng_encode.c +++ b/desmume/src/libretro-common/formats/png/rpng_encode.c @@ -25,6 +25,7 @@ #include #include +#include #include "rpng_internal.h" @@ -35,8 +36,6 @@ goto end; \ } while(0) -#ifdef HAVE_ZLIB_DEFLATE - static void dword_write_be(uint8_t *buf, uint32_t val) { *buf++ = (uint8_t)(val >> 24); @@ -348,8 +347,8 @@ static bool rpng_save_image(const char *path, stream_backend->stream_compress_free(stream); memcpy(deflate_buf + 4, "IDAT", 4); - 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)) + dword_write_be(deflate_buf + 0, ((uint32_t)stream_backend->stream_get_total_out(stream))); + if (!png_write_idat(file, deflate_buf, ((size_t)stream_backend->stream_get_total_out(stream) + 8))) GOTO_END_ERROR(); if (!png_write_iend(file)) @@ -366,7 +365,8 @@ end: free(avg_filtered); free(paeth_filtered); - stream_backend->stream_free(stream); + if (stream_backend) + stream_backend->stream_free(stream); return ret; } @@ -383,5 +383,3 @@ bool rpng_save_image_bgr24(const char *path, const uint8_t *data, return rpng_save_image(path, (const uint8_t*)data, width, height, pitch, 3); } - -#endif diff --git a/desmume/src/libretro-common/formats/png/test/Makefile b/desmume/src/libretro-common/formats/png/test/Makefile index b11516459..f7d89ed17 100644 --- a/desmume/src/libretro-common/formats/png/test/Makefile +++ b/desmume/src/libretro-common/formats/png/test/Makefile @@ -27,7 +27,7 @@ SOURCES_C := \ OBJS := $(SOURCES_C:.c=.o) -CFLAGS += -Wall -pedantic -std=gnu99 -O0 -g -DHAVE_ZLIB -DHAVE_ZLIB_DEFLATE -DRPNG_TEST -I$(LIBRETRO_COMM_DIR)/include +CFLAGS += -Wall -pedantic -std=gnu99 -O0 -g -DHAVE_ZLIB -DRPNG_TEST -I$(LIBRETRO_COMM_DIR)/include all: $(TARGET) diff --git a/desmume/src/libretro-common/formats/png/test/rpng_test.c b/desmume/src/libretro-common/formats/png/test/rpng_test.c index bb457f906..7da75d108 100644 --- a/desmume/src/libretro-common/formats/png/test/rpng_test.c +++ b/desmume/src/libretro-common/formats/png/test/rpng_test.c @@ -30,6 +30,80 @@ #include #include +#include + +static bool rpng_load_image_argb(const char *path, uint32_t **data, + unsigned *width, unsigned *height) +{ + int retval; + size_t file_len; + bool ret = true; + rpng_t *rpng = NULL; + void *ptr = NULL; + struct nbio_t* handle = (struct nbio_t*)nbio_open(path, NBIO_READ); + + if (!handle) + goto end; + + nbio_begin_read(handle); + + while (!nbio_iterate(handle)); + + ptr = nbio_get_ptr(handle, &file_len); + + if (!ptr) + { + ret = false; + goto end; + } + + rpng = rpng_alloc(); + + if (!rpng) + { + ret = false; + goto end; + } + + if (!rpng_set_buf_ptr(rpng, (uint8_t*)ptr)) + { + ret = false; + goto end; + } + + if (!rpng_start(rpng)) + { + ret = false; + goto end; + } + + while (rpng_iterate_image(rpng)); + + if (!rpng_is_valid(rpng)) + { + ret = false; + goto end; + } + + do + { + retval = rpng_process_image(rpng, + (void**)data, file_len, width, height); + }while(retval == IMAGE_PROCESS_NEXT); + + if (retval == IMAGE_PROCESS_ERROR || retval == IMAGE_PROCESS_ERROR_END) + ret = false; + +end: + if (handle) + nbio_free(handle); + if (rpng) + rpng_free(rpng); + rpng = NULL; + if (!ret) + free(*data); + return ret; +} static int test_rpng(const char *in_path) { diff --git a/desmume/src/libretro-common/formats/tga/rtga.c b/desmume/src/libretro-common/formats/tga/rtga.c index e1c153506..c5f052ea3 100644 --- a/desmume/src/libretro-common/formats/tga/rtga.c +++ b/desmume/src/libretro-common/formats/tga/rtga.c @@ -1,103 +1,478 @@ -/* Copyright (C) 2010-2016 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (rtga.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 /* ptrdiff_t on osx */ #include #include -#include +#include +#include + #include +#include -bool rtga_image_load_shift(uint8_t *buf, - void *data, - unsigned a_shift, unsigned r_shift, - unsigned g_shift, unsigned b_shift) +struct rtga { - unsigned i, bits, size, bits_mul; - uint8_t info[6] = {0}; - unsigned width = 0; - unsigned height = 0; - const uint8_t *tmp = NULL; - struct texture_image *out_img = (struct texture_image*)data; + uint8_t *buff_data; + uint32_t *output_image; + void *empty; +}; - if (!buf || buf[2] != 2) +typedef struct +{ + int (*read) (void *user,char *data,int size); /* fill 'data' with 'size' bytes. return number of bytes actually read */ + void (*skip) (void *user,int n); /* skip the next 'n' bytes, or 'unget' the last -n bytes if negative */ + int (*eof) (void *user); /* returns nonzero if we are at end of file/data */ +} rtga_io_callbacks; + +typedef struct +{ + uint32_t img_x, img_y; + int img_n, img_out_n; + + rtga_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + uint8_t buffer_start[128]; + + uint8_t *img_buffer, *img_buffer_end; + uint8_t *img_buffer_original; +} rtga__context; + +static void rtga__refill_buffer(rtga__context *s); + +static void rtga__start_mem(rtga__context *s, uint8_t const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (uint8_t *) buffer; + s->img_buffer_end = (uint8_t *) buffer+len; +} + +static uint8_t *rtga__tga_load(rtga__context *s, unsigned *x, unsigned *y, int *comp, int req_comp); + +#define rtga__err(x,y) 0 +#define rtga__errpf(x,y) ((float *) (rtga__err(x,y)?NULL:NULL)) +#define rtga__errpuc(x,y) ((unsigned char *) (rtga__err(x,y)?NULL:NULL)) + +static uint8_t *rtga_load_from_memory(uint8_t const *buffer, int len, unsigned *x, unsigned *y, int *comp, int req_comp) +{ + rtga__context s; + rtga__start_mem(&s,buffer,len); + return rtga__tga_load(&s,x,y,comp,req_comp); +} + +static void rtga__refill_buffer(rtga__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + if (n == 0) { - fprintf(stderr, "TGA image is not uncompressed RGB.\n"); - goto error; + /* at end of file, treat same as if from memory, but need to handle case + * where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file */ + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +static INLINE uint8_t rtga__get8(rtga__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + rtga__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +static void rtga__skip(rtga__context *s, int n) +{ + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int rtga__getn(rtga__context *s, uint8_t *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } } - memcpy(info, buf + 12, 6); + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} - width = info[0] + ((unsigned)info[1] * 256); - height = info[2] + ((unsigned)info[3] * 256); - bits = info[4]; +static int rtga__get16le(rtga__context *s) +{ + int z = rtga__get8(s); + return z + (rtga__get8(s) << 8); +} - fprintf(stderr, "Loaded TGA: (%ux%u @ %u bpp)\n", width, height, bits); +static uint8_t rtga__compute_y(int r, int g, int b) +{ + return (uint8_t) (((r*77) + (g*150) + (29*b)) >> 8); +} - size = width * height * sizeof(uint32_t); - out_img->pixels = (uint32_t*)malloc(size); - out_img->width = width; - out_img->height = height; +static unsigned char *rtga__convert_format( + unsigned char *data, + int img_n, + int req_comp, + unsigned int x, + unsigned int y) +{ + int i,j; + unsigned char *good; - if (!out_img->pixels) + if (req_comp == img_n) return data; + retro_assert(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) malloc(req_comp * x * y); + if (good == NULL) { - fprintf(stderr, "Failed to allocate TGA pixels.\n"); - goto error; + free(data); + return rtga__errpuc("outofmem", "Out of memory"); } - tmp = buf + 18; - bits_mul = 3; - - if (bits != 32 && bits != 24) + for (j=0; j < (int) y; ++j) { - fprintf(stderr, "Bit depth of TGA image is wrong. Only 32-bit and 24-bit supported.\n"); - goto error; + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + switch (((img_n)*8+(req_comp))) + { + case ((1)*8+(2)): + for(i=x-1; i >= 0; --i, src += 1, dest += 2) + dest[0]=src[0], dest[1]=255; + break; + case ((1)*8+(3)): + for(i=x-1; i >= 0; --i, src += 1, dest += 3) + dest[0]=dest[1]=dest[2]=src[0]; + break; + case ((1)*8+(4)): + for(i=x-1; i >= 0; --i, src += 1, dest += 4) + dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; + break; + case ((2)*8+(1)): + for(i=x-1; i >= 0; --i, src += 2, dest += 1) + dest[0]=src[0]; + break; + case ((2)*8+(3)): + for(i=x-1; i >= 0; --i, src += 2, dest += 3) + dest[0]=dest[1]=dest[2]=src[0]; + break; + case ((2)*8+(4)): + for(i=x-1; i >= 0; --i, src += 2, dest += 4) + dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; + break; + case ((3)*8+(4)): + for(i=x-1; i >= 0; --i, src += 3, dest += 4) + dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; + break; + case ((3)*8+(1)): + for(i=x-1; i >= 0; --i, src += 3, dest += 1) + dest[0]=rtga__compute_y(src[0],src[1],src[2]); + break; + case ((3)*8+(2)): + for(i=x-1; i >= 0; --i, src += 3, dest += 2) + dest[0]=rtga__compute_y(src[0],src[1],src[2]), dest[1] = 255; + break; + case ((4)*8+(1)): + for(i=x-1; i >= 0; --i, src += 4, dest += 1) + dest[0]=rtga__compute_y(src[0],src[1],src[2]); + break; + case ((4)*8+(2)): + for(i=x-1; i >= 0; --i, src += 4, dest += 2) + dest[0]=rtga__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; + break; + case ((4)*8+(3)): + for(i=x-1; i >= 0; --i, src += 4, dest += 3) + dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; + break; + default: + retro_assert(0); + break; + } + } - if (bits == 32) - bits_mul = 4; + free(data); + return good; +} - for (i = 0; i < width * height; i++) +static uint8_t *rtga__tga_load(rtga__context *s, unsigned *x, unsigned *y, int *comp, int req_comp) +{ + /* Read in the TGA header stuff */ + int tga_offset = rtga__get8(s); + int tga_indexed = rtga__get8(s); + int tga_image_type = rtga__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = rtga__get16le(s); + int tga_palette_len = rtga__get16le(s); + int tga_palette_bits = rtga__get8(s); + int tga_x_origin = rtga__get16le(s); + int tga_y_origin = rtga__get16le(s); + int tga_width = rtga__get16le(s); + int tga_height = rtga__get16le(s); + int tga_bits_per_pixel = rtga__get8(s); + int tga_comp = tga_bits_per_pixel / 8; + int tga_inverted = rtga__get8(s); + + /* image data */ + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + + (void)tga_palette_start; + (void)tga_x_origin; + (void)tga_y_origin; + + /* do a tiny bit of precessing */ + if ( tga_image_type >= 8 ) { - uint32_t b = tmp[i * bits_mul + 0]; - uint32_t g = tmp[i * bits_mul + 1]; - uint32_t r = tmp[i * bits_mul + 2]; - uint32_t a = tmp[i * bits_mul + 3]; - - if (bits == 24) - a = 0xff; - - out_img->pixels[i] = (a << a_shift) | - (r << r_shift) | (g << g_shift) | (b << b_shift); + tga_image_type -= 8; + tga_is_RLE = 1; } + /* int tga_alpha_bits = tga_inverted & 15; */ + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + /* error check */ + if ( + (tga_width < 1) || (tga_height < 1) || + (tga_image_type < 1) || (tga_image_type > 3) || + ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) && + (tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32)) + ) + return NULL; /* we don't report this as a bad TGA because we don't even know if it's TGA */ + + /* If paletted, then we will use the number of bits from the palette */ + if ( tga_indexed ) + tga_comp = tga_palette_bits / 8; + + /* TGA info */ + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + tga_data = (unsigned char*)malloc( (size_t)tga_width * tga_height * tga_comp ); + if (!tga_data) + return rtga__errpuc("outofmem", "Out of memory"); + + /* skip to the data's starting position (offset usually = 0) */ + rtga__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE) + { + for (i=0; i < tga_height; ++i) + { + int y = tga_inverted ? tga_height -i - 1 : i; + uint8_t *tga_row = tga_data + y*tga_width*tga_comp; + rtga__getn(s, tga_row, tga_width * tga_comp); + } + } + else + { + /* Do I need to load a palette? */ + if ( tga_indexed) + { + /* any data to skip? (offset usually = 0) */ + rtga__skip(s, tga_palette_start ); + /* load the palette */ + tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 ); + + if (!tga_palette) + { + free(tga_data); + return rtga__errpuc("outofmem", "Out of memory"); + } + if (!rtga__getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) { + free(tga_data); + free(tga_palette); + return rtga__errpuc("bad palette", "Corrupt TGA"); + } + } + + /* load the data */ + for (i=0; i < tga_width * tga_height; ++i) + { + /* if I'm in RLE mode, do I need to get a RLE rtga__pngchunk? */ + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + /* yep, get the next byte as a RLE command */ + int RLE_cmd = rtga__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } + else if ( !RLE_repeating ) + read_next_pixel = 1; + } + else + read_next_pixel = 1; + + /* OK, if I need to read a pixel, do it now */ + if ( read_next_pixel ) + { + /* load however much data we did have */ + if ( tga_indexed ) + { + /* read in 1 byte, then perform the lookup */ + int pal_idx = rtga__get8(s); + if ( pal_idx >= tga_palette_len ) /* invalid index */ + pal_idx = 0; + pal_idx *= tga_bits_per_pixel / 8; + for (j = 0; j*8 < tga_bits_per_pixel; ++j) + raw_data[j] = tga_palette[pal_idx+j]; + } + else + { + /* read in the data raw */ + for (j = 0; j*8 < tga_bits_per_pixel; ++j) + raw_data[j] = rtga__get8(s); + } + + /* clear the reading flag for the next pixel */ + read_next_pixel = 0; + } /* end of reading a pixel */ + + /* copy data */ + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + /* in case we're in RLE mode, keep counting down */ + --RLE_count; + } + + /* do I need to invert the image? */ + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + + /* Clear my palette, if I had one */ + if ( tga_palette != NULL ) + free( tga_palette ); + } + + /* swap RGB */ + if (tga_comp >= 3) + { + unsigned char* tga_pixel = tga_data; + + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + /* convert to target component count */ + if (req_comp && req_comp != tga_comp) + tga_data = rtga__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + return tga_data; +} + +int rtga_process_image(rtga_t *rtga, void **buf_data, + size_t size, unsigned *width, unsigned *height) +{ + int comp; + unsigned size_tex = 0; + + if (!rtga) + return IMAGE_PROCESS_ERROR; + + rtga->output_image = (uint32_t*)rtga_load_from_memory(rtga->buff_data, size, width, height, &comp, 4); + *buf_data = rtga->output_image; + size_tex = (*width) * (*height); + + /* Convert RGBA to ARGB */ + while(size_tex--) + { + unsigned int texel = rtga->output_image[size_tex]; + unsigned int A = texel & 0xFF000000; + unsigned int B = texel & 0x00FF0000; + unsigned int G = texel & 0x0000FF00; + unsigned int R = texel & 0x000000FF; + ((unsigned int*)rtga->output_image)[size_tex] = A | (R << 16) | G | (B >> 16); + }; + + return IMAGE_PROCESS_END; +} + +bool rtga_set_buf_ptr(rtga_t *rtga, void *data) +{ + if (!rtga) + return false; + + rtga->buff_data = (uint8_t*)data; + return true; - -error: - if (out_img->pixels) - free(out_img->pixels); - - out_img->pixels = NULL; - out_img->width = out_img->height = 0; - return false; +} + +void rtga_free(rtga_t *rtga) +{ + if (!rtga) + return; + + free(rtga); +} + +rtga_t *rtga_alloc(void) +{ + rtga_t *rtga = (rtga_t*)calloc(1, sizeof(*rtga)); + if (!rtga) + return NULL; + return rtga; } diff --git a/desmume/src/libretro-common/gfx/math/matrix_4x4.c b/desmume/src/libretro-common/gfx/math/matrix_4x4.c index b8dcfce3a..2ff6198bd 100644 --- a/desmume/src/libretro-common/gfx/math/matrix_4x4.c +++ b/desmume/src/libretro-common/gfx/math/matrix_4x4.c @@ -25,6 +25,15 @@ #include +void matrix_4x4_copy(math_matrix_4x4 *dst, const math_matrix_4x4 *src) +{ + unsigned i, j; + + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) + MAT_ELEM_4X4(*dst, i, j) = MAT_ELEM_4X4(*src, i, j); +} + /* * Sets mat to an identity matrix */ diff --git a/desmume/src/libretro-common/gfx/math/vector_2.c b/desmume/src/libretro-common/gfx/math/vector_2.c new file mode 100644 index 000000000..6719fac93 --- /dev/null +++ b/desmume/src/libretro-common/gfx/math/vector_2.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (vector_2.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 + +float vec2_dot(const float *a, const float *b) +{ + return (a[0]*b[0]) + (a[1]*b[1]); +} + +float vec2_cross(const float *a, const float *b) +{ + return (a[0]*b[1]) - (a[1]*b[0]); +} + +void vec2_add(float *dst, const float *src) +{ + dst[0] += src[0]; + dst[1] += src[1]; +} + +void vec2_subtract(float *dst, const float *src) +{ + dst[0] -= src[0]; + dst[1] -= src[1]; +} + +void vec2_copy(float *dst, const float *src) +{ + dst[0] = src[0]; + dst[1] = src[1]; +} diff --git a/desmume/src/libretro-common/gfx/math/vector_3.c b/desmume/src/libretro-common/gfx/math/vector_3.c new file mode 100644 index 000000000..1ec04acab --- /dev/null +++ b/desmume/src/libretro-common/gfx/math/vector_3.c @@ -0,0 +1,79 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (vector_3.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 + +float vec3_dot(const float *a, const float *b) +{ + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} + +void vec3_cross(float* dst, const float *a, const float *b) +{ + dst[0] = a[1]*b[2] - a[2]*b[1]; + dst[1] = a[2]*b[0] - a[0]*b[2]; + dst[2] = a[0]*b[1] - a[1]*b[0]; +} + +float vec3_length(const float *a) +{ + float length_sq = vec3_dot(a,a); + float length = sqrtf(length_sq); + return length; +} + +void vec3_add(float *dst, const float *src) +{ + dst[0] += src[0]; + dst[1] += src[1]; + dst[2] += src[2]; +} + +void vec3_subtract(float *dst, const float *src) +{ + dst[0] -= src[0]; + dst[1] -= src[1]; + dst[2] -= src[2]; +} + +void vec3_scale(float *dst, const float scale) +{ + dst[0] *= scale; + dst[1] *= scale; + dst[2] *= scale; +} + +void vec3_copy(float *dst, const float *src) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; +} + +void vec3_normalize(float *dst) +{ + float length = vec3_length(dst); + vec3_scale(dst,1.0f/length); +} diff --git a/desmume/src/libretro-common/glsm/glsm.c b/desmume/src/libretro-common/glsm/glsm.c index fdeee70d3..b38ac5b0e 100644 --- a/desmume/src/libretro-common/glsm/glsm.c +++ b/desmume/src/libretro-common/glsm/glsm.c @@ -20,15 +20,16 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include +#include #include #include - struct gl_cached_state { struct { - GLuint ids[MAX_TEXTURE]; + GLuint *ids; } bind_textures; #ifndef HAVE_OPENGLES @@ -176,14 +177,87 @@ struct gl_cached_state 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 GLint glsm_max_textures; static struct retro_hw_render_callback hw_render; static struct gl_cached_state gl_state; /* GL wrapper-side */ +/* + * + * Core in: + * OpenGL : 1.0 + */ +GLenum rglGetError(void) +{ + return glGetError(); +} + +/* + * + * Core in: + * OpenGL : 1.0 + */ +void rglClear(GLbitfield mask) +{ + glClear(mask); +} + +/* + * + * Core in: + * OpenGL : 2.0 + */ +void rglValidateProgram(GLuint program) +{ + glValidateProgram(program); +} + +/* + * + * Core in: + * OpenGL : 1.0 + * OpenGLES : N/A + */ +void rglPolygonMode(GLenum face, GLenum mode) +{ +#ifndef HAVE_OPENGLES + glPolygonMode(face, mode); +#endif +} + +void rglTexSubImage2D( + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + const GLvoid * pixels) +{ + glTexSubImage2D(target, level, xoffset, yoffset, + width, height, format, type, pixels); +} + +/* + * + * Core in: + * OpenGL : 1.0 + */ +void rglLineWidth(GLfloat width) +{ + glLineWidth(width); +} + +/* + * Category: FBO + * + * Core in: + * OpenGL : 3.0 + * OpenGLES : 3.0 + */ void rglBlitFramebuffer( GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, @@ -191,21 +265,31 @@ void rglBlitFramebuffer( GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { -#ifndef HAVE_OPENGLES2 +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); #endif } +/* + * + * Core in: + * OpenGLES : 3.0 + */ void rglReadBuffer(GLenum mode) { -#ifndef HAVE_OPENGLES2 +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glReadBuffer(mode); -#endif gl_state.readbuffer.mode = mode; +#endif } +/* + * + * Core in: + * OpenGLES : 2.0 + */ void rglClearDepth(GLdouble depth) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -218,6 +302,11 @@ void rglClearDepth(GLdouble depth) gl_state.cleardepth.depth = depth; } +/* + * + * Core in: + * OpenGLES : 2.0 + */ void rglPixelStorei(GLenum pname, GLint param) { glPixelStorei(pname, param); @@ -225,6 +314,11 @@ void rglPixelStorei(GLenum pname, GLint param) gl_state.pixelstore_i.param = param; } +/* + * + * Core in: + * OpenGLES : 2.0 + */ void rglDepthRange(GLclampd zNear, GLclampd zFar) { #ifdef HAVE_OPENGLES @@ -237,6 +331,11 @@ void rglDepthRange(GLclampd zNear, GLclampd zFar) gl_state.depthrange.zFar = zFar; } +/* + * + * Core in: + * OpenGLES : 2.0 + */ void rglFrontFace(GLenum mode) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -245,6 +344,11 @@ void rglFrontFace(GLenum mode) gl_state.frontface.mode = mode; } +/* + * + * Core in: + * OpenGLES : 2.0 + */ void rglDepthFunc(GLenum func) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -253,6 +357,11 @@ void rglDepthFunc(GLenum func) glDepthFunc(func); } +/* + * + * Core in: + * OpenGLES : 2.0 + */ void rglColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { @@ -265,6 +374,11 @@ void rglColorMask(GLboolean red, GLboolean green, gl_state.colormask.used = true; } +/* + * + * Core in: + * OpenGLES : 2.0 + */ void rglCullFace(GLenum mode) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -273,6 +387,11 @@ void rglCullFace(GLenum mode) gl_state.cullface.mode = mode; } +/* + * + * Core in: + * OpenGLES : 2.0 + */ void rglStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass) { glStencilOp(sfail, dpfail, dppass); @@ -282,6 +401,11 @@ void rglStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass) gl_state.stencilop.dppass = dppass; } +/* + * + * Core in: + * OpenGLES : 2.0 + */ void rglStencilFunc(GLenum func, GLint ref, GLuint mask) { glStencilFunc(func, ref, mask); @@ -291,11 +415,21 @@ void rglStencilFunc(GLenum func, GLint ref, GLuint mask) gl_state.stencilfunc.mask = mask; } +/* + * + * Core in: + * OpenGL : 1.0 + */ GLboolean rglIsEnabled(GLenum cap) { return gl_state.cap_state[cap] ? GL_TRUE : GL_FALSE; } +/* + * + * Core in: + * OpenGL : 1.0 + */ void rglClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { @@ -307,6 +441,11 @@ void rglClearColor(GLclampf red, GLclampf green, gl_state.clear_color.a = alpha; } +/* + * + * Core in: + * OpenGLES : 2.0 (maybe earlier?) + */ void rglScissor(GLint x, GLint y, GLsizei width, GLsizei height) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -318,6 +457,11 @@ void rglScissor(GLint x, GLint y, GLsizei width, GLsizei height) gl_state.scissor.h = height; } +/* + * + * Core in: + * OpenGL : 1.0 + */ void rglViewport(GLint x, GLint y, GLsizei width, GLsizei height) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -337,6 +481,12 @@ void rglBlendFunc(GLenum sfactor, GLenum dfactor) glBlendFunc(sfactor, dfactor); } +/* + * Category: Blending + * + * Core in: + * OpenGL : 1.4 + */ void rglBlendFuncSeparate(GLenum sfactor, GLenum dfactor) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -348,6 +498,12 @@ void rglBlendFuncSeparate(GLenum sfactor, GLenum dfactor) glBlendFunc(sfactor, dfactor); } +/* + * Category: Textures + * + * Core in: + * OpenGL : 1.3 + */ void rglActiveTexture(GLenum texture) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -355,6 +511,11 @@ void rglActiveTexture(GLenum texture) gl_state.active_texture = texture - GL_TEXTURE0; } +/* + * + * Core in: + * OpenGL : 1.1 + */ void rglBindTexture(GLenum target, GLuint texture) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -362,6 +523,11 @@ void rglBindTexture(GLenum target, GLuint texture) gl_state.bind_textures.ids[gl_state.active_texture] = texture; } +/* + * + * Core in: + * OpenGL : 1.0 + */ void rglDisable(GLenum cap) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -369,6 +535,11 @@ void rglDisable(GLenum cap) gl_state.cap_state[cap] = 0; } +/* + * + * Core in: + * OpenGL : 1.0 + */ void rglEnable(GLenum cap) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -376,6 +547,12 @@ void rglEnable(GLenum cap) gl_state.cap_state[cap] = 1; } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglUseProgram(GLuint program) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -383,6 +560,11 @@ void rglUseProgram(GLuint program) glUseProgram(program); } +/* + * + * Core in: + * OpenGL : 1.0 + */ void rglDepthMask(GLboolean flag) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -391,6 +573,11 @@ void rglDepthMask(GLboolean flag) gl_state.depthmask.mask = flag; } +/* + * + * Core in: + * OpenGL : 1.0 + */ void rglStencilMask(GLenum mask) { glStencilMask(mask); @@ -398,49 +585,99 @@ void rglStencilMask(GLenum mask) gl_state.stencilmask.mask = mask; } +/* + * + * Core in: + * OpenGL : 1.5 + */ void rglBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) { glBufferData(target, size, data, usage); } +/* + * + * Core in: + * OpenGL : 1.5 + */ void rglBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) { glBufferSubData(target, offset, size, data); } +/* + * + * Core in: + * OpenGL : 1.5 + */ void rglBindBuffer(GLenum target, GLuint buffer) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); glBindBuffer(target, buffer); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglLinkProgram(GLuint program) { glLinkProgram(program); } -void rglFramebufferTexture(GLenum target, GLenum attachment, - GLuint texture, GLint level) -{ -#if defined(HAVE_OPENGLES) && !defined(HAVE_OPENGLES32) -#else - glFramebufferTexture(target, attachment, texture, level); -#endif -} - +/* + * Category: FBO + * + * Core in: + * OpenGL : 3.0 + * OpenGLES : 2.0 + */ void rglFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { glFramebufferTexture2D(target, attachment, textarget, texture, level); } +/* + * Category: FBO + * + * Core in: + * OpenGL : 3.0 + * OpenGLES : 3.2 + */ +void rglFramebufferTexture(GLenum target, GLenum attachment, + GLuint texture, GLint level) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3_2) + glFramebufferTexture(target, attachment, texture, level); +#endif +} + +/* + * + * Core in: + * OpenGL : 1.1 + */ void rglDrawArrays(GLenum mode, GLint first, GLsizei count) { glDrawArrays(mode, first, count); } +/* + * + * Core in: + * OpenGL : 1.1 + */ +void rglDrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid * indices) +{ + glDrawElements(mode, count, type, indices); +} + void rglCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) @@ -449,11 +686,6 @@ void rglCompressedTexImage2D(GLenum target, GLint level, width, height, border, imageSize, data); } -void rglFramebufferRenderbuffer(GLenum target, GLenum attachment, - GLenum renderbuffertarget, GLuint renderbuffer) -{ - glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); -} void rglDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) { @@ -465,52 +697,94 @@ void rglDeleteTextures(GLsizei n, const GLuint *textures) glDeleteTextures(n, textures); } +/* + * + * Core in: + * OpenGLES : 2.0 + */ void rglRenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height) { glRenderbufferStorage(target, internalFormat, width, height); } +/* + * + * Core in: + * + * OpenGL : 3.0 + * OpenGLES : 2.0 + */ void rglBindRenderbuffer(GLenum target, GLuint renderbuffer) { glBindRenderbuffer(target, renderbuffer); } +/* + * + * Core in: + * + * OpenGLES : 2.0 + */ void rglDeleteRenderbuffers(GLsizei n, GLuint *renderbuffers) { glDeleteRenderbuffers(n, renderbuffers); } +/* + * + * Core in: + * + * OpenGL : 3.0 + * OpenGLES : 2.0 + */ 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; - } -} - +/* + * + * Core in: + * + * OpenGL : 3.0 + * OpenGLES : 2.0 + */ void rglGenerateMipmap(GLenum target) { glGenerateMipmap(target); } +/* + * Category: FBO + * + * Core in: + * OpenGL : 3.0 + */ GLenum rglCheckFramebufferStatus(GLenum target) { return glCheckFramebufferStatus(target); } +/* + * Category: FBO + * + * Core in: + * OpenGL : 3.0 + * OpenGLES : 2.0 + */ +void rglFramebufferRenderbuffer(GLenum target, GLenum attachment, + GLenum renderbuffertarget, GLuint renderbuffer) +{ + glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); +} + +/* + * Category: Shaders + * + * Core in: + * OpenGL : 3.0 + */ void rglBindFragDataLocation(GLuint program, GLuint colorNumber, const char * name) { @@ -519,98 +793,345 @@ void rglBindFragDataLocation(GLuint program, GLuint colorNumber, #endif } -void rglBindAttribLocation(GLuint program, GLuint index, const GLchar *name) -{ - glBindAttribLocation(program, index, name); -} +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglGetProgramiv(GLuint shader, GLenum pname, GLint *params) { glGetProgramiv(shader, pname, params); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 4.1 + * OpenGLES : 3.0 + */ +void rglProgramParameteri( GLuint program, + GLenum pname, + GLint value) +{ +#if !defined(HAVE_OPENGLES) || defined(HAVE_OPENGLES) && (defined(HAVE_OPENGLES3) || defined(HAVE_OPENGLES_3_1)) + glProgramParameteri(program, pname, value); +#else + printf("WARNING! Not implemented.\n"); +#endif +} + +/* + * + * Core in: + * OpenGL : 2.0 + */ +void rglGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, + GLsizei *length, GLint *size, GLenum *type, GLchar *name) +{ + glGetActiveUniform(program, index, bufsize, length, size, type, name); +} + +/* + * Category: UBO + * + * Core in: + * + * OpenGL : 2.0 + * OpenGLES : 3.0 + */ +void rglGetActiveUniformBlockiv(GLuint program, + GLuint uniformBlockIndex, + GLenum pname, + GLint *params) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + glGetActiveUniformBlockiv(program, uniformBlockIndex, + pname, params); +#else + printf("WARNING! Not implemented.\n"); +#endif +} + +/* + * + * Core in: + * + * OpenGLES : 3.0 + */ +void rglGetActiveUniformsiv( GLuint program, + GLsizei uniformCount, + const GLuint *uniformIndices, + GLenum pname, + GLint *params) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + glGetActiveUniformsiv(program, uniformCount, + uniformIndices, pname, params); +#else + printf("WARNING! Not implemented.\n"); +#endif +} + +/* + * + * Core in: + * + * OpenGLES : 3.0 + */ +void rglGetUniformIndices(GLuint program, + GLsizei uniformCount, + const GLchar **uniformNames, + GLuint *uniformIndices) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + glGetUniformIndices(program, uniformCount, + uniformNames, uniformIndices); +#else + printf("WARNING! Not implemented.\n"); +#endif +} + +/* + * Category: UBO + * + * Core in: + * + * OpenGLES : 3.0 + */ +void rglBindBufferBase( GLenum target, + GLuint index, + GLuint buffer) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + glBindBufferBase(target, index, buffer); +#else + printf("WARNING! Not implemented.\n"); +#endif +} + +/* + * + * Category: UBO + * + * Core in: + * + * OpenGLES : 3.0 + */ +GLuint rglGetUniformBlockIndex( GLuint program, + const GLchar *uniformBlockName) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + return glGetUniformBlockIndex(program, uniformBlockName); +#else + printf("WARNING! Not implemented.\n"); + return 0; +#endif +} + +/* + * Category: UBO + * + * Core in: + * + * OpenGLES : 3.0 + */ +void rglUniformBlockBinding( GLuint program, + GLuint uniformBlockIndex, + GLuint uniformBlockBinding) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + glUniformBlockBinding(program, uniformBlockIndex, + uniformBlockBinding); +#else + printf("WARNING! Not implemented.\n"); +#endif +} + +/* + * + * Core in: + * OpenGL : 2.0 + * OpenGLES : 3.0 + */ +void rglUniform1ui(GLint location, GLuint v) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + glUniform1ui(location ,v); +#endif +} + +/* + * + * Core in: + * OpenGL : 2.0 + * OpenGLES : 3.0 + */ +void rglUniform2ui(GLint location, GLuint v0, GLuint v1) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + glUniform2ui(location, v0, v1); +#endif +} + +/* + * + * Core in: + * OpenGL : 2.0 + * OpenGLES : 3.0 + */ +void rglUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + glUniform3ui(location, v0, v1, v2); +#endif +} + +/* + * + * Core in: + * OpenGL : 2.0 + * OpenGLES : 3.0 + */ +void rglUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + glUniform4ui(location, v0, v1, v2, v3); +#endif +} + +/* + * + * Core in: + * OpenGL : 2.0 + */ void rglUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { glUniformMatrix4fv(location, count, transpose, value); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglDetachShader(GLuint program, GLuint shader) { glDetachShader(program, shader); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglGetShaderiv(GLuint shader, GLenum pname, GLint *params) { glGetShaderiv(shader, pname, params); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglAttachShader(GLuint program, GLuint shader) { glAttachShader(program, shader); } +/* + * + * Core in: + * OpenGL : 2.0 + */ GLint rglGetAttribLocation(GLuint program, const GLchar *name) { return glGetAttribLocation(program, name); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length) { return glShaderSource(shader, count, string, length); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglCompileShader(GLuint shader) { glCompileShader(shader); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ GLuint rglCreateProgram(void) { return glCreateProgram(); } +/* + * + * Core in: + * OpenGL : 1.1 + */ void rglGenTextures(GLsizei n, GLuint *textures) { glGenTextures(n, textures); } +/* + * + * Core in: + * OpenGL : 2.0 + */ void rglGetShaderInfoLog(GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog) { glGetShaderInfoLog(shader, maxLength, length, infoLog); } +/* + * + * Core in: + * OpenGL : 2.0 + */ void rglGetProgramInfoLog(GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog) { glGetProgramInfoLog(shader, maxLength, length, infoLog); } +/* + * + * Core in: + * OpenGL : 2.0 + */ 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) { @@ -619,6 +1140,68 @@ void rglTexCoord2f(GLfloat s, GLfloat t) #endif } +/* + * Category: Generic vertex attributes + * + * Core in: + * OpenGL : 2.0 + * + */ +void rglDisableVertexAttribArray(GLuint index) +{ + gl_state.vertex_attrib_pointer.enabled[index] = 0; + glDisableVertexAttribArray(index); +} + +/* + * Category: Generic vertex attributes + * + * Core in: + * OpenGL : 2.0 + */ +void rglEnableVertexAttribArray(GLuint index) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + gl_state.vertex_attrib_pointer.enabled[index] = 1; + glEnableVertexAttribArray(index); +} + +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ +void rglVertexAttribIPointer( + GLuint index, + GLint size, + GLenum type, + GLsizei stride, + const GLvoid * pointer) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + glVertexAttribIPointer(index, size, type, stride, pointer); +#endif +} + +void rglVertexAttribLPointer( + GLuint index, + GLint size, + GLenum type, + GLsizei stride, + const GLvoid * pointer) +{ +#if defined(HAVE_OPENGL) + glVertexAttribLPointer(index, size, type, stride, pointer); +#endif +} + +/* + * Category: Generic vertex attributes + * + * Core in: + * OpenGL : 2.0 + */ void rglVertexAttribPointer(GLuint name, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer) @@ -626,98 +1209,300 @@ void rglVertexAttribPointer(GLuint name, GLint size, glVertexAttribPointer(name, size, type, normalized, stride, pointer); } +/* + * Category: Generic vertex attributes + * + * Core in: + * OpenGL : 2.0 + */ +void rglBindAttribLocation(GLuint program, GLuint index, const GLchar *name) +{ + glBindAttribLocation(program, index, name); +} + +/* + * + * Core in: + * OpenGL : 2.0 + */ void rglVertexAttrib4f(GLuint name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { glVertexAttrib4f(name, x, y, z, w); } +/* + * + * Core in: + * OpenGL : 2.0 + */ void rglVertexAttrib4fv(GLuint name, GLfloat* v) { glVertexAttrib4fv(name, v); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ GLuint rglCreateShader(GLenum shaderType) { return glCreateShader(shaderType); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglDeleteProgram(GLuint program) { glDeleteProgram(program); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglDeleteShader(GLuint shader) { glDeleteShader(shader); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ GLint rglGetUniformLocation(GLuint program, const GLchar *name) { return glGetUniformLocation(program, name); } +/* + * Category: VBO and PBO + * + * Core in: + * OpenGL : 1.5 + */ void rglDeleteBuffers(GLsizei n, const GLuint *buffers) { glDeleteBuffers(n, buffers); } +/* + * Category: VBO and PBO + * + * Core in: + * OpenGL : 1.5 + */ void rglGenBuffers(GLsizei n, GLuint *buffers) { glGenBuffers(n, buffers); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglUniform1f(GLint location, GLfloat v0) { glUniform1f(location, v0); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ +void rglUniform1fv(GLint location, GLsizei count, const GLfloat *value) +{ + glUniform1fv(location, count, value); +} + +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ +void rglUniform1iv(GLint location, GLsizei count, const GLint *value) +{ + glUniform1iv(location, count, value); +} + +void rglClearBufferfv( GLenum buffer, + GLint drawBuffer, + const GLfloat * value) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3) + glClearBufferfv(buffer, drawBuffer, value); +#endif +} + +void rglTexBuffer(GLenum target, GLenum internalFormat, GLuint buffer) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3_2) + glTexBuffer(target, internalFormat, buffer); +#endif +} + +/* + * + * Core in: + * OpenGL : 2.0 + * OpenGLES : 3.0 + */ +const GLubyte* rglGetStringi(GLenum name, GLuint index) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3) + return glGetStringi(name, index); +#else + return NULL; +#endif +} + +void rglClearBufferfi( GLenum buffer, + GLint drawBuffer, + GLfloat depth, + GLint stencil) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3) + glClearBufferfi(buffer, drawBuffer, depth, stencil); +#endif +} + +/* + * + * Core in: + * OpenGL : 3.0 + * OpenGLES : 3.0 + */ +void rglRenderbufferStorageMultisample( GLenum target, + GLsizei samples, + GLenum internalformat, + GLsizei width, + GLsizei height) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3) + glRenderbufferStorageMultisample(target, samples, internalformat, width, height); +#endif +} + +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglUniform1i(GLint location, GLint v0) { glUniform1i(location, v0); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglUniform2f(GLint location, GLfloat v0, GLfloat v1) { glUniform2f(location, v0, v1); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglUniform2i(GLint location, GLint v0, GLint v1) { glUniform2i(location, v0, v1); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglUniform2fv(GLint location, GLsizei count, const GLfloat *value) { glUniform2fv(location, count, value); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) { glUniform3f(location, v0, v1, v2); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglUniform3fv(GLint location, GLsizei count, const GLfloat *value) { glUniform3fv(location, count, value); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ +void rglUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) +{ + glUniform4i(location, v0, v1, v2, v3); +} + +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) { glUniform4f(location, v0, v1, v2, v3); } +/* + * Category: Shaders + * + * Core in: + * OpenGL : 2.0 + */ void rglUniform4fv(GLint location, GLsizei count, const GLfloat *value) { glUniform4fv(location, count, value); } -void rglTexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat, - GLsizei width, GLsizei height) -{ - glTexStorage2D(target, levels, internalFormat, width, height); -} +/* + * + * Core in: + * OpenGL : 1.0 + */ void rglPolygonOffset(GLfloat factor, GLfloat units) { glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); @@ -727,14 +1512,206 @@ void rglPolygonOffset(GLfloat factor, GLfloat units) gl_state.polygonoffset.units = units; } +/* + * Category: FBO + * + * Core in: + * OpenGL : 3.0 + */ +void rglGenFramebuffers(GLsizei n, GLuint *ids) +{ + glGenFramebuffers(n, ids); +} + +/* + * Category: FBO + * + * Core in: + * OpenGL : 3.0 + */ +void rglBindFramebuffer(GLenum target, GLuint framebuffer) +{ + glsm_ctl(GLSM_CTL_IMM_VBO_DRAW, NULL); + glBindFramebuffer(target, framebuffer); + gl_state.framebuf = framebuffer; +} + +/* + * Category: FBO + * + * Core in: + * OpenGL : 2.0 + * OpenGLES : 3.0 + */ void rglDrawBuffers(GLsizei n, const GLenum *bufs) { -#if defined(HAVE_OPENGLES) && !defined(HAVE_OPENGLES3) && !defined(HAVE_OPENGLES31) -#else +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glDrawBuffers(n, bufs); #endif } +/* + * Category: FBO + * + * Core in: + * OpenGL : 2.0 + * OpenGLES : 3.0 + */ +void *rglMapBufferRange( GLenum target, + GLintptr offset, + GLsizeiptr length, + GLbitfield access) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + return glMapBufferRange(target, offset, length, access); +#else + printf("WARNING! Not implemented.\n"); + return NULL; +#endif +} + +/* + * + * Core in: + * OpenGL : 4.3 + * OpenGLES : 3.1 + */ +void rglTexStorage2DMultisample(GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height, + GLboolean fixedsamplelocations) +{ +#if defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3_1) + glTexStorage2DMultisample(target, samples, internalformat, + width, height, fixedsamplelocations); +#endif +} + +/* + * + * Core in: + * OpenGLES : 3.0 + */ +void rglTexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat, + GLsizei width, GLsizei height) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + glTexStorage2D(target, levels, internalFormat, width, height); +#endif +} + +/* + * + * Core in: + * OpenGL : 4.2 + * OpenGLES : 3.1 + */ +void rglMemoryBarrier( GLbitfield barriers) +{ +#if !defined(HAVE_OPENGLES) || defined(HAVE_OPENGLES3) && defined(HAVE_OPENGLES_3_1) + glMemoryBarrier(barriers); +#else + printf("WARNING! Not implemented.\n"); +#endif +} + +/* + * + * Core in: + * OpenGL : 4.2 + * OpenGLES : 3.1 + */ +void rglBindImageTexture( GLuint unit, + GLuint texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLenum format) +{ +#if !defined(HAVE_OPENGLES) || defined(HAVE_OPENGLES3) && defined(HAVE_OPENGLES_3_1) + glBindImageTexture(unit, texture, level, layered, layer, access, format); +#else + printf("WARNING! Not implemented.\n"); +#endif +} + +/* + * + * Core in: + * OpenGL : 4.1 + * OpenGLES : 3.1 + */ +void rglGetProgramBinary( GLuint program, + GLsizei bufsize, + GLsizei *length, + GLenum *binaryFormat, + void *binary) +{ +#if !defined(HAVE_OPENGLES) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + glGetProgramBinary(program, bufsize, length, binaryFormat, binary); +#else + printf("WARNING! Not implemented.\n"); +#endif +} + +/* + * + * Core in: + * OpenGL : 4.1 + * OpenGLES : 3.1 + */ +void rglProgramBinary(GLuint program, + GLenum binaryFormat, + const void *binary, + GLsizei length) +{ +#if !defined(HAVE_OPENGLES) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3_1) + glProgramBinary(program, binaryFormat, binary, length); +#else + printf("WARNING! Not implemented.\n"); +#endif +} + +void rglTexImage2DMultisample( GLenum target, + GLsizei samples, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLboolean fixedsamplelocations) +{ +#ifndef HAVE_OPENGLES + glTexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations); +#endif +} + +/* + * + * Core in: + * OpenGL : 1.5 + */ +void * rglMapBuffer( GLenum target, GLenum access) +{ +#if defined(HAVE_OPENGLES) + return glMapBufferOES(target, access); +#else + return glMapBuffer(target, access); +#endif +} + +/* + * + * Core in: + * OpenGL : 1.5 + */ +GLboolean rglUnmapBuffer( GLenum target) +{ +#if defined(HAVE_OPENGLES) + return glUnmapBufferOES(target); +#else + return glUnmapBuffer(target); +#endif +} + void rglBlendEquation(GLenum mode) { glBlendEquation(mode); @@ -745,23 +1722,126 @@ void rglBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) glBlendColor(red, green, blue, alpha); } +/* + * Category: Blending + * + * Core in: + * OpenGL : 2.0 + */ +void rglBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +{ + glBlendEquationSeparate(modeRGB, modeAlpha); +} +/* + * + * Core in: + * OpenGL : 2.0 + * OpenGLES : 3.2 + */ +void rglCopyImageSubData( GLuint srcName, + GLenum srcTarget, + GLint srcLevel, + GLint srcX, + GLint srcY, + GLint srcZ, + GLuint dstName, + GLenum dstTarget, + GLint dstLevel, + GLint dstX, + GLint dstY, + GLint dstZ, + GLsizei srcWidth, + GLsizei srcHeight, + GLsizei srcDepth) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3_2) + glCopyImageSubData(srcName, + srcTarget, + srcLevel, + srcX, + srcY, + srcZ, + dstName, + dstTarget, + dstLevel, + dstX, + dstY, + dstZ, + srcWidth, + srcHeight, + srcDepth); +#endif +} + +/* + * Category: VAO + * + * Core in: + * OpenGL : 3.0 + * OpenGLES : 3.0 + */ void rglBindVertexArray(GLuint array) { -#if defined(HAVE_OPENGLES) && !defined(HAVE_OPENGLES3) && !defined(HAVE_OPENGLES31) -#else +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glBindVertexArray(array); #endif } +/* + * Category: VAO + * + * Core in: + * OpenGL : 3.0 + * OpenGLES : 3.0 + */ void rglGenVertexArrays(GLsizei n, GLuint *arrays) { -#if defined(HAVE_OPENGLES) && !defined(HAVE_OPENGLES3) && !defined(HAVE_OPENGLES31) -#else +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) glGenVertexArrays(n, arrays); #endif } +/* + * Category: VAO + * + * Core in: + * OpenGL : 3.0 + * OpenGLES : 3.0 + */ +void rglDeleteVertexArrays(GLsizei n, const GLuint *arrays) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + glDeleteVertexArrays(n, arrays); +#endif +} + +/* + * + * Core in: + * OpenGL : 3.2 + * OpenGLES : 3.0 + */ +void *rglFenceSync(GLenum condition, GLbitfield flags) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + return (GLsync)glFenceSync(condition, flags); +#endif +} + +/* + * + * Core in: + * OpenGL : 3.2 + * OpenGLES : 3.0 + */ +void rglWaitSync(void *sync, GLbitfield flags, uint64_t timeout) +{ +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3) + glWaitSync((GLsync)sync, flags, (GLuint64)timeout); +#endif +} + /* GLSM-side */ static void glsm_state_setup(void) @@ -779,11 +1859,17 @@ static void glsm_state_setup(void) #ifndef HAVE_OPENGLES gl_state.cap_translate[SGL_COLOR_LOGIC_OP] = GL_COLOR_LOGIC_OP; + gl_state.cap_translate[SGL_CLIP_DISTANCE0] = GL_CLIP_DISTANCE0; + gl_state.cap_translate[SGL_DEPTH_CLAMP] = GL_DEPTH_CLAMP; #endif for (i = 0; i < MAX_ATTRIB; i++) gl_state.vertex_attrib_pointer.enabled[i] = 0; + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &glsm_max_textures); + + gl_state.bind_textures.ids = (GLuint*)calloc(glsm_max_textures, sizeof(GLuint)); + gl_state.framebuf = hw_render.get_current_framebuffer(); gl_state.cullface.mode = GL_BACK; gl_state.frontface.mode = GL_CCW; @@ -909,7 +1995,7 @@ static void glsm_state_bind(void) gl_state.stencilfunc.ref, gl_state.stencilfunc.mask); - for (i = 0; i < MAX_TEXTURE; i ++) + for (i = 0; i < glsm_max_textures; i ++) { glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, gl_state.bind_textures.ids[i]); @@ -966,7 +2052,7 @@ static void glsm_state_unbind(void) glStencilFunc(GL_ALWAYS,0,1); /* Clear textures */ - for (i = 0; i < MAX_TEXTURE; i ++) + for (i = 0; i < glsm_max_textures; i ++) { glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, 0); @@ -979,10 +2065,11 @@ static void glsm_state_unbind(void) glBindFramebuffer(RARCH_GL_FRAMEBUFFER, 0); } -static bool dummy_framebuffer_lock(void *data) +static bool glsm_state_ctx_destroy(void *data) { - (void)data; - return false; + if (gl_state.bind_textures.ids) + free(gl_state.bind_textures.ids); + gl_state.bind_textures.ids = NULL; } static bool glsm_state_ctx_init(void *data) @@ -993,7 +2080,7 @@ static bool glsm_state_ctx_init(void *data) return false; #ifdef HAVE_OPENGLES -#if defined(HAVE_OPENGLES31) +#if defined(HAVE_OPENGLES_3_1) hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES_VERSION; hw_render.version_major = 3; hw_render.version_minor = 1; @@ -1018,52 +2105,30 @@ static bool glsm_state_ctx_init(void *data) 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; } +GLuint glsm_get_current_framebuffer(void) +{ + return hw_render.get_current_framebuffer(); +} + 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; + return false; case GLSM_CTL_IMM_VBO_DISABLE: - if (imm_vbo_disable == NULL || !imm_vbo_enable) - return false; - imm_vbo_disable(NULL); - break; + return false; case GLSM_CTL_IS_IMM_VBO: - return imm_vbo_enable; + return false; 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: { @@ -1076,6 +2141,9 @@ bool glsm_ctl(enum glsm_state_ctl state, void *data) case GLSM_CTL_STATE_CONTEXT_RESET: rglgen_resolve_symbols(hw_render.get_proc_address); break; + case GLSM_CTL_STATE_CONTEXT_DESTROY: + glsm_state_ctx_destroy(data); + break; case GLSM_CTL_STATE_CONTEXT_INIT: return glsm_state_ctx_init(data); case GLSM_CTL_STATE_SETUP: diff --git a/desmume/src/libretro-common/glsym/glgen.py b/desmume/src/libretro-common/glsym/glgen.py old mode 100644 new mode 100755 index 20ec669f6..898dcb3a1 --- a/desmume/src/libretro-common/glsym/glgen.py +++ b/desmume/src/libretro-common/glsym/glgen.py @@ -25,7 +25,7 @@ import sys import os import re -banned_ext = [ 'AMD', 'APPLE', 'EXT', 'NV', 'NVX', 'ATI', '3DLABS', 'SUN', 'SGI', 'SGIX', 'SGIS', 'INTEL', '3DFX', 'IBM', 'MESA', 'GREMEDY', 'OML', 'PGI', 'I3D', 'INGL', 'MTX', 'QCOM', 'IMG', 'ANGLE', 'SUNX', 'INGR' ] +banned_ext = [ 'AMD', 'APPLE', 'NV', 'NVX', 'ATI', '3DLABS', 'SUN', 'SGI', 'SGIX', 'SGIS', 'INTEL', '3DFX', 'IBM', 'MESA', 'GREMEDY', 'OML', 'PGI', 'I3D', 'INGL', 'MTX', 'QCOM', 'IMG', 'ANGLE', 'SUNX', 'INGR' ] def noext(sym): for ext in banned_ext: @@ -128,7 +128,7 @@ if __name__ == '__main__': f.write('#endif\n') with open(sys.argv[3], 'w') as f: - f.write('#include "glsym.h"\n') + f.write('#include "glsym/glsym.h"\n') f.write('#include \n') f.write('#define SYM(x) { "gl" #x, &(gl##x) }\n') f.write('const struct rglgen_sym_map rglgen_symbol_map[] = {\n') diff --git a/desmume/src/libretro-common/glsym/glsym_es2.c b/desmume/src/libretro-common/glsym/glsym_es2.c index d8004e850..2e345baa5 100644 --- a/desmume/src/libretro-common/glsym/glsym_es2.c +++ b/desmume/src/libretro-common/glsym/glsym_es2.c @@ -1,30 +1,8 @@ -/* Copyright (C) 2010-2015 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this libretro SDK code part (glsym). - * --------------------------------------------------------------------------------------- - * - * 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 "glsym/glsym.h" #include - #define SYM(x) { "gl" #x, &(gl##x) } const struct rglgen_sym_map rglgen_symbol_map[] = { + SYM(BlendBarrierKHR), SYM(DebugMessageControlKHR), SYM(DebugMessageInsertKHR), SYM(DebugMessageCallbackKHR), @@ -36,26 +14,184 @@ const struct rglgen_sym_map rglgen_symbol_map[] = { SYM(ObjectPtrLabelKHR), SYM(GetObjectPtrLabelKHR), SYM(GetPointervKHR), + SYM(GetGraphicsResetStatusKHR), + SYM(ReadnPixelsKHR), + SYM(GetnUniformfvKHR), + SYM(GetnUniformivKHR), + SYM(GetnUniformuivKHR), SYM(EGLImageTargetTexture2DOES), SYM(EGLImageTargetRenderbufferStorageOES), + SYM(CopyImageSubDataOES), + SYM(EnableiOES), + SYM(DisableiOES), + SYM(BlendEquationiOES), + SYM(BlendEquationSeparateiOES), + SYM(BlendFunciOES), + SYM(BlendFuncSeparateiOES), + SYM(ColorMaskiOES), + SYM(IsEnablediOES), + SYM(DrawElementsBaseVertexOES), + SYM(DrawRangeElementsBaseVertexOES), + SYM(DrawElementsInstancedBaseVertexOES), + SYM(MultiDrawElementsBaseVertexOES), + SYM(FramebufferTextureOES), SYM(GetProgramBinaryOES), SYM(ProgramBinaryOES), SYM(MapBufferOES), SYM(UnmapBufferOES), SYM(GetBufferPointervOES), + SYM(PrimitiveBoundingBoxOES), + SYM(MinSampleShadingOES), + SYM(PatchParameteriOES), SYM(TexImage3DOES), SYM(TexSubImage3DOES), SYM(CopyTexSubImage3DOES), SYM(CompressedTexImage3DOES), SYM(CompressedTexSubImage3DOES), SYM(FramebufferTexture3DOES), + SYM(TexParameterIivOES), + SYM(TexParameterIuivOES), + SYM(GetTexParameterIivOES), + SYM(GetTexParameterIuivOES), + SYM(SamplerParameterIivOES), + SYM(SamplerParameterIuivOES), + SYM(GetSamplerParameterIivOES), + SYM(GetSamplerParameterIuivOES), + SYM(TexBufferOES), + SYM(TexBufferRangeOES), + SYM(TexStorage3DMultisampleOES), + SYM(TextureViewOES), SYM(BindVertexArrayOES), SYM(DeleteVertexArraysOES), SYM(GenVertexArraysOES), SYM(IsVertexArrayOES), + SYM(DrawArraysInstancedBaseInstanceEXT), + SYM(DrawElementsInstancedBaseInstanceEXT), + SYM(DrawElementsInstancedBaseVertexBaseInstanceEXT), + SYM(BindFragDataLocationIndexedEXT), + SYM(BindFragDataLocationEXT), + SYM(GetProgramResourceLocationIndexEXT), + SYM(GetFragDataIndexEXT), + SYM(BufferStorageEXT), + SYM(CopyImageSubDataEXT), + SYM(LabelObjectEXT), + SYM(GetObjectLabelEXT), + SYM(InsertEventMarkerEXT), + SYM(PushGroupMarkerEXT), + SYM(PopGroupMarkerEXT), + SYM(DiscardFramebufferEXT), + SYM(GenQueriesEXT), + SYM(DeleteQueriesEXT), + SYM(IsQueryEXT), + SYM(BeginQueryEXT), + SYM(EndQueryEXT), + SYM(QueryCounterEXT), + SYM(GetQueryivEXT), + SYM(GetQueryObjectivEXT), + SYM(GetQueryObjectuivEXT), + SYM(DrawBuffersEXT), + SYM(EnableiEXT), + SYM(DisableiEXT), + SYM(BlendEquationiEXT), + SYM(BlendEquationSeparateiEXT), + SYM(BlendFunciEXT), + SYM(BlendFuncSeparateiEXT), + SYM(ColorMaskiEXT), + SYM(IsEnablediEXT), + SYM(DrawElementsBaseVertexEXT), + SYM(DrawRangeElementsBaseVertexEXT), + SYM(DrawElementsInstancedBaseVertexEXT), + SYM(MultiDrawElementsBaseVertexEXT), + SYM(DrawArraysInstancedEXT), + SYM(DrawElementsInstancedEXT), + SYM(FramebufferTextureEXT), + SYM(VertexAttribDivisorEXT), + SYM(MapBufferRangeEXT), + SYM(FlushMappedBufferRangeEXT), + SYM(MultiDrawArraysEXT), + SYM(MultiDrawElementsEXT), + SYM(MultiDrawArraysIndirectEXT), + SYM(MultiDrawElementsIndirectEXT), + SYM(RenderbufferStorageMultisampleEXT), + SYM(FramebufferTexture2DMultisampleEXT), + SYM(ReadBufferIndexedEXT), + SYM(DrawBuffersIndexedEXT), + SYM(GetIntegeri_vEXT), + SYM(PrimitiveBoundingBoxEXT), + SYM(RasterSamplesEXT), + SYM(GetGraphicsResetStatusEXT), + SYM(ReadnPixelsEXT), + SYM(GetnUniformfvEXT), + SYM(GetnUniformivEXT), + SYM(ActiveShaderProgramEXT), + SYM(BindProgramPipelineEXT), + SYM(CreateShaderProgramvEXT), + SYM(DeleteProgramPipelinesEXT), + SYM(GenProgramPipelinesEXT), + SYM(GetProgramPipelineInfoLogEXT), + SYM(GetProgramPipelineivEXT), + SYM(IsProgramPipelineEXT), + SYM(ProgramParameteriEXT), + SYM(ProgramUniform1fEXT), + SYM(ProgramUniform1fvEXT), + SYM(ProgramUniform1iEXT), + SYM(ProgramUniform1ivEXT), + SYM(ProgramUniform2fEXT), + SYM(ProgramUniform2fvEXT), + SYM(ProgramUniform2iEXT), + SYM(ProgramUniform2ivEXT), + SYM(ProgramUniform3fEXT), + SYM(ProgramUniform3fvEXT), + SYM(ProgramUniform3iEXT), + SYM(ProgramUniform3ivEXT), + SYM(ProgramUniform4fEXT), + SYM(ProgramUniform4fvEXT), + SYM(ProgramUniform4iEXT), + SYM(ProgramUniform4ivEXT), + SYM(ProgramUniformMatrix2fvEXT), + SYM(ProgramUniformMatrix3fvEXT), + SYM(ProgramUniformMatrix4fvEXT), + SYM(UseProgramStagesEXT), + SYM(ValidateProgramPipelineEXT), + SYM(ProgramUniform1uiEXT), + SYM(ProgramUniform2uiEXT), + SYM(ProgramUniform3uiEXT), + SYM(ProgramUniform4uiEXT), + SYM(ProgramUniform1uivEXT), + SYM(ProgramUniform2uivEXT), + SYM(ProgramUniform3uivEXT), + SYM(ProgramUniform4uivEXT), + SYM(ProgramUniformMatrix2x3fvEXT), + SYM(ProgramUniformMatrix3x2fvEXT), + SYM(ProgramUniformMatrix2x4fvEXT), + SYM(ProgramUniformMatrix4x2fvEXT), + SYM(ProgramUniformMatrix3x4fvEXT), + SYM(ProgramUniformMatrix4x3fvEXT), + SYM(TexPageCommitmentEXT), + SYM(PatchParameteriEXT), + SYM(TexParameterIivEXT), + SYM(TexParameterIuivEXT), + SYM(GetTexParameterIivEXT), + SYM(GetTexParameterIuivEXT), + SYM(SamplerParameterIivEXT), + SYM(SamplerParameterIuivEXT), + SYM(GetSamplerParameterIivEXT), + SYM(GetSamplerParameterIuivEXT), + SYM(TexBufferEXT), + SYM(TexBufferRangeEXT), + SYM(TexStorage1DEXT), + SYM(TexStorage2DEXT), + SYM(TexStorage3DEXT), + SYM(TextureStorage1DEXT), + SYM(TextureStorage2DEXT), + SYM(TextureStorage3DEXT), + SYM(TextureViewEXT), + SYM(FramebufferTextureMultiviewOVR), + SYM(FramebufferTextureMultisampleMultiviewOVR), { NULL, NULL }, }; +RGLSYMGLBLENDBARRIERKHRPROC __rglgen_glBlendBarrierKHR; RGLSYMGLDEBUGMESSAGECONTROLKHRPROC __rglgen_glDebugMessageControlKHR; RGLSYMGLDEBUGMESSAGEINSERTKHRPROC __rglgen_glDebugMessageInsertKHR; RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC __rglgen_glDebugMessageCallbackKHR; @@ -67,21 +203,178 @@ RGLSYMGLGETOBJECTLABELKHRPROC __rglgen_glGetObjectLabelKHR; RGLSYMGLOBJECTPTRLABELKHRPROC __rglgen_glObjectPtrLabelKHR; RGLSYMGLGETOBJECTPTRLABELKHRPROC __rglgen_glGetObjectPtrLabelKHR; RGLSYMGLGETPOINTERVKHRPROC __rglgen_glGetPointervKHR; +RGLSYMGLGETGRAPHICSRESETSTATUSKHRPROC __rglgen_glGetGraphicsResetStatusKHR; +RGLSYMGLREADNPIXELSKHRPROC __rglgen_glReadnPixelsKHR; +RGLSYMGLGETNUNIFORMFVKHRPROC __rglgen_glGetnUniformfvKHR; +RGLSYMGLGETNUNIFORMIVKHRPROC __rglgen_glGetnUniformivKHR; +RGLSYMGLGETNUNIFORMUIVKHRPROC __rglgen_glGetnUniformuivKHR; RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC __rglgen_glEGLImageTargetTexture2DOES; RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC __rglgen_glEGLImageTargetRenderbufferStorageOES; +RGLSYMGLCOPYIMAGESUBDATAOESPROC __rglgen_glCopyImageSubDataOES; +RGLSYMGLENABLEIOESPROC __rglgen_glEnableiOES; +RGLSYMGLDISABLEIOESPROC __rglgen_glDisableiOES; +RGLSYMGLBLENDEQUATIONIOESPROC __rglgen_glBlendEquationiOES; +RGLSYMGLBLENDEQUATIONSEPARATEIOESPROC __rglgen_glBlendEquationSeparateiOES; +RGLSYMGLBLENDFUNCIOESPROC __rglgen_glBlendFunciOES; +RGLSYMGLBLENDFUNCSEPARATEIOESPROC __rglgen_glBlendFuncSeparateiOES; +RGLSYMGLCOLORMASKIOESPROC __rglgen_glColorMaskiOES; +RGLSYMGLISENABLEDIOESPROC __rglgen_glIsEnablediOES; +RGLSYMGLDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glDrawElementsBaseVertexOES; +RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXOESPROC __rglgen_glDrawRangeElementsBaseVertexOES; +RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC __rglgen_glDrawElementsInstancedBaseVertexOES; +RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glMultiDrawElementsBaseVertexOES; +RGLSYMGLFRAMEBUFFERTEXTUREOESPROC __rglgen_glFramebufferTextureOES; RGLSYMGLGETPROGRAMBINARYOESPROC __rglgen_glGetProgramBinaryOES; RGLSYMGLPROGRAMBINARYOESPROC __rglgen_glProgramBinaryOES; RGLSYMGLMAPBUFFEROESPROC __rglgen_glMapBufferOES; RGLSYMGLUNMAPBUFFEROESPROC __rglgen_glUnmapBufferOES; RGLSYMGLGETBUFFERPOINTERVOESPROC __rglgen_glGetBufferPointervOES; +RGLSYMGLPRIMITIVEBOUNDINGBOXOESPROC __rglgen_glPrimitiveBoundingBoxOES; +RGLSYMGLMINSAMPLESHADINGOESPROC __rglgen_glMinSampleShadingOES; +RGLSYMGLPATCHPARAMETERIOESPROC __rglgen_glPatchParameteriOES; RGLSYMGLTEXIMAGE3DOESPROC __rglgen_glTexImage3DOES; RGLSYMGLTEXSUBIMAGE3DOESPROC __rglgen_glTexSubImage3DOES; RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC __rglgen_glCopyTexSubImage3DOES; RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC __rglgen_glCompressedTexImage3DOES; RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC __rglgen_glCompressedTexSubImage3DOES; RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC __rglgen_glFramebufferTexture3DOES; +RGLSYMGLTEXPARAMETERIIVOESPROC __rglgen_glTexParameterIivOES; +RGLSYMGLTEXPARAMETERIUIVOESPROC __rglgen_glTexParameterIuivOES; +RGLSYMGLGETTEXPARAMETERIIVOESPROC __rglgen_glGetTexParameterIivOES; +RGLSYMGLGETTEXPARAMETERIUIVOESPROC __rglgen_glGetTexParameterIuivOES; +RGLSYMGLSAMPLERPARAMETERIIVOESPROC __rglgen_glSamplerParameterIivOES; +RGLSYMGLSAMPLERPARAMETERIUIVOESPROC __rglgen_glSamplerParameterIuivOES; +RGLSYMGLGETSAMPLERPARAMETERIIVOESPROC __rglgen_glGetSamplerParameterIivOES; +RGLSYMGLGETSAMPLERPARAMETERIUIVOESPROC __rglgen_glGetSamplerParameterIuivOES; +RGLSYMGLTEXBUFFEROESPROC __rglgen_glTexBufferOES; +RGLSYMGLTEXBUFFERRANGEOESPROC __rglgen_glTexBufferRangeOES; +RGLSYMGLTEXSTORAGE3DMULTISAMPLEOESPROC __rglgen_glTexStorage3DMultisampleOES; +RGLSYMGLTEXTUREVIEWOESPROC __rglgen_glTextureViewOES; RGLSYMGLBINDVERTEXARRAYOESPROC __rglgen_glBindVertexArrayOES; RGLSYMGLDELETEVERTEXARRAYSOESPROC __rglgen_glDeleteVertexArraysOES; RGLSYMGLGENVERTEXARRAYSOESPROC __rglgen_glGenVertexArraysOES; RGLSYMGLISVERTEXARRAYOESPROC __rglgen_glIsVertexArrayOES; +RGLSYMGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC __rglgen_glDrawArraysInstancedBaseInstanceEXT; +RGLSYMGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC __rglgen_glDrawElementsInstancedBaseInstanceEXT; +RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC __rglgen_glDrawElementsInstancedBaseVertexBaseInstanceEXT; +RGLSYMGLBINDFRAGDATALOCATIONINDEXEDEXTPROC __rglgen_glBindFragDataLocationIndexedEXT; +RGLSYMGLBINDFRAGDATALOCATIONEXTPROC __rglgen_glBindFragDataLocationEXT; +RGLSYMGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC __rglgen_glGetProgramResourceLocationIndexEXT; +RGLSYMGLGETFRAGDATAINDEXEXTPROC __rglgen_glGetFragDataIndexEXT; +RGLSYMGLBUFFERSTORAGEEXTPROC __rglgen_glBufferStorageEXT; +RGLSYMGLCOPYIMAGESUBDATAEXTPROC __rglgen_glCopyImageSubDataEXT; +RGLSYMGLLABELOBJECTEXTPROC __rglgen_glLabelObjectEXT; +RGLSYMGLGETOBJECTLABELEXTPROC __rglgen_glGetObjectLabelEXT; +RGLSYMGLINSERTEVENTMARKEREXTPROC __rglgen_glInsertEventMarkerEXT; +RGLSYMGLPUSHGROUPMARKEREXTPROC __rglgen_glPushGroupMarkerEXT; +RGLSYMGLPOPGROUPMARKEREXTPROC __rglgen_glPopGroupMarkerEXT; +RGLSYMGLDISCARDFRAMEBUFFEREXTPROC __rglgen_glDiscardFramebufferEXT; +RGLSYMGLGENQUERIESEXTPROC __rglgen_glGenQueriesEXT; +RGLSYMGLDELETEQUERIESEXTPROC __rglgen_glDeleteQueriesEXT; +RGLSYMGLISQUERYEXTPROC __rglgen_glIsQueryEXT; +RGLSYMGLBEGINQUERYEXTPROC __rglgen_glBeginQueryEXT; +RGLSYMGLENDQUERYEXTPROC __rglgen_glEndQueryEXT; +RGLSYMGLQUERYCOUNTEREXTPROC __rglgen_glQueryCounterEXT; +RGLSYMGLGETQUERYIVEXTPROC __rglgen_glGetQueryivEXT; +RGLSYMGLGETQUERYOBJECTIVEXTPROC __rglgen_glGetQueryObjectivEXT; +RGLSYMGLGETQUERYOBJECTUIVEXTPROC __rglgen_glGetQueryObjectuivEXT; +RGLSYMGLDRAWBUFFERSEXTPROC __rglgen_glDrawBuffersEXT; +RGLSYMGLENABLEIEXTPROC __rglgen_glEnableiEXT; +RGLSYMGLDISABLEIEXTPROC __rglgen_glDisableiEXT; +RGLSYMGLBLENDEQUATIONIEXTPROC __rglgen_glBlendEquationiEXT; +RGLSYMGLBLENDEQUATIONSEPARATEIEXTPROC __rglgen_glBlendEquationSeparateiEXT; +RGLSYMGLBLENDFUNCIEXTPROC __rglgen_glBlendFunciEXT; +RGLSYMGLBLENDFUNCSEPARATEIEXTPROC __rglgen_glBlendFuncSeparateiEXT; +RGLSYMGLCOLORMASKIEXTPROC __rglgen_glColorMaskiEXT; +RGLSYMGLISENABLEDIEXTPROC __rglgen_glIsEnablediEXT; +RGLSYMGLDRAWELEMENTSBASEVERTEXEXTPROC __rglgen_glDrawElementsBaseVertexEXT; +RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC __rglgen_glDrawRangeElementsBaseVertexEXT; +RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC __rglgen_glDrawElementsInstancedBaseVertexEXT; +RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC __rglgen_glMultiDrawElementsBaseVertexEXT; +RGLSYMGLDRAWARRAYSINSTANCEDEXTPROC __rglgen_glDrawArraysInstancedEXT; +RGLSYMGLDRAWELEMENTSINSTANCEDEXTPROC __rglgen_glDrawElementsInstancedEXT; +RGLSYMGLFRAMEBUFFERTEXTUREEXTPROC __rglgen_glFramebufferTextureEXT; +RGLSYMGLVERTEXATTRIBDIVISOREXTPROC __rglgen_glVertexAttribDivisorEXT; +RGLSYMGLMAPBUFFERRANGEEXTPROC __rglgen_glMapBufferRangeEXT; +RGLSYMGLFLUSHMAPPEDBUFFERRANGEEXTPROC __rglgen_glFlushMappedBufferRangeEXT; +RGLSYMGLMULTIDRAWARRAYSEXTPROC __rglgen_glMultiDrawArraysEXT; +RGLSYMGLMULTIDRAWELEMENTSEXTPROC __rglgen_glMultiDrawElementsEXT; +RGLSYMGLMULTIDRAWARRAYSINDIRECTEXTPROC __rglgen_glMultiDrawArraysIndirectEXT; +RGLSYMGLMULTIDRAWELEMENTSINDIRECTEXTPROC __rglgen_glMultiDrawElementsIndirectEXT; +RGLSYMGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __rglgen_glRenderbufferStorageMultisampleEXT; +RGLSYMGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC __rglgen_glFramebufferTexture2DMultisampleEXT; +RGLSYMGLREADBUFFERINDEXEDEXTPROC __rglgen_glReadBufferIndexedEXT; +RGLSYMGLDRAWBUFFERSINDEXEDEXTPROC __rglgen_glDrawBuffersIndexedEXT; +RGLSYMGLGETINTEGERI_VEXTPROC __rglgen_glGetIntegeri_vEXT; +RGLSYMGLPRIMITIVEBOUNDINGBOXEXTPROC __rglgen_glPrimitiveBoundingBoxEXT; +RGLSYMGLRASTERSAMPLESEXTPROC __rglgen_glRasterSamplesEXT; +RGLSYMGLGETGRAPHICSRESETSTATUSEXTPROC __rglgen_glGetGraphicsResetStatusEXT; +RGLSYMGLREADNPIXELSEXTPROC __rglgen_glReadnPixelsEXT; +RGLSYMGLGETNUNIFORMFVEXTPROC __rglgen_glGetnUniformfvEXT; +RGLSYMGLGETNUNIFORMIVEXTPROC __rglgen_glGetnUniformivEXT; +RGLSYMGLACTIVESHADERPROGRAMEXTPROC __rglgen_glActiveShaderProgramEXT; +RGLSYMGLBINDPROGRAMPIPELINEEXTPROC __rglgen_glBindProgramPipelineEXT; +RGLSYMGLCREATESHADERPROGRAMVEXTPROC __rglgen_glCreateShaderProgramvEXT; +RGLSYMGLDELETEPROGRAMPIPELINESEXTPROC __rglgen_glDeleteProgramPipelinesEXT; +RGLSYMGLGENPROGRAMPIPELINESEXTPROC __rglgen_glGenProgramPipelinesEXT; +RGLSYMGLGETPROGRAMPIPELINEINFOLOGEXTPROC __rglgen_glGetProgramPipelineInfoLogEXT; +RGLSYMGLGETPROGRAMPIPELINEIVEXTPROC __rglgen_glGetProgramPipelineivEXT; +RGLSYMGLISPROGRAMPIPELINEEXTPROC __rglgen_glIsProgramPipelineEXT; +RGLSYMGLPROGRAMPARAMETERIEXTPROC __rglgen_glProgramParameteriEXT; +RGLSYMGLPROGRAMUNIFORM1FEXTPROC __rglgen_glProgramUniform1fEXT; +RGLSYMGLPROGRAMUNIFORM1FVEXTPROC __rglgen_glProgramUniform1fvEXT; +RGLSYMGLPROGRAMUNIFORM1IEXTPROC __rglgen_glProgramUniform1iEXT; +RGLSYMGLPROGRAMUNIFORM1IVEXTPROC __rglgen_glProgramUniform1ivEXT; +RGLSYMGLPROGRAMUNIFORM2FEXTPROC __rglgen_glProgramUniform2fEXT; +RGLSYMGLPROGRAMUNIFORM2FVEXTPROC __rglgen_glProgramUniform2fvEXT; +RGLSYMGLPROGRAMUNIFORM2IEXTPROC __rglgen_glProgramUniform2iEXT; +RGLSYMGLPROGRAMUNIFORM2IVEXTPROC __rglgen_glProgramUniform2ivEXT; +RGLSYMGLPROGRAMUNIFORM3FEXTPROC __rglgen_glProgramUniform3fEXT; +RGLSYMGLPROGRAMUNIFORM3FVEXTPROC __rglgen_glProgramUniform3fvEXT; +RGLSYMGLPROGRAMUNIFORM3IEXTPROC __rglgen_glProgramUniform3iEXT; +RGLSYMGLPROGRAMUNIFORM3IVEXTPROC __rglgen_glProgramUniform3ivEXT; +RGLSYMGLPROGRAMUNIFORM4FEXTPROC __rglgen_glProgramUniform4fEXT; +RGLSYMGLPROGRAMUNIFORM4FVEXTPROC __rglgen_glProgramUniform4fvEXT; +RGLSYMGLPROGRAMUNIFORM4IEXTPROC __rglgen_glProgramUniform4iEXT; +RGLSYMGLPROGRAMUNIFORM4IVEXTPROC __rglgen_glProgramUniform4ivEXT; +RGLSYMGLPROGRAMUNIFORMMATRIX2FVEXTPROC __rglgen_glProgramUniformMatrix2fvEXT; +RGLSYMGLPROGRAMUNIFORMMATRIX3FVEXTPROC __rglgen_glProgramUniformMatrix3fvEXT; +RGLSYMGLPROGRAMUNIFORMMATRIX4FVEXTPROC __rglgen_glProgramUniformMatrix4fvEXT; +RGLSYMGLUSEPROGRAMSTAGESEXTPROC __rglgen_glUseProgramStagesEXT; +RGLSYMGLVALIDATEPROGRAMPIPELINEEXTPROC __rglgen_glValidateProgramPipelineEXT; +RGLSYMGLPROGRAMUNIFORM1UIEXTPROC __rglgen_glProgramUniform1uiEXT; +RGLSYMGLPROGRAMUNIFORM2UIEXTPROC __rglgen_glProgramUniform2uiEXT; +RGLSYMGLPROGRAMUNIFORM3UIEXTPROC __rglgen_glProgramUniform3uiEXT; +RGLSYMGLPROGRAMUNIFORM4UIEXTPROC __rglgen_glProgramUniform4uiEXT; +RGLSYMGLPROGRAMUNIFORM1UIVEXTPROC __rglgen_glProgramUniform1uivEXT; +RGLSYMGLPROGRAMUNIFORM2UIVEXTPROC __rglgen_glProgramUniform2uivEXT; +RGLSYMGLPROGRAMUNIFORM3UIVEXTPROC __rglgen_glProgramUniform3uivEXT; +RGLSYMGLPROGRAMUNIFORM4UIVEXTPROC __rglgen_glProgramUniform4uivEXT; +RGLSYMGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC __rglgen_glProgramUniformMatrix2x3fvEXT; +RGLSYMGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC __rglgen_glProgramUniformMatrix3x2fvEXT; +RGLSYMGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC __rglgen_glProgramUniformMatrix2x4fvEXT; +RGLSYMGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC __rglgen_glProgramUniformMatrix4x2fvEXT; +RGLSYMGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC __rglgen_glProgramUniformMatrix3x4fvEXT; +RGLSYMGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC __rglgen_glProgramUniformMatrix4x3fvEXT; +RGLSYMGLTEXPAGECOMMITMENTEXTPROC __rglgen_glTexPageCommitmentEXT; +RGLSYMGLPATCHPARAMETERIEXTPROC __rglgen_glPatchParameteriEXT; +RGLSYMGLTEXPARAMETERIIVEXTPROC __rglgen_glTexParameterIivEXT; +RGLSYMGLTEXPARAMETERIUIVEXTPROC __rglgen_glTexParameterIuivEXT; +RGLSYMGLGETTEXPARAMETERIIVEXTPROC __rglgen_glGetTexParameterIivEXT; +RGLSYMGLGETTEXPARAMETERIUIVEXTPROC __rglgen_glGetTexParameterIuivEXT; +RGLSYMGLSAMPLERPARAMETERIIVEXTPROC __rglgen_glSamplerParameterIivEXT; +RGLSYMGLSAMPLERPARAMETERIUIVEXTPROC __rglgen_glSamplerParameterIuivEXT; +RGLSYMGLGETSAMPLERPARAMETERIIVEXTPROC __rglgen_glGetSamplerParameterIivEXT; +RGLSYMGLGETSAMPLERPARAMETERIUIVEXTPROC __rglgen_glGetSamplerParameterIuivEXT; +RGLSYMGLTEXBUFFEREXTPROC __rglgen_glTexBufferEXT; +RGLSYMGLTEXBUFFERRANGEEXTPROC __rglgen_glTexBufferRangeEXT; +RGLSYMGLTEXSTORAGE1DEXTPROC __rglgen_glTexStorage1DEXT; +RGLSYMGLTEXSTORAGE2DEXTPROC __rglgen_glTexStorage2DEXT; +RGLSYMGLTEXSTORAGE3DEXTPROC __rglgen_glTexStorage3DEXT; +RGLSYMGLTEXTURESTORAGE1DEXTPROC __rglgen_glTextureStorage1DEXT; +RGLSYMGLTEXTURESTORAGE2DEXTPROC __rglgen_glTextureStorage2DEXT; +RGLSYMGLTEXTURESTORAGE3DEXTPROC __rglgen_glTextureStorage3DEXT; +RGLSYMGLTEXTUREVIEWEXTPROC __rglgen_glTextureViewEXT; +RGLSYMGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultiviewOVR; +RGLSYMGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultisampleMultiviewOVR; diff --git a/desmume/src/libretro-common/glsym/glsym_es3.c b/desmume/src/libretro-common/glsym/glsym_es3.c new file mode 100644 index 000000000..2b9a3be7b --- /dev/null +++ b/desmume/src/libretro-common/glsym/glsym_es3.c @@ -0,0 +1,138 @@ +#include "glsym/glsym.h" +#include +#define SYM(x) { "gl" #x, &(gl##x) } +const struct rglgen_sym_map rglgen_symbol_map[] = { + SYM(BlendBarrierKHR), + SYM(DebugMessageControlKHR), + SYM(DebugMessageInsertKHR), + SYM(DebugMessageCallbackKHR), + SYM(GetDebugMessageLogKHR), + SYM(PushDebugGroupKHR), + SYM(PopDebugGroupKHR), + SYM(ObjectLabelKHR), + SYM(GetObjectLabelKHR), + SYM(ObjectPtrLabelKHR), + SYM(GetObjectPtrLabelKHR), + SYM(GetPointervKHR), + SYM(GetGraphicsResetStatusKHR), + SYM(ReadnPixelsKHR), + SYM(GetnUniformfvKHR), + SYM(GetnUniformivKHR), + SYM(GetnUniformuivKHR), + SYM(EGLImageTargetTexture2DOES), + SYM(EGLImageTargetRenderbufferStorageOES), + SYM(CopyImageSubDataOES), + SYM(EnableiOES), + SYM(DisableiOES), + SYM(BlendEquationiOES), + SYM(BlendEquationSeparateiOES), + SYM(BlendFunciOES), + SYM(BlendFuncSeparateiOES), + SYM(ColorMaskiOES), + SYM(IsEnablediOES), + SYM(DrawElementsBaseVertexOES), + SYM(DrawRangeElementsBaseVertexOES), + SYM(DrawElementsInstancedBaseVertexOES), + SYM(MultiDrawElementsBaseVertexOES), + SYM(FramebufferTextureOES), + SYM(GetProgramBinaryOES), + SYM(ProgramBinaryOES), + SYM(MapBufferOES), + SYM(UnmapBufferOES), + SYM(GetBufferPointervOES), + SYM(PrimitiveBoundingBoxOES), + SYM(MinSampleShadingOES), + SYM(PatchParameteriOES), + SYM(TexImage3DOES), + SYM(TexSubImage3DOES), + SYM(CopyTexSubImage3DOES), + SYM(CompressedTexImage3DOES), + SYM(CompressedTexSubImage3DOES), + SYM(FramebufferTexture3DOES), + SYM(TexParameterIivOES), + SYM(TexParameterIuivOES), + SYM(GetTexParameterIivOES), + SYM(GetTexParameterIuivOES), + SYM(SamplerParameterIivOES), + SYM(SamplerParameterIuivOES), + SYM(GetSamplerParameterIivOES), + SYM(GetSamplerParameterIuivOES), + SYM(TexBufferOES), + SYM(TexBufferRangeOES), + SYM(TexStorage3DMultisampleOES), + SYM(TextureViewOES), + SYM(BindVertexArrayOES), + SYM(DeleteVertexArraysOES), + SYM(GenVertexArraysOES), + SYM(IsVertexArrayOES), + SYM(FramebufferTextureMultiviewOVR), + SYM(FramebufferTextureMultisampleMultiviewOVR), + + { NULL, NULL }, +}; +RGLSYMGLBLENDBARRIERKHRPROC __rglgen_glBlendBarrierKHR; +RGLSYMGLDEBUGMESSAGECONTROLKHRPROC __rglgen_glDebugMessageControlKHR; +RGLSYMGLDEBUGMESSAGEINSERTKHRPROC __rglgen_glDebugMessageInsertKHR; +RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC __rglgen_glDebugMessageCallbackKHR; +RGLSYMGLGETDEBUGMESSAGELOGKHRPROC __rglgen_glGetDebugMessageLogKHR; +RGLSYMGLPUSHDEBUGGROUPKHRPROC __rglgen_glPushDebugGroupKHR; +RGLSYMGLPOPDEBUGGROUPKHRPROC __rglgen_glPopDebugGroupKHR; +RGLSYMGLOBJECTLABELKHRPROC __rglgen_glObjectLabelKHR; +RGLSYMGLGETOBJECTLABELKHRPROC __rglgen_glGetObjectLabelKHR; +RGLSYMGLOBJECTPTRLABELKHRPROC __rglgen_glObjectPtrLabelKHR; +RGLSYMGLGETOBJECTPTRLABELKHRPROC __rglgen_glGetObjectPtrLabelKHR; +RGLSYMGLGETPOINTERVKHRPROC __rglgen_glGetPointervKHR; +RGLSYMGLGETGRAPHICSRESETSTATUSKHRPROC __rglgen_glGetGraphicsResetStatusKHR; +RGLSYMGLREADNPIXELSKHRPROC __rglgen_glReadnPixelsKHR; +RGLSYMGLGETNUNIFORMFVKHRPROC __rglgen_glGetnUniformfvKHR; +RGLSYMGLGETNUNIFORMIVKHRPROC __rglgen_glGetnUniformivKHR; +RGLSYMGLGETNUNIFORMUIVKHRPROC __rglgen_glGetnUniformuivKHR; +RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC __rglgen_glEGLImageTargetTexture2DOES; +RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC __rglgen_glEGLImageTargetRenderbufferStorageOES; +RGLSYMGLCOPYIMAGESUBDATAOESPROC __rglgen_glCopyImageSubDataOES; +RGLSYMGLENABLEIOESPROC __rglgen_glEnableiOES; +RGLSYMGLDISABLEIOESPROC __rglgen_glDisableiOES; +RGLSYMGLBLENDEQUATIONIOESPROC __rglgen_glBlendEquationiOES; +RGLSYMGLBLENDEQUATIONSEPARATEIOESPROC __rglgen_glBlendEquationSeparateiOES; +RGLSYMGLBLENDFUNCIOESPROC __rglgen_glBlendFunciOES; +RGLSYMGLBLENDFUNCSEPARATEIOESPROC __rglgen_glBlendFuncSeparateiOES; +RGLSYMGLCOLORMASKIOESPROC __rglgen_glColorMaskiOES; +RGLSYMGLISENABLEDIOESPROC __rglgen_glIsEnablediOES; +RGLSYMGLDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glDrawElementsBaseVertexOES; +RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXOESPROC __rglgen_glDrawRangeElementsBaseVertexOES; +RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC __rglgen_glDrawElementsInstancedBaseVertexOES; +RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glMultiDrawElementsBaseVertexOES; +RGLSYMGLFRAMEBUFFERTEXTUREOESPROC __rglgen_glFramebufferTextureOES; +RGLSYMGLGETPROGRAMBINARYOESPROC __rglgen_glGetProgramBinaryOES; +RGLSYMGLPROGRAMBINARYOESPROC __rglgen_glProgramBinaryOES; +RGLSYMGLMAPBUFFEROESPROC __rglgen_glMapBufferOES; +RGLSYMGLUNMAPBUFFEROESPROC __rglgen_glUnmapBufferOES; +RGLSYMGLGETBUFFERPOINTERVOESPROC __rglgen_glGetBufferPointervOES; +RGLSYMGLPRIMITIVEBOUNDINGBOXOESPROC __rglgen_glPrimitiveBoundingBoxOES; +RGLSYMGLMINSAMPLESHADINGOESPROC __rglgen_glMinSampleShadingOES; +RGLSYMGLPATCHPARAMETERIOESPROC __rglgen_glPatchParameteriOES; +RGLSYMGLTEXIMAGE3DOESPROC __rglgen_glTexImage3DOES; +RGLSYMGLTEXSUBIMAGE3DOESPROC __rglgen_glTexSubImage3DOES; +RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC __rglgen_glCopyTexSubImage3DOES; +RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC __rglgen_glCompressedTexImage3DOES; +RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC __rglgen_glCompressedTexSubImage3DOES; +RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC __rglgen_glFramebufferTexture3DOES; +RGLSYMGLTEXPARAMETERIIVOESPROC __rglgen_glTexParameterIivOES; +RGLSYMGLTEXPARAMETERIUIVOESPROC __rglgen_glTexParameterIuivOES; +RGLSYMGLGETTEXPARAMETERIIVOESPROC __rglgen_glGetTexParameterIivOES; +RGLSYMGLGETTEXPARAMETERIUIVOESPROC __rglgen_glGetTexParameterIuivOES; +RGLSYMGLSAMPLERPARAMETERIIVOESPROC __rglgen_glSamplerParameterIivOES; +RGLSYMGLSAMPLERPARAMETERIUIVOESPROC __rglgen_glSamplerParameterIuivOES; +RGLSYMGLGETSAMPLERPARAMETERIIVOESPROC __rglgen_glGetSamplerParameterIivOES; +RGLSYMGLGETSAMPLERPARAMETERIUIVOESPROC __rglgen_glGetSamplerParameterIuivOES; +RGLSYMGLTEXBUFFEROESPROC __rglgen_glTexBufferOES; +RGLSYMGLTEXBUFFERRANGEOESPROC __rglgen_glTexBufferRangeOES; +RGLSYMGLTEXSTORAGE3DMULTISAMPLEOESPROC __rglgen_glTexStorage3DMultisampleOES; +RGLSYMGLTEXTUREVIEWOESPROC __rglgen_glTextureViewOES; +RGLSYMGLBINDVERTEXARRAYOESPROC __rglgen_glBindVertexArrayOES; +RGLSYMGLDELETEVERTEXARRAYSOESPROC __rglgen_glDeleteVertexArraysOES; +RGLSYMGLGENVERTEXARRAYSOESPROC __rglgen_glGenVertexArraysOES; +RGLSYMGLISVERTEXARRAYOESPROC __rglgen_glIsVertexArrayOES; +RGLSYMGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultiviewOVR; +RGLSYMGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultisampleMultiviewOVR; + diff --git a/desmume/src/libretro-common/glsym/rglgen.py b/desmume/src/libretro-common/glsym/rglgen.py new file mode 100755 index 000000000..897d8cbea --- /dev/null +++ b/desmume/src/libretro-common/glsym/rglgen.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 + +""" + License statement applies to this file (glgen.py) only. +""" + +""" + 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. +""" + +import sys +import os +import re + +banned_ext = [ 'AMD', 'APPLE', 'NV', 'NVX', 'ATI', '3DLABS', 'SUN', 'SGI', 'SGIX', 'SGIS', 'INTEL', '3DFX', 'IBM', 'MESA', 'GREMEDY', 'OML', 'PGI', 'I3D', 'INGL', 'MTX', 'QCOM', 'IMG', 'ANGLE', 'SUNX', 'INGR' ] + +def noext(sym): + for ext in banned_ext: + if sym.endswith(ext): + return False + return True + +def find_gl_symbols(lines): + typedefs = [] + syms = [] + for line in lines: + m = re.search(r'^typedef.+PFN(\S+)PROC.+$', line) + g = re.search(r'^.+(gl\S+)\W*\(.+\).*$', line) + if m and noext(m.group(1)): + typedefs.append(m.group(0).replace('PFN', 'RGLSYM').replace('GLDEBUGPROC', 'RGLGENGLDEBUGPROC')) + if g and noext(g.group(1)): + syms.append(g.group(1)) + return (typedefs, syms) + +def generate_defines(gl_syms): + res = [] + for line in gl_syms: + res.append('#define {} __rglgen_{}'.format(line, line)) + return res + +def generate_declarations(gl_syms): + return ['RGLSYM' + x.upper() + 'PROC ' + '__rglgen_' + x + ';' for x in gl_syms] + +def generate_macros(gl_syms): + return [' SYM(' + x.replace('gl', '') + '),' for x in gl_syms] + +def dump(f, lines): + f.write('\n'.join(lines)) + f.write('\n\n') + +if __name__ == '__main__': + + if len(sys.argv) > 4: + for banned in sys.argv[4:]: + banned_ext.append(banned) + + with open(sys.argv[1], 'r') as f: + lines = f.readlines() + typedefs, syms = find_gl_symbols(lines) + + overrides = generate_defines(syms) + declarations = generate_declarations(syms) + externs = ['extern ' + x for x in declarations] + + macros = generate_macros(syms) + + with open(sys.argv[2], 'w') as f: + f.write('#ifndef RGLGEN_DECL_H__\n') + f.write('#define RGLGEN_DECL_H__\n') + + f.write('#ifdef __cplusplus\n') + f.write('extern "C" {\n') + f.write('#endif\n') + + f.write('#ifdef GL_APIENTRY\n') + f.write('typedef void (GL_APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*);\n') + f.write('#else\n') + f.write('#ifndef APIENTRY\n') + f.write('#define APIENTRY\n') + f.write('#endif\n') + f.write('#ifndef APIENTRYP\n') + f.write('#define APIENTRYP APIENTRY *\n') + f.write('#endif\n') + f.write('typedef void (APIENTRY *RGLGENGLDEBUGPROCARB)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*);\n') + f.write('typedef void (APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*);\n') + f.write('#endif\n') + + f.write('#ifndef GL_OES_EGL_image\n') + f.write('typedef void *GLeglImageOES;\n') + f.write('#endif\n') + + f.write('#if !defined(GL_OES_fixed_point) && !defined(HAVE_OPENGLES2)\n') + f.write('typedef GLint GLfixed;\n') + f.write('#endif\n') + + dump(f, typedefs) + dump(f, overrides) + dump(f, externs) + + f.write('struct rglgen_sym_map { const char *sym; void *ptr; };\n') + f.write('extern const struct rglgen_sym_map rglgen_symbol_map[];\n') + + f.write('#ifdef __cplusplus\n') + f.write('}\n') + f.write('#endif\n') + + f.write('#endif\n') + + with open(sys.argv[3], 'w') as f: + f.write('#include "glsym/glsym.h"\n') + f.write('#include \n') + f.write('#define SYM(x) { "gl" #x, &(gl##x) }\n') + f.write('const struct rglgen_sym_map rglgen_symbol_map[] = {\n') + dump(f, macros) + f.write(' { NULL, NULL },\n') + f.write('};\n') + dump(f, declarations) + + diff --git a/desmume/src/libretro-common/include/algorithms/mismatch.h b/desmume/src/libretro-common/include/algorithms/mismatch.h new file mode 100644 index 000000000..1c87bf5be --- /dev/null +++ b/desmume/src/libretro-common/include/algorithms/mismatch.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (mismatch.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_ALGORITHMS_MISMATCH_H__ +#define __LIBRETRO_SDK_ALGORITHMS_MISMATCH_H__ + +#include +#include + +#include +#include + +RETRO_BEGIN_DECLS + +size_t find_change(const uint16_t *a, const uint16_t *b); + +size_t find_same(const uint16_t *a, const uint16_t *b); + +RETRO_END_DECLS + +#endif diff --git a/desmume/src/libretro-common/include/compat/getopt.h b/desmume/src/libretro-common/include/compat/getopt.h index ecb7cd55b..034e6ce30 100644 --- a/desmume/src/libretro-common/include/compat/getopt.h +++ b/desmume/src/libretro-common/include/compat/getopt.h @@ -38,9 +38,9 @@ * prefer to use the actual name. */ #define getopt_long(argc, argv, optstring, longopts, longindex) __getopt_long_retro(argc, argv, optstring, longopts, longindex) -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS struct option { @@ -57,9 +57,8 @@ int getopt_long(int argc, char *argv[], const char *optstring, const struct option *longopts, int *longindex); extern char *optarg; extern int optind, opterr, optopt; -#ifdef __cplusplus -} -#endif + +RETRO_END_DECLS /* If these are variously #defined, then we have bigger problems */ #ifndef no_argument diff --git a/desmume/src/libretro-common/include/compat/intrinsics.h b/desmume/src/libretro-common/include/compat/intrinsics.h new file mode 100644 index 000000000..51a0ed53d --- /dev/null +++ b/desmume/src/libretro-common/include/compat/intrinsics.h @@ -0,0 +1,91 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (intrinsics.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __LIBRETRO_SDK_COMPAT_INTRINSICS_H +#define __LIBRETRO_SDK_COMPAT_INTRINSICS_H + +#include +#include +#include + +#include +#include + +#ifdef _MSC_VER +#if (_MSC_VER > 1310) +#include +#endif +#endif + +RETRO_BEGIN_DECLS + +/* Count Leading Zero, unsigned 16bit input value */ +static INLINE unsigned compat_clz_u16(uint16_t val) +{ +#ifdef __GNUC__ + return __builtin_clz(val << 16 | 0x8000); +#else + unsigned ret = 0; + + while(!(val & 0x8000) && ret < 16) + { + val <<= 1; + ret++; + } + + return ret; +#endif +} + +/* Count Trailing Zero */ +#if defined(__GNUC__) && !defined(RARCH_CONSOLE) +static INLINE int compat_ctz(unsigned x) +{ + return __builtin_ctz(x); +} +#elif _MSC_VER >= 1400 +static INLINE int compat_ctz(unsigned x) +{ + unsigned long r = 0; + _BitScanReverse((unsigned long*)&r, x); + return (int)r; +} +#else +/* Only checks at nibble granularity, + * because that's what we need. */ +static INLINE int compat_ctz(unsigned x) +{ + if (x & 0x000f) + return 0; + if (x & 0x00f0) + return 4; + if (x & 0x0f00) + return 8; + if (x & 0xf000) + return 12; + return 16; +} +#endif + +RETRO_END_DECLS + +#endif diff --git a/desmume/src/libretro-common/include/compat/posix_string.h b/desmume/src/libretro-common/include/compat/posix_string.h index ac746b74f..2731231e2 100644 --- a/desmume/src/libretro-common/include/compat/posix_string.h +++ b/desmume/src/libretro-common/include/compat/posix_string.h @@ -23,13 +23,13 @@ #ifndef __LIBRETRO_SDK_COMPAT_POSIX_STRING_H #define __LIBRETRO_SDK_COMPAT_POSIX_STRING_H +#include + #ifdef _MSC_VER #include #endif -#ifdef __cplusplus -extern "C" { -#endif +RETRO_BEGIN_DECLS #ifdef _WIN32 #undef strtok_r @@ -56,8 +56,6 @@ int isblank(int c); #endif -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/compat/strcasestr.h b/desmume/src/libretro-common/include/compat/strcasestr.h index 0a8d2ca9c..31dc11bb4 100644 --- a/desmume/src/libretro-common/include/compat/strcasestr.h +++ b/desmume/src/libretro-common/include/compat/strcasestr.h @@ -30,9 +30,9 @@ #ifndef HAVE_STRCASESTR -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS /* Avoid possible naming collisions during link * since we prefer to use the actual name. */ @@ -40,9 +40,8 @@ extern "C" { char *strcasestr(const char *haystack, const char *needle); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS + #endif #endif diff --git a/desmume/src/libretro-common/include/compat/strl.h b/desmume/src/libretro-common/include/compat/strl.h index 465a75ee1..50d31aa64 100644 --- a/desmume/src/libretro-common/include/compat/strl.h +++ b/desmume/src/libretro-common/include/compat/strl.h @@ -30,9 +30,9 @@ #include "../../../config.h" #endif -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS #ifdef __MACH__ #ifndef HAVE_STRL @@ -52,9 +52,7 @@ size_t strlcat(char *dest, const char *source, size_t size); #endif -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/compat/zconf.h b/desmume/src/libretro-common/include/compat/zconf.h new file mode 100644 index 000000000..9987a7755 --- /dev/null +++ b/desmume/src/libretro-common/include/compat/zconf.h @@ -0,0 +1,511 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2013 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzvprintf z_gzvprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateGetDictionary z_inflateGetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateResetKeep z_inflateResetKeep +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/desmume/src/libretro-common/include/compat/zconf.h.in b/desmume/src/libretro-common/include/compat/zconf.h.in new file mode 100644 index 000000000..9987a7755 --- /dev/null +++ b/desmume/src/libretro-common/include/compat/zconf.h.in @@ -0,0 +1,511 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2013 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzvprintf z_gzvprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateGetDictionary z_inflateGetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateResetKeep z_inflateResetKeep +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/desmume/src/libretro-common/include/compat/zlib.h b/desmume/src/libretro-common/include/compat/zlib.h index bf3d53db4..894c8c05d 100644 --- a/desmume/src/libretro-common/include/compat/zlib.h +++ b/desmume/src/libretro-common/include/compat/zlib.h @@ -3,6 +3,10 @@ #ifdef WANT_ZLIB +#ifdef RARCH_INTERNAL +#include "zconf.h.in" +#endif + /* zlib.h -- interface of the 'zlib' general purpose compression library version 1.2.8, April 28th, 2013 diff --git a/desmume/src/libretro-common/include/conversion/float_to_s16.h b/desmume/src/libretro-common/include/conversion/float_to_s16.h new file mode 100644 index 000000000..3ee1aad11 --- /dev/null +++ b/desmume/src/libretro-common/include/conversion/float_to_s16.h @@ -0,0 +1,113 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (float_to_s16.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_CONVERSION_FLOAT_TO_S16_H__ +#define __LIBRETRO_SDK_CONVERSION_FLOAT_TO_S16_H__ + +#include + +RETRO_BEGIN_DECLS + +#include +#include + +/** + * convert_float_to_s16_C: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * + * Converts floating point + * to signed integer 16-bit. + * + * C implementation callback function. + **/ +void convert_float_to_s16_C(int16_t *out, + const float *in, size_t samples); + +#if defined(__SSE2__) +#define convert_float_to_s16 convert_float_to_s16_SSE2 +/** + * convert_float_to_s16_SSE2: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * + * Converts floating point + * to signed integer 16-bit. + * + * SSE2 implementation callback function. + **/ +void convert_float_to_s16_SSE2(int16_t *out, + const float *in, size_t samples); +#elif defined(__ALTIVEC__) +#define convert_float_to_s16 convert_float_to_s16_altivec +/** + * convert_float_to_s16_altivec: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * + * Converts floating point + * to signed integer 16-bit. + * + * AltiVec implementation callback function. + **/ +void convert_float_to_s16_altivec(int16_t *out, + const float *in, size_t samples); +#elif defined(__ARM_NEON__) && !defined(VITA) +#define convert_float_to_s16 convert_float_to_s16_arm + +void (*convert_float_to_s16_arm)(int16_t *out, + const float *in, size_t samples); + +void convert_float_s16_asm(int16_t *out, const float *in, size_t samples); +#elif defined(_MIPS_ARCH_ALLEGREX) +#define convert_float_to_s16 convert_float_to_s16_ALLEGREX +/** + * convert_float_to_s16_ALLEGREX: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * + * Converts floating point + * to signed integer 16-bit. + * + * MIPS ALLEGREX implementation callback function. + **/ +void convert_float_to_s16_ALLEGREX(int16_t *out, + const float *in, size_t samples); +#else +#define convert_float_to_s16 convert_float_to_s16_C +#endif + +/** + * convert_float_to_s16_init_simd: + * + * Sets up function pointers for conversion + * functions based on CPU features. + **/ +void convert_float_to_s16_init_simd(void); + +RETRO_END_DECLS + +#endif diff --git a/desmume/src/libretro-common/include/conversion/s16_to_float.h b/desmume/src/libretro-common/include/conversion/s16_to_float.h new file mode 100644 index 000000000..b418a6139 --- /dev/null +++ b/desmume/src/libretro-common/include/conversion/s16_to_float.h @@ -0,0 +1,120 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (s16_to_float.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_CONVERSION_S16_TO_FLOAT_H__ +#define __LIBRETRO_SDK_CONVERSION_S16_TO_FLOAT_H__ + +#include +#include + +#include + +RETRO_BEGIN_DECLS + +#if defined(__SSE2__) +#define convert_s16_to_float convert_s16_to_float_SSE2 + +/** + * convert_s16_to_float_SSE2: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * @gain : gain applied (.e.g. audio volume) + * + * Converts from signed integer 16-bit + * to floating point. + * + * SSE2 implementation callback function. + **/ +void convert_s16_to_float_SSE2(float *out, + const int16_t *in, size_t samples, float gain); + +#elif defined(__ALTIVEC__) +#define convert_s16_to_float convert_s16_to_float_altivec + +/** + * convert_s16_to_float_altivec: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * @gain : gain applied (.e.g. audio volume) + * + * Converts from signed integer 16-bit + * to floating point. + * + * AltiVec implementation callback function. + **/ +void convert_s16_to_float_altivec(float *out, + const int16_t *in, size_t samples, float gain); + +#elif defined(__ARM_NEON__) && !defined(VITA) +#define convert_s16_to_float convert_s16_to_float_arm + +void (*convert_s16_to_float_arm)(float *out, + const int16_t *in, size_t samples, float gain); + +#elif defined(_MIPS_ARCH_ALLEGREX) +#define convert_s16_to_float convert_s16_to_float_ALLEGREX + +/** + * convert_s16_to_float_ALLEGREX: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * @gain : gain applied (.e.g. audio volume) + * + * Converts from signed integer 16-bit + * to floating point. + * + * MIPS ALLEGREX implementation callback function. + **/ +void convert_s16_to_float_ALLEGREX(float *out, + const int16_t *in, size_t samples, float gain); +#else +#define convert_s16_to_float convert_s16_to_float_C +#endif + +/** + * convert_s16_to_float_C: + * @out : output buffer + * @in : input buffer + * @samples : size of samples to be converted + * @gain : gain applied (.e.g. audio volume) + * + * Converts from signed integer 16-bit + * to floating point. + * + * C implementation callback function. + **/ +void convert_s16_to_float_C(float *out, + const int16_t *in, size_t samples, float gain); + +/** + * convert_s16_to_float_init_simd: + * + * Sets up function pointers for conversion + * functions based on CPU features. + **/ +void convert_s16_to_float_init_simd(void); + +RETRO_END_DECLS + +#endif diff --git a/desmume/src/libretro-common/include/dynamic/dylib.h b/desmume/src/libretro-common/include/dynamic/dylib.h index 489a3cde1..7313e9a54 100644 --- a/desmume/src/libretro-common/include/dynamic/dylib.h +++ b/desmume/src/libretro-common/include/dynamic/dylib.h @@ -29,15 +29,15 @@ #include "config.h" #endif +#include + #if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB) #define NEED_DYNAMIC #else #undef NEED_DYNAMIC #endif -#ifdef __cplusplus -extern "C" { -#endif +RETRO_BEGIN_DECLS typedef void *dylib_t; typedef void (*function_t)(void); @@ -66,9 +66,6 @@ char *dylib_error(void); function_t dylib_proc(dylib_t lib, const char *proc); #endif -#ifdef __cplusplus -} -#endif - +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/features/features_cpu.h b/desmume/src/libretro-common/include/features/features_cpu.h new file mode 100644 index 000000000..eed29d0e5 --- /dev/null +++ b/desmume/src/libretro-common/include/features/features_cpu.h @@ -0,0 +1,71 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (features_cpu.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_CPU_INFO_H +#define _LIBRETRO_SDK_CPU_INFO_H + +#include + +#include + +#include + +RETRO_BEGIN_DECLS + +/** + * cpu_features_get_perf_counter: + * + * Gets performance counter. + * + * Returns: performance counter. + **/ +retro_perf_tick_t cpu_features_get_perf_counter(void); + +/** + * cpu_features_get_time_usec: + * + * Gets time in microseconds. * + * Returns: time in microseconds. + **/ +retro_time_t cpu_features_get_time_usec(void); + +/** + * cpu_features_get: + * + * Gets CPU features.. + * + * Returns: bitmask of all CPU features available. + **/ +uint64_t cpu_features_get(void); + +/** + * cpu_features_get_core_amount: + * + * Gets the amount of available CPU cores. + * + * Returns: amount of CPU cores available. + **/ +unsigned cpu_features_get_core_amount(void); + +RETRO_END_DECLS + +#endif diff --git a/desmume/src/libretro-common/include/file/config_file.h b/desmume/src/libretro-common/include/file/config_file.h index 81baca941..344f0931c 100644 --- a/desmume/src/libretro-common/include/file/config_file.h +++ b/desmume/src/libretro-common/include/file/config_file.h @@ -24,9 +24,9 @@ #ifndef __LIBRETRO_SDK_CONFIG_FILE_H #define __LIBRETRO_SDK_CONFIG_FILE_H -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS #include #include @@ -158,9 +158,7 @@ bool config_file_write(config_file_t *conf, const char *path); * Does not close the file. */ void config_file_dump(config_file_t *conf, FILE *file); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/file/file_path.h b/desmume/src/libretro-common/include/file/file_path.h index a5bcfe480..b861373b7 100644 --- a/desmume/src/libretro-common/include/file/file_path.h +++ b/desmume/src/libretro-common/include/file/file_path.h @@ -28,12 +28,12 @@ #include #include +#include + #include #include -#ifdef __cplusplus -extern "C" { -#endif +RETRO_BEGIN_DECLS /* Order in this enum is equivalent to negative sort order in filelist * (i.e. DIRECTORY is on top of PLAIN_FILE) */ @@ -211,6 +211,16 @@ void fill_dated_filename(char *out_filename, void fill_pathname_noext(char *out_path, const char *in_path, const char *replace, size_t size); +/** + * find_last_slash: + * @str : input path + * + * Gets a pointer to the last slash in the input path. + * + * Returns: a pointer to the last slash in the input path. + **/ +char *find_last_slash(const char *str); + /** * fill_pathname_dir: * @in_dir : input directory path @@ -241,6 +251,13 @@ void fill_pathname_dir(char *in_dir, const char *in_basename, **/ void fill_pathname_base(char *out_path, const char *in_path, size_t size); +void fill_pathname_base_noext(char *out_dir, + const char *in_path, size_t size); + +void fill_pathname_base_ext(char *out, + const char *in_path, const char *ext, + size_t size); + /** * fill_pathname_basedir: * @out_dir : output directory @@ -253,6 +270,9 @@ void fill_pathname_base(char *out_path, const char *in_path, size_t size); **/ void fill_pathname_basedir(char *out_path, const char *in_path, size_t size); +void fill_pathname_basedir_noext(char *out_dir, + const char *in_path, size_t size); + /** * fill_pathname_parent_dir: * @out_dir : output directory @@ -294,18 +314,18 @@ 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); +void fill_pathname_join_special_ext(char *out_path, + const char *dir, const char *path, + const char *last, const char *ext, + size_t size); + +void fill_pathname_join_concat(char *out_path, + const char *dir, const char *path, + const char *concat, + size_t size); + +void fill_pathname_join_noext(char *out_path, + const char *dir, const char *path, size_t size); /** * fill_pathname_join_delim: @@ -321,6 +341,10 @@ void fill_string_join(char *out_path, void fill_pathname_join_delim(char *out_path, const char *dir, const char *path, const char delim, size_t size); +void fill_pathname_join_delim_concat(char *out_path, const char *dir, + const char *path, const char delim, const char *concat, + size_t size); + /** * fill_short_pathname_representation: * @out_rep : output representation @@ -339,6 +363,9 @@ void fill_pathname_join_delim(char *out_path, const char *dir, void fill_short_pathname_representation(char* out_rep, const char *in_path, size_t size); +void fill_short_pathname_representation_noext(char* out_rep, + const char *in_path, size_t size); + void fill_pathname_expand_special(char *out_path, const char *in_path, size_t size); @@ -402,8 +429,6 @@ void fill_pathname_application_path(char *buf, size_t size); **/ bool path_mkdir(const char *dir); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/filters.h b/desmume/src/libretro-common/include/filters.h index 6c2559ec8..6ca3a5e29 100644 --- a/desmume/src/libretro-common/include/filters.h +++ b/desmume/src/libretro-common/include/filters.h @@ -29,6 +29,7 @@ #include #include #include +#include static INLINE double sinc(double val) { diff --git a/desmume/src/libretro-common/include/formats/image.h b/desmume/src/libretro-common/include/formats/image.h index 9ca5cd141..458a923b4 100644 --- a/desmume/src/libretro-common/include/formats/image.h +++ b/desmume/src/libretro-common/include/formats/image.h @@ -1,6 +1,6 @@ /* RetroArch - A frontend for libretro. * Copyright (C) 2010-2014 - Hans-Kristian Arntzen - * Copyright (C) 2011-2015 - Daniel De Matteis + * Copyright (C) 2011-2016 - 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- @@ -18,11 +18,12 @@ #define __RARCH_IMAGE_CONTEXT_H #include + +#include + #include -#ifdef __cplusplus -extern "C" { -#endif +RETRO_BEGIN_DECLS enum image_process_code { @@ -39,18 +40,50 @@ struct texture_image uint32_t *pixels; }; -bool video_texture_image_set_color_shifts(unsigned *r_shift, unsigned *g_shift, +enum image_type_enum +{ + IMAGE_TYPE_NONE = 0, + IMAGE_TYPE_PNG, + IMAGE_TYPE_JPEG, + IMAGE_TYPE_BMP, + IMAGE_TYPE_TGA +}; + +bool image_texture_set_color_shifts(unsigned *r_shift, unsigned *g_shift, unsigned *b_shift, unsigned *a_shift); -bool video_texture_image_color_convert(unsigned r_shift, +bool image_texture_color_convert(unsigned r_shift, unsigned g_shift, unsigned b_shift, unsigned a_shift, struct texture_image *out_img); -bool video_texture_image_load(struct texture_image *img, const char *path); -void video_texture_image_free(struct texture_image *img); +bool image_texture_load(struct texture_image *img, const char *path); +void image_texture_free(struct texture_image *img); +void image_texture_set_rgba(void); +void image_texture_unset_rgba(void); -#ifdef __cplusplus -} -#endif +/* Image transfer */ + +void image_transfer_free(void *data, enum image_type_enum type); + +void *image_transfer_new(enum image_type_enum type); + +bool image_transfer_start(void *data, enum image_type_enum type); + +void image_transfer_set_buffer_ptr( + void *data, + enum image_type_enum type, + void *ptr); + +int image_transfer_process( + void *data, + enum image_type_enum type, + uint32_t **buf, size_t size, + unsigned *width, unsigned *height); + +bool image_transfer_iterate(void *data, enum image_type_enum type); + +bool image_transfer_is_valid(void *data, enum image_type_enum type); + +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/formats/jsonsax.h b/desmume/src/libretro-common/include/formats/jsonsax.h index 76860fe5f..86d6d6b20 100644 --- a/desmume/src/libretro-common/include/formats/jsonsax.h +++ b/desmume/src/libretro-common/include/formats/jsonsax.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2015 The RetroArch team +/* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (jsonsax.h). diff --git a/desmume/src/libretro-common/include/formats/rbmp.h b/desmume/src/libretro-common/include/formats/rbmp.h index e74d2b196..bc0702758 100644 --- a/desmume/src/libretro-common/include/formats/rbmp.h +++ b/desmume/src/libretro-common/include/formats/rbmp.h @@ -23,11 +23,11 @@ #ifndef __LIBRETRO_SDK_FORMAT_RBMP_H__ #define __LIBRETRO_SDK_FORMAT_RBMP_H__ +#include + #include -#ifdef __cplusplus -extern "C" { -#endif +RETRO_BEGIN_DECLS enum rbmp_source_type { @@ -38,6 +38,8 @@ enum rbmp_source_type RBMP_SOURCE_TYPE_ARGB8888 }; +typedef struct rbmp rbmp_t; + bool rbmp_save_image( const char *filename, const void *frame, @@ -46,8 +48,15 @@ bool rbmp_save_image( unsigned pitch, enum rbmp_source_type type); -#ifdef __cplusplus -} -#endif +int rbmp_process_image(rbmp_t *rbmp, void **buf, + size_t size, unsigned *width, unsigned *height); + +bool rbmp_set_buf_ptr(rbmp_t *rbmp, void *data); + +void rbmp_free(rbmp_t *rbmp); + +rbmp_t *rbmp_alloc(void); + +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/formats/rjpeg.h b/desmume/src/libretro-common/include/formats/rjpeg.h new file mode 100644 index 000000000..27050ea41 --- /dev/null +++ b/desmume/src/libretro-common/include/formats/rjpeg.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (rjpeg.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_RJPEG_H__ +#define __LIBRETRO_SDK_FORMAT_RJPEG_H__ + +#include +#include + +#include + +#include + +RETRO_BEGIN_DECLS + +typedef struct rjpeg rjpeg_t; + +int rjpeg_process_image(rjpeg_t *rjpeg, void **buf, + size_t size, unsigned *width, unsigned *height); + +bool rjpeg_set_buf_ptr(rjpeg_t *rjpeg, void *data); + +void rjpeg_free(rjpeg_t *rjpeg); + +rjpeg_t *rjpeg_alloc(void); + +RETRO_END_DECLS + +#endif + diff --git a/desmume/src/libretro-common/include/formats/rpng.h b/desmume/src/libretro-common/include/formats/rpng.h index 7997edadd..08b1a693d 100644 --- a/desmume/src/libretro-common/include/formats/rpng.h +++ b/desmume/src/libretro-common/include/formats/rpng.h @@ -26,45 +26,37 @@ #include #include -#include -#include +#include -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS typedef struct rpng rpng_t; -bool rpng_load_image_argb(const char *path, uint32_t **data, - unsigned *width, unsigned *height); - -rpng_t *rpng_nbio_load_image_argb_init(const char *path); +rpng_t *rpng_init(const char *path); bool rpng_is_valid(rpng_t *rpng); -bool rpng_set_buf_ptr(rpng_t *rpng, uint8_t *data); +bool rpng_set_buf_ptr(rpng_t *rpng, void *data); rpng_t *rpng_alloc(void); -void rpng_nbio_load_image_free(rpng_t *rpng); +void rpng_free(rpng_t *rpng); -bool rpng_nbio_load_image_argb_iterate(rpng_t *rpng); +bool rpng_iterate_image(rpng_t *rpng); -int rpng_nbio_load_image_argb_process(rpng_t *rpng, - uint32_t **data, unsigned *width, unsigned *height); +int rpng_process_image(rpng_t *rpng, + void **data, size_t size, unsigned *width, unsigned *height); -bool rpng_nbio_load_image_argb_start(rpng_t *rpng); +bool rpng_start(rpng_t *rpng); -#ifdef HAVE_ZLIB_DEFLATE bool rpng_save_image_argb(const char *path, const uint32_t *data, unsigned width, unsigned height, unsigned pitch); bool rpng_save_image_bgr24(const char *path, const uint8_t *data, unsigned width, unsigned height, unsigned pitch); -#endif -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/formats/rtga.h b/desmume/src/libretro-common/include/formats/rtga.h new file mode 100644 index 000000000..bb6d97a29 --- /dev/null +++ b/desmume/src/libretro-common/include/formats/rtga.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (rtga.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_RTGA_H__ +#define __LIBRETRO_SDK_FORMAT_RTGA_H__ + +#include +#include + +#include + +#include + +RETRO_BEGIN_DECLS + +typedef struct rtga rtga_t; + +int rtga_process_image(rtga_t *rtga, void **buf, + size_t size, unsigned *width, unsigned *height); + +bool rtga_set_buf_ptr(rtga_t *rtga, void *data); + +void rtga_free(rtga_t *rtga); + +rtga_t *rtga_alloc(void); + +RETRO_END_DECLS + +#endif diff --git a/desmume/src/libretro-common/include/formats/rxml.h b/desmume/src/libretro-common/include/formats/rxml.h index ecebefee9..c3f3335c1 100644 --- a/desmume/src/libretro-common/include/formats/rxml.h +++ b/desmume/src/libretro-common/include/formats/rxml.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2015 The RetroArch team +/* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rxml.h). @@ -22,9 +22,9 @@ #ifndef __LIBRETRO_SDK_FORMAT_RXML_H__ #define __LIBRETRO_SDK_FORMAT_RXML_H__ -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS /* Total NIH. Very trivial "XML" implementation for use in RetroArch. * Error checking is minimal. Invalid documents may lead to very @@ -89,9 +89,7 @@ typedef rxml_document_t *xmlDocPtr; #define xmlFreeParserCtxt(ctx) ((void)0) #endif -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/gfx/math/matrix_3x3.h b/desmume/src/libretro-common/include/gfx/math/matrix_3x3.h index 507d41e68..f3819b6e0 100644 --- a/desmume/src/libretro-common/include/gfx/math/matrix_3x3.h +++ b/desmume/src/libretro-common/include/gfx/math/matrix_3x3.h @@ -41,7 +41,7 @@ void matrix_3x3_transpose(math_matrix_3x3 *out, const math_matrix_3x3 *in); void matrix_3x3_multiply(math_matrix_3x3 *out, const math_matrix_3x3 *a, const math_matrix_3x3 *b); -void matrix_3x3_divide_scalar(math_matrix_3x3 *mat, float s); +void matrix_3x3_divide_scalar(math_matrix_3x3 *mat, const float s); float matrix_3x3_determinant(const math_matrix_3x3 *mat); void matrix_3x3_adjoint(math_matrix_3x3 *mat); bool matrix_3x3_invert(math_matrix_3x3 *mat); diff --git a/desmume/src/libretro-common/include/gfx/math/matrix_4x4.h b/desmume/src/libretro-common/include/gfx/math/matrix_4x4.h index 59620830e..ab6f16e83 100644 --- a/desmume/src/libretro-common/include/gfx/math/matrix_4x4.h +++ b/desmume/src/libretro-common/include/gfx/math/matrix_4x4.h @@ -35,6 +35,7 @@ typedef struct math_matrix_4x4 #define MAT_ELEM_4X4(mat, r, c) ((mat).data[4 * (c) + (r)]) +void matrix_4x4_copy(math_matrix_4x4 *dst, const math_matrix_4x4 *src); void matrix_4x4_identity(math_matrix_4x4 *mat); void matrix_4x4_transpose(math_matrix_4x4 *out, const math_matrix_4x4 *in); diff --git a/desmume/src/libretro-common/include/gfx/math/vector_2.h b/desmume/src/libretro-common/include/gfx/math/vector_2.h new file mode 100644 index 000000000..430652bbb --- /dev/null +++ b/desmume/src/libretro-common/include/gfx/math/vector_2.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (vector_2.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_GFX_MATH_VECTOR_3_H__ +#define __LIBRETRO_SDK_GFX_MATH_VECTOR_3_H__ + +#include + +typedef float vec2_t[2]; + +float vec2_dot(const float *a, const float *b); + +float vec2_cross(const float *a, const float *b) ; + +void vec2_add(float *dst, const float *src); + +void vec2_subtract(float *dst, const float *src); + +void vec2_copy(float *dst, const float *src); + +#endif + diff --git a/desmume/src/libretro-common/include/gfx/math/vector_3.h b/desmume/src/libretro-common/include/gfx/math/vector_3.h new file mode 100644 index 000000000..022401122 --- /dev/null +++ b/desmume/src/libretro-common/include/gfx/math/vector_3.h @@ -0,0 +1,47 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (vector_3.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_GFX_MATH_VECTOR_3_H__ +#define __LIBRETRO_SDK_GFX_MATH_VECTOR_3_H__ + +#include + +typedef float vec3_t[3]; + +float vec3_dot(const float *a, const float *b); + +void vec3_cross(float* dst, const float *a, const float *b); + +float vec3_length(const float *a); + +void vec3_add(float *dst, const float *src); + +void vec3_subtract(float *dst, const float *src); + +void vec3_scale(float *dst, const float scale); + +void vec3_copy(float *dst, const float *src); + +void vec3_normalize(float *dst); + +#endif + diff --git a/desmume/src/libretro-common/include/gfx/scaler/filter.h b/desmume/src/libretro-common/include/gfx/scaler/filter.h index e3b43c4ad..11aa02020 100644 --- a/desmume/src/libretro-common/include/gfx/scaler/filter.h +++ b/desmume/src/libretro-common/include/gfx/scaler/filter.h @@ -23,18 +23,16 @@ #ifndef __LIBRETRO_SDK_SCALER_FILTER_H__ #define __LIBRETRO_SDK_SCALER_FILTER_H__ -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS #include #include bool scaler_gen_filter(struct scaler_ctx *ctx); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/gfx/scaler/scaler.h b/desmume/src/libretro-common/include/gfx/scaler/scaler.h index e4937f7e8..8a68f92af 100644 --- a/desmume/src/libretro-common/include/gfx/scaler/scaler.h +++ b/desmume/src/libretro-common/include/gfx/scaler/scaler.h @@ -23,15 +23,15 @@ #ifndef __LIBRETRO_SDK_SCALER_H__ #define __LIBRETRO_SDK_SCALER_H__ -#ifdef __cplusplus -extern "C" { -#endif +#include #include #include #include #include +RETRO_BEGIN_DECLS + #define FILTER_UNITY (1 << 14) enum scaler_pix_fmt @@ -145,9 +145,7 @@ void *scaler_alloc(size_t elem_size, size_t size); **/ void scaler_free(void *ptr); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/glsm/glsm.h b/desmume/src/libretro-common/include/glsm/glsm.h index 940433cd9..f35b2e382 100644 --- a/desmume/src/libretro-common/include/glsm/glsm.h +++ b/desmume/src/libretro-common/include/glsm/glsm.h @@ -23,13 +23,13 @@ #ifndef LIBRETRO_SDK_GLSM_H #define LIBRETRO_SDK_GLSM_H +#include + #include #include #include -#ifdef __cplusplus -extern "C" { -#endif +RETRO_BEGIN_DECLS #ifdef HAVE_OPENGLES2 typedef GLfloat GLdouble; @@ -80,8 +80,11 @@ typedef GLclampf GLclampd; #define GL_ALPHA_TEST 0x0BC0 #endif +#ifndef GL_CLIP_DISTANCE0 +#define GL_CLIP_DISTANCE0 0x3000 +#endif + #define MAX_ATTRIB 8 -#define MAX_TEXTURE 32 enum { @@ -113,13 +116,13 @@ enum glsm_state_ctl GLSM_CTL_STATE_BIND, GLSM_CTL_STATE_UNBIND, GLSM_CTL_STATE_CONTEXT_RESET, + GLSM_CTL_STATE_CONTEXT_DESTROY, 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 }; @@ -145,10 +148,10 @@ typedef struct glsm_ctx_params unsigned minor; } glsm_ctx_params_t; +GLuint glsm_get_current_framebuffer(void); + bool glsm_ctl(enum glsm_state_ctl state, void *data); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/glsm/glsmsym.h b/desmume/src/libretro-common/include/glsm/glsmsym.h index 78553a372..559611743 100644 --- a/desmume/src/libretro-common/include/glsm/glsmsym.h +++ b/desmume/src/libretro-common/include/glsm/glsmsym.h @@ -25,9 +25,9 @@ #include -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS /* deprecated old FF-style GL symbols */ #define glTexCoord2f rglTexCoord2f @@ -72,6 +72,8 @@ extern "C" { #define glEnableVertexAttribArray rglEnableVertexAttribArray #define glDisableVertexAttribArray rglDisableVertexAttribArray #define glVertexAttribPointer rglVertexAttribPointer +#define glVertexAttribIPointer rglVertexAttribIPointer +#define glVertexAttribLPointer rglVertexAttribLPointer #define glGetUniformLocation rglGetUniformLocation #define glGenBuffers rglGenBuffers #define glDisable(T) rglDisable(S##T) @@ -93,8 +95,14 @@ extern "C" { #define glUniform2fv rglUniform2fv #define glUniform3f rglUniform3f #define glUniform3fv rglUniform3fv +#define glUniform4i rglUniform4i #define glUniform4f rglUniform4f #define glUniform4fv rglUniform4fv +#define glUniform1ui rglUniform1ui +#define glUniform2ui rglUniform2ui +#define glUniform3ui rglUniform3ui +#define glUniform4ui rglUniform4ui +#define glGetActiveUniform rglGetActiveUniform #define glBlendFunc rglBlendFunc #define glBlendFuncSeparate rglBlendFuncSeparate #define glDepthFunc rglDepthFunc @@ -119,7 +127,104 @@ extern "C" { #define glBindVertexArray rglBindVertexArray #define glBlendEquation rglBlendEquation #define glBlendColor rglBlendColor +#define glBlendEquationSeparate rglBlendEquationSeparate +#define glCopyImageSubData rglCopyImageSubData +#define glMapBuffer rglMapBuffer +#define glUnmapBuffer rglUnmapBuffer +#define glMapBufferRange rglMapBufferRange +#define glUniformBlockBinding rglUniformBlockBinding +#define glGetUniformBlockIndex rglGetUniformBlockIndex +#define glGetActiveUniformBlockiv rglGetActiveUniformBlockiv +#define glBindBufferBase rglBindBufferBase +#define glGetUniformIndices rglGetUniformIndices +#define glGetActiveUniformsiv rglGetActiveUniformsiv +#define glGetError rglGetError +#define glClear rglClear +#define glPolygonMode rglPolygonMode +#define glLineWidth rglLineWidth +#define glTexImage2DMultisample rglTexImage2DMultisample +#define glTexStorage2DMultisample rglTexStorage2DMultisample +#define glMemoryBarrier rglMemoryBarrier +#define glBindImageTexture rglBindImageTexture +#define glProgramBinary rglProgramBinary +#define glGetProgramBinary rglGetProgramBinary +#define glProgramParameteri rglProgramParameteri +#define glTexSubImage2D rglTexSubImage2D +#define glDeleteVertexArrays rglDeleteVertexArrays +#define glRenderbufferStorageMultisample rglRenderbufferStorageMultisample +#define glUniform1iv rglUniform1iv +#define glUniform1fv rglUniform1fv +#define glValidateProgram rglValidateProgram +#define glGetStringi rglGetStringi +#define glTexBuffer rglTexBuffer +#define glClearBufferfv rglClearBufferfv +#define glClearBufferfi rglClearBufferfi +#define glWaitSync rglWaitSync +#define glFenceSync rglFenceSync +const GLubyte* rglGetStringi(GLenum name, GLuint index); +void rglTexBuffer(GLenum target, GLenum internalFormat, GLuint buffer); +void rglClearBufferfv( GLenum buffer, + GLint drawBuffer, + const GLfloat * value); +void rglClearBufferfi( GLenum buffer, + GLint drawBuffer, + GLfloat depth, + GLint stencil); +void rglValidateProgram(GLuint program); +void rglRenderbufferStorageMultisample( GLenum target, + GLsizei samples, + GLenum internalformat, + GLsizei width, + GLsizei height); +void rglUniform1iv(GLint location, GLsizei count, const GLint *value); +void rglUniform1fv(GLint location, GLsizei count, const GLfloat *value); +void rglProgramParameteri( GLuint program, + GLenum pname, + GLint value); +void rglGetProgramBinary( GLuint program, + GLsizei bufsize, + GLsizei *length, + GLenum *binaryFormat, + void *binary); +void rglProgramBinary(GLuint program, + GLenum binaryFormat, + const void *binary, + GLsizei length); +void rglBindImageTexture( GLuint unit, + GLuint texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLenum format); +void rglTexStorage2DMultisample(GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height, + GLboolean fixedsamplelocations); +void rglGetActiveUniformsiv( GLuint program, + GLsizei uniformCount, + const GLuint *uniformIndices, + GLenum pname, + GLint *params); +void rglGetUniformIndices( GLuint program, + GLsizei uniformCount, + const GLchar **uniformNames, + GLuint *uniformIndices); +void rglBindBufferBase( GLenum target, + GLuint index, + GLuint buffer); +void rglGetActiveUniformBlockiv( GLuint program, + GLuint uniformBlockIndex, + GLenum pname, + GLint *params); +GLuint rglGetUniformBlockIndex( GLuint program, + const GLchar *uniformBlockName); +void * rglMapBuffer( GLenum target, GLenum access); +void *rglMapBufferRange( GLenum target, + GLintptr offset, + GLsizeiptr length, + GLbitfield access); +GLboolean rglUnmapBuffer( GLenum target); void rglBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); void rglBlendEquation(GLenum mode); void rglGenVertexArrays(GLsizei n, GLuint *arrays); @@ -194,6 +299,7 @@ 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 rglUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); 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); @@ -231,8 +337,67 @@ GLint rglGetAttribLocation(GLuint program, const GLchar *name); void rglDrawBuffers(GLsizei n, const GLenum *bufs); void rglBindVertexArray(GLuint array); -#ifdef __cplusplus -} -#endif +void rglGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, + GLsizei *length, GLint *size, GLenum *type, GLchar *name); +void rglUniform1ui(GLint location, GLuint v); +void rglUniform2ui(GLint location, GLuint v0, GLuint v1); +void rglUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2); +void rglUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void rglBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); +void rglCopyImageSubData( GLuint srcName, + GLenum srcTarget, + GLint srcLevel, + GLint srcX, + GLint srcY, + GLint srcZ, + GLuint dstName, + GLenum dstTarget, + GLint dstLevel, + GLint dstX, + GLint dstY, + GLint dstZ, + GLsizei srcWidth, + GLsizei srcHeight, + GLsizei srcDepth); +void rglVertexAttribIPointer( + GLuint index, + GLint size, + GLenum type, + GLsizei stride, + const GLvoid * pointer); +void rglVertexAttribLPointer( + GLuint index, + GLint size, + GLenum type, + GLsizei stride, + const GLvoid * pointer); +void rglUniformBlockBinding( GLuint program, + GLuint uniformBlockIndex, + GLuint uniformBlockBinding); +GLenum rglGetError(void); +void rglClear(GLbitfield mask); +void rglPolygonMode(GLenum face, GLenum mode); +void rglLineWidth(GLfloat width); +void rglTexImage2DMultisample( GLenum target, + GLsizei samples, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLboolean fixedsamplelocations); +void rglMemoryBarrier( GLbitfield barriers); +void rglTexSubImage2D( GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + const GLvoid * pixels); +void rglDeleteVertexArrays(GLsizei n, const GLuint *arrays); +void *rglFenceSync(GLenum condition, GLbitfield flags); +void rglWaitSync(void *sync, GLbitfield flags, uint64_t timeout); + +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/glsym/glsym.h b/desmume/src/libretro-common/include/glsym/glsym.h index 28aaf724c..4dd7bfd0a 100644 --- a/desmume/src/libretro-common/include/glsym/glsym.h +++ b/desmume/src/libretro-common/include/glsym/glsym.h @@ -26,8 +26,10 @@ #include "rglgen.h" #ifndef HAVE_PSGL -#ifdef HAVE_OPENGLES2 +#if defined(HAVE_OPENGLES2) #include "glsym_es2.h" +#elif defined(HAVE_OPENGLES3) +#include "glsym_es3.h" #else #include "glsym_gl.h" #endif diff --git a/desmume/src/libretro-common/include/glsym/glsym_es2.h b/desmume/src/libretro-common/include/glsym/glsym_es2.h index b68f8a98f..526b6df70 100644 --- a/desmume/src/libretro-common/include/glsym/glsym_es2.h +++ b/desmume/src/libretro-common/include/glsym/glsym_es2.h @@ -1,25 +1,3 @@ -/* Copyright (C) 2010-2015 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this libretro SDK code part (glsym). - * --------------------------------------------------------------------------------------- - * - * 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 RGLGEN_DECL_H__ #define RGLGEN_DECL_H__ #ifdef __cplusplus @@ -50,6 +28,7 @@ typedef unsigned long long int GLuint64; typedef unsigned long long int GLuint64EXT; typedef struct __GLsync *GLsync; #endif +typedef void (GL_APIENTRYP RGLSYMGLBLENDBARRIERKHRPROC) (void); typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGECONTROLKHRPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGEINSERTKHRPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC) (RGLGENGLDEBUGPROCKHR callback, const void *userParam); @@ -61,24 +40,182 @@ typedef void (GL_APIENTRYP RGLSYMGLGETOBJECTLABELKHRPROC) (GLenum identifier, GL typedef void (GL_APIENTRYP RGLSYMGLOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei length, const GLchar *label); typedef void (GL_APIENTRYP RGLSYMGLGETOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); typedef void (GL_APIENTRYP RGLSYMGLGETPOINTERVKHRPROC) (GLenum pname, void **params); +typedef GLenum (GL_APIENTRYP RGLSYMGLGETGRAPHICSRESETSTATUSKHRPROC) (void); +typedef void (GL_APIENTRYP RGLSYMGLREADNPIXELSKHRPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMFVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); +typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMUIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params); typedef void (GL_APIENTRYP RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); typedef void (GL_APIENTRYP RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); +typedef void (GL_APIENTRYP RGLSYMGLCOPYIMAGESUBDATAOESPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +typedef void (GL_APIENTRYP RGLSYMGLENABLEIOESPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP RGLSYMGLDISABLEIOESPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP RGLSYMGLBLENDEQUATIONIOESPROC) (GLuint buf, GLenum mode); +typedef void (GL_APIENTRYP RGLSYMGLBLENDEQUATIONSEPARATEIOESPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GL_APIENTRYP RGLSYMGLBLENDFUNCIOESPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (GL_APIENTRYP RGLSYMGLBLENDFUNCSEPARATEIOESPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (GL_APIENTRYP RGLSYMGLCOLORMASKIOESPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef GLboolean (GL_APIENTRYP RGLSYMGLISENABLEDIOESPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (GL_APIENTRYP RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); +typedef void (GL_APIENTRYP RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex); +typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREOESPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); typedef void (GL_APIENTRYP RGLSYMGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); typedef void (GL_APIENTRYP RGLSYMGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLint length); typedef void *(GL_APIENTRYP RGLSYMGLMAPBUFFEROESPROC) (GLenum target, GLenum access); typedef GLboolean (GL_APIENTRYP RGLSYMGLUNMAPBUFFEROESPROC) (GLenum target); typedef void (GL_APIENTRYP RGLSYMGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void **params); +typedef void (GL_APIENTRYP RGLSYMGLPRIMITIVEBOUNDINGBOXOESPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); +typedef void (GL_APIENTRYP RGLSYMGLMINSAMPLESHADINGOESPROC) (GLfloat value); +typedef void (GL_APIENTRYP RGLSYMGLPATCHPARAMETERIOESPROC) (GLenum pname, GLint value); typedef void (GL_APIENTRYP RGLSYMGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); typedef void (GL_APIENTRYP RGLSYMGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); typedef void (GL_APIENTRYP RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); typedef void (GL_APIENTRYP RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); typedef void (GL_APIENTRYP RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GL_APIENTRYP RGLSYMGLTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GL_APIENTRYP RGLSYMGLTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, const GLuint *params); +typedef void (GL_APIENTRYP RGLSYMGLGETTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP RGLSYMGLGETTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP RGLSYMGLSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, const GLint *param); +typedef void (GL_APIENTRYP RGLSYMGLSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, const GLuint *param); +typedef void (GL_APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP RGLSYMGLTEXBUFFEROESPROC) (GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GL_APIENTRYP RGLSYMGLTEXBUFFERRANGEOESPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GL_APIENTRYP RGLSYMGLTEXSTORAGE3DMULTISAMPLEOESPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (GL_APIENTRYP RGLSYMGLTEXTUREVIEWOESPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); typedef void (GL_APIENTRYP RGLSYMGLBINDVERTEXARRAYOESPROC) (GLuint array); typedef void (GL_APIENTRYP RGLSYMGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays); typedef void (GL_APIENTRYP RGLSYMGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays); typedef GLboolean (GL_APIENTRYP RGLSYMGLISVERTEXARRAYOESPROC) (GLuint array); +typedef void (GL_APIENTRYP RGLSYMGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); +typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance); +typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); +typedef void (GL_APIENTRYP RGLSYMGLBINDFRAGDATALOCATIONINDEXEDEXTPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name); +typedef void (GL_APIENTRYP RGLSYMGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name); +typedef GLint (GL_APIENTRYP RGLSYMGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC) (GLuint program, GLenum programInterface, const GLchar *name); +typedef GLint (GL_APIENTRYP RGLSYMGLGETFRAGDATAINDEXEXTPROC) (GLuint program, const GLchar *name); +typedef void (GL_APIENTRYP RGLSYMGLBUFFERSTORAGEEXTPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); +typedef void (GL_APIENTRYP RGLSYMGLCOPYIMAGESUBDATAEXTPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +typedef void (GL_APIENTRYP RGLSYMGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label); +typedef void (GL_APIENTRYP RGLSYMGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); +typedef void (GL_APIENTRYP RGLSYMGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker); +typedef void (GL_APIENTRYP RGLSYMGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker); +typedef void (GL_APIENTRYP RGLSYMGLPOPGROUPMARKEREXTPROC) (void); +typedef void (GL_APIENTRYP RGLSYMGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); +typedef void (GL_APIENTRYP RGLSYMGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids); +typedef void (GL_APIENTRYP RGLSYMGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (GL_APIENTRYP RGLSYMGLISQUERYEXTPROC) (GLuint id); +typedef void (GL_APIENTRYP RGLSYMGLBEGINQUERYEXTPROC) (GLenum target, GLuint id); +typedef void (GL_APIENTRYP RGLSYMGLENDQUERYEXTPROC) (GLenum target); +typedef void (GL_APIENTRYP RGLSYMGLQUERYCOUNTEREXTPROC) (GLuint id, GLenum target); +typedef void (GL_APIENTRYP RGLSYMGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP RGLSYMGLGETQUERYOBJECTIVEXTPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP RGLSYMGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP RGLSYMGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs); +typedef void (GL_APIENTRYP RGLSYMGLENABLEIEXTPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP RGLSYMGLDISABLEIEXTPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP RGLSYMGLBLENDEQUATIONIEXTPROC) (GLuint buf, GLenum mode); +typedef void (GL_APIENTRYP RGLSYMGLBLENDEQUATIONSEPARATEIEXTPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GL_APIENTRYP RGLSYMGLBLENDFUNCIEXTPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (GL_APIENTRYP RGLSYMGLBLENDFUNCSEPARATEIEXTPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (GL_APIENTRYP RGLSYMGLCOLORMASKIEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef GLboolean (GL_APIENTRYP RGLSYMGLISENABLEDIEXTPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (GL_APIENTRYP RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); +typedef void (GL_APIENTRYP RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex); +typedef void (GL_APIENTRYP RGLSYMGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); +typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GL_APIENTRYP RGLSYMGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor); +typedef void *(GL_APIENTRYP RGLSYMGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GL_APIENTRYP RGLSYMGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length); +typedef void (GL_APIENTRYP RGLSYMGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +typedef void (GL_APIENTRYP RGLSYMGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount); +typedef void (GL_APIENTRYP RGLSYMGLMULTIDRAWARRAYSINDIRECTEXTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride); +typedef void (GL_APIENTRYP RGLSYMGLMULTIDRAWELEMENTSINDIRECTEXTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride); +typedef void (GL_APIENTRYP RGLSYMGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); +typedef void (GL_APIENTRYP RGLSYMGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index); +typedef void (GL_APIENTRYP RGLSYMGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum *location, const GLint *indices); +typedef void (GL_APIENTRYP RGLSYMGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint *data); +typedef void (GL_APIENTRYP RGLSYMGLPRIMITIVEBOUNDINGBOXEXTPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); +typedef void (GL_APIENTRYP RGLSYMGLRASTERSAMPLESEXTPROC) (GLuint samples, GLboolean fixedsamplelocations); +typedef GLenum (GL_APIENTRYP RGLSYMGLGETGRAPHICSRESETSTATUSEXTPROC) (void); +typedef void (GL_APIENTRYP RGLSYMGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); +typedef void (GL_APIENTRYP RGLSYMGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program); +typedef void (GL_APIENTRYP RGLSYMGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline); +typedef GLuint (GL_APIENTRYP RGLSYMGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings); +typedef void (GL_APIENTRYP RGLSYMGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines); +typedef void (GL_APIENTRYP RGLSYMGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines); +typedef void (GL_APIENTRYP RGLSYMGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (GL_APIENTRYP RGLSYMGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params); +typedef GLboolean (GL_APIENTRYP RGLSYMGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP RGLSYMGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program); +typedef void (GL_APIENTRYP RGLSYMGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP RGLSYMGLTEXPAGECOMMITMENTEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); +typedef void (GL_APIENTRYP RGLSYMGLPATCHPARAMETERIEXTPROC) (GLenum pname, GLint value); +typedef void (GL_APIENTRYP RGLSYMGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GL_APIENTRYP RGLSYMGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params); +typedef void (GL_APIENTRYP RGLSYMGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP RGLSYMGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP RGLSYMGLSAMPLERPARAMETERIIVEXTPROC) (GLuint sampler, GLenum pname, const GLint *param); +typedef void (GL_APIENTRYP RGLSYMGLSAMPLERPARAMETERIUIVEXTPROC) (GLuint sampler, GLenum pname, const GLuint *param); +typedef void (GL_APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIIVEXTPROC) (GLuint sampler, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIUIVEXTPROC) (GLuint sampler, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP RGLSYMGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GL_APIENTRYP RGLSYMGLTEXBUFFERRANGEEXTPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GL_APIENTRYP RGLSYMGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (GL_APIENTRYP RGLSYMGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP RGLSYMGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (GL_APIENTRYP RGLSYMGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (GL_APIENTRYP RGLSYMGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP RGLSYMGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (GL_APIENTRYP RGLSYMGLTEXTUREVIEWEXTPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); +typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); +typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews); +#define glBlendBarrierKHR __rglgen_glBlendBarrierKHR #define glDebugMessageControlKHR __rglgen_glDebugMessageControlKHR #define glDebugMessageInsertKHR __rglgen_glDebugMessageInsertKHR #define glDebugMessageCallbackKHR __rglgen_glDebugMessageCallbackKHR @@ -90,24 +227,182 @@ typedef GLboolean (GL_APIENTRYP RGLSYMGLISVERTEXARRAYOESPROC) (GLuint array); #define glObjectPtrLabelKHR __rglgen_glObjectPtrLabelKHR #define glGetObjectPtrLabelKHR __rglgen_glGetObjectPtrLabelKHR #define glGetPointervKHR __rglgen_glGetPointervKHR +#define glGetGraphicsResetStatusKHR __rglgen_glGetGraphicsResetStatusKHR +#define glReadnPixelsKHR __rglgen_glReadnPixelsKHR +#define glGetnUniformfvKHR __rglgen_glGetnUniformfvKHR +#define glGetnUniformivKHR __rglgen_glGetnUniformivKHR +#define glGetnUniformuivKHR __rglgen_glGetnUniformuivKHR #define glEGLImageTargetTexture2DOES __rglgen_glEGLImageTargetTexture2DOES #define glEGLImageTargetRenderbufferStorageOES __rglgen_glEGLImageTargetRenderbufferStorageOES +#define glCopyImageSubDataOES __rglgen_glCopyImageSubDataOES +#define glEnableiOES __rglgen_glEnableiOES +#define glDisableiOES __rglgen_glDisableiOES +#define glBlendEquationiOES __rglgen_glBlendEquationiOES +#define glBlendEquationSeparateiOES __rglgen_glBlendEquationSeparateiOES +#define glBlendFunciOES __rglgen_glBlendFunciOES +#define glBlendFuncSeparateiOES __rglgen_glBlendFuncSeparateiOES +#define glColorMaskiOES __rglgen_glColorMaskiOES +#define glIsEnablediOES __rglgen_glIsEnablediOES +#define glDrawElementsBaseVertexOES __rglgen_glDrawElementsBaseVertexOES +#define glDrawRangeElementsBaseVertexOES __rglgen_glDrawRangeElementsBaseVertexOES +#define glDrawElementsInstancedBaseVertexOES __rglgen_glDrawElementsInstancedBaseVertexOES +#define glMultiDrawElementsBaseVertexOES __rglgen_glMultiDrawElementsBaseVertexOES +#define glFramebufferTextureOES __rglgen_glFramebufferTextureOES #define glGetProgramBinaryOES __rglgen_glGetProgramBinaryOES #define glProgramBinaryOES __rglgen_glProgramBinaryOES #define glMapBufferOES __rglgen_glMapBufferOES #define glUnmapBufferOES __rglgen_glUnmapBufferOES #define glGetBufferPointervOES __rglgen_glGetBufferPointervOES +#define glPrimitiveBoundingBoxOES __rglgen_glPrimitiveBoundingBoxOES +#define glMinSampleShadingOES __rglgen_glMinSampleShadingOES +#define glPatchParameteriOES __rglgen_glPatchParameteriOES #define glTexImage3DOES __rglgen_glTexImage3DOES #define glTexSubImage3DOES __rglgen_glTexSubImage3DOES #define glCopyTexSubImage3DOES __rglgen_glCopyTexSubImage3DOES #define glCompressedTexImage3DOES __rglgen_glCompressedTexImage3DOES #define glCompressedTexSubImage3DOES __rglgen_glCompressedTexSubImage3DOES #define glFramebufferTexture3DOES __rglgen_glFramebufferTexture3DOES +#define glTexParameterIivOES __rglgen_glTexParameterIivOES +#define glTexParameterIuivOES __rglgen_glTexParameterIuivOES +#define glGetTexParameterIivOES __rglgen_glGetTexParameterIivOES +#define glGetTexParameterIuivOES __rglgen_glGetTexParameterIuivOES +#define glSamplerParameterIivOES __rglgen_glSamplerParameterIivOES +#define glSamplerParameterIuivOES __rglgen_glSamplerParameterIuivOES +#define glGetSamplerParameterIivOES __rglgen_glGetSamplerParameterIivOES +#define glGetSamplerParameterIuivOES __rglgen_glGetSamplerParameterIuivOES +#define glTexBufferOES __rglgen_glTexBufferOES +#define glTexBufferRangeOES __rglgen_glTexBufferRangeOES +#define glTexStorage3DMultisampleOES __rglgen_glTexStorage3DMultisampleOES +#define glTextureViewOES __rglgen_glTextureViewOES #define glBindVertexArrayOES __rglgen_glBindVertexArrayOES #define glDeleteVertexArraysOES __rglgen_glDeleteVertexArraysOES #define glGenVertexArraysOES __rglgen_glGenVertexArraysOES #define glIsVertexArrayOES __rglgen_glIsVertexArrayOES +#define glDrawArraysInstancedBaseInstanceEXT __rglgen_glDrawArraysInstancedBaseInstanceEXT +#define glDrawElementsInstancedBaseInstanceEXT __rglgen_glDrawElementsInstancedBaseInstanceEXT +#define glDrawElementsInstancedBaseVertexBaseInstanceEXT __rglgen_glDrawElementsInstancedBaseVertexBaseInstanceEXT +#define glBindFragDataLocationIndexedEXT __rglgen_glBindFragDataLocationIndexedEXT +#define glBindFragDataLocationEXT __rglgen_glBindFragDataLocationEXT +#define glGetProgramResourceLocationIndexEXT __rglgen_glGetProgramResourceLocationIndexEXT +#define glGetFragDataIndexEXT __rglgen_glGetFragDataIndexEXT +#define glBufferStorageEXT __rglgen_glBufferStorageEXT +#define glCopyImageSubDataEXT __rglgen_glCopyImageSubDataEXT +#define glLabelObjectEXT __rglgen_glLabelObjectEXT +#define glGetObjectLabelEXT __rglgen_glGetObjectLabelEXT +#define glInsertEventMarkerEXT __rglgen_glInsertEventMarkerEXT +#define glPushGroupMarkerEXT __rglgen_glPushGroupMarkerEXT +#define glPopGroupMarkerEXT __rglgen_glPopGroupMarkerEXT +#define glDiscardFramebufferEXT __rglgen_glDiscardFramebufferEXT +#define glGenQueriesEXT __rglgen_glGenQueriesEXT +#define glDeleteQueriesEXT __rglgen_glDeleteQueriesEXT +#define glIsQueryEXT __rglgen_glIsQueryEXT +#define glBeginQueryEXT __rglgen_glBeginQueryEXT +#define glEndQueryEXT __rglgen_glEndQueryEXT +#define glQueryCounterEXT __rglgen_glQueryCounterEXT +#define glGetQueryivEXT __rglgen_glGetQueryivEXT +#define glGetQueryObjectivEXT __rglgen_glGetQueryObjectivEXT +#define glGetQueryObjectuivEXT __rglgen_glGetQueryObjectuivEXT +#define glDrawBuffersEXT __rglgen_glDrawBuffersEXT +#define glEnableiEXT __rglgen_glEnableiEXT +#define glDisableiEXT __rglgen_glDisableiEXT +#define glBlendEquationiEXT __rglgen_glBlendEquationiEXT +#define glBlendEquationSeparateiEXT __rglgen_glBlendEquationSeparateiEXT +#define glBlendFunciEXT __rglgen_glBlendFunciEXT +#define glBlendFuncSeparateiEXT __rglgen_glBlendFuncSeparateiEXT +#define glColorMaskiEXT __rglgen_glColorMaskiEXT +#define glIsEnablediEXT __rglgen_glIsEnablediEXT +#define glDrawElementsBaseVertexEXT __rglgen_glDrawElementsBaseVertexEXT +#define glDrawRangeElementsBaseVertexEXT __rglgen_glDrawRangeElementsBaseVertexEXT +#define glDrawElementsInstancedBaseVertexEXT __rglgen_glDrawElementsInstancedBaseVertexEXT +#define glMultiDrawElementsBaseVertexEXT __rglgen_glMultiDrawElementsBaseVertexEXT +#define glDrawArraysInstancedEXT __rglgen_glDrawArraysInstancedEXT +#define glDrawElementsInstancedEXT __rglgen_glDrawElementsInstancedEXT +#define glFramebufferTextureEXT __rglgen_glFramebufferTextureEXT +#define glVertexAttribDivisorEXT __rglgen_glVertexAttribDivisorEXT +#define glMapBufferRangeEXT __rglgen_glMapBufferRangeEXT +#define glFlushMappedBufferRangeEXT __rglgen_glFlushMappedBufferRangeEXT +#define glMultiDrawArraysEXT __rglgen_glMultiDrawArraysEXT +#define glMultiDrawElementsEXT __rglgen_glMultiDrawElementsEXT +#define glMultiDrawArraysIndirectEXT __rglgen_glMultiDrawArraysIndirectEXT +#define glMultiDrawElementsIndirectEXT __rglgen_glMultiDrawElementsIndirectEXT +#define glRenderbufferStorageMultisampleEXT __rglgen_glRenderbufferStorageMultisampleEXT +#define glFramebufferTexture2DMultisampleEXT __rglgen_glFramebufferTexture2DMultisampleEXT +#define glReadBufferIndexedEXT __rglgen_glReadBufferIndexedEXT +#define glDrawBuffersIndexedEXT __rglgen_glDrawBuffersIndexedEXT +#define glGetIntegeri_vEXT __rglgen_glGetIntegeri_vEXT +#define glPrimitiveBoundingBoxEXT __rglgen_glPrimitiveBoundingBoxEXT +#define glRasterSamplesEXT __rglgen_glRasterSamplesEXT +#define glGetGraphicsResetStatusEXT __rglgen_glGetGraphicsResetStatusEXT +#define glReadnPixelsEXT __rglgen_glReadnPixelsEXT +#define glGetnUniformfvEXT __rglgen_glGetnUniformfvEXT +#define glGetnUniformivEXT __rglgen_glGetnUniformivEXT +#define glActiveShaderProgramEXT __rglgen_glActiveShaderProgramEXT +#define glBindProgramPipelineEXT __rglgen_glBindProgramPipelineEXT +#define glCreateShaderProgramvEXT __rglgen_glCreateShaderProgramvEXT +#define glDeleteProgramPipelinesEXT __rglgen_glDeleteProgramPipelinesEXT +#define glGenProgramPipelinesEXT __rglgen_glGenProgramPipelinesEXT +#define glGetProgramPipelineInfoLogEXT __rglgen_glGetProgramPipelineInfoLogEXT +#define glGetProgramPipelineivEXT __rglgen_glGetProgramPipelineivEXT +#define glIsProgramPipelineEXT __rglgen_glIsProgramPipelineEXT +#define glProgramParameteriEXT __rglgen_glProgramParameteriEXT +#define glProgramUniform1fEXT __rglgen_glProgramUniform1fEXT +#define glProgramUniform1fvEXT __rglgen_glProgramUniform1fvEXT +#define glProgramUniform1iEXT __rglgen_glProgramUniform1iEXT +#define glProgramUniform1ivEXT __rglgen_glProgramUniform1ivEXT +#define glProgramUniform2fEXT __rglgen_glProgramUniform2fEXT +#define glProgramUniform2fvEXT __rglgen_glProgramUniform2fvEXT +#define glProgramUniform2iEXT __rglgen_glProgramUniform2iEXT +#define glProgramUniform2ivEXT __rglgen_glProgramUniform2ivEXT +#define glProgramUniform3fEXT __rglgen_glProgramUniform3fEXT +#define glProgramUniform3fvEXT __rglgen_glProgramUniform3fvEXT +#define glProgramUniform3iEXT __rglgen_glProgramUniform3iEXT +#define glProgramUniform3ivEXT __rglgen_glProgramUniform3ivEXT +#define glProgramUniform4fEXT __rglgen_glProgramUniform4fEXT +#define glProgramUniform4fvEXT __rglgen_glProgramUniform4fvEXT +#define glProgramUniform4iEXT __rglgen_glProgramUniform4iEXT +#define glProgramUniform4ivEXT __rglgen_glProgramUniform4ivEXT +#define glProgramUniformMatrix2fvEXT __rglgen_glProgramUniformMatrix2fvEXT +#define glProgramUniformMatrix3fvEXT __rglgen_glProgramUniformMatrix3fvEXT +#define glProgramUniformMatrix4fvEXT __rglgen_glProgramUniformMatrix4fvEXT +#define glUseProgramStagesEXT __rglgen_glUseProgramStagesEXT +#define glValidateProgramPipelineEXT __rglgen_glValidateProgramPipelineEXT +#define glProgramUniform1uiEXT __rglgen_glProgramUniform1uiEXT +#define glProgramUniform2uiEXT __rglgen_glProgramUniform2uiEXT +#define glProgramUniform3uiEXT __rglgen_glProgramUniform3uiEXT +#define glProgramUniform4uiEXT __rglgen_glProgramUniform4uiEXT +#define glProgramUniform1uivEXT __rglgen_glProgramUniform1uivEXT +#define glProgramUniform2uivEXT __rglgen_glProgramUniform2uivEXT +#define glProgramUniform3uivEXT __rglgen_glProgramUniform3uivEXT +#define glProgramUniform4uivEXT __rglgen_glProgramUniform4uivEXT +#define glProgramUniformMatrix2x3fvEXT __rglgen_glProgramUniformMatrix2x3fvEXT +#define glProgramUniformMatrix3x2fvEXT __rglgen_glProgramUniformMatrix3x2fvEXT +#define glProgramUniformMatrix2x4fvEXT __rglgen_glProgramUniformMatrix2x4fvEXT +#define glProgramUniformMatrix4x2fvEXT __rglgen_glProgramUniformMatrix4x2fvEXT +#define glProgramUniformMatrix3x4fvEXT __rglgen_glProgramUniformMatrix3x4fvEXT +#define glProgramUniformMatrix4x3fvEXT __rglgen_glProgramUniformMatrix4x3fvEXT +#define glTexPageCommitmentEXT __rglgen_glTexPageCommitmentEXT +#define glPatchParameteriEXT __rglgen_glPatchParameteriEXT +#define glTexParameterIivEXT __rglgen_glTexParameterIivEXT +#define glTexParameterIuivEXT __rglgen_glTexParameterIuivEXT +#define glGetTexParameterIivEXT __rglgen_glGetTexParameterIivEXT +#define glGetTexParameterIuivEXT __rglgen_glGetTexParameterIuivEXT +#define glSamplerParameterIivEXT __rglgen_glSamplerParameterIivEXT +#define glSamplerParameterIuivEXT __rglgen_glSamplerParameterIuivEXT +#define glGetSamplerParameterIivEXT __rglgen_glGetSamplerParameterIivEXT +#define glGetSamplerParameterIuivEXT __rglgen_glGetSamplerParameterIuivEXT +#define glTexBufferEXT __rglgen_glTexBufferEXT +#define glTexBufferRangeEXT __rglgen_glTexBufferRangeEXT +#define glTexStorage1DEXT __rglgen_glTexStorage1DEXT +#define glTexStorage2DEXT __rglgen_glTexStorage2DEXT +#define glTexStorage3DEXT __rglgen_glTexStorage3DEXT +#define glTextureStorage1DEXT __rglgen_glTextureStorage1DEXT +#define glTextureStorage2DEXT __rglgen_glTextureStorage2DEXT +#define glTextureStorage3DEXT __rglgen_glTextureStorage3DEXT +#define glTextureViewEXT __rglgen_glTextureViewEXT +#define glFramebufferTextureMultiviewOVR __rglgen_glFramebufferTextureMultiviewOVR +#define glFramebufferTextureMultisampleMultiviewOVR __rglgen_glFramebufferTextureMultisampleMultiviewOVR +extern RGLSYMGLBLENDBARRIERKHRPROC __rglgen_glBlendBarrierKHR; extern RGLSYMGLDEBUGMESSAGECONTROLKHRPROC __rglgen_glDebugMessageControlKHR; extern RGLSYMGLDEBUGMESSAGEINSERTKHRPROC __rglgen_glDebugMessageInsertKHR; extern RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC __rglgen_glDebugMessageCallbackKHR; @@ -119,23 +414,180 @@ extern RGLSYMGLGETOBJECTLABELKHRPROC __rglgen_glGetObjectLabelKHR; extern RGLSYMGLOBJECTPTRLABELKHRPROC __rglgen_glObjectPtrLabelKHR; extern RGLSYMGLGETOBJECTPTRLABELKHRPROC __rglgen_glGetObjectPtrLabelKHR; extern RGLSYMGLGETPOINTERVKHRPROC __rglgen_glGetPointervKHR; +extern RGLSYMGLGETGRAPHICSRESETSTATUSKHRPROC __rglgen_glGetGraphicsResetStatusKHR; +extern RGLSYMGLREADNPIXELSKHRPROC __rglgen_glReadnPixelsKHR; +extern RGLSYMGLGETNUNIFORMFVKHRPROC __rglgen_glGetnUniformfvKHR; +extern RGLSYMGLGETNUNIFORMIVKHRPROC __rglgen_glGetnUniformivKHR; +extern RGLSYMGLGETNUNIFORMUIVKHRPROC __rglgen_glGetnUniformuivKHR; extern RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC __rglgen_glEGLImageTargetTexture2DOES; extern RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC __rglgen_glEGLImageTargetRenderbufferStorageOES; +extern RGLSYMGLCOPYIMAGESUBDATAOESPROC __rglgen_glCopyImageSubDataOES; +extern RGLSYMGLENABLEIOESPROC __rglgen_glEnableiOES; +extern RGLSYMGLDISABLEIOESPROC __rglgen_glDisableiOES; +extern RGLSYMGLBLENDEQUATIONIOESPROC __rglgen_glBlendEquationiOES; +extern RGLSYMGLBLENDEQUATIONSEPARATEIOESPROC __rglgen_glBlendEquationSeparateiOES; +extern RGLSYMGLBLENDFUNCIOESPROC __rglgen_glBlendFunciOES; +extern RGLSYMGLBLENDFUNCSEPARATEIOESPROC __rglgen_glBlendFuncSeparateiOES; +extern RGLSYMGLCOLORMASKIOESPROC __rglgen_glColorMaskiOES; +extern RGLSYMGLISENABLEDIOESPROC __rglgen_glIsEnablediOES; +extern RGLSYMGLDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glDrawElementsBaseVertexOES; +extern RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXOESPROC __rglgen_glDrawRangeElementsBaseVertexOES; +extern RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC __rglgen_glDrawElementsInstancedBaseVertexOES; +extern RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glMultiDrawElementsBaseVertexOES; +extern RGLSYMGLFRAMEBUFFERTEXTUREOESPROC __rglgen_glFramebufferTextureOES; extern RGLSYMGLGETPROGRAMBINARYOESPROC __rglgen_glGetProgramBinaryOES; extern RGLSYMGLPROGRAMBINARYOESPROC __rglgen_glProgramBinaryOES; extern RGLSYMGLMAPBUFFEROESPROC __rglgen_glMapBufferOES; extern RGLSYMGLUNMAPBUFFEROESPROC __rglgen_glUnmapBufferOES; extern RGLSYMGLGETBUFFERPOINTERVOESPROC __rglgen_glGetBufferPointervOES; +extern RGLSYMGLPRIMITIVEBOUNDINGBOXOESPROC __rglgen_glPrimitiveBoundingBoxOES; +extern RGLSYMGLMINSAMPLESHADINGOESPROC __rglgen_glMinSampleShadingOES; +extern RGLSYMGLPATCHPARAMETERIOESPROC __rglgen_glPatchParameteriOES; extern RGLSYMGLTEXIMAGE3DOESPROC __rglgen_glTexImage3DOES; extern RGLSYMGLTEXSUBIMAGE3DOESPROC __rglgen_glTexSubImage3DOES; extern RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC __rglgen_glCopyTexSubImage3DOES; extern RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC __rglgen_glCompressedTexImage3DOES; extern RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC __rglgen_glCompressedTexSubImage3DOES; extern RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC __rglgen_glFramebufferTexture3DOES; +extern RGLSYMGLTEXPARAMETERIIVOESPROC __rglgen_glTexParameterIivOES; +extern RGLSYMGLTEXPARAMETERIUIVOESPROC __rglgen_glTexParameterIuivOES; +extern RGLSYMGLGETTEXPARAMETERIIVOESPROC __rglgen_glGetTexParameterIivOES; +extern RGLSYMGLGETTEXPARAMETERIUIVOESPROC __rglgen_glGetTexParameterIuivOES; +extern RGLSYMGLSAMPLERPARAMETERIIVOESPROC __rglgen_glSamplerParameterIivOES; +extern RGLSYMGLSAMPLERPARAMETERIUIVOESPROC __rglgen_glSamplerParameterIuivOES; +extern RGLSYMGLGETSAMPLERPARAMETERIIVOESPROC __rglgen_glGetSamplerParameterIivOES; +extern RGLSYMGLGETSAMPLERPARAMETERIUIVOESPROC __rglgen_glGetSamplerParameterIuivOES; +extern RGLSYMGLTEXBUFFEROESPROC __rglgen_glTexBufferOES; +extern RGLSYMGLTEXBUFFERRANGEOESPROC __rglgen_glTexBufferRangeOES; +extern RGLSYMGLTEXSTORAGE3DMULTISAMPLEOESPROC __rglgen_glTexStorage3DMultisampleOES; +extern RGLSYMGLTEXTUREVIEWOESPROC __rglgen_glTextureViewOES; extern RGLSYMGLBINDVERTEXARRAYOESPROC __rglgen_glBindVertexArrayOES; extern RGLSYMGLDELETEVERTEXARRAYSOESPROC __rglgen_glDeleteVertexArraysOES; extern RGLSYMGLGENVERTEXARRAYSOESPROC __rglgen_glGenVertexArraysOES; extern RGLSYMGLISVERTEXARRAYOESPROC __rglgen_glIsVertexArrayOES; +extern RGLSYMGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC __rglgen_glDrawArraysInstancedBaseInstanceEXT; +extern RGLSYMGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC __rglgen_glDrawElementsInstancedBaseInstanceEXT; +extern RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC __rglgen_glDrawElementsInstancedBaseVertexBaseInstanceEXT; +extern RGLSYMGLBINDFRAGDATALOCATIONINDEXEDEXTPROC __rglgen_glBindFragDataLocationIndexedEXT; +extern RGLSYMGLBINDFRAGDATALOCATIONEXTPROC __rglgen_glBindFragDataLocationEXT; +extern RGLSYMGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC __rglgen_glGetProgramResourceLocationIndexEXT; +extern RGLSYMGLGETFRAGDATAINDEXEXTPROC __rglgen_glGetFragDataIndexEXT; +extern RGLSYMGLBUFFERSTORAGEEXTPROC __rglgen_glBufferStorageEXT; +extern RGLSYMGLCOPYIMAGESUBDATAEXTPROC __rglgen_glCopyImageSubDataEXT; +extern RGLSYMGLLABELOBJECTEXTPROC __rglgen_glLabelObjectEXT; +extern RGLSYMGLGETOBJECTLABELEXTPROC __rglgen_glGetObjectLabelEXT; +extern RGLSYMGLINSERTEVENTMARKEREXTPROC __rglgen_glInsertEventMarkerEXT; +extern RGLSYMGLPUSHGROUPMARKEREXTPROC __rglgen_glPushGroupMarkerEXT; +extern RGLSYMGLPOPGROUPMARKEREXTPROC __rglgen_glPopGroupMarkerEXT; +extern RGLSYMGLDISCARDFRAMEBUFFEREXTPROC __rglgen_glDiscardFramebufferEXT; +extern RGLSYMGLGENQUERIESEXTPROC __rglgen_glGenQueriesEXT; +extern RGLSYMGLDELETEQUERIESEXTPROC __rglgen_glDeleteQueriesEXT; +extern RGLSYMGLISQUERYEXTPROC __rglgen_glIsQueryEXT; +extern RGLSYMGLBEGINQUERYEXTPROC __rglgen_glBeginQueryEXT; +extern RGLSYMGLENDQUERYEXTPROC __rglgen_glEndQueryEXT; +extern RGLSYMGLQUERYCOUNTEREXTPROC __rglgen_glQueryCounterEXT; +extern RGLSYMGLGETQUERYIVEXTPROC __rglgen_glGetQueryivEXT; +extern RGLSYMGLGETQUERYOBJECTIVEXTPROC __rglgen_glGetQueryObjectivEXT; +extern RGLSYMGLGETQUERYOBJECTUIVEXTPROC __rglgen_glGetQueryObjectuivEXT; +extern RGLSYMGLDRAWBUFFERSEXTPROC __rglgen_glDrawBuffersEXT; +extern RGLSYMGLENABLEIEXTPROC __rglgen_glEnableiEXT; +extern RGLSYMGLDISABLEIEXTPROC __rglgen_glDisableiEXT; +extern RGLSYMGLBLENDEQUATIONIEXTPROC __rglgen_glBlendEquationiEXT; +extern RGLSYMGLBLENDEQUATIONSEPARATEIEXTPROC __rglgen_glBlendEquationSeparateiEXT; +extern RGLSYMGLBLENDFUNCIEXTPROC __rglgen_glBlendFunciEXT; +extern RGLSYMGLBLENDFUNCSEPARATEIEXTPROC __rglgen_glBlendFuncSeparateiEXT; +extern RGLSYMGLCOLORMASKIEXTPROC __rglgen_glColorMaskiEXT; +extern RGLSYMGLISENABLEDIEXTPROC __rglgen_glIsEnablediEXT; +extern RGLSYMGLDRAWELEMENTSBASEVERTEXEXTPROC __rglgen_glDrawElementsBaseVertexEXT; +extern RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC __rglgen_glDrawRangeElementsBaseVertexEXT; +extern RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC __rglgen_glDrawElementsInstancedBaseVertexEXT; +extern RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC __rglgen_glMultiDrawElementsBaseVertexEXT; +extern RGLSYMGLDRAWARRAYSINSTANCEDEXTPROC __rglgen_glDrawArraysInstancedEXT; +extern RGLSYMGLDRAWELEMENTSINSTANCEDEXTPROC __rglgen_glDrawElementsInstancedEXT; +extern RGLSYMGLFRAMEBUFFERTEXTUREEXTPROC __rglgen_glFramebufferTextureEXT; +extern RGLSYMGLVERTEXATTRIBDIVISOREXTPROC __rglgen_glVertexAttribDivisorEXT; +extern RGLSYMGLMAPBUFFERRANGEEXTPROC __rglgen_glMapBufferRangeEXT; +extern RGLSYMGLFLUSHMAPPEDBUFFERRANGEEXTPROC __rglgen_glFlushMappedBufferRangeEXT; +extern RGLSYMGLMULTIDRAWARRAYSEXTPROC __rglgen_glMultiDrawArraysEXT; +extern RGLSYMGLMULTIDRAWELEMENTSEXTPROC __rglgen_glMultiDrawElementsEXT; +extern RGLSYMGLMULTIDRAWARRAYSINDIRECTEXTPROC __rglgen_glMultiDrawArraysIndirectEXT; +extern RGLSYMGLMULTIDRAWELEMENTSINDIRECTEXTPROC __rglgen_glMultiDrawElementsIndirectEXT; +extern RGLSYMGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __rglgen_glRenderbufferStorageMultisampleEXT; +extern RGLSYMGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC __rglgen_glFramebufferTexture2DMultisampleEXT; +extern RGLSYMGLREADBUFFERINDEXEDEXTPROC __rglgen_glReadBufferIndexedEXT; +extern RGLSYMGLDRAWBUFFERSINDEXEDEXTPROC __rglgen_glDrawBuffersIndexedEXT; +extern RGLSYMGLGETINTEGERI_VEXTPROC __rglgen_glGetIntegeri_vEXT; +extern RGLSYMGLPRIMITIVEBOUNDINGBOXEXTPROC __rglgen_glPrimitiveBoundingBoxEXT; +extern RGLSYMGLRASTERSAMPLESEXTPROC __rglgen_glRasterSamplesEXT; +extern RGLSYMGLGETGRAPHICSRESETSTATUSEXTPROC __rglgen_glGetGraphicsResetStatusEXT; +extern RGLSYMGLREADNPIXELSEXTPROC __rglgen_glReadnPixelsEXT; +extern RGLSYMGLGETNUNIFORMFVEXTPROC __rglgen_glGetnUniformfvEXT; +extern RGLSYMGLGETNUNIFORMIVEXTPROC __rglgen_glGetnUniformivEXT; +extern RGLSYMGLACTIVESHADERPROGRAMEXTPROC __rglgen_glActiveShaderProgramEXT; +extern RGLSYMGLBINDPROGRAMPIPELINEEXTPROC __rglgen_glBindProgramPipelineEXT; +extern RGLSYMGLCREATESHADERPROGRAMVEXTPROC __rglgen_glCreateShaderProgramvEXT; +extern RGLSYMGLDELETEPROGRAMPIPELINESEXTPROC __rglgen_glDeleteProgramPipelinesEXT; +extern RGLSYMGLGENPROGRAMPIPELINESEXTPROC __rglgen_glGenProgramPipelinesEXT; +extern RGLSYMGLGETPROGRAMPIPELINEINFOLOGEXTPROC __rglgen_glGetProgramPipelineInfoLogEXT; +extern RGLSYMGLGETPROGRAMPIPELINEIVEXTPROC __rglgen_glGetProgramPipelineivEXT; +extern RGLSYMGLISPROGRAMPIPELINEEXTPROC __rglgen_glIsProgramPipelineEXT; +extern RGLSYMGLPROGRAMPARAMETERIEXTPROC __rglgen_glProgramParameteriEXT; +extern RGLSYMGLPROGRAMUNIFORM1FEXTPROC __rglgen_glProgramUniform1fEXT; +extern RGLSYMGLPROGRAMUNIFORM1FVEXTPROC __rglgen_glProgramUniform1fvEXT; +extern RGLSYMGLPROGRAMUNIFORM1IEXTPROC __rglgen_glProgramUniform1iEXT; +extern RGLSYMGLPROGRAMUNIFORM1IVEXTPROC __rglgen_glProgramUniform1ivEXT; +extern RGLSYMGLPROGRAMUNIFORM2FEXTPROC __rglgen_glProgramUniform2fEXT; +extern RGLSYMGLPROGRAMUNIFORM2FVEXTPROC __rglgen_glProgramUniform2fvEXT; +extern RGLSYMGLPROGRAMUNIFORM2IEXTPROC __rglgen_glProgramUniform2iEXT; +extern RGLSYMGLPROGRAMUNIFORM2IVEXTPROC __rglgen_glProgramUniform2ivEXT; +extern RGLSYMGLPROGRAMUNIFORM3FEXTPROC __rglgen_glProgramUniform3fEXT; +extern RGLSYMGLPROGRAMUNIFORM3FVEXTPROC __rglgen_glProgramUniform3fvEXT; +extern RGLSYMGLPROGRAMUNIFORM3IEXTPROC __rglgen_glProgramUniform3iEXT; +extern RGLSYMGLPROGRAMUNIFORM3IVEXTPROC __rglgen_glProgramUniform3ivEXT; +extern RGLSYMGLPROGRAMUNIFORM4FEXTPROC __rglgen_glProgramUniform4fEXT; +extern RGLSYMGLPROGRAMUNIFORM4FVEXTPROC __rglgen_glProgramUniform4fvEXT; +extern RGLSYMGLPROGRAMUNIFORM4IEXTPROC __rglgen_glProgramUniform4iEXT; +extern RGLSYMGLPROGRAMUNIFORM4IVEXTPROC __rglgen_glProgramUniform4ivEXT; +extern RGLSYMGLPROGRAMUNIFORMMATRIX2FVEXTPROC __rglgen_glProgramUniformMatrix2fvEXT; +extern RGLSYMGLPROGRAMUNIFORMMATRIX3FVEXTPROC __rglgen_glProgramUniformMatrix3fvEXT; +extern RGLSYMGLPROGRAMUNIFORMMATRIX4FVEXTPROC __rglgen_glProgramUniformMatrix4fvEXT; +extern RGLSYMGLUSEPROGRAMSTAGESEXTPROC __rglgen_glUseProgramStagesEXT; +extern RGLSYMGLVALIDATEPROGRAMPIPELINEEXTPROC __rglgen_glValidateProgramPipelineEXT; +extern RGLSYMGLPROGRAMUNIFORM1UIEXTPROC __rglgen_glProgramUniform1uiEXT; +extern RGLSYMGLPROGRAMUNIFORM2UIEXTPROC __rglgen_glProgramUniform2uiEXT; +extern RGLSYMGLPROGRAMUNIFORM3UIEXTPROC __rglgen_glProgramUniform3uiEXT; +extern RGLSYMGLPROGRAMUNIFORM4UIEXTPROC __rglgen_glProgramUniform4uiEXT; +extern RGLSYMGLPROGRAMUNIFORM1UIVEXTPROC __rglgen_glProgramUniform1uivEXT; +extern RGLSYMGLPROGRAMUNIFORM2UIVEXTPROC __rglgen_glProgramUniform2uivEXT; +extern RGLSYMGLPROGRAMUNIFORM3UIVEXTPROC __rglgen_glProgramUniform3uivEXT; +extern RGLSYMGLPROGRAMUNIFORM4UIVEXTPROC __rglgen_glProgramUniform4uivEXT; +extern RGLSYMGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC __rglgen_glProgramUniformMatrix2x3fvEXT; +extern RGLSYMGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC __rglgen_glProgramUniformMatrix3x2fvEXT; +extern RGLSYMGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC __rglgen_glProgramUniformMatrix2x4fvEXT; +extern RGLSYMGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC __rglgen_glProgramUniformMatrix4x2fvEXT; +extern RGLSYMGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC __rglgen_glProgramUniformMatrix3x4fvEXT; +extern RGLSYMGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC __rglgen_glProgramUniformMatrix4x3fvEXT; +extern RGLSYMGLTEXPAGECOMMITMENTEXTPROC __rglgen_glTexPageCommitmentEXT; +extern RGLSYMGLPATCHPARAMETERIEXTPROC __rglgen_glPatchParameteriEXT; +extern RGLSYMGLTEXPARAMETERIIVEXTPROC __rglgen_glTexParameterIivEXT; +extern RGLSYMGLTEXPARAMETERIUIVEXTPROC __rglgen_glTexParameterIuivEXT; +extern RGLSYMGLGETTEXPARAMETERIIVEXTPROC __rglgen_glGetTexParameterIivEXT; +extern RGLSYMGLGETTEXPARAMETERIUIVEXTPROC __rglgen_glGetTexParameterIuivEXT; +extern RGLSYMGLSAMPLERPARAMETERIIVEXTPROC __rglgen_glSamplerParameterIivEXT; +extern RGLSYMGLSAMPLERPARAMETERIUIVEXTPROC __rglgen_glSamplerParameterIuivEXT; +extern RGLSYMGLGETSAMPLERPARAMETERIIVEXTPROC __rglgen_glGetSamplerParameterIivEXT; +extern RGLSYMGLGETSAMPLERPARAMETERIUIVEXTPROC __rglgen_glGetSamplerParameterIuivEXT; +extern RGLSYMGLTEXBUFFEREXTPROC __rglgen_glTexBufferEXT; +extern RGLSYMGLTEXBUFFERRANGEEXTPROC __rglgen_glTexBufferRangeEXT; +extern RGLSYMGLTEXSTORAGE1DEXTPROC __rglgen_glTexStorage1DEXT; +extern RGLSYMGLTEXSTORAGE2DEXTPROC __rglgen_glTexStorage2DEXT; +extern RGLSYMGLTEXSTORAGE3DEXTPROC __rglgen_glTexStorage3DEXT; +extern RGLSYMGLTEXTURESTORAGE1DEXTPROC __rglgen_glTextureStorage1DEXT; +extern RGLSYMGLTEXTURESTORAGE2DEXTPROC __rglgen_glTextureStorage2DEXT; +extern RGLSYMGLTEXTURESTORAGE3DEXTPROC __rglgen_glTextureStorage3DEXT; +extern RGLSYMGLTEXTUREVIEWEXTPROC __rglgen_glTextureViewEXT; +extern RGLSYMGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultiviewOVR; +extern RGLSYMGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultisampleMultiviewOVR; struct rglgen_sym_map { const char *sym; void *ptr; }; extern const struct rglgen_sym_map rglgen_symbol_map[]; diff --git a/desmume/src/libretro-common/include/glsym/glsym_es3.h b/desmume/src/libretro-common/include/glsym/glsym_es3.h new file mode 100644 index 000000000..201f5d715 --- /dev/null +++ b/desmume/src/libretro-common/include/glsym/glsym_es3.h @@ -0,0 +1,234 @@ +#ifndef RGLGEN_DECL_H__ +#define RGLGEN_DECL_H__ +#ifdef __cplusplus +extern "C" { +#endif +#ifdef GL_APIENTRY +typedef void (GL_APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); +typedef void (GL_APIENTRY *RGLGENGLDEBUGPROCKHR)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); +#else +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif +typedef void (APIENTRY *RGLGENGLDEBUGPROCARB)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); +typedef void (APIENTRY *RGLGENGLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar*, GLvoid*); +#endif +#ifndef GL_OES_EGL_image +typedef void *GLeglImageOES; +#endif +#if !defined(GL_OES_fixed_point) && !defined(HAVE_OPENGLES2) +typedef GLint GLfixed; +#endif +#if defined(OSX) && !defined(MAC_OS_X_VERSION_10_7) +typedef long long int GLint64; +typedef unsigned long long int GLuint64; +typedef unsigned long long int GLuint64EXT; +typedef struct __GLsync *GLsync; +#endif +typedef void (GL_APIENTRYP RGLSYMGLBLENDBARRIERKHRPROC) (void); +typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGECONTROLKHRPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGEINSERTKHRPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +typedef void (GL_APIENTRYP RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC) (RGLGENGLDEBUGPROCKHR callback, const void *userParam); +typedef GLuint (GL_APIENTRYP RGLSYMGLGETDEBUGMESSAGELOGKHRPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +typedef void (GL_APIENTRYP RGLSYMGLPUSHDEBUGGROUPKHRPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message); +typedef void (GL_APIENTRYP RGLSYMGLPOPDEBUGGROUPKHRPROC) (void); +typedef void (GL_APIENTRYP RGLSYMGLOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +typedef void (GL_APIENTRYP RGLSYMGLGETOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +typedef void (GL_APIENTRYP RGLSYMGLOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei length, const GLchar *label); +typedef void (GL_APIENTRYP RGLSYMGLGETOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +typedef void (GL_APIENTRYP RGLSYMGLGETPOINTERVKHRPROC) (GLenum pname, void **params); +typedef GLenum (GL_APIENTRYP RGLSYMGLGETGRAPHICSRESETSTATUSKHRPROC) (void); +typedef void (GL_APIENTRYP RGLSYMGLREADNPIXELSKHRPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMFVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); +typedef void (GL_APIENTRYP RGLSYMGLGETNUNIFORMUIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params); +typedef void (GL_APIENTRYP RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); +typedef void (GL_APIENTRYP RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); +typedef void (GL_APIENTRYP RGLSYMGLCOPYIMAGESUBDATAOESPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +typedef void (GL_APIENTRYP RGLSYMGLENABLEIOESPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP RGLSYMGLDISABLEIOESPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP RGLSYMGLBLENDEQUATIONIOESPROC) (GLuint buf, GLenum mode); +typedef void (GL_APIENTRYP RGLSYMGLBLENDEQUATIONSEPARATEIOESPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GL_APIENTRYP RGLSYMGLBLENDFUNCIOESPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (GL_APIENTRYP RGLSYMGLBLENDFUNCSEPARATEIOESPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (GL_APIENTRYP RGLSYMGLCOLORMASKIOESPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef GLboolean (GL_APIENTRYP RGLSYMGLISENABLEDIOESPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (GL_APIENTRYP RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (GL_APIENTRYP RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); +typedef void (GL_APIENTRYP RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex); +typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREOESPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GL_APIENTRYP RGLSYMGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +typedef void (GL_APIENTRYP RGLSYMGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLint length); +typedef void *(GL_APIENTRYP RGLSYMGLMAPBUFFEROESPROC) (GLenum target, GLenum access); +typedef GLboolean (GL_APIENTRYP RGLSYMGLUNMAPBUFFEROESPROC) (GLenum target); +typedef void (GL_APIENTRYP RGLSYMGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void **params); +typedef void (GL_APIENTRYP RGLSYMGLPRIMITIVEBOUNDINGBOXOESPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); +typedef void (GL_APIENTRYP RGLSYMGLMINSAMPLESHADINGOESPROC) (GLfloat value); +typedef void (GL_APIENTRYP RGLSYMGLPATCHPARAMETERIOESPROC) (GLenum pname, GLint value); +typedef void (GL_APIENTRYP RGLSYMGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP RGLSYMGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GL_APIENTRYP RGLSYMGLTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GL_APIENTRYP RGLSYMGLTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, const GLuint *params); +typedef void (GL_APIENTRYP RGLSYMGLGETTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP RGLSYMGLGETTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP RGLSYMGLSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, const GLint *param); +typedef void (GL_APIENTRYP RGLSYMGLSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, const GLuint *param); +typedef void (GL_APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP RGLSYMGLGETSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP RGLSYMGLTEXBUFFEROESPROC) (GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GL_APIENTRYP RGLSYMGLTEXBUFFERRANGEOESPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GL_APIENTRYP RGLSYMGLTEXSTORAGE3DMULTISAMPLEOESPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (GL_APIENTRYP RGLSYMGLTEXTUREVIEWOESPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); +typedef void (GL_APIENTRYP RGLSYMGLBINDVERTEXARRAYOESPROC) (GLuint array); +typedef void (GL_APIENTRYP RGLSYMGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays); +typedef void (GL_APIENTRYP RGLSYMGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays); +typedef GLboolean (GL_APIENTRYP RGLSYMGLISVERTEXARRAYOESPROC) (GLuint array); +typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); +typedef void (GL_APIENTRYP RGLSYMGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews); + +#define glBlendBarrierKHR __rglgen_glBlendBarrierKHR +#define glDebugMessageControlKHR __rglgen_glDebugMessageControlKHR +#define glDebugMessageInsertKHR __rglgen_glDebugMessageInsertKHR +#define glDebugMessageCallbackKHR __rglgen_glDebugMessageCallbackKHR +#define glGetDebugMessageLogKHR __rglgen_glGetDebugMessageLogKHR +#define glPushDebugGroupKHR __rglgen_glPushDebugGroupKHR +#define glPopDebugGroupKHR __rglgen_glPopDebugGroupKHR +#define glObjectLabelKHR __rglgen_glObjectLabelKHR +#define glGetObjectLabelKHR __rglgen_glGetObjectLabelKHR +#define glObjectPtrLabelKHR __rglgen_glObjectPtrLabelKHR +#define glGetObjectPtrLabelKHR __rglgen_glGetObjectPtrLabelKHR +#define glGetPointervKHR __rglgen_glGetPointervKHR +#define glGetGraphicsResetStatusKHR __rglgen_glGetGraphicsResetStatusKHR +#define glReadnPixelsKHR __rglgen_glReadnPixelsKHR +#define glGetnUniformfvKHR __rglgen_glGetnUniformfvKHR +#define glGetnUniformivKHR __rglgen_glGetnUniformivKHR +#define glGetnUniformuivKHR __rglgen_glGetnUniformuivKHR +#define glEGLImageTargetTexture2DOES __rglgen_glEGLImageTargetTexture2DOES +#define glEGLImageTargetRenderbufferStorageOES __rglgen_glEGLImageTargetRenderbufferStorageOES +#define glCopyImageSubDataOES __rglgen_glCopyImageSubDataOES +#define glEnableiOES __rglgen_glEnableiOES +#define glDisableiOES __rglgen_glDisableiOES +#define glBlendEquationiOES __rglgen_glBlendEquationiOES +#define glBlendEquationSeparateiOES __rglgen_glBlendEquationSeparateiOES +#define glBlendFunciOES __rglgen_glBlendFunciOES +#define glBlendFuncSeparateiOES __rglgen_glBlendFuncSeparateiOES +#define glColorMaskiOES __rglgen_glColorMaskiOES +#define glIsEnablediOES __rglgen_glIsEnablediOES +#define glDrawElementsBaseVertexOES __rglgen_glDrawElementsBaseVertexOES +#define glDrawRangeElementsBaseVertexOES __rglgen_glDrawRangeElementsBaseVertexOES +#define glDrawElementsInstancedBaseVertexOES __rglgen_glDrawElementsInstancedBaseVertexOES +#define glMultiDrawElementsBaseVertexOES __rglgen_glMultiDrawElementsBaseVertexOES +#define glFramebufferTextureOES __rglgen_glFramebufferTextureOES +#define glGetProgramBinaryOES __rglgen_glGetProgramBinaryOES +#define glProgramBinaryOES __rglgen_glProgramBinaryOES +#define glMapBufferOES __rglgen_glMapBufferOES +#define glUnmapBufferOES __rglgen_glUnmapBufferOES +#define glGetBufferPointervOES __rglgen_glGetBufferPointervOES +#define glPrimitiveBoundingBoxOES __rglgen_glPrimitiveBoundingBoxOES +#define glMinSampleShadingOES __rglgen_glMinSampleShadingOES +#define glPatchParameteriOES __rglgen_glPatchParameteriOES +#define glTexImage3DOES __rglgen_glTexImage3DOES +#define glTexSubImage3DOES __rglgen_glTexSubImage3DOES +#define glCopyTexSubImage3DOES __rglgen_glCopyTexSubImage3DOES +#define glCompressedTexImage3DOES __rglgen_glCompressedTexImage3DOES +#define glCompressedTexSubImage3DOES __rglgen_glCompressedTexSubImage3DOES +#define glFramebufferTexture3DOES __rglgen_glFramebufferTexture3DOES +#define glTexParameterIivOES __rglgen_glTexParameterIivOES +#define glTexParameterIuivOES __rglgen_glTexParameterIuivOES +#define glGetTexParameterIivOES __rglgen_glGetTexParameterIivOES +#define glGetTexParameterIuivOES __rglgen_glGetTexParameterIuivOES +#define glSamplerParameterIivOES __rglgen_glSamplerParameterIivOES +#define glSamplerParameterIuivOES __rglgen_glSamplerParameterIuivOES +#define glGetSamplerParameterIivOES __rglgen_glGetSamplerParameterIivOES +#define glGetSamplerParameterIuivOES __rglgen_glGetSamplerParameterIuivOES +#define glTexBufferOES __rglgen_glTexBufferOES +#define glTexBufferRangeOES __rglgen_glTexBufferRangeOES +#define glTexStorage3DMultisampleOES __rglgen_glTexStorage3DMultisampleOES +#define glTextureViewOES __rglgen_glTextureViewOES +#define glBindVertexArrayOES __rglgen_glBindVertexArrayOES +#define glDeleteVertexArraysOES __rglgen_glDeleteVertexArraysOES +#define glGenVertexArraysOES __rglgen_glGenVertexArraysOES +#define glIsVertexArrayOES __rglgen_glIsVertexArrayOES +#define glFramebufferTextureMultiviewOVR __rglgen_glFramebufferTextureMultiviewOVR +#define glFramebufferTextureMultisampleMultiviewOVR __rglgen_glFramebufferTextureMultisampleMultiviewOVR + +extern RGLSYMGLBLENDBARRIERKHRPROC __rglgen_glBlendBarrierKHR; +extern RGLSYMGLDEBUGMESSAGECONTROLKHRPROC __rglgen_glDebugMessageControlKHR; +extern RGLSYMGLDEBUGMESSAGEINSERTKHRPROC __rglgen_glDebugMessageInsertKHR; +extern RGLSYMGLDEBUGMESSAGECALLBACKKHRPROC __rglgen_glDebugMessageCallbackKHR; +extern RGLSYMGLGETDEBUGMESSAGELOGKHRPROC __rglgen_glGetDebugMessageLogKHR; +extern RGLSYMGLPUSHDEBUGGROUPKHRPROC __rglgen_glPushDebugGroupKHR; +extern RGLSYMGLPOPDEBUGGROUPKHRPROC __rglgen_glPopDebugGroupKHR; +extern RGLSYMGLOBJECTLABELKHRPROC __rglgen_glObjectLabelKHR; +extern RGLSYMGLGETOBJECTLABELKHRPROC __rglgen_glGetObjectLabelKHR; +extern RGLSYMGLOBJECTPTRLABELKHRPROC __rglgen_glObjectPtrLabelKHR; +extern RGLSYMGLGETOBJECTPTRLABELKHRPROC __rglgen_glGetObjectPtrLabelKHR; +extern RGLSYMGLGETPOINTERVKHRPROC __rglgen_glGetPointervKHR; +extern RGLSYMGLGETGRAPHICSRESETSTATUSKHRPROC __rglgen_glGetGraphicsResetStatusKHR; +extern RGLSYMGLREADNPIXELSKHRPROC __rglgen_glReadnPixelsKHR; +extern RGLSYMGLGETNUNIFORMFVKHRPROC __rglgen_glGetnUniformfvKHR; +extern RGLSYMGLGETNUNIFORMIVKHRPROC __rglgen_glGetnUniformivKHR; +extern RGLSYMGLGETNUNIFORMUIVKHRPROC __rglgen_glGetnUniformuivKHR; +extern RGLSYMGLEGLIMAGETARGETTEXTURE2DOESPROC __rglgen_glEGLImageTargetTexture2DOES; +extern RGLSYMGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC __rglgen_glEGLImageTargetRenderbufferStorageOES; +extern RGLSYMGLCOPYIMAGESUBDATAOESPROC __rglgen_glCopyImageSubDataOES; +extern RGLSYMGLENABLEIOESPROC __rglgen_glEnableiOES; +extern RGLSYMGLDISABLEIOESPROC __rglgen_glDisableiOES; +extern RGLSYMGLBLENDEQUATIONIOESPROC __rglgen_glBlendEquationiOES; +extern RGLSYMGLBLENDEQUATIONSEPARATEIOESPROC __rglgen_glBlendEquationSeparateiOES; +extern RGLSYMGLBLENDFUNCIOESPROC __rglgen_glBlendFunciOES; +extern RGLSYMGLBLENDFUNCSEPARATEIOESPROC __rglgen_glBlendFuncSeparateiOES; +extern RGLSYMGLCOLORMASKIOESPROC __rglgen_glColorMaskiOES; +extern RGLSYMGLISENABLEDIOESPROC __rglgen_glIsEnablediOES; +extern RGLSYMGLDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glDrawElementsBaseVertexOES; +extern RGLSYMGLDRAWRANGEELEMENTSBASEVERTEXOESPROC __rglgen_glDrawRangeElementsBaseVertexOES; +extern RGLSYMGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC __rglgen_glDrawElementsInstancedBaseVertexOES; +extern RGLSYMGLMULTIDRAWELEMENTSBASEVERTEXOESPROC __rglgen_glMultiDrawElementsBaseVertexOES; +extern RGLSYMGLFRAMEBUFFERTEXTUREOESPROC __rglgen_glFramebufferTextureOES; +extern RGLSYMGLGETPROGRAMBINARYOESPROC __rglgen_glGetProgramBinaryOES; +extern RGLSYMGLPROGRAMBINARYOESPROC __rglgen_glProgramBinaryOES; +extern RGLSYMGLMAPBUFFEROESPROC __rglgen_glMapBufferOES; +extern RGLSYMGLUNMAPBUFFEROESPROC __rglgen_glUnmapBufferOES; +extern RGLSYMGLGETBUFFERPOINTERVOESPROC __rglgen_glGetBufferPointervOES; +extern RGLSYMGLPRIMITIVEBOUNDINGBOXOESPROC __rglgen_glPrimitiveBoundingBoxOES; +extern RGLSYMGLMINSAMPLESHADINGOESPROC __rglgen_glMinSampleShadingOES; +extern RGLSYMGLPATCHPARAMETERIOESPROC __rglgen_glPatchParameteriOES; +extern RGLSYMGLTEXIMAGE3DOESPROC __rglgen_glTexImage3DOES; +extern RGLSYMGLTEXSUBIMAGE3DOESPROC __rglgen_glTexSubImage3DOES; +extern RGLSYMGLCOPYTEXSUBIMAGE3DOESPROC __rglgen_glCopyTexSubImage3DOES; +extern RGLSYMGLCOMPRESSEDTEXIMAGE3DOESPROC __rglgen_glCompressedTexImage3DOES; +extern RGLSYMGLCOMPRESSEDTEXSUBIMAGE3DOESPROC __rglgen_glCompressedTexSubImage3DOES; +extern RGLSYMGLFRAMEBUFFERTEXTURE3DOESPROC __rglgen_glFramebufferTexture3DOES; +extern RGLSYMGLTEXPARAMETERIIVOESPROC __rglgen_glTexParameterIivOES; +extern RGLSYMGLTEXPARAMETERIUIVOESPROC __rglgen_glTexParameterIuivOES; +extern RGLSYMGLGETTEXPARAMETERIIVOESPROC __rglgen_glGetTexParameterIivOES; +extern RGLSYMGLGETTEXPARAMETERIUIVOESPROC __rglgen_glGetTexParameterIuivOES; +extern RGLSYMGLSAMPLERPARAMETERIIVOESPROC __rglgen_glSamplerParameterIivOES; +extern RGLSYMGLSAMPLERPARAMETERIUIVOESPROC __rglgen_glSamplerParameterIuivOES; +extern RGLSYMGLGETSAMPLERPARAMETERIIVOESPROC __rglgen_glGetSamplerParameterIivOES; +extern RGLSYMGLGETSAMPLERPARAMETERIUIVOESPROC __rglgen_glGetSamplerParameterIuivOES; +extern RGLSYMGLTEXBUFFEROESPROC __rglgen_glTexBufferOES; +extern RGLSYMGLTEXBUFFERRANGEOESPROC __rglgen_glTexBufferRangeOES; +extern RGLSYMGLTEXSTORAGE3DMULTISAMPLEOESPROC __rglgen_glTexStorage3DMultisampleOES; +extern RGLSYMGLTEXTUREVIEWOESPROC __rglgen_glTextureViewOES; +extern RGLSYMGLBINDVERTEXARRAYOESPROC __rglgen_glBindVertexArrayOES; +extern RGLSYMGLDELETEVERTEXARRAYSOESPROC __rglgen_glDeleteVertexArraysOES; +extern RGLSYMGLGENVERTEXARRAYSOESPROC __rglgen_glGenVertexArraysOES; +extern RGLSYMGLISVERTEXARRAYOESPROC __rglgen_glIsVertexArrayOES; +extern RGLSYMGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultiviewOVR; +extern RGLSYMGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC __rglgen_glFramebufferTextureMultisampleMultiviewOVR; + +struct rglgen_sym_map { const char *sym; void *ptr; }; +extern const struct rglgen_sym_map rglgen_symbol_map[]; +#ifdef __cplusplus +} +#endif +#endif diff --git a/desmume/src/libretro-common/include/glsym/rglgen.h b/desmume/src/libretro-common/include/glsym/rglgen.h index a528d3063..bf127f857 100644 --- a/desmume/src/libretro-common/include/glsym/rglgen.h +++ b/desmume/src/libretro-common/include/glsym/rglgen.h @@ -27,11 +27,11 @@ #include "config.h" #endif +#include + #include "rglgen_headers.h" -#ifdef __cplusplus -extern "C" { -#endif +RETRO_BEGIN_DECLS struct rglgen_sym_map; @@ -41,9 +41,7 @@ void rglgen_resolve_symbols(rglgen_proc_address_t proc); void rglgen_resolve_symbols_custom(rglgen_proc_address_t proc, const struct rglgen_sym_map *map); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/glsym/rglgen_headers.h b/desmume/src/libretro-common/include/glsym/rglgen_headers.h index 46195ad65..e60ec25de 100644 --- a/desmume/src/libretro-common/include/glsym/rglgen_headers.h +++ b/desmume/src/libretro-common/include/glsym/rglgen_headers.h @@ -49,7 +49,7 @@ #include #elif defined(HAVE_OPENGLES3) #include -#include /* There are no GLES3 extensions yet. */ +#include #elif defined(HAVE_OPENGLES2) #include #include diff --git a/desmume/src/libretro-common/include/hash/rhash.c b/desmume/src/libretro-common/include/hash/rhash.c new file mode 100644 index 000000000..a36c27d69 --- /dev/null +++ b/desmume/src/libretro-common/include/hash/rhash.c @@ -0,0 +1,557 @@ +/* Copyright (C) 2010-2015 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (rhash.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 +#ifdef _WIN32 +#include +#else +#include +#endif +#include +#include +#include +#include + +#define LSL32(x, n) ((uint32_t)(x) << (n)) +#define LSR32(x, n) ((uint32_t)(x) >> (n)) +#define ROR32(x, n) (LSR32(x, n) | LSL32(x, 32 - (n))) + +/* First 32 bits of the fractional parts of the square roots of the first 8 primes 2..19 */ +static const uint32_t T_H[8] = { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, +}; + +/* First 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311 */ +static const uint32_t T_K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, +}; + +/* SHA256 implementation from bSNES. Written by valditx. */ + +struct sha256_ctx +{ + union + { + uint8_t u8[64]; + uint32_t u32[16]; + } in; + unsigned inlen; + + uint32_t w[64]; + uint32_t h[8]; + uint64_t len; +}; + +static void sha256_init(struct sha256_ctx *p) +{ + memset(p, 0, sizeof(struct sha256_ctx)); + memcpy(p->h, T_H, sizeof(T_H)); +} + +static void sha256_block(struct sha256_ctx *p) +{ + unsigned i; + uint32_t s0, s1; + uint32_t a, b, c, d, e, f, g, h; + + for (i = 0; i < 16; i++) + p->w[i] = load32be(p->in.u32 + i); + + for (i = 16; i < 64; i++) + { + s0 = ROR32(p->w[i - 15], 7) ^ ROR32(p->w[i - 15], 18) ^ LSR32(p->w[i - 15], 3); + s1 = ROR32(p->w[i - 2], 17) ^ ROR32(p->w[i - 2], 19) ^ LSR32(p->w[i - 2], 10); + p->w[i] = p->w[i - 16] + s0 + p->w[i - 7] + s1; + } + + a = p->h[0]; b = p->h[1]; c = p->h[2]; d = p->h[3]; + e = p->h[4]; f = p->h[5]; g = p->h[6]; h = p->h[7]; + + 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]; + + 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; + p->h[4] += e; p->h[5] += f; p->h[6] += g; p->h[7] += h; + + /* Next block */ + p->inlen = 0; +} + +static void sha256_chunk(struct sha256_ctx *p, + const uint8_t *s, unsigned len) +{ + p->len += len; + + while (len) + { + 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; + + if (p->inlen == 64) + sha256_block(p); + } +} + +static void sha256_final(struct sha256_ctx *p) +{ + uint64_t len; + p->in.u8[p->inlen++] = 0x80; + + if (p->inlen > 56) + { + memset(p->in.u8 + p->inlen, 0, 64 - p->inlen); + sha256_block(p); + } + + memset(p->in.u8 + p->inlen, 0, 56 - p->inlen); + + len = p->len << 3; + store32be(p->in.u32 + 14, (uint32_t)(len >> 32)); + store32be(p->in.u32 + 15, (uint32_t)len); + sha256_block(p); +} + +static void sha256_subhash(struct sha256_ctx *p, uint32_t *t) +{ + unsigned i; + for (i = 0; i < 8; i++) + store32be(t++, p->h[i]); +} + +/** + * sha256_hash: + * @s : Output. + * @in : Input. + * @size : Size of @s. + * + * Hashes SHA256 and outputs a human readable string. + **/ +void sha256_hash(char *s, const uint8_t *in, size_t size) +{ + unsigned i; + struct sha256_ctx sha; + + union + { + uint32_t u32[8]; + uint8_t u8[32]; + } shahash; + + sha256_init(&sha); + sha256_chunk(&sha, in, size); + sha256_final(&sha); + sha256_subhash(&sha, shahash.u32); + + for (i = 0; i < 32; i++) + snprintf(s + 2 * i, 3, "%02x", (unsigned)shahash.u8[i]); +} + +#ifndef HAVE_ZLIB +/* Zlib CRC32. */ +static const uint32_t crc32_table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +uint32_t crc32_adjust(uint32_t checksum, uint8_t input) +{ + return ((checksum >> 8) & 0x00ffffff) ^ crc32_table[(checksum ^ input) & 0xff]; +} + +uint32_t crc32_calculate(const uint8_t *data, size_t length) +{ + size_t i; + uint32_t checksum = ~0; + for (i = 0; i < length; i++) + checksum = crc32_adjust(checksum, data[i]); + return ~checksum; +} +#endif + +/* SHA-1 implementation. */ + +/* + * sha1.c + * + * Copyright (C) 1998, 2009 + * Paul E. Jones + * All Rights Reserved + * + ***************************************************************************** + * $Id: sha1.c 12 2009-06-22 19:34:25Z paulej $ + ***************************************************************************** + * + * Description: + * This file implements the Secure Hashing Standard as defined + * in FIPS PUB 180-1 published April 17, 1995. + * + * The Secure Hashing Standard, which uses the Secure Hashing + * Algorithm (SHA), produces a 160-bit message digest for a + * given data stream. In theory, it is highly improbable that + * two messages will produce the same message digest. Therefore, + * this algorithm can serve as a means of providing a "fingerprint" + * for a message. + * + * Portability Issues: + * SHA-1 is defined in terms of 32-bit "words". This code was + * written with the expectation that the processor has at least + * a 32-bit machine word size. If the machine word size is larger, + * the code should still function properly. One caveat to that + * is that the input functions taking characters and character + * arrays assume that only 8 bits of information are stored in each + * character. + * + * Caveats: + * SHA-1 is designed to work with messages less than 2^64 bits + * long. Although SHA-1 allows a message digest to be generated for + * messages of any number of bits less than 2^64, this + * implementation only works with messages with a length that is a + * multiple of the size of an 8-bit character. + * + */ + +/* Define the circular shift macro */ +#define SHA1CircularShift(bits,word) ((((word) << (bits)) & 0xFFFFFFFF) | ((word) >> (32-(bits)))) + +static void SHA1Reset(SHA1Context *context) +{ + if (!context) + return; + + context->Length_Low = 0; + context->Length_High = 0; + context->Message_Block_Index = 0; + + context->Message_Digest[0] = 0x67452301; + context->Message_Digest[1] = 0xEFCDAB89; + context->Message_Digest[2] = 0x98BADCFE; + context->Message_Digest[3] = 0x10325476; + context->Message_Digest[4] = 0xC3D2E1F0; + + context->Computed = 0; + context->Corrupted = 0; +} + +static void SHA1ProcessMessageBlock(SHA1Context *context) +{ + const unsigned K[] = /* Constants defined in SHA-1 */ + { + 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6 + }; + int t; /* Loop counter */ + unsigned temp; /* Temporary word value */ + unsigned W[80]; /* Word sequence */ + unsigned A, B, C, D, E; /* Word buffers */ + + /* Initialize the first 16 words in the array W */ + for(t = 0; t < 16; t++) + { + W[t] = ((unsigned) context->Message_Block[t * 4]) << 24; + W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16; + W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8; + W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]); + } + + for(t = 16; t < 80; t++) + W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + + A = context->Message_Digest[0]; + B = context->Message_Digest[1]; + C = context->Message_Digest[2]; + D = context->Message_Digest[3]; + E = context->Message_Digest[4]; + + for(t = 0; t < 20; t++) + { + temp = SHA1CircularShift(5,A) + + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 20; t < 40; t++) + { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 40; t < 60; t++) + { + temp = SHA1CircularShift(5,A) + + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 60; t < 80; t++) + { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + context->Message_Digest[0] = + (context->Message_Digest[0] + A) & 0xFFFFFFFF; + context->Message_Digest[1] = + (context->Message_Digest[1] + B) & 0xFFFFFFFF; + context->Message_Digest[2] = + (context->Message_Digest[2] + C) & 0xFFFFFFFF; + context->Message_Digest[3] = + (context->Message_Digest[3] + D) & 0xFFFFFFFF; + context->Message_Digest[4] = + (context->Message_Digest[4] + E) & 0xFFFFFFFF; + + context->Message_Block_Index = 0; +} + +static void SHA1PadMessage(SHA1Context *context) +{ + if (!context) + return; + + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + context->Message_Block[context->Message_Block_Index++] = 0x80; + + if (context->Message_Block_Index > 55) + { + while(context->Message_Block_Index < 64) + context->Message_Block[context->Message_Block_Index++] = 0; + + SHA1ProcessMessageBlock(context); + } + + while(context->Message_Block_Index < 56) + context->Message_Block[context->Message_Block_Index++] = 0; + + /* Store the message length as the last 8 octets */ + context->Message_Block[56] = (context->Length_High >> 24) & 0xFF; + context->Message_Block[57] = (context->Length_High >> 16) & 0xFF; + context->Message_Block[58] = (context->Length_High >> 8) & 0xFF; + context->Message_Block[59] = (context->Length_High) & 0xFF; + context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF; + context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF; + context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF; + context->Message_Block[63] = (context->Length_Low) & 0xFF; + + SHA1ProcessMessageBlock(context); +} + +static int SHA1Result(SHA1Context *context) +{ + if (context->Corrupted) + return 0; + + if (!context->Computed) + { + SHA1PadMessage(context); + context->Computed = 1; + } + + return 1; +} + +static void SHA1Input(SHA1Context *context, + const unsigned char *message_array, + unsigned length) +{ + if (!length) + return; + + if (context->Computed || context->Corrupted) + { + context->Corrupted = 1; + return; + } + + while(length-- && !context->Corrupted) + { + context->Message_Block[context->Message_Block_Index++] = + (*message_array & 0xFF); + + context->Length_Low += 8; + /* Force it to 32 bits */ + context->Length_Low &= 0xFFFFFFFF; + if (context->Length_Low == 0) + { + context->Length_High++; + /* Force it to 32 bits */ + context->Length_High &= 0xFFFFFFFF; + if (context->Length_High == 0) + context->Corrupted = 1; /* Message is too long */ + } + + if (context->Message_Block_Index == 64) + SHA1ProcessMessageBlock(context); + + message_array++; + } +} + +int sha1_calculate(const char *path, char *result) +{ + unsigned char buff[4096] = {0}; + SHA1Context sha; + int rv = 1; + RFILE *fd = filestream_open(path, RFILE_MODE_READ, -1); + + if (!fd) + goto error; + + SHA1Reset(&sha); + + do + { + rv = filestream_read(fd, buff, 4096); + if (rv < 0) + goto error; + + SHA1Input(&sha, buff, rv); + }while(rv); + + if (!SHA1Result(&sha)) + goto error; + + sprintf(result, "%08X%08X%08X%08X%08X", + sha.Message_Digest[0], + sha.Message_Digest[1], + sha.Message_Digest[2], + sha.Message_Digest[3], sha.Message_Digest[4]); + + filestream_close(fd); + return 0; + +error: + if (fd) + filestream_close(fd); + return -1; +} + +uint32_t djb2_calculate(const char *str) +{ + const unsigned char *aux = (const unsigned char*)str; + uint32_t hash = 5381; + + while ( *aux ) + hash = ( hash << 5 ) + hash + *aux++; + + return hash; +} diff --git a/desmume/src/libretro-common/include/libco.h b/desmume/src/libretro-common/include/libco.h index 5a8b11db4..9925d7e37 100644 --- a/desmume/src/libretro-common/include/libco.h +++ b/desmume/src/libretro-common/include/libco.h @@ -23,6 +23,8 @@ #ifndef LIBCO_H #define LIBCO_H +#include + #ifdef LIBCO_C #ifdef LIBCO_MP #define thread_local __thread @@ -31,9 +33,7 @@ #endif #endif -#ifdef __cplusplus -extern "C" { -#endif +RETRO_BEGIN_DECLS typedef void* cothread_t; @@ -73,9 +73,7 @@ void co_delete(cothread_t cothread); */ void co_switch(cothread_t cothread); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS /* ifndef LIBCO_H */ #endif diff --git a/desmume/src/libretro-common/include/libretro.h b/desmume/src/libretro-common/include/libretro.h new file mode 100644 index 000000000..e6809262a --- /dev/null +++ b/desmume/src/libretro-common/include/libretro.h @@ -0,0 +1,2128 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this libretro API header (libretro.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_H__ +#define LIBRETRO_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __cplusplus +#if defined(_MSC_VER) && !defined(SN_TARGET_PS3) +/* Hack applied for MSVC when compiling in C89 mode + * as it isn't C99-compliant. */ +#define bool unsigned char +#define true 1 +#define false 0 +#else +#include +#endif +#endif + +#ifndef RETRO_CALLCONV +# if defined(__GNUC__) && defined(__i386__) && !defined(__x86_64__) +# define RETRO_CALLCONV __attribute__((cdecl)) +# elif defined(_MSC_VER) && defined(_M_X86) && !defined(_M_X64) +# define RETRO_CALLCONV __cdecl +# else +# define RETRO_CALLCONV /* all other platforms only have one calling convention each */ +# endif +#endif + +#ifndef RETRO_API +# if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) +# ifdef RETRO_IMPORT_SYMBOLS +# ifdef __GNUC__ +# define RETRO_API RETRO_CALLCONV __attribute__((__dllimport__)) +# else +# define RETRO_API RETRO_CALLCONV __declspec(dllimport) +# endif +# else +# ifdef __GNUC__ +# define RETRO_API RETRO_CALLCONV __attribute__((__dllexport__)) +# else +# define RETRO_API RETRO_CALLCONV __declspec(dllexport) +# endif +# endif +# else +# if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__CELLOS_LV2__) +# define RETRO_API RETRO_CALLCONV __attribute__((__visibility__("default"))) +# else +# define RETRO_API RETRO_CALLCONV +# endif +# endif +#endif + +/* Used for checking API/ABI mismatches that can break libretro + * implementations. + * It is not incremented for compatible changes to the API. + */ +#define RETRO_API_VERSION 1 + +/* + * Libretro's fundamental device abstractions. + * + * Libretro's input system consists of some standardized device types, + * such as a joypad (with/without analog), mouse, keyboard, lightgun + * and a pointer. + * + * The functionality of these devices are fixed, and individual cores + * map their own concept of a controller to libretro's abstractions. + * This makes it possible for frontends to map the abstract types to a + * real input device, and not having to worry about binding input + * correctly to arbitrary controller layouts. + */ + +#define RETRO_DEVICE_TYPE_SHIFT 8 +#define RETRO_DEVICE_MASK ((1 << RETRO_DEVICE_TYPE_SHIFT) - 1) +#define RETRO_DEVICE_SUBCLASS(base, id) (((id + 1) << RETRO_DEVICE_TYPE_SHIFT) | base) + +/* Input disabled. */ +#define RETRO_DEVICE_NONE 0 + +/* The JOYPAD is called RetroPad. It is essentially a Super Nintendo + * controller, but with additional L2/R2/L3/R3 buttons, similar to a + * PS1 DualShock. */ +#define RETRO_DEVICE_JOYPAD 1 + +/* The mouse is a simple mouse, similar to Super Nintendo's mouse. + * X and Y coordinates are reported relatively to last poll (poll callback). + * It is up to the libretro implementation to keep track of where the mouse + * pointer is supposed to be on the screen. + * The frontend must make sure not to interfere with its own hardware + * mouse pointer. + */ +#define RETRO_DEVICE_MOUSE 2 + +/* KEYBOARD device lets one poll for raw key pressed. + * It is poll based, so input callback will return with the current + * pressed state. + * For event/text based keyboard input, see + * RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. + */ +#define RETRO_DEVICE_KEYBOARD 3 + +/* Lightgun X/Y coordinates are reported relatively to last poll, + * similar to mouse. */ +#define RETRO_DEVICE_LIGHTGUN 4 + +/* The ANALOG device is an extension to JOYPAD (RetroPad). + * Similar to DualShock it adds two analog sticks. + * This is treated as a separate device type as it returns values in the + * full analog range of [-0x8000, 0x7fff]. Positive X axis is right. + * Positive Y axis is down. + * Only use ANALOG type when polling for analog values of the axes. + */ +#define RETRO_DEVICE_ANALOG 5 + +/* Abstracts the concept of a pointing mechanism, e.g. touch. + * This allows libretro to query in absolute coordinates where on the + * screen a mouse (or something similar) is being placed. + * For a touch centric device, coordinates reported are the coordinates + * of the press. + * + * Coordinates in X and Y are reported as: + * [-0x7fff, 0x7fff]: -0x7fff corresponds to the far left/top of the screen, + * and 0x7fff corresponds to the far right/bottom of the screen. + * The "screen" is here defined as area that is passed to the frontend and + * later displayed on the monitor. + * + * The frontend is free to scale/resize this screen as it sees fit, however, + * (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the + * game image, etc. + * + * To check if the pointer coordinates are valid (e.g. a touch display + * actually being touched), PRESSED returns 1 or 0. + * + * If using a mouse on a desktop, PRESSED will usually correspond to the + * left mouse button, but this is a frontend decision. + * PRESSED will only return 1 if the pointer is inside the game screen. + * + * For multi-touch, the index variable can be used to successively query + * more presses. + * If index = 0 returns true for _PRESSED, coordinates can be extracted + * with _X, _Y for index = 0. One can then query _PRESSED, _X, _Y with + * index = 1, and so on. + * Eventually _PRESSED will return false for an index. No further presses + * are registered at this point. */ +#define RETRO_DEVICE_POINTER 6 + +/* Buttons for the RetroPad (JOYPAD). + * The placement of these is equivalent to placements on the + * Super Nintendo controller. + * L2/R2/L3/R3 buttons correspond to the PS1 DualShock. */ +#define RETRO_DEVICE_ID_JOYPAD_B 0 +#define RETRO_DEVICE_ID_JOYPAD_Y 1 +#define RETRO_DEVICE_ID_JOYPAD_SELECT 2 +#define RETRO_DEVICE_ID_JOYPAD_START 3 +#define RETRO_DEVICE_ID_JOYPAD_UP 4 +#define RETRO_DEVICE_ID_JOYPAD_DOWN 5 +#define RETRO_DEVICE_ID_JOYPAD_LEFT 6 +#define RETRO_DEVICE_ID_JOYPAD_RIGHT 7 +#define RETRO_DEVICE_ID_JOYPAD_A 8 +#define RETRO_DEVICE_ID_JOYPAD_X 9 +#define RETRO_DEVICE_ID_JOYPAD_L 10 +#define RETRO_DEVICE_ID_JOYPAD_R 11 +#define RETRO_DEVICE_ID_JOYPAD_L2 12 +#define RETRO_DEVICE_ID_JOYPAD_R2 13 +#define RETRO_DEVICE_ID_JOYPAD_L3 14 +#define RETRO_DEVICE_ID_JOYPAD_R3 15 + +/* Index / Id values for ANALOG device. */ +#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 +#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 +#define RETRO_DEVICE_ID_ANALOG_X 0 +#define RETRO_DEVICE_ID_ANALOG_Y 1 + +/* Id values for MOUSE. */ +#define RETRO_DEVICE_ID_MOUSE_X 0 +#define RETRO_DEVICE_ID_MOUSE_Y 1 +#define RETRO_DEVICE_ID_MOUSE_LEFT 2 +#define RETRO_DEVICE_ID_MOUSE_RIGHT 3 +#define RETRO_DEVICE_ID_MOUSE_WHEELUP 4 +#define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5 +#define RETRO_DEVICE_ID_MOUSE_MIDDLE 6 +#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP 7 +#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN 8 + +/* Id values for LIGHTGUN types. */ +#define RETRO_DEVICE_ID_LIGHTGUN_X 0 +#define RETRO_DEVICE_ID_LIGHTGUN_Y 1 +#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2 +#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 +#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 +#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 +#define RETRO_DEVICE_ID_LIGHTGUN_START 6 + +/* Id values for POINTER. */ +#define RETRO_DEVICE_ID_POINTER_X 0 +#define RETRO_DEVICE_ID_POINTER_Y 1 +#define RETRO_DEVICE_ID_POINTER_PRESSED 2 + +/* Returned from retro_get_region(). */ +#define RETRO_REGION_NTSC 0 +#define RETRO_REGION_PAL 1 + +/* Id values for LANGUAGE */ +enum retro_language +{ + RETRO_LANGUAGE_ENGLISH = 0, + RETRO_LANGUAGE_JAPANESE = 1, + RETRO_LANGUAGE_FRENCH = 2, + RETRO_LANGUAGE_SPANISH = 3, + RETRO_LANGUAGE_GERMAN = 4, + RETRO_LANGUAGE_ITALIAN = 5, + RETRO_LANGUAGE_DUTCH = 6, + RETRO_LANGUAGE_PORTUGUESE = 7, + RETRO_LANGUAGE_RUSSIAN = 8, + RETRO_LANGUAGE_KOREAN = 9, + RETRO_LANGUAGE_CHINESE_TRADITIONAL = 10, + RETRO_LANGUAGE_CHINESE_SIMPLIFIED = 11, + RETRO_LANGUAGE_ESPERANTO = 12, + RETRO_LANGUAGE_POLISH = 13, + RETRO_LANGUAGE_LAST, + + /* Ensure sizeof(enum) == sizeof(int) */ + RETRO_LANGUAGE_DUMMY = INT_MAX +}; + +/* Passed to retro_get_memory_data/size(). + * If the memory type doesn't apply to the + * implementation NULL/0 can be returned. + */ +#define RETRO_MEMORY_MASK 0xff + +/* Regular save RAM. This RAM is usually found on a game cartridge, + * backed up by a battery. + * If save game data is too complex for a single memory buffer, + * the SAVE_DIRECTORY (preferably) or SYSTEM_DIRECTORY environment + * callback can be used. */ +#define RETRO_MEMORY_SAVE_RAM 0 + +/* Some games have a built-in clock to keep track of time. + * This memory is usually just a couple of bytes to keep track of time. + */ +#define RETRO_MEMORY_RTC 1 + +/* System ram lets a frontend peek into a game systems main RAM. */ +#define RETRO_MEMORY_SYSTEM_RAM 2 + +/* Video ram lets a frontend peek into a game systems video RAM (VRAM). */ +#define RETRO_MEMORY_VIDEO_RAM 3 + +/* Keysyms used for ID in input state callback when polling RETRO_KEYBOARD. */ +enum retro_key +{ + RETROK_UNKNOWN = 0, + RETROK_FIRST = 0, + RETROK_BACKSPACE = 8, + RETROK_TAB = 9, + RETROK_CLEAR = 12, + RETROK_RETURN = 13, + RETROK_PAUSE = 19, + RETROK_ESCAPE = 27, + RETROK_SPACE = 32, + RETROK_EXCLAIM = 33, + RETROK_QUOTEDBL = 34, + RETROK_HASH = 35, + RETROK_DOLLAR = 36, + RETROK_AMPERSAND = 38, + RETROK_QUOTE = 39, + RETROK_LEFTPAREN = 40, + RETROK_RIGHTPAREN = 41, + RETROK_ASTERISK = 42, + RETROK_PLUS = 43, + RETROK_COMMA = 44, + RETROK_MINUS = 45, + RETROK_PERIOD = 46, + RETROK_SLASH = 47, + RETROK_0 = 48, + RETROK_1 = 49, + RETROK_2 = 50, + RETROK_3 = 51, + RETROK_4 = 52, + RETROK_5 = 53, + RETROK_6 = 54, + RETROK_7 = 55, + RETROK_8 = 56, + RETROK_9 = 57, + RETROK_COLON = 58, + RETROK_SEMICOLON = 59, + RETROK_LESS = 60, + RETROK_EQUALS = 61, + RETROK_GREATER = 62, + RETROK_QUESTION = 63, + RETROK_AT = 64, + RETROK_LEFTBRACKET = 91, + RETROK_BACKSLASH = 92, + RETROK_RIGHTBRACKET = 93, + RETROK_CARET = 94, + RETROK_UNDERSCORE = 95, + RETROK_BACKQUOTE = 96, + RETROK_a = 97, + RETROK_b = 98, + RETROK_c = 99, + RETROK_d = 100, + RETROK_e = 101, + RETROK_f = 102, + RETROK_g = 103, + RETROK_h = 104, + RETROK_i = 105, + RETROK_j = 106, + RETROK_k = 107, + RETROK_l = 108, + RETROK_m = 109, + RETROK_n = 110, + RETROK_o = 111, + RETROK_p = 112, + RETROK_q = 113, + RETROK_r = 114, + RETROK_s = 115, + RETROK_t = 116, + RETROK_u = 117, + RETROK_v = 118, + RETROK_w = 119, + RETROK_x = 120, + RETROK_y = 121, + RETROK_z = 122, + RETROK_DELETE = 127, + + RETROK_KP0 = 256, + RETROK_KP1 = 257, + RETROK_KP2 = 258, + RETROK_KP3 = 259, + RETROK_KP4 = 260, + RETROK_KP5 = 261, + RETROK_KP6 = 262, + RETROK_KP7 = 263, + RETROK_KP8 = 264, + RETROK_KP9 = 265, + RETROK_KP_PERIOD = 266, + RETROK_KP_DIVIDE = 267, + RETROK_KP_MULTIPLY = 268, + RETROK_KP_MINUS = 269, + RETROK_KP_PLUS = 270, + RETROK_KP_ENTER = 271, + RETROK_KP_EQUALS = 272, + + RETROK_UP = 273, + RETROK_DOWN = 274, + RETROK_RIGHT = 275, + RETROK_LEFT = 276, + RETROK_INSERT = 277, + RETROK_HOME = 278, + RETROK_END = 279, + RETROK_PAGEUP = 280, + RETROK_PAGEDOWN = 281, + + RETROK_F1 = 282, + RETROK_F2 = 283, + RETROK_F3 = 284, + RETROK_F4 = 285, + RETROK_F5 = 286, + RETROK_F6 = 287, + RETROK_F7 = 288, + RETROK_F8 = 289, + RETROK_F9 = 290, + RETROK_F10 = 291, + RETROK_F11 = 292, + RETROK_F12 = 293, + RETROK_F13 = 294, + RETROK_F14 = 295, + RETROK_F15 = 296, + + RETROK_NUMLOCK = 300, + RETROK_CAPSLOCK = 301, + RETROK_SCROLLOCK = 302, + RETROK_RSHIFT = 303, + RETROK_LSHIFT = 304, + RETROK_RCTRL = 305, + RETROK_LCTRL = 306, + RETROK_RALT = 307, + RETROK_LALT = 308, + RETROK_RMETA = 309, + RETROK_LMETA = 310, + RETROK_LSUPER = 311, + RETROK_RSUPER = 312, + RETROK_MODE = 313, + RETROK_COMPOSE = 314, + + RETROK_HELP = 315, + RETROK_PRINT = 316, + RETROK_SYSREQ = 317, + RETROK_BREAK = 318, + RETROK_MENU = 319, + RETROK_POWER = 320, + RETROK_EURO = 321, + RETROK_UNDO = 322, + + RETROK_LAST, + + RETROK_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ +}; + +enum retro_mod +{ + RETROKMOD_NONE = 0x0000, + + RETROKMOD_SHIFT = 0x01, + RETROKMOD_CTRL = 0x02, + RETROKMOD_ALT = 0x04, + RETROKMOD_META = 0x08, + + RETROKMOD_NUMLOCK = 0x10, + RETROKMOD_CAPSLOCK = 0x20, + RETROKMOD_SCROLLOCK = 0x40, + + RETROKMOD_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ +}; + +/* If set, this call is not part of the public libretro API yet. It can + * change or be removed at any time. */ +#define RETRO_ENVIRONMENT_EXPERIMENTAL 0x10000 +/* Environment callback to be used internally in frontend. */ +#define RETRO_ENVIRONMENT_PRIVATE 0x20000 + +/* Environment commands. */ +#define RETRO_ENVIRONMENT_SET_ROTATION 1 /* const unsigned * -- + * Sets screen rotation of graphics. + * Is only implemented if rotation can be accelerated by hardware. + * Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, + * 270 degrees counter-clockwise respectively. + */ +#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 /* bool * -- + * Boolean value whether or not the implementation should use overscan, + * or crop away overscan. + */ +#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 /* bool * -- + * Boolean value whether or not frontend supports frame duping, + * passing NULL to video frame callback. + */ + + /* Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), + * and reserved to avoid possible ABI clash. + */ + +#define RETRO_ENVIRONMENT_SET_MESSAGE 6 /* const struct retro_message * -- + * Sets a message to be displayed in implementation-specific manner + * for a certain amount of 'frames'. + * Should not be used for trivial messages, which should simply be + * logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a + * fallback, stderr). + */ +#define RETRO_ENVIRONMENT_SHUTDOWN 7 /* N/A (NULL) -- + * Requests the frontend to shutdown. + * Should only be used if game has a specific + * way to shutdown the game from a menu item or similar. + */ +#define RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL 8 + /* const unsigned * -- + * Gives a hint to the frontend how demanding this implementation + * is on a system. E.g. reporting a level of 2 means + * this implementation should run decently on all frontends + * of level 2 and up. + * + * It can be used by the frontend to potentially warn + * about too demanding implementations. + * + * The levels are "floating". + * + * This function can be called on a per-game basis, + * as certain games an implementation can play might be + * particularly demanding. + * If called, it should be called in retro_load_game(). + */ +#define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9 + /* const char ** -- + * Returns the "system" directory of the frontend. + * This directory can be used to store system specific + * content such as BIOSes, configuration data, etc. + * The returned value can be NULL. + * If so, no such directory is defined, + * and it's up to the implementation to find a suitable directory. + * + * NOTE: Some cores used this folder also for "save" data such as + * memory cards, etc, for lack of a better place to put it. + * This is now discouraged, and if possible, cores should try to + * use the new GET_SAVE_DIRECTORY. + */ +#define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 + /* const enum retro_pixel_format * -- + * Sets the internal pixel format used by the implementation. + * The default pixel format is RETRO_PIXEL_FORMAT_0RGB1555. + * This pixel format however, is deprecated (see enum retro_pixel_format). + * If the call returns false, the frontend does not support this pixel + * format. + * + * This function should be called inside retro_load_game() or + * retro_get_system_av_info(). + */ +#define RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS 11 + /* const struct retro_input_descriptor * -- + * Sets an array of retro_input_descriptors. + * It is up to the frontend to present this in a usable way. + * The array is terminated by retro_input_descriptor::description + * being set to NULL. + * This function can be called at any time, but it is recommended + * to call it as early as possible. + */ +#define RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK 12 + /* const struct retro_keyboard_callback * -- + * Sets a callback function used to notify core about keyboard events. + */ +#define RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE 13 + /* const struct retro_disk_control_callback * -- + * Sets an interface which frontend can use to eject and insert + * disk images. + * This is used for games which consist of multiple images and + * must be manually swapped out by the user (e.g. PSX). + */ +#define RETRO_ENVIRONMENT_SET_HW_RENDER 14 + /* struct retro_hw_render_callback * -- + * Sets an interface to let a libretro core render with + * hardware acceleration. + * Should be called in retro_load_game(). + * If successful, libretro cores will be able to render to a + * frontend-provided framebuffer. + * The size of this framebuffer will be at least as large as + * max_width/max_height provided in get_av_info(). + * If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or + * NULL to retro_video_refresh_t. + */ +#define RETRO_ENVIRONMENT_GET_VARIABLE 15 + /* struct retro_variable * -- + * Interface to acquire user-defined information from environment + * that cannot feasibly be supported in a multi-system way. + * 'key' should be set to a key which has already been set by + * SET_VARIABLES. + * 'data' will be set to a value or NULL. + */ +#define RETRO_ENVIRONMENT_SET_VARIABLES 16 + /* const struct retro_variable * -- + * Allows an implementation to signal the environment + * which variables it might want to check for later using + * GET_VARIABLE. + * This allows the frontend to present these variables to + * a user dynamically. + * This should be called as early as possible (ideally in + * retro_set_environment). + * + * 'data' points to an array of retro_variable structs + * terminated by a { NULL, NULL } element. + * retro_variable::key should be namespaced to not collide + * with other implementations' keys. E.g. A core called + * 'foo' should use keys named as 'foo_option'. + * retro_variable::value should contain a human readable + * description of the key as well as a '|' delimited list + * of expected values. + * + * The number of possible options should be very limited, + * i.e. it should be feasible to cycle through options + * without a keyboard. + * + * First entry should be treated as a default. + * + * Example entry: + * { "foo_option", "Speed hack coprocessor X; false|true" } + * + * Text before first ';' is description. This ';' must be + * followed by a space, and followed by a list of possible + * values split up with '|'. + * + * Only strings are operated on. The possible values will + * generally be displayed and stored as-is by the frontend. + */ +#define RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE 17 + /* bool * -- + * Result is set to true if some variables are updated by + * frontend since last call to RETRO_ENVIRONMENT_GET_VARIABLE. + * Variables should be queried with GET_VARIABLE. + */ +#define RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME 18 + /* const bool * -- + * If true, the libretro implementation supports calls to + * retro_load_game() with NULL as argument. + * Used by cores which can run without particular game data. + * This should be called within retro_set_environment() only. + */ +#define RETRO_ENVIRONMENT_GET_LIBRETRO_PATH 19 + /* const char ** -- + * Retrieves the absolute path from where this libretro + * implementation was loaded. + * NULL is returned if the libretro was loaded statically + * (i.e. linked statically to frontend), or if the path cannot be + * determined. + * Mostly useful in cooperation with SET_SUPPORT_NO_GAME as assets can + * be loaded without ugly hacks. + */ + + /* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. + * It was not used by any known core at the time, + * and was removed from the API. */ +#define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22 + /* const struct retro_audio_callback * -- + * Sets an interface which is used to notify a libretro core about audio + * being available for writing. + * The callback can be called from any thread, so a core using this must + * have a thread safe audio implementation. + * It is intended for games where audio and video are completely + * asynchronous and audio can be generated on the fly. + * This interface is not recommended for use with emulators which have + * highly synchronous audio. + * + * The callback only notifies about writability; the libretro core still + * has to call the normal audio callbacks + * to write audio. The audio callbacks must be called from within the + * notification callback. + * The amount of audio data to write is up to the implementation. + * Generally, the audio callback will be called continously in a loop. + * + * Due to thread safety guarantees and lack of sync between audio and + * video, a frontend can selectively disallow this interface based on + * internal configuration. A core using this interface must also + * implement the "normal" audio interface. + * + * A libretro core using SET_AUDIO_CALLBACK should also make use of + * SET_FRAME_TIME_CALLBACK. + */ +#define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21 + /* const struct retro_frame_time_callback * -- + * Lets the core know how much time has passed since last + * invocation of retro_run(). + * The frontend can tamper with the timing to fake fast-forward, + * slow-motion, frame stepping, etc. + * In this case the delta time will use the reference value + * in frame_time_callback.. + */ +#define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23 + /* struct retro_rumble_interface * -- + * Gets an interface which is used by a libretro core to set + * state of rumble motors in controllers. + * A strong and weak motor is supported, and they can be + * controlled indepedently. + */ +#define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24 + /* uint64_t * -- + * Gets a bitmask telling which device type are expected to be + * handled properly in a call to retro_input_state_t. + * Devices which are not handled or recognized always return + * 0 in retro_input_state_t. + * Example bitmask: caps = (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG). + * Should only be called in retro_run(). + */ +#define RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE (25 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_sensor_interface * -- + * Gets access to the sensor interface. + * The purpose of this interface is to allow + * setting state related to sensors such as polling rate, + * enabling/disable it entirely, etc. + * Reading sensor state is done via the normal + * input_state_callback API. + */ +#define RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE (26 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_camera_callback * -- + * Gets an interface to a video camera driver. + * A libretro core can use this interface to get access to a + * video camera. + * New video frames are delivered in a callback in same + * thread as retro_run(). + * + * GET_CAMERA_INTERFACE should be called in retro_load_game(). + * + * Depending on the camera implementation used, camera frames + * will be delivered as a raw framebuffer, + * or as an OpenGL texture directly. + * + * The core has to tell the frontend here which types of + * buffers can be handled properly. + * An OpenGL texture can only be handled when using a + * libretro GL core (SET_HW_RENDER). + * It is recommended to use a libretro GL core when + * using camera interface. + * + * The camera is not started automatically. The retrieved start/stop + * functions must be used to explicitly + * start and stop the camera driver. + */ +#define RETRO_ENVIRONMENT_GET_LOG_INTERFACE 27 + /* struct retro_log_callback * -- + * Gets an interface for logging. This is useful for + * logging in a cross-platform way + * as certain platforms cannot use use stderr for logging. + * It also allows the frontend to + * show logging information in a more suitable way. + * If this interface is not used, libretro cores should + * log to stderr as desired. + */ +#define RETRO_ENVIRONMENT_GET_PERF_INTERFACE 28 + /* struct retro_perf_callback * -- + * Gets an interface for performance counters. This is useful + * for performance logging in a cross-platform way and for detecting + * architecture-specific features, such as SIMD support. + */ +#define RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE 29 + /* struct retro_location_callback * -- + * Gets access to the location interface. + * The purpose of this interface is to be able to retrieve + * location-based information from the host device, + * such as current latitude / longitude. + */ +#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 /* Old name, kept for compatibility. */ +#define RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY 30 + /* const char ** -- + * Returns the "core assets" directory of the frontend. + * This directory can be used to store specific assets that the + * core relies upon, such as art assets, + * input data, etc etc. + * The returned value can be NULL. + * If so, no such directory is defined, + * and it's up to the implementation to find a suitable directory. + */ +#define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31 + /* const char ** -- + * Returns the "save" directory of the frontend. + * This directory can be used to store SRAM, memory cards, + * high scores, etc, if the libretro core + * cannot use the regular memory interface (retro_get_memory_data()). + * + * NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for + * similar things before. + * They should still check GET_SYSTEM_DIRECTORY if they want to + * be backwards compatible. + * The path here can be NULL. It should only be non-NULL if the + * frontend user has set a specific save path. + */ +#define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32 + /* const struct retro_system_av_info * -- + * Sets a new av_info structure. This can only be called from + * within retro_run(). + * This should *only* be used if the core is completely altering the + * internal resolutions, aspect ratios, timings, sampling rate, etc. + * Calling this can require a full reinitialization of video/audio + * drivers in the frontend, + * + * so it is important to call it very sparingly, and usually only with + * the users explicit consent. + * An eventual driver reinitialize will happen so that video and + * audio callbacks + * happening after this call within the same retro_run() call will + * target the newly initialized driver. + * + * This callback makes it possible to support configurable resolutions + * in games, which can be useful to + * avoid setting the "worst case" in max_width/max_height. + * + * ***HIGHLY RECOMMENDED*** Do not call this callback every time + * resolution changes in an emulator core if it's + * expected to be a temporary change, for the reasons of possible + * driver reinitialization. + * This call is not a free pass for not trying to provide + * correct values in retro_get_system_av_info(). If you need to change + * things like aspect ratio or nominal width/height, + * use RETRO_ENVIRONMENT_SET_GEOMETRY, which is a softer variant + * of SET_SYSTEM_AV_INFO. + * + * If this returns false, the frontend does not acknowledge a + * changed av_info struct. + */ +#define RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK 33 + /* const struct retro_get_proc_address_interface * -- + * Allows a libretro core to announce support for the + * get_proc_address() interface. + * This interface allows for a standard way to extend libretro where + * use of environment calls are too indirect, + * e.g. for cases where the frontend wants to call directly into the core. + * + * If a core wants to expose this interface, SET_PROC_ADDRESS_CALLBACK + * **MUST** be called from within retro_set_environment(). + */ +#define RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO 34 + /* const struct retro_subsystem_info * -- + * This environment call introduces the concept of libretro "subsystems". + * A subsystem is a variant of a libretro core which supports + * different kinds of games. + * The purpose of this is to support e.g. emulators which might + * have special needs, e.g. Super Nintendo's Super GameBoy, Sufami Turbo. + * It can also be used to pick among subsystems in an explicit way + * if the libretro implementation is a multi-system emulator itself. + * + * Loading a game via a subsystem is done with retro_load_game_special(), + * and this environment call allows a libretro core to expose which + * subsystems are supported for use with retro_load_game_special(). + * A core passes an array of retro_game_special_info which is terminated + * with a zeroed out retro_game_special_info struct. + * + * If a core wants to use this functionality, SET_SUBSYSTEM_INFO + * **MUST** be called from within retro_set_environment(). + */ +#define RETRO_ENVIRONMENT_SET_CONTROLLER_INFO 35 + /* const struct retro_controller_info * -- + * This environment call lets a libretro core tell the frontend + * which controller types are recognized in calls to + * retro_set_controller_port_device(). + * + * Some emulators such as Super Nintendo + * support multiple lightgun types which must be specifically + * selected from. + * It is therefore sometimes necessary for a frontend to be able + * to tell the core about a special kind of input device which is + * not covered by the libretro input API. + * + * In order for a frontend to understand the workings of an input device, + * it must be a specialized type + * of the generic device types already defined in the libretro API. + * + * Which devices are supported can vary per input port. + * The core must pass an array of const struct retro_controller_info which + * is terminated with a blanked out struct. Each element of the struct + * corresponds to an ascending port index to + * retro_set_controller_port_device(). + * Even if special device types are set in the libretro core, + * libretro should only poll input based on the base input device types. + */ +#define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const struct retro_memory_map * -- + * This environment call lets a libretro core tell the frontend + * about the memory maps this core emulates. + * This can be used to implement, for example, cheats in a core-agnostic way. + * + * Should only be used by emulators; it doesn't make much sense for + * anything else. + * It is recommended to expose all relevant pointers through + * retro_get_memory_* as well. + * + * Can be called from retro_init and retro_load_game. + */ +#define RETRO_ENVIRONMENT_SET_GEOMETRY 37 + /* const struct retro_game_geometry * -- + * This environment call is similar to SET_SYSTEM_AV_INFO for changing + * video parameters, but provides a guarantee that drivers will not be + * reinitialized. + * This can only be called from within retro_run(). + * + * The purpose of this call is to allow a core to alter nominal + * width/heights as well as aspect ratios on-the-fly, which can be + * useful for some emulators to change in run-time. + * + * max_width/max_height arguments are ignored and cannot be changed + * with this call as this could potentially require a reinitialization or a + * non-constant time operation. + * If max_width/max_height are to be changed, SET_SYSTEM_AV_INFO is required. + * + * A frontend must guarantee that this environment call completes in + * constant time. + */ +#define RETRO_ENVIRONMENT_GET_USERNAME 38 + /* const char ** + * Returns the specified username of the frontend, if specified by the user. + * This username can be used as a nickname for a core that has online facilities + * or any other mode where personalization of the user is desirable. + * The returned value can be NULL. + * If this environ callback is used by a core that requires a valid username, + * a default username should be specified by the core. + */ +#define RETRO_ENVIRONMENT_GET_LANGUAGE 39 + /* unsigned * -- + * Returns the specified language of the frontend, if specified by the user. + * It can be used by the core for localization purposes. + */ +#define RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER (40 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* struct retro_framebuffer * -- + * Returns a preallocated framebuffer which the core can use for rendering + * the frame into when not using SET_HW_RENDER. + * The framebuffer returned from this call must not be used + * after the current call to retro_run() returns. + * + * The goal of this call is to allow zero-copy behavior where a core + * can render directly into video memory, avoiding extra bandwidth cost by copying + * memory from core to video memory. + * + * If this call succeeds and the core renders into it, + * the framebuffer pointer and pitch can be passed to retro_video_refresh_t. + * If the buffer from GET_CURRENT_SOFTWARE_FRAMEBUFFER is to be used, + * the core must pass the exact + * same pointer as returned by GET_CURRENT_SOFTWARE_FRAMEBUFFER; + * i.e. passing a pointer which is offset from the + * buffer is undefined. The width, height and pitch parameters + * must also match exactly to the values obtained from GET_CURRENT_SOFTWARE_FRAMEBUFFER. + * + * It is possible for a frontend to return a different pixel format + * than the one used in SET_PIXEL_FORMAT. This can happen if the frontend + * needs to perform conversion. + * + * It is still valid for a core to render to a different buffer + * even if GET_CURRENT_SOFTWARE_FRAMEBUFFER succeeds. + * + * A frontend must make sure that the pointer obtained from this function is + * writeable (and readable). + */ + +enum retro_hw_render_interface_type +{ + RETRO_HW_RENDER_INTERFACE_VULKAN = 0, + RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX +}; + +/* Base struct. All retro_hw_render_interface_* types + * contain at least these fields. */ +struct retro_hw_render_interface +{ + enum retro_hw_render_interface_type interface_type; + unsigned interface_version; +}; +#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const struct retro_hw_render_interface ** -- + * Returns an API specific rendering interface for accessing API specific data. + * Not all HW rendering APIs support or need this. + * The contents of the returned pointer is specific to the rendering API + * being used. See the various headers like libretro_vulkan.h, etc. + * + * GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called. + * Similarly, after context_destroyed callback returns, + * the contents of the HW_RENDER_INTERFACE are invalidated. + */ + +#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const bool * -- + * If true, the libretro implementation supports achievements + * either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS + * or via retro_get_memory_data/retro_get_memory_size. + * + * This must be called before the first call to retro_run. + */ + +enum retro_hw_render_context_negotiation_interface_type +{ + RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN = 0, + RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_DUMMY = INT_MAX +}; + +/* Base struct. All retro_hw_render_context_negotiation_interface_* types + * contain at least these fields. */ +struct retro_hw_render_context_negotiation_interface +{ + enum retro_hw_render_context_negotiation_interface_type interface_type; + unsigned interface_version; +}; +#define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const struct retro_hw_render_context_negotiation_interface * -- + * Sets an interface which lets the libretro core negotiate with frontend how a context is created. + * The semantics of this interface depends on which API is used in SET_HW_RENDER earlier. + * This interface will be used when the frontend is trying to create a HW rendering context, + * so it will be used after SET_HW_RENDER, but before the context_reset callback. + */ + +#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */ +#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */ +#define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */ +#define RETRO_MEMDESC_ALIGN_4 (2 << 16) +#define RETRO_MEMDESC_ALIGN_8 (3 << 16) +#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) /* All memory in this region is accessed at least 2 bytes at the time. */ +#define RETRO_MEMDESC_MINSIZE_4 (2 << 24) +#define RETRO_MEMDESC_MINSIZE_8 (3 << 24) +struct retro_memory_descriptor +{ + uint64_t flags; + + /* Pointer to the start of the relevant ROM or RAM chip. + * It's strongly recommended to use 'offset' if possible, rather than + * doing math on the pointer. + * + * If the same byte is mapped my multiple descriptors, their descriptors + * must have the same pointer. + * If 'start' does not point to the first byte in the pointer, put the + * difference in 'offset' instead. + * + * May be NULL if there's nothing usable here (e.g. hardware registers and + * open bus). No flags should be set if the pointer is NULL. + * It's recommended to minimize the number of descriptors if possible, + * but not mandatory. */ + void *ptr; + size_t offset; + + /* This is the location in the emulated address space + * where the mapping starts. */ + size_t start; + + /* Which bits must be same as in 'start' for this mapping to apply. + * The first memory descriptor to claim a certain byte is the one + * that applies. + * A bit which is set in 'start' must also be set in this. + * Can be zero, in which case each byte is assumed mapped exactly once. + * In this case, 'len' must be a power of two. */ + size_t select; + + /* If this is nonzero, the set bits are assumed not connected to the + * memory chip's address pins. */ + size_t disconnect; + + /* This one tells the size of the current memory area. + * If, after start+disconnect are applied, the address is higher than + * this, the highest bit of the address is cleared. + * + * If the address is still too high, the next highest bit is cleared. + * Can be zero, in which case it's assumed to be infinite (as limited + * by 'select' and 'disconnect'). */ + size_t len; + + /* To go from emulated address to physical address, the following + * order applies: + * Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. */ + + /* The address space name must consist of only a-zA-Z0-9_-, + * should be as short as feasible (maximum length is 8 plus the NUL), + * and may not be any other address space plus one or more 0-9A-F + * at the end. + * However, multiple memory descriptors for the same address space is + * allowed, and the address space name can be empty. NULL is treated + * as empty. + * + * Address space names are case sensitive, but avoid lowercase if possible. + * The same pointer may exist in multiple address spaces. + * + * Examples: + * blank+blank - valid (multiple things may be mapped in the same namespace) + * 'Sp'+'Sp' - valid (multiple things may be mapped in the same namespace) + * 'A'+'B' - valid (neither is a prefix of each other) + * 'S'+blank - valid ('S' is not in 0-9A-F) + * 'a'+blank - valid ('a' is not in 0-9A-F) + * 'a'+'A' - valid (neither is a prefix of each other) + * 'AR'+blank - valid ('R' is not in 0-9A-F) + * 'ARB'+blank - valid (the B can't be part of the address either, because + * there is no namespace 'AR') + * blank+'B' - not valid, because it's ambigous which address space B1234 + * would refer to. + * The length can't be used for that purpose; the frontend may want + * to append arbitrary data to an address, without a separator. */ + const char *addrspace; + + /* TODO: When finalizing this one, add a description field, which should be + * "WRAM" or something roughly equally long. */ + + /* TODO: When finalizing this one, replace 'select' with 'limit', which tells + * which bits can vary and still refer to the same address (limit = ~select). + * TODO: limit? range? vary? something else? */ + + /* TODO: When finalizing this one, if 'len' is above what 'select' (or + * 'limit') allows, it's bankswitched. Bankswitched data must have both 'len' + * and 'select' != 0, and the mappings don't tell how the system switches the + * banks. */ + + /* TODO: When finalizing this one, fix the 'len' bit removal order. + * For len=0x1800, pointer 0x1C00 should go to 0x1400, not 0x0C00. + * Algorithm: Take bits highest to lowest, but if it goes above len, clear + * the most recent addition and continue on the next bit. + * TODO: Can the above be optimized? Is "remove the lowest bit set in both + * pointer and 'len'" equivalent? */ + + /* TODO: Some emulators (MAME?) emulate big endian systems by only accessing + * the emulated memory in 32-bit chunks, native endian. But that's nothing + * compared to Darek Mihocka + * (section Emulation 103 - Nearly Free Byte Reversal) - he flips the ENTIRE + * RAM backwards! I'll want to represent both of those, via some flags. + * + * I suspect MAME either didn't think of that idea, or don't want the #ifdef. + * Not sure which, nor do I really care. */ + + /* TODO: Some of those flags are unused and/or don't really make sense. Clean + * them up. */ +}; + +/* The frontend may use the largest value of 'start'+'select' in a + * certain namespace to infer the size of the address space. + * + * If the address space is larger than that, a mapping with .ptr=NULL + * should be at the end of the array, with .select set to all ones for + * as long as the address space is big. + * + * Sample descriptors (minus .ptr, and RETRO_MEMFLAG_ on the flags): + * SNES WRAM: + * .start=0x7E0000, .len=0x20000 + * (Note that this must be mapped before the ROM in most cases; some of the + * ROM mappers + * try to claim $7E0000, or at least $7E8000.) + * SNES SPC700 RAM: + * .addrspace="S", .len=0x10000 + * SNES WRAM mirrors: + * .flags=MIRROR, .start=0x000000, .select=0xC0E000, .len=0x2000 + * .flags=MIRROR, .start=0x800000, .select=0xC0E000, .len=0x2000 + * SNES WRAM mirrors, alternate equivalent descriptor: + * .flags=MIRROR, .select=0x40E000, .disconnect=~0x1FFF + * (Various similar constructions can be created by combining parts of + * the above two.) + * SNES LoROM (512KB, mirrored a couple of times): + * .flags=CONST, .start=0x008000, .select=0x408000, .disconnect=0x8000, .len=512*1024 + * .flags=CONST, .start=0x400000, .select=0x400000, .disconnect=0x8000, .len=512*1024 + * SNES HiROM (4MB): + * .flags=CONST, .start=0x400000, .select=0x400000, .len=4*1024*1024 + * .flags=CONST, .offset=0x8000, .start=0x008000, .select=0x408000, .len=4*1024*1024 + * SNES ExHiROM (8MB): + * .flags=CONST, .offset=0, .start=0xC00000, .select=0xC00000, .len=4*1024*1024 + * .flags=CONST, .offset=4*1024*1024, .start=0x400000, .select=0xC00000, .len=4*1024*1024 + * .flags=CONST, .offset=0x8000, .start=0x808000, .select=0xC08000, .len=4*1024*1024 + * .flags=CONST, .offset=4*1024*1024+0x8000, .start=0x008000, .select=0xC08000, .len=4*1024*1024 + * Clarify the size of the address space: + * .ptr=NULL, .select=0xFFFFFF + * .len can be implied by .select in many of them, but was included for clarity. + */ + +struct retro_memory_map +{ + const struct retro_memory_descriptor *descriptors; + unsigned num_descriptors; +}; + +struct retro_controller_description +{ + /* Human-readable description of the controller. Even if using a generic + * input device type, this can be set to the particular device type the + * core uses. */ + const char *desc; + + /* Device type passed to retro_set_controller_port_device(). If the device + * type is a sub-class of a generic input device type, use the + * RETRO_DEVICE_SUBCLASS macro to create an ID. + * + * E.g. RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1). */ + unsigned id; +}; + +struct retro_controller_info +{ + const struct retro_controller_description *types; + unsigned num_types; +}; + +struct retro_subsystem_memory_info +{ + /* The extension associated with a memory type, e.g. "psram". */ + const char *extension; + + /* The memory type for retro_get_memory(). This should be at + * least 0x100 to avoid conflict with standardized + * libretro memory types. */ + unsigned type; +}; + +struct retro_subsystem_rom_info +{ + /* Describes what the content is (SGB BIOS, GB ROM, etc). */ + const char *desc; + + /* Same definition as retro_get_system_info(). */ + const char *valid_extensions; + + /* Same definition as retro_get_system_info(). */ + bool need_fullpath; + + /* Same definition as retro_get_system_info(). */ + bool block_extract; + + /* This is set if the content is required to load a game. + * If this is set to false, a zeroed-out retro_game_info can be passed. */ + bool required; + + /* Content can have multiple associated persistent + * memory types (retro_get_memory()). */ + const struct retro_subsystem_memory_info *memory; + unsigned num_memory; +}; + +struct retro_subsystem_info +{ + /* Human-readable string of the subsystem type, e.g. "Super GameBoy" */ + const char *desc; + + /* A computer friendly short string identifier for the subsystem type. + * This name must be [a-z]. + * E.g. if desc is "Super GameBoy", this can be "sgb". + * This identifier can be used for command-line interfaces, etc. + */ + const char *ident; + + /* Infos for each content file. The first entry is assumed to be the + * "most significant" content for frontend purposes. + * E.g. with Super GameBoy, the first content should be the GameBoy ROM, + * as it is the most "significant" content to a user. + * If a frontend creates new file paths based on the content used + * (e.g. savestates), it should use the path for the first ROM to do so. */ + const struct retro_subsystem_rom_info *roms; + + /* Number of content files associated with a subsystem. */ + unsigned num_roms; + + /* The type passed to retro_load_game_special(). */ + unsigned id; +}; + +typedef void (RETRO_CALLCONV *retro_proc_address_t)(void); + +/* libretro API extension functions: + * (None here so far). + * + * Get a symbol from a libretro core. + * Cores should only return symbols which are actual + * extensions to the libretro API. + * + * Frontends should not use this to obtain symbols to standard + * libretro entry points (static linking or dlsym). + * + * The symbol name must be equal to the function name, + * e.g. if void retro_foo(void); exists, the symbol must be called "retro_foo". + * The returned function pointer must be cast to the corresponding type. + */ +typedef retro_proc_address_t (RETRO_CALLCONV *retro_get_proc_address_t)(const char *sym); + +struct retro_get_proc_address_interface +{ + retro_get_proc_address_t get_proc_address; +}; + +enum retro_log_level +{ + RETRO_LOG_DEBUG = 0, + RETRO_LOG_INFO, + RETRO_LOG_WARN, + RETRO_LOG_ERROR, + + RETRO_LOG_DUMMY = INT_MAX +}; + +/* Logging function. Takes log level argument as well. */ +typedef void (RETRO_CALLCONV *retro_log_printf_t)(enum retro_log_level level, + const char *fmt, ...); + +struct retro_log_callback +{ + retro_log_printf_t log; +}; + +/* Performance related functions */ + +/* ID values for SIMD CPU features */ +#define RETRO_SIMD_SSE (1 << 0) +#define RETRO_SIMD_SSE2 (1 << 1) +#define RETRO_SIMD_VMX (1 << 2) +#define RETRO_SIMD_VMX128 (1 << 3) +#define RETRO_SIMD_AVX (1 << 4) +#define RETRO_SIMD_NEON (1 << 5) +#define RETRO_SIMD_SSE3 (1 << 6) +#define RETRO_SIMD_SSSE3 (1 << 7) +#define RETRO_SIMD_MMX (1 << 8) +#define RETRO_SIMD_MMXEXT (1 << 9) +#define RETRO_SIMD_SSE4 (1 << 10) +#define RETRO_SIMD_SSE42 (1 << 11) +#define RETRO_SIMD_AVX2 (1 << 12) +#define RETRO_SIMD_VFPU (1 << 13) +#define RETRO_SIMD_PS (1 << 14) +#define RETRO_SIMD_AES (1 << 15) +#define RETRO_SIMD_VFPV3 (1 << 16) +#define RETRO_SIMD_VFPV4 (1 << 17) +#define RETRO_SIMD_POPCNT (1 << 18) +#define RETRO_SIMD_MOVBE (1 << 19) + +typedef uint64_t retro_perf_tick_t; +typedef int64_t retro_time_t; + +struct retro_perf_counter +{ + const char *ident; + retro_perf_tick_t start; + retro_perf_tick_t total; + retro_perf_tick_t call_cnt; + + bool registered; +}; + +/* Returns current time in microseconds. + * Tries to use the most accurate timer available. + */ +typedef retro_time_t (RETRO_CALLCONV *retro_perf_get_time_usec_t)(void); + +/* A simple counter. Usually nanoseconds, but can also be CPU cycles. + * Can be used directly if desired (when creating a more sophisticated + * performance counter system). + * */ +typedef retro_perf_tick_t (RETRO_CALLCONV *retro_perf_get_counter_t)(void); + +/* Returns a bit-mask of detected CPU features (RETRO_SIMD_*). */ +typedef uint64_t (RETRO_CALLCONV *retro_get_cpu_features_t)(void); + +/* Asks frontend to log and/or display the state of performance counters. + * Performance counters can always be poked into manually as well. + */ +typedef void (RETRO_CALLCONV *retro_perf_log_t)(void); + +/* Register a performance counter. + * ident field must be set with a discrete value and other values in + * retro_perf_counter must be 0. + * Registering can be called multiple times. To avoid calling to + * frontend redundantly, you can check registered field first. */ +typedef void (RETRO_CALLCONV *retro_perf_register_t)(struct retro_perf_counter *counter); + +/* Starts a registered counter. */ +typedef void (RETRO_CALLCONV *retro_perf_start_t)(struct retro_perf_counter *counter); + +/* Stops a registered counter. */ +typedef void (RETRO_CALLCONV *retro_perf_stop_t)(struct retro_perf_counter *counter); + +/* For convenience it can be useful to wrap register, start and stop in macros. + * E.g.: + * #ifdef LOG_PERFORMANCE + * #define RETRO_PERFORMANCE_INIT(perf_cb, name) static struct retro_perf_counter name = {#name}; if (!name.registered) perf_cb.perf_register(&(name)) + * #define RETRO_PERFORMANCE_START(perf_cb, name) perf_cb.perf_start(&(name)) + * #define RETRO_PERFORMANCE_STOP(perf_cb, name) perf_cb.perf_stop(&(name)) + * #else + * ... Blank macros ... + * #endif + * + * These can then be used mid-functions around code snippets. + * + * extern struct retro_perf_callback perf_cb; * Somewhere in the core. + * + * void do_some_heavy_work(void) + * { + * RETRO_PERFORMANCE_INIT(cb, work_1; + * RETRO_PERFORMANCE_START(cb, work_1); + * heavy_work_1(); + * RETRO_PERFORMANCE_STOP(cb, work_1); + * + * RETRO_PERFORMANCE_INIT(cb, work_2); + * RETRO_PERFORMANCE_START(cb, work_2); + * heavy_work_2(); + * RETRO_PERFORMANCE_STOP(cb, work_2); + * } + * + * void retro_deinit(void) + * { + * perf_cb.perf_log(); * Log all perf counters here for example. + * } + */ + +struct retro_perf_callback +{ + retro_perf_get_time_usec_t get_time_usec; + retro_get_cpu_features_t get_cpu_features; + + retro_perf_get_counter_t get_perf_counter; + retro_perf_register_t perf_register; + retro_perf_start_t perf_start; + retro_perf_stop_t perf_stop; + retro_perf_log_t perf_log; +}; + +/* FIXME: Document the sensor API and work out behavior. + * It will be marked as experimental until then. + */ +enum retro_sensor_action +{ + RETRO_SENSOR_ACCELEROMETER_ENABLE = 0, + RETRO_SENSOR_ACCELEROMETER_DISABLE, + + RETRO_SENSOR_DUMMY = INT_MAX +}; + +/* Id values for SENSOR types. */ +#define RETRO_SENSOR_ACCELEROMETER_X 0 +#define RETRO_SENSOR_ACCELEROMETER_Y 1 +#define RETRO_SENSOR_ACCELEROMETER_Z 2 + +typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port, + enum retro_sensor_action action, unsigned rate); + +typedef float (RETRO_CALLCONV *retro_sensor_get_input_t)(unsigned port, unsigned id); + +struct retro_sensor_interface +{ + retro_set_sensor_state_t set_sensor_state; + retro_sensor_get_input_t get_sensor_input; +}; + +enum retro_camera_buffer +{ + RETRO_CAMERA_BUFFER_OPENGL_TEXTURE = 0, + RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER, + + RETRO_CAMERA_BUFFER_DUMMY = INT_MAX +}; + +/* Starts the camera driver. Can only be called in retro_run(). */ +typedef bool (RETRO_CALLCONV *retro_camera_start_t)(void); + +/* Stops the camera driver. Can only be called in retro_run(). */ +typedef void (RETRO_CALLCONV *retro_camera_stop_t)(void); + +/* Callback which signals when the camera driver is initialized + * and/or deinitialized. + * retro_camera_start_t can be called in initialized callback. + */ +typedef void (RETRO_CALLCONV *retro_camera_lifetime_status_t)(void); + +/* A callback for raw framebuffer data. buffer points to an XRGB8888 buffer. + * Width, height and pitch are similar to retro_video_refresh_t. + * First pixel is top-left origin. + */ +typedef void (RETRO_CALLCONV *retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, + unsigned width, unsigned height, size_t pitch); + +/* A callback for when OpenGL textures are used. + * + * texture_id is a texture owned by camera driver. + * Its state or content should be considered immutable, except for things like + * texture filtering and clamping. + * + * texture_target is the texture target for the GL texture. + * These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly + * more depending on extensions. + * + * affine points to a packed 3x3 column-major matrix used to apply an affine + * transform to texture coordinates. (affine_matrix * vec3(coord_x, coord_y, 1.0)) + * After transform, normalized texture coord (0, 0) should be bottom-left + * and (1, 1) should be top-right (or (width, height) for RECTANGLE). + * + * GL-specific typedefs are avoided here to avoid relying on gl.h in + * the API definition. + */ +typedef void (RETRO_CALLCONV *retro_camera_frame_opengl_texture_t)(unsigned texture_id, + unsigned texture_target, const float *affine); + +struct retro_camera_callback +{ + /* Set by libretro core. + * Example bitmask: caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER). + */ + uint64_t caps; + + /* Desired resolution for camera. Is only used as a hint. */ + unsigned width; + unsigned height; + + /* Set by frontend. */ + retro_camera_start_t start; + retro_camera_stop_t stop; + + /* Set by libretro core if raw framebuffer callbacks will be used. */ + retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer; + + /* Set by libretro core if OpenGL texture callbacks will be used. */ + retro_camera_frame_opengl_texture_t frame_opengl_texture; + + /* Set by libretro core. Called after camera driver is initialized and + * ready to be started. + * Can be NULL, in which this callback is not called. + */ + retro_camera_lifetime_status_t initialized; + + /* Set by libretro core. Called right before camera driver is + * deinitialized. + * Can be NULL, in which this callback is not called. + */ + retro_camera_lifetime_status_t deinitialized; +}; + +/* Sets the interval of time and/or distance at which to update/poll + * location-based data. + * + * To ensure compatibility with all location-based implementations, + * values for both interval_ms and interval_distance should be provided. + * + * interval_ms is the interval expressed in milliseconds. + * interval_distance is the distance interval expressed in meters. + */ +typedef void (RETRO_CALLCONV *retro_location_set_interval_t)(unsigned interval_ms, + unsigned interval_distance); + +/* Start location services. The device will start listening for changes to the + * current location at regular intervals (which are defined with + * retro_location_set_interval_t). */ +typedef bool (RETRO_CALLCONV *retro_location_start_t)(void); + +/* Stop location services. The device will stop listening for changes + * to the current location. */ +typedef void (RETRO_CALLCONV *retro_location_stop_t)(void); + +/* Get the position of the current location. Will set parameters to + * 0 if no new location update has happened since the last time. */ +typedef bool (RETRO_CALLCONV *retro_location_get_position_t)(double *lat, double *lon, + double *horiz_accuracy, double *vert_accuracy); + +/* Callback which signals when the location driver is initialized + * and/or deinitialized. + * retro_location_start_t can be called in initialized callback. + */ +typedef void (RETRO_CALLCONV *retro_location_lifetime_status_t)(void); + +struct retro_location_callback +{ + retro_location_start_t start; + retro_location_stop_t stop; + retro_location_get_position_t get_position; + retro_location_set_interval_t set_interval; + + retro_location_lifetime_status_t initialized; + retro_location_lifetime_status_t deinitialized; +}; + +enum retro_rumble_effect +{ + RETRO_RUMBLE_STRONG = 0, + RETRO_RUMBLE_WEAK = 1, + + RETRO_RUMBLE_DUMMY = INT_MAX +}; + +/* Sets rumble state for joypad plugged in port 'port'. + * Rumble effects are controlled independently, + * and setting e.g. strong rumble does not override weak rumble. + * Strength has a range of [0, 0xffff]. + * + * Returns true if rumble state request was honored. + * Calling this before first retro_run() is likely to return false. */ +typedef bool (RETRO_CALLCONV *retro_set_rumble_state_t)(unsigned port, + enum retro_rumble_effect effect, uint16_t strength); + +struct retro_rumble_interface +{ + retro_set_rumble_state_t set_rumble_state; +}; + +/* Notifies libretro that audio data should be written. */ +typedef void (RETRO_CALLCONV *retro_audio_callback_t)(void); + +/* True: Audio driver in frontend is active, and callback is + * expected to be called regularily. + * False: Audio driver in frontend is paused or inactive. + * Audio callback will not be called until set_state has been + * called with true. + * Initial state is false (inactive). + */ +typedef void (RETRO_CALLCONV *retro_audio_set_state_callback_t)(bool enabled); + +struct retro_audio_callback +{ + retro_audio_callback_t callback; + retro_audio_set_state_callback_t set_state; +}; + +/* Notifies a libretro core of time spent since last invocation + * of retro_run() in microseconds. + * + * It will be called right before retro_run() every frame. + * The frontend can tamper with timing to support cases like + * fast-forward, slow-motion and framestepping. + * + * In those scenarios the reference frame time value will be used. */ +typedef int64_t retro_usec_t; +typedef void (RETRO_CALLCONV *retro_frame_time_callback_t)(retro_usec_t usec); +struct retro_frame_time_callback +{ + retro_frame_time_callback_t callback; + /* Represents the time of one frame. It is computed as + * 1000000 / fps, but the implementation will resolve the + * rounding to ensure that framestepping, etc is exact. */ + retro_usec_t reference; +}; + +/* Pass this to retro_video_refresh_t if rendering to hardware. + * Passing NULL to retro_video_refresh_t is still a frame dupe as normal. + * */ +#define RETRO_HW_FRAME_BUFFER_VALID ((void*)-1) + +/* Invalidates the current HW context. + * Any GL state is lost, and must not be deinitialized explicitly. + * If explicit deinitialization is desired by the libretro core, + * it should implement context_destroy callback. + * If called, all GPU resources must be reinitialized. + * Usually called when frontend reinits video driver. + * Also called first time video driver is initialized, + * allowing libretro core to initialize resources. + */ +typedef void (RETRO_CALLCONV *retro_hw_context_reset_t)(void); + +/* Gets current framebuffer which is to be rendered to. + * Could change every frame potentially. + */ +typedef uintptr_t (RETRO_CALLCONV *retro_hw_get_current_framebuffer_t)(void); + +/* Get a symbol from HW context. */ +typedef retro_proc_address_t (RETRO_CALLCONV *retro_hw_get_proc_address_t)(const char *sym); + +enum retro_hw_context_type +{ + RETRO_HW_CONTEXT_NONE = 0, + /* OpenGL 2.x. Driver can choose to use latest compatibility context. */ + RETRO_HW_CONTEXT_OPENGL = 1, + /* OpenGL ES 2.0. */ + RETRO_HW_CONTEXT_OPENGLES2 = 2, + /* Modern desktop core GL context. Use version_major/ + * version_minor fields to set GL version. */ + RETRO_HW_CONTEXT_OPENGL_CORE = 3, + /* OpenGL ES 3.0 */ + RETRO_HW_CONTEXT_OPENGLES3 = 4, + /* OpenGL ES 3.1+. Set version_major/version_minor. For GLES2 and GLES3, + * use the corresponding enums directly. */ + RETRO_HW_CONTEXT_OPENGLES_VERSION = 5, + + /* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */ + RETRO_HW_CONTEXT_VULKAN = 6, + + RETRO_HW_CONTEXT_DUMMY = INT_MAX +}; + +struct retro_hw_render_callback +{ + /* Which API to use. Set by libretro core. */ + enum retro_hw_context_type context_type; + + /* Called when a context has been created or when it has been reset. + * An OpenGL context is only valid after context_reset() has been called. + * + * When context_reset is called, OpenGL resources in the libretro + * implementation are guaranteed to be invalid. + * + * It is possible that context_reset is called multiple times during an + * application lifecycle. + * If context_reset is called without any notification (context_destroy), + * the OpenGL context was lost and resources should just be recreated + * without any attempt to "free" old resources. + */ + retro_hw_context_reset_t context_reset; + + /* Set by frontend. + * TODO: This is rather obsolete. The frontend should not + * be providing preallocated framebuffers. */ + retro_hw_get_current_framebuffer_t get_current_framebuffer; + + /* Set by frontend. */ + retro_hw_get_proc_address_t get_proc_address; + + /* Set if render buffers should have depth component attached. + * TODO: Obsolete. */ + bool depth; + + /* Set if stencil buffers should be attached. + * TODO: Obsolete. */ + bool stencil; + + /* If depth and stencil are true, a packed 24/8 buffer will be added. + * Only attaching stencil is invalid and will be ignored. */ + + /* Use conventional bottom-left origin convention. If false, + * standard libretro top-left origin semantics are used. + * TODO: Move to GL specific interface. */ + bool bottom_left_origin; + + /* Major version number for core GL context or GLES 3.1+. */ + unsigned version_major; + + /* Minor version number for core GL context or GLES 3.1+. */ + unsigned version_minor; + + /* If this is true, the frontend will go very far to avoid + * resetting context in scenarios like toggling fullscreen, etc. + * TODO: Obsolete? Maybe frontend should just always assume this ... + */ + bool cache_context; + + /* The reset callback might still be called in extreme situations + * such as if the context is lost beyond recovery. + * + * For optimal stability, set this to false, and allow context to be + * reset at any time. + */ + + /* A callback to be called before the context is destroyed in a + * controlled way by the frontend. */ + retro_hw_context_reset_t context_destroy; + + /* OpenGL resources can be deinitialized cleanly at this step. + * context_destroy can be set to NULL, in which resources will + * just be destroyed without any notification. + * + * Even when context_destroy is non-NULL, it is possible that + * context_reset is called without any destroy notification. + * This happens if context is lost by external factors (such as + * notified by GL_ARB_robustness). + * + * In this case, the context is assumed to be already dead, + * and the libretro implementation must not try to free any OpenGL + * resources in the subsequent context_reset. + */ + + /* Creates a debug context. */ + bool debug_context; +}; + +/* Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. + * Called by the frontend in response to keyboard events. + * down is set if the key is being pressed, or false if it is being released. + * keycode is the RETROK value of the char. + * character is the text character of the pressed key. (UTF-32). + * key_modifiers is a set of RETROKMOD values or'ed together. + * + * The pressed/keycode state can be indepedent of the character. + * It is also possible that multiple characters are generated from a + * single keypress. + * Keycode events should be treated separately from character events. + * However, when possible, the frontend should try to synchronize these. + * If only a character is posted, keycode should be RETROK_UNKNOWN. + * + * Similarily if only a keycode event is generated with no corresponding + * character, character should be 0. + */ +typedef void (RETRO_CALLCONV *retro_keyboard_event_t)(bool down, unsigned keycode, + uint32_t character, uint16_t key_modifiers); + +struct retro_keyboard_callback +{ + retro_keyboard_event_t callback; +}; + +/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. + * Should be set for implementations which can swap out multiple disk + * images in runtime. + * + * If the implementation can do this automatically, it should strive to do so. + * However, there are cases where the user must manually do so. + * + * Overview: To swap a disk image, eject the disk image with + * set_eject_state(true). + * Set the disk index with set_image_index(index). Insert the disk again + * with set_eject_state(false). + */ + +/* If ejected is true, "ejects" the virtual disk tray. + * When ejected, the disk image index can be set. + */ +typedef bool (RETRO_CALLCONV *retro_set_eject_state_t)(bool ejected); + +/* Gets current eject state. The initial state is 'not ejected'. */ +typedef bool (RETRO_CALLCONV *retro_get_eject_state_t)(void); + +/* Gets current disk index. First disk is index 0. + * If return value is >= get_num_images(), no disk is currently inserted. + */ +typedef unsigned (RETRO_CALLCONV *retro_get_image_index_t)(void); + +/* Sets image index. Can only be called when disk is ejected. + * The implementation supports setting "no disk" by using an + * index >= get_num_images(). + */ +typedef bool (RETRO_CALLCONV *retro_set_image_index_t)(unsigned index); + +/* Gets total number of images which are available to use. */ +typedef unsigned (RETRO_CALLCONV *retro_get_num_images_t)(void); + +struct retro_game_info; + +/* Replaces the disk image associated with index. + * Arguments to pass in info have same requirements as retro_load_game(). + * Virtual disk tray must be ejected when calling this. + * + * Replacing a disk image with info = NULL will remove the disk image + * from the internal list. + * As a result, calls to get_image_index() can change. + * + * E.g. replace_image_index(1, NULL), and previous get_image_index() + * returned 4 before. + * Index 1 will be removed, and the new index is 3. + */ +typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index, + const struct retro_game_info *info); + +/* Adds a new valid index (get_num_images()) to the internal disk list. + * This will increment subsequent return values from get_num_images() by 1. + * This image index cannot be used until a disk image has been set + * with replace_image_index. */ +typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void); + +struct retro_disk_control_callback +{ + retro_set_eject_state_t set_eject_state; + retro_get_eject_state_t get_eject_state; + + retro_get_image_index_t get_image_index; + retro_set_image_index_t set_image_index; + retro_get_num_images_t get_num_images; + + retro_replace_image_index_t replace_image_index; + retro_add_image_index_t add_image_index; +}; + +enum retro_pixel_format +{ + /* 0RGB1555, native endian. + * 0 bit must be set to 0. + * This pixel format is default for compatibility concerns only. + * If a 15/16-bit pixel format is desired, consider using RGB565. */ + RETRO_PIXEL_FORMAT_0RGB1555 = 0, + + /* XRGB8888, native endian. + * X bits are ignored. */ + RETRO_PIXEL_FORMAT_XRGB8888 = 1, + + /* RGB565, native endian. + * This pixel format is the recommended format to use if a 15/16-bit + * format is desired as it is the pixel format that is typically + * available on a wide range of low-power devices. + * + * It is also natively supported in APIs like OpenGL ES. */ + RETRO_PIXEL_FORMAT_RGB565 = 2, + + /* Ensure sizeof() == sizeof(int). */ + RETRO_PIXEL_FORMAT_UNKNOWN = INT_MAX +}; + +struct retro_message +{ + const char *msg; /* Message to be displayed. */ + unsigned frames; /* Duration in frames of message. */ +}; + +/* Describes how the libretro implementation maps a libretro input bind + * to its internal input system through a human readable string. + * This string can be used to better let a user configure input. */ +struct retro_input_descriptor +{ + /* Associates given parameters with a description. */ + unsigned port; + unsigned device; + unsigned index; + unsigned id; + + /* Human readable description for parameters. + * The pointer must remain valid until + * retro_unload_game() is called. */ + const char *description; +}; + +struct retro_system_info +{ + /* All pointers are owned by libretro implementation, and pointers must + * remain valid until retro_deinit() is called. */ + + const char *library_name; /* Descriptive name of library. Should not + * contain any version numbers, etc. */ + const char *library_version; /* Descriptive version of core. */ + + const char *valid_extensions; /* A string listing probably content + * extensions the core will be able to + * load, separated with pipe. + * I.e. "bin|rom|iso". + * Typically used for a GUI to filter + * out extensions. */ + + /* If true, retro_load_game() is guaranteed to provide a valid pathname + * in retro_game_info::path. + * ::data and ::size are both invalid. + * + * If false, ::data and ::size are guaranteed to be valid, but ::path + * might not be valid. + * + * This is typically set to true for libretro implementations that must + * load from file. + * Implementations should strive for setting this to false, as it allows + * the frontend to perform patching, etc. */ + bool need_fullpath; + + /* If true, the frontend is not allowed to extract any archives before + * loading the real content. + * Necessary for certain libretro implementations that load games + * from zipped archives. */ + bool block_extract; +}; + +struct retro_game_geometry +{ + unsigned base_width; /* Nominal video width of game. */ + unsigned base_height; /* Nominal video height of game. */ + unsigned max_width; /* Maximum possible width of game. */ + unsigned max_height; /* Maximum possible height of game. */ + + float aspect_ratio; /* Nominal aspect ratio of game. If + * aspect_ratio is <= 0.0, an aspect ratio + * of base_width / base_height is assumed. + * A frontend could override this setting, + * if desired. */ +}; + +struct retro_system_timing +{ + double fps; /* FPS of video content. */ + double sample_rate; /* Sampling rate of audio. */ +}; + +struct retro_system_av_info +{ + struct retro_game_geometry geometry; + struct retro_system_timing timing; +}; + +struct retro_variable +{ + /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. + * If NULL, obtains the complete environment string if more + * complex parsing is necessary. + * The environment string is formatted as key-value pairs + * delimited by semicolons as so: + * "key1=value1;key2=value2;..." + */ + const char *key; + + /* Value to be obtained. If key does not exist, it is set to NULL. */ + const char *value; +}; + +struct retro_game_info +{ + const char *path; /* Path to game, UTF-8 encoded. + * Usually used as a reference. + * May be NULL if rom was loaded from stdin + * or similar. + * retro_system_info::need_fullpath guaranteed + * that this path is valid. */ + const void *data; /* Memory buffer of loaded game. Will be NULL + * if need_fullpath was set. */ + size_t size; /* Size of memory buffer. */ + const char *meta; /* String of implementation specific meta-data. */ +}; + +#define RETRO_MEMORY_ACCESS_WRITE (1 << 0) + /* The core will write to the buffer provided by retro_framebuffer::data. */ +#define RETRO_MEMORY_ACCESS_READ (1 << 1) + /* The core will read from retro_framebuffer::data. */ +#define RETRO_MEMORY_TYPE_CACHED (1 << 0) + /* The memory in data is cached. + * If not cached, random writes and/or reading from the buffer is expected to be very slow. */ +struct retro_framebuffer +{ + void *data; /* The framebuffer which the core can render into. + Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. + The initial contents of data are unspecified. */ + unsigned width; /* The framebuffer width used by the core. Set by core. */ + unsigned height; /* The framebuffer height used by the core. Set by core. */ + size_t pitch; /* The number of bytes between the beginning of a scanline, + and beginning of the next scanline. + Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ + enum retro_pixel_format format; /* The pixel format the core must use to render into data. + This format could differ from the format used in + SET_PIXEL_FORMAT. + Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ + + unsigned access_flags; /* How the core will access the memory in the framebuffer. + RETRO_MEMORY_ACCESS_* flags. + Set by core. */ + unsigned memory_flags; /* Flags telling core how the memory has been mapped. + RETRO_MEMORY_TYPE_* flags. + Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ +}; + +/* Callbacks */ + +/* Environment callback. Gives implementations a way of performing + * uncommon tasks. Extensible. */ +typedef bool (RETRO_CALLCONV *retro_environment_t)(unsigned cmd, void *data); + +/* Render a frame. Pixel format is 15-bit 0RGB1555 native endian + * unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). + * + * Width and height specify dimensions of buffer. + * Pitch specifices length in bytes between two lines in buffer. + * + * For performance reasons, it is highly recommended to have a frame + * that is packed in memory, i.e. pitch == width * byte_per_pixel. + * Certain graphic APIs, such as OpenGL ES, do not like textures + * that are not packed in memory. + */ +typedef void (RETRO_CALLCONV *retro_video_refresh_t)(const void *data, unsigned width, + unsigned height, size_t pitch); + +/* Renders a single audio frame. Should only be used if implementation + * generates a single sample at a time. + * Format is signed 16-bit native endian. + */ +typedef void (RETRO_CALLCONV *retro_audio_sample_t)(int16_t left, int16_t right); + +/* Renders multiple audio frames in one go. + * + * One frame is defined as a sample of left and right channels, interleaved. + * I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames. + * Only one of the audio callbacks must ever be used. + */ +typedef size_t (RETRO_CALLCONV *retro_audio_sample_batch_t)(const int16_t *data, + size_t frames); + +/* Polls input. */ +typedef void (RETRO_CALLCONV *retro_input_poll_t)(void); + +/* Queries for input for player 'port'. device will be masked with + * RETRO_DEVICE_MASK. + * + * Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that + * have been set with retro_set_controller_port_device() + * will still use the higher level RETRO_DEVICE_JOYPAD to request input. + */ +typedef int16_t (RETRO_CALLCONV *retro_input_state_t)(unsigned port, unsigned device, + unsigned index, unsigned id); + +/* Sets callbacks. retro_set_environment() is guaranteed to be called + * before retro_init(). + * + * The rest of the set_* functions are guaranteed to have been called + * before the first call to retro_run() is made. */ +RETRO_API void retro_set_environment(retro_environment_t); +RETRO_API void retro_set_video_refresh(retro_video_refresh_t); +RETRO_API void retro_set_audio_sample(retro_audio_sample_t); +RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t); +RETRO_API void retro_set_input_poll(retro_input_poll_t); +RETRO_API void retro_set_input_state(retro_input_state_t); + +/* Library global initialization/deinitialization. */ +RETRO_API void retro_init(void); +RETRO_API void retro_deinit(void); + +/* Must return RETRO_API_VERSION. Used to validate ABI compatibility + * when the API is revised. */ +RETRO_API unsigned retro_api_version(void); + +/* Gets statically known system info. Pointers provided in *info + * must be statically allocated. + * Can be called at any time, even before retro_init(). */ +RETRO_API void retro_get_system_info(struct retro_system_info *info); + +/* Gets information about system audio/video timings and geometry. + * Can be called only after retro_load_game() has successfully completed. + * NOTE: The implementation of this function might not initialize every + * variable if needed. + * E.g. geom.aspect_ratio might not be initialized if core doesn't + * desire a particular aspect ratio. */ +RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info); + +/* Sets device to be used for player 'port'. + * By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all + * available ports. + * Setting a particular device type is not a guarantee that libretro cores + * will only poll input based on that particular device type. It is only a + * hint to the libretro core when a core cannot automatically detect the + * appropriate input device type on its own. It is also relevant when a + * core can change its behavior depending on device type. */ +RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device); + +/* Resets the current game. */ +RETRO_API void retro_reset(void); + +/* Runs the game for one video frame. + * During retro_run(), input_poll callback must be called at least once. + * + * If a frame is not rendered for reasons where a game "dropped" a frame, + * this still counts as a frame, and retro_run() should explicitly dupe + * a frame if GET_CAN_DUPE returns true. + * In this case, the video callback can take a NULL argument for data. + */ +RETRO_API void retro_run(void); + +/* Returns the amount of data the implementation requires to serialize + * internal state (save states). + * Between calls to retro_load_game() and retro_unload_game(), the + * returned size is never allowed to be larger than a previous returned + * value, to ensure that the frontend can allocate a save state buffer once. + */ +RETRO_API size_t retro_serialize_size(void); + +/* Serializes internal state. If failed, or size is lower than + * retro_serialize_size(), it should return false, true otherwise. */ +RETRO_API bool retro_serialize(void *data, size_t size); +RETRO_API bool retro_unserialize(const void *data, size_t size); + +RETRO_API void retro_cheat_reset(void); +RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code); + +/* Loads a game. */ +RETRO_API bool retro_load_game(const struct retro_game_info *game); + +/* Loads a "special" kind of game. Should not be used, + * except in extreme cases. */ +RETRO_API bool retro_load_game_special( + unsigned game_type, + const struct retro_game_info *info, size_t num_info +); + +/* Unloads a currently loaded game. */ +RETRO_API void retro_unload_game(void); + +/* Gets region of game. */ +RETRO_API unsigned retro_get_region(void); + +/* Gets region of memory. */ +RETRO_API void *retro_get_memory_data(unsigned id); +RETRO_API size_t retro_get_memory_size(unsigned id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/desmume/src/libretro-common/include/libretro_vulkan.h b/desmume/src/libretro-common/include/libretro_vulkan.h new file mode 100644 index 000000000..7fb36ec10 --- /dev/null +++ b/desmume/src/libretro-common/include/libretro_vulkan.h @@ -0,0 +1,398 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------------- + * The following license statement only applies to this libretro API header (libretro_vulkan.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_VULKAN_H__ +#define LIBRETRO_VULKAN_H__ + +#include +#include + +#define RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION 5 +#define RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION 1 + +struct retro_vulkan_image +{ + VkImageView image_view; + VkImageLayout image_layout; + VkImageViewCreateInfo create_info; +}; + +typedef void (*retro_vulkan_set_image_t)(void *handle, + const struct retro_vulkan_image *image, + uint32_t num_semaphores, + const VkSemaphore *semaphores, + uint32_t src_queue_family); + +typedef uint32_t (*retro_vulkan_get_sync_index_t)(void *handle); +typedef uint32_t (*retro_vulkan_get_sync_index_mask_t)(void *handle); +typedef void (*retro_vulkan_set_command_buffers_t)(void *handle, + uint32_t num_cmd, + const VkCommandBuffer *cmd); +typedef void (*retro_vulkan_wait_sync_index_t)(void *handle); +typedef void (*retro_vulkan_lock_queue_t)(void *handle); +typedef void (*retro_vulkan_unlock_queue_t)(void *handle); +typedef void (*retro_vulkan_set_signal_semaphore_t)(void *handle, VkSemaphore semaphore); + +typedef const VkApplicationInfo *(*retro_vulkan_get_application_info_t)(void); + +struct retro_vulkan_context +{ + VkPhysicalDevice gpu; + VkDevice device; + VkQueue queue; + uint32_t queue_family_index; + VkQueue presentation_queue; + uint32_t presentation_queue_family_index; +}; + +typedef bool (*retro_vulkan_create_device_t)( + struct retro_vulkan_context *context, + VkInstance instance, + VkPhysicalDevice gpu, + VkSurfaceKHR surface, + PFN_vkGetInstanceProcAddr get_instance_proc_addr, + const char **required_device_extensions, + unsigned num_required_device_extensions, + const char **required_device_layers, + unsigned num_required_device_layers, + const VkPhysicalDeviceFeatures *required_features); + +typedef void (*retro_vulkan_destroy_device_t)(void); + +/* Note on thread safety: + * The Vulkan API is heavily designed around multi-threading, and + * the libretro interface for it should also be threading friendly. + * A core should be able to build command buffers and submit + * command buffers to the GPU from any thread. + */ + +struct retro_hw_render_context_negotiation_interface_vulkan +{ + /* Must be set to RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN. */ + enum retro_hw_render_context_negotiation_interface_type interface_type; + /* Must be set to RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION. */ + unsigned interface_version; + + /* If non-NULL, returns a VkApplicationInfo struct that the frontend can use instead of + * its "default" application info. + */ + retro_vulkan_get_application_info_t get_application_info; + + /* If non-NULL, the libretro core will choose one or more physical devices, + * create one or more logical devices and create one or more queues. + * The core must prepare a designated PhysicalDevice, Device, Queue and queue family index + * which the frontend will use for its internal operation. + * + * If gpu is not VK_NULL_HANDLE, the physical device provided to the frontend must be this PhysicalDevice. + * The core is still free to use other physical devices. + * + * The frontend will request certain extensions and layers for a device which is created. + * The core must ensure that the queue and queue_family_index support GRAPHICS and COMPUTE. + * + * If surface is not VK_NULL_HANDLE, the core must consider presentation when creating the queues. + * If presentation to "surface" is supported on the queue, presentation_queue must be equal to queue. + * If not, a second queue must be provided in presentation_queue and presentation_queue_index. + * If surface is not VK_NULL_HANDLE, the instance from frontend will have been created with supported for + * VK_KHR_surface extension. + * + * The core is free to set its own queue priorities. + * Device provided to frontend is owned by the frontend, but any additional device resources must be freed by core + * in destroy_device callback. + * + * If this function returns true, a PhysicalDevice, Device and Queues are initialized. + * If false, none of the above have been initialized and the frontend will attempt + * to fallback to "default" device creation, as if this function was never called. + */ + retro_vulkan_create_device_t create_device; + + /* If non-NULL, this callback is called similar to context_destroy for HW_RENDER_INTERFACE. + * However, it will be called even if context_reset was not called. + * This can happen if the context never succeeds in being created. + * destroy_device will always be called before the VkInstance + * of the frontend is destroyed if create_device was called successfully so that the core has a chance of + * tearing down its own device resources. + * + * Only auxillary resources should be freed here, i.e. resources which are not part of retro_vulkan_context. + */ + retro_vulkan_destroy_device_t destroy_device; +}; + +struct retro_hw_render_interface_vulkan +{ + /* Must be set to RETRO_HW_RENDER_INTERFACE_VULKAN. */ + enum retro_hw_render_interface_type interface_type; + /* Must be set to RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION. */ + unsigned interface_version; + + /* Opaque handle to the Vulkan backend in the frontend + * which must be passed along to all function pointers + * in this interface. + * + * The rationale for including a handle here (which libretro v1 + * doesn't currently do in general) is: + * + * - Vulkan cores should be able to be freely threaded without lots of fuzz. + * This would break frontends which currently rely on TLS + * to deal with multiple cores loaded at the same time. + * - Fixing this in general is TODO for an eventual libretro v2. + */ + void *handle; + + /* The Vulkan instance the context is using. */ + VkInstance instance; + /* The physical device used. */ + VkPhysicalDevice gpu; + /* The logical device used. */ + VkDevice device; + + /* Allows a core to fetch all its needed symbols without having to link + * against the loader itself. */ + PFN_vkGetDeviceProcAddr get_device_proc_addr; + PFN_vkGetInstanceProcAddr get_instance_proc_addr; + + /* The queue the core must use to submit data. + * This queue and index must remain constant throughout the lifetime + * of the context. + * + * This queue will be the queue that supports graphics and compute + * if the device supports compute. + */ + VkQueue queue; + unsigned queue_index; + + /* Before calling retro_video_refresh_t with RETRO_HW_FRAME_BUFFER_VALID, + * set which image to use for this frame. + * + * If num_semaphores is non-zero, the frontend will wait for the + * semaphores provided to be signaled before using the results further + * in the pipeline. + * + * Semaphores provided by a single call to set_image will only be + * waited for once (waiting for a semaphore resets it). + * E.g. set_image, video_refresh, and then another + * video_refresh without set_image, + * but same image will only wait for semaphores once. + * + * For this reason, ownership transfer will only occur if semaphores + * are waited on for a particular frame in the frontend. + * + * Using semaphores is optional for synchronization purposes, + * but if not using + * semaphores, an image memory barrier in vkCmdPipelineBarrier + * should be used in the graphics_queue. + * Example: + * + * vkCmdPipelineBarrier(cmd, + * srcStageMask = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + * dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + * image_memory_barrier = { + * srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + * dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + * }); + * + * The use of pipeline barriers instead of semaphores is encouraged + * as it is simpler and more fine-grained. A layout transition + * must generally happen anyways which requires a + * pipeline barrier. + * + * The image passed to set_image must have imageUsage flags set to at least + * VK_IMAGE_USAGE_TRANSFER_SRC_BIT and VK_IMAGE_USAGE_SAMPLED_BIT. + * The core will naturally want to use flags such as + * VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT and/or + * VK_IMAGE_USAGE_TRANSFER_DST_BIT depending + * on how the final image is created. + * + * The image must also have been created with MUTABLE_FORMAT bit set if + * 8-bit formats are used, so that the frontend can reinterpret sRGB + * formats as it sees fit. + * + * Images passed to set_image should be created with TILING_OPTIMAL. + * The image layout should be transitioned to either + * VK_IMAGE_LAYOUT_GENERIC or VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL. + * The actual image layout used must be set in image_layout. + * + * The image must be a 2D texture which may or not be layered + * and/or mipmapped. + * + * The image must be suitable for linear sampling. + * While the image_view is typically the only field used, + * the frontend may want to reinterpret the texture as sRGB vs. + * non-sRGB for example so the VkImageViewCreateInfo used to + * create the image view must also be passed in. + * + * The data in the pointer to the image struct will not be copied + * as the pNext field in create_info cannot be reliably deep-copied. + * The image pointer passed to set_image must be valid until + * retro_video_refresh_t has returned. + * + * If frame duping is used when passing NULL to retro_video_refresh_t, + * the frontend is free to either use the latest image passed to + * set_image or reuse the older pointer passed to set_image the + * frame RETRO_HW_FRAME_BUFFER_VALID was last used. + * + * Essentially, the lifetime of the pointer passed to + * retro_video_refresh_t should be extended if frame duping is used + * so that the frontend can reuse the older pointer. + * + * The image itself however, must not be touched by the core until + * wait_sync_index has been completed later. The frontend may perform + * layout transitions on the image, so even read-only access is not defined. + * The exception to read-only rule is if GENERAL layout is used for the image. + * In this case, the frontend is not allowed to perform any layout transitions, + * so concurrent reads from core and frontend are allowed. + * + * If frame duping is used, or if set_command_buffers is used, + * the frontend will not wait for any semaphores. + * + * The src_queue_family is used to specify which queue family + * the image is currently owned by. If using multiple queue families + * (e.g. async compute), the frontend will need to acquire ownership of the + * image before rendering with it and release the image afterwards. + * + * If src_queue_family is equal to the queue family (queue_index), + * no ownership transfer will occur. + * Similarly, if src_queue_family is VK_QUEUE_FAMILY_IGNORED, + * no ownership transfer will occur. + * + * The frontend will always release ownership back to src_queue_family. + * Waiting for frontend to complete with wait_sync_index() ensures that + * the frontend has released ownership back to the application. + * Note that in Vulkan, transfering ownership is a two-part process. + * + * Example frame: + * - core releases ownership from src_queue_index to queue_index with VkImageMemoryBarrier. + * - core calls set_image with src_queue_index. + * - Frontend will acquire the image with src_queue_index -> queue_index as well, completing the ownership transfer. + * - Frontend renders the frame. + * - Frontend releases ownership with queue_index -> src_queue_index. + * - Next time image is used, core must acquire ownership from queue_index ... + * + * Since the frontend releases ownership, we cannot necessarily dupe the frame because + * the core needs to make the roundtrip of ownership transfer. + */ + retro_vulkan_set_image_t set_image; + + /* Get the current sync index for this frame which is obtained in + * frontend by calling e.g. vkAcquireNextImageKHR before calling + * retro_run(). + * + * This index will correspond to which swapchain buffer is currently + * the active one. + * + * Knowing this index is very useful for maintaining safe asynchronous CPU + * and GPU operation without stalling. + * + * The common pattern for synchronization is to receive fences when + * submitting command buffers to Vulkan (vkQueueSubmit) and add this fence + * to a list of fences for frame number get_sync_index(). + * + * Next time we receive the same get_sync_index(), we can wait for the + * fences from before, which will usually return immediately as the + * frontend will generally also avoid letting the GPU run ahead too much. + * + * After the fence has signaled, we know that the GPU has completed all + * GPU work related to work submitted in the frame we last saw get_sync_index(). + * + * This means we can safely reuse or free resources allocated in this frame. + * + * In theory, even if we wait for the fences correctly, it is not technically + * safe to write to the image we earlier passed to the frontend since we're + * not waiting for the frontend GPU jobs to complete. + * + * The frontend will guarantee that the appropriate pipeline barrier + * in graphics_queue has been used such that + * VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT cannot + * start until the frontend is done with the image. + */ + retro_vulkan_get_sync_index_t get_sync_index; + + /* Returns a bitmask of how many swapchain images we currently have + * in the frontend. + * + * If bit #N is set in the return value, get_sync_index can return N. + * Knowing this value is useful for preallocating per-frame management + * structures ahead of time. + * + * While this value will typically remain constant throughout the + * applications lifecycle, it may for example change if the frontend + * suddently changes fullscreen state and/or latency. + * + * If this value ever changes, it is safe to assume that the device + * is completely idle and all synchronization objects can be deleted + * right away as desired. + */ + retro_vulkan_get_sync_index_mask_t get_sync_index_mask; + + /* Instead of submitting the command buffer to the queue first, the core + * can pass along its command buffer to the frontend, and the frontend + * will submit the command buffer together with the frontends command buffers. + * + * This has the advantage that the overhead of vkQueueSubmit can be + * amortized into a single call. For this mode, semaphores in set_image + * will be ignored, so vkCmdPipelineBarrier must be used to synchronize + * the core and frontend. + * + * The command buffers in set_command_buffers are only executed once, + * even if frame duping is used. + * + * If frame duping is used, set_image should be used for the frames + * which should be duped instead. + * + * Command buffers passed to the frontend with set_command_buffers + * must not actually be submitted to the GPU until retro_video_refresh_t + * is called. + * + * The frontend must submit the command buffer before submitting any + * other command buffers provided by set_command_buffers. */ + retro_vulkan_set_command_buffers_t set_command_buffers; + + /* Waits on CPU for device activity for the current sync index to complete. + * This is useful since the core will not have a relevant fence to sync with + * when the frontend is submitting the command buffers. */ + retro_vulkan_wait_sync_index_t wait_sync_index; + + /* If the core submits command buffers itself to any of the queues provided + * in this interface, the core must lock and unlock the frontend from + * racing on the VkQueue. + * + * Queue submission can happen on any thread. + * Even if queue submission happens on the same thread as retro_run(), + * the lock/unlock functions must still be called. + * + * NOTE: Queue submissions are heavy-weight. */ + retro_vulkan_lock_queue_t lock_queue; + retro_vulkan_unlock_queue_t unlock_queue; + + /* Sets a semaphore which is signaled when the image in set_image can safely be reused. + * The semaphore is consumed next call to retro_video_refresh_t. + * The semaphore will be signalled even for duped frames. + * The semaphore will be signalled only once, so set_signal_semaphore should be called every frame. + * The semaphore may be VK_NULL_HANDLE, which disables semaphore signalling for next call to retro_video_refresh_t. + * + * This is mostly useful to support use cases where you're rendering to a single image that + * is recycled in a ping-pong fashion with the frontend to save memory (but potentially less throughput). + */ + retro_vulkan_set_signal_semaphore_t set_signal_semaphore; +}; + +#endif + diff --git a/desmume/src/libretro-common/include/lists/dir_list.h b/desmume/src/libretro-common/include/lists/dir_list.h index bfbda4dda..2ef8f9ff8 100644 --- a/desmume/src/libretro-common/include/lists/dir_list.h +++ b/desmume/src/libretro-common/include/lists/dir_list.h @@ -23,11 +23,11 @@ #ifndef __LIBRETRO_SDK_DIR_LIST_H #define __LIBRETRO_SDK_DIR_LIST_H +#include + #include -#ifdef __cplusplus -extern "C" { -#endif +RETRO_BEGIN_DECLS /** * dir_list_new: @@ -63,8 +63,6 @@ void dir_list_sort(struct string_list *list, bool dir_first); **/ void dir_list_free(struct string_list *list); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/lists/file_list.h b/desmume/src/libretro-common/include/lists/file_list.h index d23c2ce3a..ad616f0e0 100644 --- a/desmume/src/libretro-common/include/lists/file_list.h +++ b/desmume/src/libretro-common/include/lists/file_list.h @@ -23,9 +23,9 @@ #ifndef __LIBRETRO_SDK_FILE_LIST_H__ #define __LIBRETRO_SDK_FILE_LIST_H__ -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS #include #include @@ -117,8 +117,6 @@ void file_list_sort_on_type(file_list_t *list); bool file_list_search(const file_list_t *list, const char *needle, size_t *index); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/lists/string_list.h b/desmume/src/libretro-common/include/lists/string_list.h index 4168116f7..9b3d0e47e 100644 --- a/desmume/src/libretro-common/include/lists/string_list.h +++ b/desmume/src/libretro-common/include/lists/string_list.h @@ -23,13 +23,13 @@ #ifndef __LIBRETRO_SDK_STRING_LIST_H #define __LIBRETRO_SDK_STRING_LIST_H +#include + #include #include #include -#ifdef __cplusplus -extern "C" { -#endif +RETRO_BEGIN_DECLS union string_list_elem_attr { @@ -141,8 +141,6 @@ void string_list_join_concat(char *buffer, size_t size, void string_list_set(struct string_list *list, unsigned idx, const char *str); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/math/complex.h b/desmume/src/libretro-common/include/math/complex.h new file mode 100644 index 000000000..39a5df415 --- /dev/null +++ b/desmume/src/libretro-common/include/math/complex.h @@ -0,0 +1,80 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (complex.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_MATH_COMPLEX_H__ +#define __LIBRETRO_SDK_MATH_COMPLEX_H__ + +#include + +#include + +typedef struct +{ + float real; + float imag; +} fft_complex_t; + +static INLINE fft_complex_t fft_complex_mul(fft_complex_t a, + fft_complex_t b) +{ + fft_complex_t out = { + a.real * b.real - a.imag * b.imag, + a.imag * b.real + a.real * b.imag, + }; + + return out; + +} + +static INLINE fft_complex_t fft_complex_add(fft_complex_t a, + fft_complex_t b) +{ + fft_complex_t out = { + a.real + b.real, + a.imag + b.imag, + }; + + return out; + +} + +static INLINE fft_complex_t fft_complex_sub(fft_complex_t a, + fft_complex_t b) +{ + fft_complex_t out = { + a.real - b.real, + a.imag - b.imag, + }; + + return out; + +} + +static INLINE fft_complex_t fft_complex_conj(fft_complex_t a) +{ + fft_complex_t out = { + a.real, -a.imag, + }; + + return out; +} + +#endif diff --git a/desmume/src/libretro-common/include/math/fxp.h b/desmume/src/libretro-common/include/math/fxp.h new file mode 100644 index 000000000..f6717754f --- /dev/null +++ b/desmume/src/libretro-common/include/math/fxp.h @@ -0,0 +1,62 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (fxp.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_MATH_FXP_H__ +#define __LIBRETRO_SDK_MATH_FXP_H__ + +#include + +#ifdef _MSC_VER +#include +#endif + +#include + +static INLINE int64_t fx32_mul(const int32_t a, const int32_t b) +{ +#ifdef _MSC_VER + return __emul(a, b); +#else + return ((int64_t)a) * ((int64_t)b); +#endif +} + +static INLINE int32_t fx32_shiftdown(const int64_t a) +{ +#ifdef _MSC_VER + return (int32_t)__ll_rshift(a, 12); +#else + return (int32_t)(a >> 12); +#endif +} + +static INLINE int64_t fx32_shiftup(const int32_t a) +{ +#ifdef _MSC_VER + return __ll_lshift(a, 12); +#else + return ((int64_t)a) << 12; +#endif +} + +#endif + diff --git a/desmume/src/libretro-common/include/memalign.h b/desmume/src/libretro-common/include/memalign.h index a8aef5cbb..6d217437e 100644 --- a/desmume/src/libretro-common/include/memalign.h +++ b/desmume/src/libretro-common/include/memalign.h @@ -25,16 +25,16 @@ #include -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS void *memalign_alloc(size_t boundary, size_t size); +void *memalign_alloc_aligned(size_t size); + void memalign_free(void *ptr); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/net/net_compat.h b/desmume/src/libretro-common/include/net/net_compat.h index 89cf4142c..76c9c51df 100644 --- a/desmume/src/libretro-common/include/net/net_compat.h +++ b/desmume/src/libretro-common/include/net/net_compat.h @@ -74,18 +74,18 @@ #define listen sceNetListen #define send sceNetSend #define recv sceNetRecv -#define MSG_DONTWAIT PSP2_NET_MSG_DONTWAIT -#define AF_INET PSP2_NET_AF_INET +#define MSG_DONTWAIT SCE_NET_MSG_DONTWAIT +#define AF_INET SCE_NET_AF_INET #define AF_UNSPEC 0 -#define INADDR_ANY PSP2_NET_INADDR_ANY +#define INADDR_ANY SCE_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 SOCK_STREAM SCE_NET_SOCK_STREAM +#define SOCK_DGRAM SCE_NET_SOCK_DGRAM +#define SOL_SOCKET SCE_NET_SOL_SOCKET +#define SO_REUSEADDR SCE_NET_SO_REUSEADDR +#define SO_SNDBUF SCE_NET_SO_SNDBUF +#define SO_SNDTIMEO SCE_NET_SO_SNDTIMEO +#define SO_NBIO SCE_NET_SO_NBIO #define htonl sceNetHtonl #define ntohl sceNetNtohl #define htons sceNetHtons @@ -136,14 +136,6 @@ struct hostent #ifdef GEKKO #define sendto(s, msg, len, flags, addr, tolen) net_sendto(s, msg, len, 0, addr, 8) #define socket(domain, type, protocol) net_socket(domain, type, protocol) - -static INLINE int inet_pton(int af, const char *src, void *dst) -{ - if (af != AF_INET) - return -1; - - return inet_aton (src, dst); -} #endif static INLINE bool isagain(int bytes) @@ -155,7 +147,7 @@ static INLINE bool isagain(int bytes) return false; return true; #elif defined(VITA) - return (bytes<0 && (bytes == PSP2_NET_ERROR_EAGAIN || bytes == PSP2_NET_ERROR_EWOULDBLOCK)); + return (bytes<0 && (bytes == SCE_NET_ERROR_EAGAIN || bytes == SCE_NET_ERROR_EWOULDBLOCK)); #else return (bytes < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)); #endif @@ -211,23 +203,15 @@ struct addrinfo #endif +uint16_t inet_htons(uint16_t hostshort); + +int inet_ptrton(int af, const char *src, void *dst); + int getaddrinfo_retro(const char *node, const char *service, - const struct addrinfo *hints, - struct addrinfo **res); + struct addrinfo *hints, struct addrinfo **res); void freeaddrinfo_retro(struct addrinfo *res); -bool socket_nonblock(int fd); - -int socket_close(int fd); - -int socket_select(int nfds, fd_set *readfs, fd_set *writefds, - fd_set *errorfds, struct timeval *timeout); - -int socket_send_all_blocking(int fd, const void *data_, size_t size); - -int socket_receive_all_blocking(int fd, void *data_, size_t size); - /** * network_init: * diff --git a/desmume/src/libretro-common/include/net/net_http.h b/desmume/src/libretro-common/include/net/net_http.h index 1f1da7f45..bac244e94 100644 --- a/desmume/src/libretro-common/include/net/net_http.h +++ b/desmume/src/libretro-common/include/net/net_http.h @@ -27,9 +27,9 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS struct http_t; struct http_connection_t; @@ -68,8 +68,6 @@ uint8_t* net_http_data(struct http_t *state, size_t* len, bool accept_error); /* Cleans up all memory. */ void net_http_delete(struct http_t *state); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/net/net_socket.h b/desmume/src/libretro-common/include/net/net_socket.h new file mode 100644 index 000000000..d2e73d33e --- /dev/null +++ b/desmume/src/libretro-common/include/net/net_socket.h @@ -0,0 +1,91 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (net_socket.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_NET_SOCKET_H +#define _LIBRETRO_SDK_NET_SOCKET_H + +#include +#include +#include + +#include + +RETRO_BEGIN_DECLS + +enum socket_domain +{ + SOCKET_DOMAIN_INET = 0 +}; + +enum socket_type +{ + SOCKET_TYPE_DATAGRAM = 0, + SOCKET_TYPE_STREAM, + SOCKET_TYPE_SEQPACKET +}; + +enum socket_protocol +{ + SOCKET_PROTOCOL_NONE = 0, + SOCKET_PROTOCOL_TCP, + SOCKET_PROTOCOL_UDP +}; + +typedef struct socket_target +{ + unsigned port; + const char *server; + enum socket_domain domain; + enum socket_protocol prot; +} socket_target_t; + +int socket_init(void **address, uint16_t port, const char *server, enum socket_type type); + +int socket_close(int fd); + +bool socket_nonblock(int fd); + +int socket_select(int nfds, fd_set *readfs, fd_set *writefds, + fd_set *errorfds, struct timeval *timeout); + +int socket_send_all_blocking(int fd, const void *data_, size_t size, bool no_signal); + +int socket_receive_all_blocking(int fd, void *data_, size_t size); + +ssize_t socket_receive_all_nonblocking(int fd, bool *error, + void *data_, size_t size); + +bool socket_bind(int fd, void *data); + +int socket_connect(int fd, void *data, bool timeout_enable); + +int socket_create( + const char *name, + enum socket_domain domain_type, + enum socket_type socket_type, + enum socket_protocol protocol_type); + +void socket_set_target(void *data, socket_target_t *in_addr); + +RETRO_END_DECLS + +#endif diff --git a/desmume/src/libretro-common/include/queues/fifo_queue.h b/desmume/src/libretro-common/include/queues/fifo_queue.h index 5b4bb0166..bbb5c0bbe 100644 --- a/desmume/src/libretro-common/include/queues/fifo_queue.h +++ b/desmume/src/libretro-common/include/queues/fifo_queue.h @@ -26,9 +26,9 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS typedef struct fifo_buffer fifo_buffer_t; @@ -46,9 +46,7 @@ size_t fifo_read_avail(fifo_buffer_t *buffer); size_t fifo_write_avail(fifo_buffer_t *buffer); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/queues/message_queue.h b/desmume/src/libretro-common/include/queues/message_queue.h index f006eb38e..6dadb8961 100644 --- a/desmume/src/libretro-common/include/queues/message_queue.h +++ b/desmume/src/libretro-common/include/queues/message_queue.h @@ -25,9 +25,9 @@ #include -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS typedef struct msg_queue msg_queue_t; @@ -83,8 +83,6 @@ void msg_queue_clear(msg_queue_t *queue); **/ void msg_queue_free(msg_queue_t *queue); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/queues/task_queue.h b/desmume/src/libretro-common/include/queues/task_queue.h index 793eb5403..93e1f65c8 100644 --- a/desmume/src/libretro-common/include/queues/task_queue.h +++ b/desmume/src/libretro-common/include/queues/task_queue.h @@ -24,11 +24,13 @@ #define __LIBRETRO_SDK_TASK_QUEUE_H__ #include +#include #include -#ifdef __cplusplus -extern "C" { -#endif +#include +#include + +RETRO_BEGIN_DECLS enum task_queue_ctl_state { @@ -56,6 +58,14 @@ enum task_queue_ctl_state */ TASK_QUEUE_CTL_FIND, + /** + * Calls func for every running task when handler + * parameter matches task handler, allowing the + * list parameter to be filled with user-defined + * data. + */ + TASK_QUEUE_CTL_RETRIEVE, + /* Blocks until all tasks have finished. * This must only be called from the main thread. */ TASK_QUEUE_CTL_WAIT, @@ -82,8 +92,13 @@ enum task_queue_ctl_state TASK_QUEUE_CTL_UNSET_THREADED, - TASK_QUEUE_CTL_IS_THREADED -}; + TASK_QUEUE_CTL_IS_THREADED, + + /** + * Signals a task to end without waiting for + * it to complete. */ + TASK_QUEUE_CTL_CANCEL + }; typedef struct retro_task retro_task_t; typedef void (*retro_task_callback_t)(void *task_data, @@ -94,6 +109,8 @@ typedef void (*retro_task_handler_t)(retro_task_t *task); typedef bool (*retro_task_finder_t)(retro_task_t *task, void *userdata); +typedef bool (*retro_task_retriever_t)(retro_task_t *task, void *data); + typedef struct { char *source_file; @@ -106,6 +123,10 @@ struct retro_task /* always called from the main loop */ retro_task_callback_t callback; + /* task cleanup handler to free allocated resources, will + * be called immediately after running the main callback */ + retro_task_handler_t cleanup; + /* set to true by the handler to signal * the task has finished executing. */ bool finished; @@ -114,6 +135,9 @@ struct retro_task * to signal the task *must* end. */ bool cancelled; + /* if true no OSD messages will be displayed. */ + bool mute; + /* created by the handler, destroyed by the user */ void *task_data; @@ -144,12 +168,28 @@ typedef struct task_finder_data void *userdata; } task_finder_data_t; -void task_queue_push_progress(retro_task_t *task); +typedef struct task_retriever_info +{ + struct task_retriever_info *next; + void *data; +} task_retriever_info_t; + +typedef struct task_retriever_data +{ + retro_task_handler_t handler; + size_t element_size; + retro_task_retriever_t func; + task_retriever_info_t *list; +} task_retriever_data_t; bool task_queue_ctl(enum task_queue_ctl_state state, void *data); -#ifdef __cplusplus -} -#endif +void *task_queue_retriever_info_next(task_retriever_info_t **link); + +void task_queue_retriever_info_free(task_retriever_info_t *list); + +void task_queue_cancel_task(void *task); + +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/retro_common.h b/desmume/src/libretro-common/include/retro_common.h index d84cafb58..6e9e6bf43 100644 --- a/desmume/src/libretro-common/include/retro_common.h +++ b/desmume/src/libretro-common/include/retro_common.h @@ -33,4 +33,5 @@ in a public API, you may need this. /* conditional compilation is handled inside here */ #include -#endif \ No newline at end of file +#endif + diff --git a/desmume/src/libretro-common/include/retro_common_api.h b/desmume/src/libretro-common/include/retro_common_api.h new file mode 100644 index 000000000..053261249 --- /dev/null +++ b/desmume/src/libretro-common/include/retro_common_api.h @@ -0,0 +1,108 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (retro_common_api.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_COMMON_RETRO_COMMON_API_H +#define _LIBRETRO_COMMON_RETRO_COMMON_API_H + +/* +This file is designed to normalize the libretro-common compiling environment +for public API headers. This should be leaner than a normal compiling environment, +since it gets #included into other project's sources. +*/ + +/* ------------------------------------ */ + +/* +Ordinarily we want to put #ifdef __cplusplus extern "C" in C library +headers to enable them to get used by c++ sources. +However, we want to support building this library as C++ as well, so a +special technique is called for. +*/ + +#define RETRO_BEGIN_DECLS +#define RETRO_END_DECLS + +#ifdef __cplusplus + +#ifdef CXX_BUILD +/* build wants everything to be built as c++, so no extern "C" */ +#else +#undef RETRO_BEGIN_DECLS +#undef RETRO_END_DECLS +#define RETRO_BEGIN_DECLS extern "C" { +#define RETRO_END_DECLS } +#endif + +#else + +/* header is included by a C source file, so no extern "C" */ + +#endif + +/* +IMO, this non-standard ssize_t should not be used. +However, it's a good example of how to handle something like this. +*/ +#ifdef _MSC_VER +#ifndef HAVE_SSIZE_T +#define HAVE_SSIZE_T +#if defined(_WIN64) +typedef __int64 ssize_t; +#elif defined(_WIN32) +typedef int ssize_t; +#endif +#endif +#elif defined(__MACH__) +#include +#endif + +#ifdef _WIN32 +#define STRING_REP_INT64 "%I64u" +#define STRING_REP_UINT64 "%I64u" +#define STRING_REP_ULONG "%Iu" +#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L +#define STRING_REP_INT64 "%llu" +#define STRING_REP_UINT64 "%llu" +#define STRING_REP_ULONG "%zu" +#else +#define STRING_REP_INT64 "%llu" +#define STRING_REP_UINT64 "%llu" +#define STRING_REP_ULONG "%lu" +#endif + +/* +I would like to see retro_inline.h moved in here; possibly boolean too. + +rationale: these are used in public APIs, and it is easier to find problems +and write code that works the first time portably when theyre included uniformly +than to do the analysis from scratch each time you think you need it, for each feature. + +Moreover it helps force you to make hard decisions: if you EVER bring in boolean.h, +then you should pay the price everywhere, so you can see how much grief it will cause. + +Of course, another school of thought is that you should do as little damage as possible +in as few places as possible... +*/ + + +/* _LIBRETRO_COMMON_RETRO_COMMON_API_H */ +#endif diff --git a/desmume/src/libretro-common/include/retro_dirent.h b/desmume/src/libretro-common/include/retro_dirent.h index ca867cb19..9b4f53b1d 100644 --- a/desmume/src/libretro-common/include/retro_dirent.h +++ b/desmume/src/libretro-common/include/retro_dirent.h @@ -23,11 +23,11 @@ #ifndef __RETRO_DIRENT_H #define __RETRO_DIRENT_H +#include + #include -#ifdef __cplusplus -extern "C" { -#endif +RETRO_BEGIN_DECLS struct RDIR; @@ -49,12 +49,10 @@ const char *retro_dirent_get_name(struct RDIR *rdir); * Returns: true if directory listing entry is * a directory, false if not. */ -bool retro_dirent_is_dir(struct RDIR *rdir); +bool retro_dirent_is_dir(struct RDIR *rdir, const char *path); void retro_closedir(struct RDIR *rdir); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/retro_environment.h b/desmume/src/libretro-common/include/retro_environment.h index 8d4ea1719..fa08ddc5e 100644 --- a/desmume/src/libretro-common/include/retro_environment.h +++ b/desmume/src/libretro-common/include/retro_environment.h @@ -23,6 +23,14 @@ #ifndef __LIBRETRO_SDK_ENVIRONMENT_H #define __LIBRETRO_SDK_ENVIRONMENT_H +/* +This file is designed to create a normalized environment for compiling +libretro-common's private implementations, or any other sources which might +enjoy use of it's environment (RetroArch for instance). +This should be an elaborately crafted environment so that sources don't +need to be full of platform-specific workarounds. +*/ + #if defined (__cplusplus) #if 0 printf("This is C++, version %d.\n", __cplusplus); @@ -65,4 +73,6 @@ printf("This is C++, version %d.\n", __cplusplus); /* This is not standard C. __STDC__ is not defined. */ #endif + + #endif diff --git a/desmume/src/libretro-common/include/retro_inline.h b/desmume/src/libretro-common/include/retro_inline.h index d11e6e209..bdc763ca9 100644 --- a/desmume/src/libretro-common/include/retro_inline.h +++ b/desmume/src/libretro-common/include/retro_inline.h @@ -25,7 +25,7 @@ #ifndef INLINE -#if defined(_WIN32) +#if defined(_WIN32) || defined(__INTEL_COMPILER) #define INLINE __inline #elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L #define INLINE inline diff --git a/desmume/src/libretro-common/include/retro_miscellaneous.h b/desmume/src/libretro-common/include/retro_miscellaneous.h index 4d4607b21..b133550bd 100644 --- a/desmume/src/libretro-common/include/retro_miscellaneous.h +++ b/desmume/src/libretro-common/include/retro_miscellaneous.h @@ -50,6 +50,7 @@ #endif #include +#include #ifdef _MSC_VER #include diff --git a/desmume/src/libretro-common/include/retro_stat.h b/desmume/src/libretro-common/include/retro_stat.h index 37e4348e1..a6d53abfb 100644 --- a/desmume/src/libretro-common/include/retro_stat.h +++ b/desmume/src/libretro-common/include/retro_stat.h @@ -26,11 +26,11 @@ #include #include +#include + #include -#ifdef __cplusplus -extern "C" { -#endif +RETRO_BEGIN_DECLS /** * path_is_directory: @@ -58,8 +58,6 @@ int32_t path_get_size(const char *path); **/ bool mkdir_norecurse(const char *dir); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/rthreads/rsemaphore.h b/desmume/src/libretro-common/include/rthreads/rsemaphore.h index 6c0f1a392..8df818783 100644 --- a/desmume/src/libretro-common/include/rthreads/rsemaphore.h +++ b/desmume/src/libretro-common/include/rthreads/rsemaphore.h @@ -23,9 +23,9 @@ #ifndef __LIBRETRO_SDK_SEMAPHORE_H #define __LIBRETRO_SDK_SEMAPHORE_H -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS typedef struct ssem ssem_t; @@ -47,8 +47,6 @@ void ssem_wait(ssem_t *semaphore); void ssem_signal(ssem_t *semaphore); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #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 196af8c27..eb805b6f8 100644 --- a/desmume/src/libretro-common/include/rthreads/rthreads.h +++ b/desmume/src/libretro-common/include/rthreads/rthreads.h @@ -23,14 +23,14 @@ #ifndef __LIBRETRO_SDK_RTHREADS_H__ #define __LIBRETRO_SDK_RTHREADS_H__ +#include + #include #include #include #include -#if defined(__cplusplus) -extern "C" { -#endif +RETRO_BEGIN_DECLS typedef struct sthread sthread_t; typedef struct slock slock_t; @@ -183,8 +183,6 @@ int scond_broadcast(scond_t *cond); **/ void scond_signal(scond_t *cond); -#if defined(__cplusplus) -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/streams/file_stream.h b/desmume/src/libretro-common/include/streams/file_stream.h index 5fd1aa148..3e896e2f1 100644 --- a/desmume/src/libretro-common/include/streams/file_stream.h +++ b/desmume/src/libretro-common/include/streams/file_stream.h @@ -28,18 +28,17 @@ #include -#include +#include #include -#ifdef __cplusplus -extern "C" { -#endif +RETRO_BEGIN_DECLS typedef struct RFILE RFILE; enum { RFILE_MODE_READ = 0, + RFILE_MODE_READ_TEXT, RFILE_MODE_WRITE, RFILE_MODE_READ_WRITE, @@ -64,14 +63,20 @@ int filestream_close(RFILE *stream); int filestream_read_file(const char *path, void **buf, ssize_t *len); +char *filestream_gets(RFILE *stream, char *s, size_t len); + +char *filestream_getline(RFILE *stream); + +int filestream_getc(RFILE *stream); + +int filestream_eof(RFILE *stream); + bool filestream_write_file(const char *path, const void *data, ssize_t size); int filestream_putc(RFILE *stream, int c); int filestream_get_fd(RFILE *stream); -#ifdef __cplusplus -} -#endif +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/streams/interface_stream.h b/desmume/src/libretro-common/include/streams/interface_stream.h index c5b2e46b6..e58fddd59 100644 --- a/desmume/src/libretro-common/include/streams/interface_stream.h +++ b/desmume/src/libretro-common/include/streams/interface_stream.h @@ -25,7 +25,9 @@ #include #include +#include +#include #include enum intfstream_type diff --git a/desmume/src/libretro-common/include/string/stdstring.h b/desmume/src/libretro-common/include/string/stdstring.h index ecc866643..8faf2ba25 100644 --- a/desmume/src/libretro-common/include/string/stdstring.h +++ b/desmume/src/libretro-common/include/string/stdstring.h @@ -28,9 +28,9 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS bool string_is_empty(const char *data); @@ -42,11 +42,20 @@ char *string_to_upper(char *s); char *string_to_lower(char *s); +char *string_ucwords(char* s); + char *string_replace_substring(const char *in, const char *pattern, const char *by); -#ifdef __cplusplus -} -#endif +/* Remove leading whitespaces */ +char *string_trim_whitespace_left(char *const s); + +/* Remove trailing whitespaces */ +char *string_trim_whitespace_right(char *const s); + +/* Remove leading and trailing whitespaces */ +char *string_trim_whitespace(char *const s); + +RETRO_END_DECLS #endif diff --git a/desmume/src/libretro-common/include/utils/md5.h b/desmume/src/libretro-common/include/utils/md5.h new file mode 100644 index 000000000..2da44bf35 --- /dev/null +++ b/desmume/src/libretro-common/include/utils/md5.h @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#ifdef HAVE_OPENSSL +#include +#elif !defined(_MD5_H) +#define _MD5_H + +/* 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; + +extern void MD5_Init(MD5_CTX *ctx); +extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); +extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); + +#endif diff --git a/desmume/src/libretro-common/include/vulkan/vulkan_symbol_wrapper.h b/desmume/src/libretro-common/include/vulkan/vulkan_symbol_wrapper.h new file mode 100644 index 000000000..06f404e2c --- /dev/null +++ b/desmume/src/libretro-common/include/vulkan/vulkan_symbol_wrapper.h @@ -0,0 +1,356 @@ + +/* This header is autogenerated by vulkan_loader_generator.py */ +#ifndef VULKAN_SYMBOL_WRAPPER_H +#define VULKAN_SYMBOL_WRAPPER_H +#define VK_NO_PROTOTYPES +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern PFN_vkCreateInstance vulkan_symbol_wrapper_vkCreateInstance; +#define vkCreateInstance vulkan_symbol_wrapper_vkCreateInstance +extern PFN_vkEnumerateInstanceExtensionProperties vulkan_symbol_wrapper_vkEnumerateInstanceExtensionProperties; +#define vkEnumerateInstanceExtensionProperties vulkan_symbol_wrapper_vkEnumerateInstanceExtensionProperties +extern PFN_vkEnumerateInstanceLayerProperties vulkan_symbol_wrapper_vkEnumerateInstanceLayerProperties; +#define vkEnumerateInstanceLayerProperties vulkan_symbol_wrapper_vkEnumerateInstanceLayerProperties +extern PFN_vkDestroyInstance vulkan_symbol_wrapper_vkDestroyInstance; +#define vkDestroyInstance vulkan_symbol_wrapper_vkDestroyInstance +extern PFN_vkEnumeratePhysicalDevices vulkan_symbol_wrapper_vkEnumeratePhysicalDevices; +#define vkEnumeratePhysicalDevices vulkan_symbol_wrapper_vkEnumeratePhysicalDevices +extern PFN_vkGetPhysicalDeviceFeatures vulkan_symbol_wrapper_vkGetPhysicalDeviceFeatures; +#define vkGetPhysicalDeviceFeatures vulkan_symbol_wrapper_vkGetPhysicalDeviceFeatures +extern PFN_vkGetPhysicalDeviceFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceFormatProperties; +#define vkGetPhysicalDeviceFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceFormatProperties +extern PFN_vkGetPhysicalDeviceImageFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceImageFormatProperties; +#define vkGetPhysicalDeviceImageFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceImageFormatProperties +extern PFN_vkGetPhysicalDeviceProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceProperties; +#define vkGetPhysicalDeviceProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceProperties +extern PFN_vkGetPhysicalDeviceQueueFamilyProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceQueueFamilyProperties; +#define vkGetPhysicalDeviceQueueFamilyProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceQueueFamilyProperties +extern PFN_vkGetPhysicalDeviceMemoryProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceMemoryProperties; +#define vkGetPhysicalDeviceMemoryProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceMemoryProperties +extern PFN_vkGetDeviceProcAddr vulkan_symbol_wrapper_vkGetDeviceProcAddr; +#define vkGetDeviceProcAddr vulkan_symbol_wrapper_vkGetDeviceProcAddr +extern PFN_vkCreateDevice vulkan_symbol_wrapper_vkCreateDevice; +#define vkCreateDevice vulkan_symbol_wrapper_vkCreateDevice +extern PFN_vkDestroyDevice vulkan_symbol_wrapper_vkDestroyDevice; +#define vkDestroyDevice vulkan_symbol_wrapper_vkDestroyDevice +extern PFN_vkEnumerateDeviceExtensionProperties vulkan_symbol_wrapper_vkEnumerateDeviceExtensionProperties; +#define vkEnumerateDeviceExtensionProperties vulkan_symbol_wrapper_vkEnumerateDeviceExtensionProperties +extern PFN_vkEnumerateDeviceLayerProperties vulkan_symbol_wrapper_vkEnumerateDeviceLayerProperties; +#define vkEnumerateDeviceLayerProperties vulkan_symbol_wrapper_vkEnumerateDeviceLayerProperties +extern PFN_vkGetDeviceQueue vulkan_symbol_wrapper_vkGetDeviceQueue; +#define vkGetDeviceQueue vulkan_symbol_wrapper_vkGetDeviceQueue +extern PFN_vkQueueSubmit vulkan_symbol_wrapper_vkQueueSubmit; +#define vkQueueSubmit vulkan_symbol_wrapper_vkQueueSubmit +extern PFN_vkQueueWaitIdle vulkan_symbol_wrapper_vkQueueWaitIdle; +#define vkQueueWaitIdle vulkan_symbol_wrapper_vkQueueWaitIdle +extern PFN_vkDeviceWaitIdle vulkan_symbol_wrapper_vkDeviceWaitIdle; +#define vkDeviceWaitIdle vulkan_symbol_wrapper_vkDeviceWaitIdle +extern PFN_vkAllocateMemory vulkan_symbol_wrapper_vkAllocateMemory; +#define vkAllocateMemory vulkan_symbol_wrapper_vkAllocateMemory +extern PFN_vkFreeMemory vulkan_symbol_wrapper_vkFreeMemory; +#define vkFreeMemory vulkan_symbol_wrapper_vkFreeMemory +extern PFN_vkMapMemory vulkan_symbol_wrapper_vkMapMemory; +#define vkMapMemory vulkan_symbol_wrapper_vkMapMemory +extern PFN_vkUnmapMemory vulkan_symbol_wrapper_vkUnmapMemory; +#define vkUnmapMemory vulkan_symbol_wrapper_vkUnmapMemory +extern PFN_vkFlushMappedMemoryRanges vulkan_symbol_wrapper_vkFlushMappedMemoryRanges; +#define vkFlushMappedMemoryRanges vulkan_symbol_wrapper_vkFlushMappedMemoryRanges +extern PFN_vkInvalidateMappedMemoryRanges vulkan_symbol_wrapper_vkInvalidateMappedMemoryRanges; +#define vkInvalidateMappedMemoryRanges vulkan_symbol_wrapper_vkInvalidateMappedMemoryRanges +extern PFN_vkGetDeviceMemoryCommitment vulkan_symbol_wrapper_vkGetDeviceMemoryCommitment; +#define vkGetDeviceMemoryCommitment vulkan_symbol_wrapper_vkGetDeviceMemoryCommitment +extern PFN_vkBindBufferMemory vulkan_symbol_wrapper_vkBindBufferMemory; +#define vkBindBufferMemory vulkan_symbol_wrapper_vkBindBufferMemory +extern PFN_vkBindImageMemory vulkan_symbol_wrapper_vkBindImageMemory; +#define vkBindImageMemory vulkan_symbol_wrapper_vkBindImageMemory +extern PFN_vkGetBufferMemoryRequirements vulkan_symbol_wrapper_vkGetBufferMemoryRequirements; +#define vkGetBufferMemoryRequirements vulkan_symbol_wrapper_vkGetBufferMemoryRequirements +extern PFN_vkGetImageMemoryRequirements vulkan_symbol_wrapper_vkGetImageMemoryRequirements; +#define vkGetImageMemoryRequirements vulkan_symbol_wrapper_vkGetImageMemoryRequirements +extern PFN_vkGetImageSparseMemoryRequirements vulkan_symbol_wrapper_vkGetImageSparseMemoryRequirements; +#define vkGetImageSparseMemoryRequirements vulkan_symbol_wrapper_vkGetImageSparseMemoryRequirements +extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceSparseImageFormatProperties; +#define vkGetPhysicalDeviceSparseImageFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceSparseImageFormatProperties +extern PFN_vkQueueBindSparse vulkan_symbol_wrapper_vkQueueBindSparse; +#define vkQueueBindSparse vulkan_symbol_wrapper_vkQueueBindSparse +extern PFN_vkCreateFence vulkan_symbol_wrapper_vkCreateFence; +#define vkCreateFence vulkan_symbol_wrapper_vkCreateFence +extern PFN_vkDestroyFence vulkan_symbol_wrapper_vkDestroyFence; +#define vkDestroyFence vulkan_symbol_wrapper_vkDestroyFence +extern PFN_vkResetFences vulkan_symbol_wrapper_vkResetFences; +#define vkResetFences vulkan_symbol_wrapper_vkResetFences +extern PFN_vkGetFenceStatus vulkan_symbol_wrapper_vkGetFenceStatus; +#define vkGetFenceStatus vulkan_symbol_wrapper_vkGetFenceStatus +extern PFN_vkWaitForFences vulkan_symbol_wrapper_vkWaitForFences; +#define vkWaitForFences vulkan_symbol_wrapper_vkWaitForFences +extern PFN_vkCreateSemaphore vulkan_symbol_wrapper_vkCreateSemaphore; +#define vkCreateSemaphore vulkan_symbol_wrapper_vkCreateSemaphore +extern PFN_vkDestroySemaphore vulkan_symbol_wrapper_vkDestroySemaphore; +#define vkDestroySemaphore vulkan_symbol_wrapper_vkDestroySemaphore +extern PFN_vkCreateEvent vulkan_symbol_wrapper_vkCreateEvent; +#define vkCreateEvent vulkan_symbol_wrapper_vkCreateEvent +extern PFN_vkDestroyEvent vulkan_symbol_wrapper_vkDestroyEvent; +#define vkDestroyEvent vulkan_symbol_wrapper_vkDestroyEvent +extern PFN_vkGetEventStatus vulkan_symbol_wrapper_vkGetEventStatus; +#define vkGetEventStatus vulkan_symbol_wrapper_vkGetEventStatus +extern PFN_vkSetEvent vulkan_symbol_wrapper_vkSetEvent; +#define vkSetEvent vulkan_symbol_wrapper_vkSetEvent +extern PFN_vkResetEvent vulkan_symbol_wrapper_vkResetEvent; +#define vkResetEvent vulkan_symbol_wrapper_vkResetEvent +extern PFN_vkCreateQueryPool vulkan_symbol_wrapper_vkCreateQueryPool; +#define vkCreateQueryPool vulkan_symbol_wrapper_vkCreateQueryPool +extern PFN_vkDestroyQueryPool vulkan_symbol_wrapper_vkDestroyQueryPool; +#define vkDestroyQueryPool vulkan_symbol_wrapper_vkDestroyQueryPool +extern PFN_vkGetQueryPoolResults vulkan_symbol_wrapper_vkGetQueryPoolResults; +#define vkGetQueryPoolResults vulkan_symbol_wrapper_vkGetQueryPoolResults +extern PFN_vkCreateBuffer vulkan_symbol_wrapper_vkCreateBuffer; +#define vkCreateBuffer vulkan_symbol_wrapper_vkCreateBuffer +extern PFN_vkDestroyBuffer vulkan_symbol_wrapper_vkDestroyBuffer; +#define vkDestroyBuffer vulkan_symbol_wrapper_vkDestroyBuffer +extern PFN_vkCreateBufferView vulkan_symbol_wrapper_vkCreateBufferView; +#define vkCreateBufferView vulkan_symbol_wrapper_vkCreateBufferView +extern PFN_vkDestroyBufferView vulkan_symbol_wrapper_vkDestroyBufferView; +#define vkDestroyBufferView vulkan_symbol_wrapper_vkDestroyBufferView +extern PFN_vkCreateImage vulkan_symbol_wrapper_vkCreateImage; +#define vkCreateImage vulkan_symbol_wrapper_vkCreateImage +extern PFN_vkDestroyImage vulkan_symbol_wrapper_vkDestroyImage; +#define vkDestroyImage vulkan_symbol_wrapper_vkDestroyImage +extern PFN_vkGetImageSubresourceLayout vulkan_symbol_wrapper_vkGetImageSubresourceLayout; +#define vkGetImageSubresourceLayout vulkan_symbol_wrapper_vkGetImageSubresourceLayout +extern PFN_vkCreateImageView vulkan_symbol_wrapper_vkCreateImageView; +#define vkCreateImageView vulkan_symbol_wrapper_vkCreateImageView +extern PFN_vkDestroyImageView vulkan_symbol_wrapper_vkDestroyImageView; +#define vkDestroyImageView vulkan_symbol_wrapper_vkDestroyImageView +extern PFN_vkCreateShaderModule vulkan_symbol_wrapper_vkCreateShaderModule; +#define vkCreateShaderModule vulkan_symbol_wrapper_vkCreateShaderModule +extern PFN_vkDestroyShaderModule vulkan_symbol_wrapper_vkDestroyShaderModule; +#define vkDestroyShaderModule vulkan_symbol_wrapper_vkDestroyShaderModule +extern PFN_vkCreatePipelineCache vulkan_symbol_wrapper_vkCreatePipelineCache; +#define vkCreatePipelineCache vulkan_symbol_wrapper_vkCreatePipelineCache +extern PFN_vkDestroyPipelineCache vulkan_symbol_wrapper_vkDestroyPipelineCache; +#define vkDestroyPipelineCache vulkan_symbol_wrapper_vkDestroyPipelineCache +extern PFN_vkGetPipelineCacheData vulkan_symbol_wrapper_vkGetPipelineCacheData; +#define vkGetPipelineCacheData vulkan_symbol_wrapper_vkGetPipelineCacheData +extern PFN_vkMergePipelineCaches vulkan_symbol_wrapper_vkMergePipelineCaches; +#define vkMergePipelineCaches vulkan_symbol_wrapper_vkMergePipelineCaches +extern PFN_vkCreateGraphicsPipelines vulkan_symbol_wrapper_vkCreateGraphicsPipelines; +#define vkCreateGraphicsPipelines vulkan_symbol_wrapper_vkCreateGraphicsPipelines +extern PFN_vkCreateComputePipelines vulkan_symbol_wrapper_vkCreateComputePipelines; +#define vkCreateComputePipelines vulkan_symbol_wrapper_vkCreateComputePipelines +extern PFN_vkDestroyPipeline vulkan_symbol_wrapper_vkDestroyPipeline; +#define vkDestroyPipeline vulkan_symbol_wrapper_vkDestroyPipeline +extern PFN_vkCreatePipelineLayout vulkan_symbol_wrapper_vkCreatePipelineLayout; +#define vkCreatePipelineLayout vulkan_symbol_wrapper_vkCreatePipelineLayout +extern PFN_vkDestroyPipelineLayout vulkan_symbol_wrapper_vkDestroyPipelineLayout; +#define vkDestroyPipelineLayout vulkan_symbol_wrapper_vkDestroyPipelineLayout +extern PFN_vkCreateSampler vulkan_symbol_wrapper_vkCreateSampler; +#define vkCreateSampler vulkan_symbol_wrapper_vkCreateSampler +extern PFN_vkDestroySampler vulkan_symbol_wrapper_vkDestroySampler; +#define vkDestroySampler vulkan_symbol_wrapper_vkDestroySampler +extern PFN_vkCreateDescriptorSetLayout vulkan_symbol_wrapper_vkCreateDescriptorSetLayout; +#define vkCreateDescriptorSetLayout vulkan_symbol_wrapper_vkCreateDescriptorSetLayout +extern PFN_vkDestroyDescriptorSetLayout vulkan_symbol_wrapper_vkDestroyDescriptorSetLayout; +#define vkDestroyDescriptorSetLayout vulkan_symbol_wrapper_vkDestroyDescriptorSetLayout +extern PFN_vkCreateDescriptorPool vulkan_symbol_wrapper_vkCreateDescriptorPool; +#define vkCreateDescriptorPool vulkan_symbol_wrapper_vkCreateDescriptorPool +extern PFN_vkDestroyDescriptorPool vulkan_symbol_wrapper_vkDestroyDescriptorPool; +#define vkDestroyDescriptorPool vulkan_symbol_wrapper_vkDestroyDescriptorPool +extern PFN_vkResetDescriptorPool vulkan_symbol_wrapper_vkResetDescriptorPool; +#define vkResetDescriptorPool vulkan_symbol_wrapper_vkResetDescriptorPool +extern PFN_vkAllocateDescriptorSets vulkan_symbol_wrapper_vkAllocateDescriptorSets; +#define vkAllocateDescriptorSets vulkan_symbol_wrapper_vkAllocateDescriptorSets +extern PFN_vkFreeDescriptorSets vulkan_symbol_wrapper_vkFreeDescriptorSets; +#define vkFreeDescriptorSets vulkan_symbol_wrapper_vkFreeDescriptorSets +extern PFN_vkUpdateDescriptorSets vulkan_symbol_wrapper_vkUpdateDescriptorSets; +#define vkUpdateDescriptorSets vulkan_symbol_wrapper_vkUpdateDescriptorSets +extern PFN_vkCreateFramebuffer vulkan_symbol_wrapper_vkCreateFramebuffer; +#define vkCreateFramebuffer vulkan_symbol_wrapper_vkCreateFramebuffer +extern PFN_vkDestroyFramebuffer vulkan_symbol_wrapper_vkDestroyFramebuffer; +#define vkDestroyFramebuffer vulkan_symbol_wrapper_vkDestroyFramebuffer +extern PFN_vkCreateRenderPass vulkan_symbol_wrapper_vkCreateRenderPass; +#define vkCreateRenderPass vulkan_symbol_wrapper_vkCreateRenderPass +extern PFN_vkDestroyRenderPass vulkan_symbol_wrapper_vkDestroyRenderPass; +#define vkDestroyRenderPass vulkan_symbol_wrapper_vkDestroyRenderPass +extern PFN_vkGetRenderAreaGranularity vulkan_symbol_wrapper_vkGetRenderAreaGranularity; +#define vkGetRenderAreaGranularity vulkan_symbol_wrapper_vkGetRenderAreaGranularity +extern PFN_vkCreateCommandPool vulkan_symbol_wrapper_vkCreateCommandPool; +#define vkCreateCommandPool vulkan_symbol_wrapper_vkCreateCommandPool +extern PFN_vkDestroyCommandPool vulkan_symbol_wrapper_vkDestroyCommandPool; +#define vkDestroyCommandPool vulkan_symbol_wrapper_vkDestroyCommandPool +extern PFN_vkResetCommandPool vulkan_symbol_wrapper_vkResetCommandPool; +#define vkResetCommandPool vulkan_symbol_wrapper_vkResetCommandPool +extern PFN_vkAllocateCommandBuffers vulkan_symbol_wrapper_vkAllocateCommandBuffers; +#define vkAllocateCommandBuffers vulkan_symbol_wrapper_vkAllocateCommandBuffers +extern PFN_vkFreeCommandBuffers vulkan_symbol_wrapper_vkFreeCommandBuffers; +#define vkFreeCommandBuffers vulkan_symbol_wrapper_vkFreeCommandBuffers +extern PFN_vkBeginCommandBuffer vulkan_symbol_wrapper_vkBeginCommandBuffer; +#define vkBeginCommandBuffer vulkan_symbol_wrapper_vkBeginCommandBuffer +extern PFN_vkEndCommandBuffer vulkan_symbol_wrapper_vkEndCommandBuffer; +#define vkEndCommandBuffer vulkan_symbol_wrapper_vkEndCommandBuffer +extern PFN_vkResetCommandBuffer vulkan_symbol_wrapper_vkResetCommandBuffer; +#define vkResetCommandBuffer vulkan_symbol_wrapper_vkResetCommandBuffer +extern PFN_vkCmdBindPipeline vulkan_symbol_wrapper_vkCmdBindPipeline; +#define vkCmdBindPipeline vulkan_symbol_wrapper_vkCmdBindPipeline +extern PFN_vkCmdSetViewport vulkan_symbol_wrapper_vkCmdSetViewport; +#define vkCmdSetViewport vulkan_symbol_wrapper_vkCmdSetViewport +extern PFN_vkCmdSetScissor vulkan_symbol_wrapper_vkCmdSetScissor; +#define vkCmdSetScissor vulkan_symbol_wrapper_vkCmdSetScissor +extern PFN_vkCmdSetLineWidth vulkan_symbol_wrapper_vkCmdSetLineWidth; +#define vkCmdSetLineWidth vulkan_symbol_wrapper_vkCmdSetLineWidth +extern PFN_vkCmdSetDepthBias vulkan_symbol_wrapper_vkCmdSetDepthBias; +#define vkCmdSetDepthBias vulkan_symbol_wrapper_vkCmdSetDepthBias +extern PFN_vkCmdSetBlendConstants vulkan_symbol_wrapper_vkCmdSetBlendConstants; +#define vkCmdSetBlendConstants vulkan_symbol_wrapper_vkCmdSetBlendConstants +extern PFN_vkCmdSetDepthBounds vulkan_symbol_wrapper_vkCmdSetDepthBounds; +#define vkCmdSetDepthBounds vulkan_symbol_wrapper_vkCmdSetDepthBounds +extern PFN_vkCmdSetStencilCompareMask vulkan_symbol_wrapper_vkCmdSetStencilCompareMask; +#define vkCmdSetStencilCompareMask vulkan_symbol_wrapper_vkCmdSetStencilCompareMask +extern PFN_vkCmdSetStencilWriteMask vulkan_symbol_wrapper_vkCmdSetStencilWriteMask; +#define vkCmdSetStencilWriteMask vulkan_symbol_wrapper_vkCmdSetStencilWriteMask +extern PFN_vkCmdSetStencilReference vulkan_symbol_wrapper_vkCmdSetStencilReference; +#define vkCmdSetStencilReference vulkan_symbol_wrapper_vkCmdSetStencilReference +extern PFN_vkCmdBindDescriptorSets vulkan_symbol_wrapper_vkCmdBindDescriptorSets; +#define vkCmdBindDescriptorSets vulkan_symbol_wrapper_vkCmdBindDescriptorSets +extern PFN_vkCmdBindIndexBuffer vulkan_symbol_wrapper_vkCmdBindIndexBuffer; +#define vkCmdBindIndexBuffer vulkan_symbol_wrapper_vkCmdBindIndexBuffer +extern PFN_vkCmdBindVertexBuffers vulkan_symbol_wrapper_vkCmdBindVertexBuffers; +#define vkCmdBindVertexBuffers vulkan_symbol_wrapper_vkCmdBindVertexBuffers +extern PFN_vkCmdDraw vulkan_symbol_wrapper_vkCmdDraw; +#define vkCmdDraw vulkan_symbol_wrapper_vkCmdDraw +extern PFN_vkCmdDrawIndexed vulkan_symbol_wrapper_vkCmdDrawIndexed; +#define vkCmdDrawIndexed vulkan_symbol_wrapper_vkCmdDrawIndexed +extern PFN_vkCmdDrawIndirect vulkan_symbol_wrapper_vkCmdDrawIndirect; +#define vkCmdDrawIndirect vulkan_symbol_wrapper_vkCmdDrawIndirect +extern PFN_vkCmdDrawIndexedIndirect vulkan_symbol_wrapper_vkCmdDrawIndexedIndirect; +#define vkCmdDrawIndexedIndirect vulkan_symbol_wrapper_vkCmdDrawIndexedIndirect +extern PFN_vkCmdDispatch vulkan_symbol_wrapper_vkCmdDispatch; +#define vkCmdDispatch vulkan_symbol_wrapper_vkCmdDispatch +extern PFN_vkCmdDispatchIndirect vulkan_symbol_wrapper_vkCmdDispatchIndirect; +#define vkCmdDispatchIndirect vulkan_symbol_wrapper_vkCmdDispatchIndirect +extern PFN_vkCmdCopyBuffer vulkan_symbol_wrapper_vkCmdCopyBuffer; +#define vkCmdCopyBuffer vulkan_symbol_wrapper_vkCmdCopyBuffer +extern PFN_vkCmdCopyImage vulkan_symbol_wrapper_vkCmdCopyImage; +#define vkCmdCopyImage vulkan_symbol_wrapper_vkCmdCopyImage +extern PFN_vkCmdBlitImage vulkan_symbol_wrapper_vkCmdBlitImage; +#define vkCmdBlitImage vulkan_symbol_wrapper_vkCmdBlitImage +extern PFN_vkCmdCopyBufferToImage vulkan_symbol_wrapper_vkCmdCopyBufferToImage; +#define vkCmdCopyBufferToImage vulkan_symbol_wrapper_vkCmdCopyBufferToImage +extern PFN_vkCmdCopyImageToBuffer vulkan_symbol_wrapper_vkCmdCopyImageToBuffer; +#define vkCmdCopyImageToBuffer vulkan_symbol_wrapper_vkCmdCopyImageToBuffer +extern PFN_vkCmdUpdateBuffer vulkan_symbol_wrapper_vkCmdUpdateBuffer; +#define vkCmdUpdateBuffer vulkan_symbol_wrapper_vkCmdUpdateBuffer +extern PFN_vkCmdFillBuffer vulkan_symbol_wrapper_vkCmdFillBuffer; +#define vkCmdFillBuffer vulkan_symbol_wrapper_vkCmdFillBuffer +extern PFN_vkCmdClearColorImage vulkan_symbol_wrapper_vkCmdClearColorImage; +#define vkCmdClearColorImage vulkan_symbol_wrapper_vkCmdClearColorImage +extern PFN_vkCmdClearDepthStencilImage vulkan_symbol_wrapper_vkCmdClearDepthStencilImage; +#define vkCmdClearDepthStencilImage vulkan_symbol_wrapper_vkCmdClearDepthStencilImage +extern PFN_vkCmdClearAttachments vulkan_symbol_wrapper_vkCmdClearAttachments; +#define vkCmdClearAttachments vulkan_symbol_wrapper_vkCmdClearAttachments +extern PFN_vkCmdResolveImage vulkan_symbol_wrapper_vkCmdResolveImage; +#define vkCmdResolveImage vulkan_symbol_wrapper_vkCmdResolveImage +extern PFN_vkCmdSetEvent vulkan_symbol_wrapper_vkCmdSetEvent; +#define vkCmdSetEvent vulkan_symbol_wrapper_vkCmdSetEvent +extern PFN_vkCmdResetEvent vulkan_symbol_wrapper_vkCmdResetEvent; +#define vkCmdResetEvent vulkan_symbol_wrapper_vkCmdResetEvent +extern PFN_vkCmdWaitEvents vulkan_symbol_wrapper_vkCmdWaitEvents; +#define vkCmdWaitEvents vulkan_symbol_wrapper_vkCmdWaitEvents +extern PFN_vkCmdPipelineBarrier vulkan_symbol_wrapper_vkCmdPipelineBarrier; +#define vkCmdPipelineBarrier vulkan_symbol_wrapper_vkCmdPipelineBarrier +extern PFN_vkCmdBeginQuery vulkan_symbol_wrapper_vkCmdBeginQuery; +#define vkCmdBeginQuery vulkan_symbol_wrapper_vkCmdBeginQuery +extern PFN_vkCmdEndQuery vulkan_symbol_wrapper_vkCmdEndQuery; +#define vkCmdEndQuery vulkan_symbol_wrapper_vkCmdEndQuery +extern PFN_vkCmdResetQueryPool vulkan_symbol_wrapper_vkCmdResetQueryPool; +#define vkCmdResetQueryPool vulkan_symbol_wrapper_vkCmdResetQueryPool +extern PFN_vkCmdWriteTimestamp vulkan_symbol_wrapper_vkCmdWriteTimestamp; +#define vkCmdWriteTimestamp vulkan_symbol_wrapper_vkCmdWriteTimestamp +extern PFN_vkCmdCopyQueryPoolResults vulkan_symbol_wrapper_vkCmdCopyQueryPoolResults; +#define vkCmdCopyQueryPoolResults vulkan_symbol_wrapper_vkCmdCopyQueryPoolResults +extern PFN_vkCmdPushConstants vulkan_symbol_wrapper_vkCmdPushConstants; +#define vkCmdPushConstants vulkan_symbol_wrapper_vkCmdPushConstants +extern PFN_vkCmdBeginRenderPass vulkan_symbol_wrapper_vkCmdBeginRenderPass; +#define vkCmdBeginRenderPass vulkan_symbol_wrapper_vkCmdBeginRenderPass +extern PFN_vkCmdNextSubpass vulkan_symbol_wrapper_vkCmdNextSubpass; +#define vkCmdNextSubpass vulkan_symbol_wrapper_vkCmdNextSubpass +extern PFN_vkCmdEndRenderPass vulkan_symbol_wrapper_vkCmdEndRenderPass; +#define vkCmdEndRenderPass vulkan_symbol_wrapper_vkCmdEndRenderPass +extern PFN_vkCmdExecuteCommands vulkan_symbol_wrapper_vkCmdExecuteCommands; +#define vkCmdExecuteCommands vulkan_symbol_wrapper_vkCmdExecuteCommands +extern PFN_vkDestroySurfaceKHR vulkan_symbol_wrapper_vkDestroySurfaceKHR; +#define vkDestroySurfaceKHR vulkan_symbol_wrapper_vkDestroySurfaceKHR +extern PFN_vkGetPhysicalDeviceSurfaceSupportKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceSupportKHR; +#define vkGetPhysicalDeviceSurfaceSupportKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceSupportKHR +extern PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceCapabilitiesKHR; +#define vkGetPhysicalDeviceSurfaceCapabilitiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceCapabilitiesKHR +extern PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceFormatsKHR; +#define vkGetPhysicalDeviceSurfaceFormatsKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceFormatsKHR +extern PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfacePresentModesKHR; +#define vkGetPhysicalDeviceSurfacePresentModesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfacePresentModesKHR +extern PFN_vkCreateSwapchainKHR vulkan_symbol_wrapper_vkCreateSwapchainKHR; +#define vkCreateSwapchainKHR vulkan_symbol_wrapper_vkCreateSwapchainKHR +extern PFN_vkDestroySwapchainKHR vulkan_symbol_wrapper_vkDestroySwapchainKHR; +#define vkDestroySwapchainKHR vulkan_symbol_wrapper_vkDestroySwapchainKHR +extern PFN_vkGetSwapchainImagesKHR vulkan_symbol_wrapper_vkGetSwapchainImagesKHR; +#define vkGetSwapchainImagesKHR vulkan_symbol_wrapper_vkGetSwapchainImagesKHR +extern PFN_vkAcquireNextImageKHR vulkan_symbol_wrapper_vkAcquireNextImageKHR; +#define vkAcquireNextImageKHR vulkan_symbol_wrapper_vkAcquireNextImageKHR +extern PFN_vkQueuePresentKHR vulkan_symbol_wrapper_vkQueuePresentKHR; +#define vkQueuePresentKHR vulkan_symbol_wrapper_vkQueuePresentKHR +extern PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceDisplayPropertiesKHR; +#define vkGetPhysicalDeviceDisplayPropertiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceDisplayPropertiesKHR +extern PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceDisplayPlanePropertiesKHR; +#define vkGetPhysicalDeviceDisplayPlanePropertiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceDisplayPlanePropertiesKHR +extern PFN_vkGetDisplayPlaneSupportedDisplaysKHR vulkan_symbol_wrapper_vkGetDisplayPlaneSupportedDisplaysKHR; +#define vkGetDisplayPlaneSupportedDisplaysKHR vulkan_symbol_wrapper_vkGetDisplayPlaneSupportedDisplaysKHR +extern PFN_vkGetDisplayModePropertiesKHR vulkan_symbol_wrapper_vkGetDisplayModePropertiesKHR; +#define vkGetDisplayModePropertiesKHR vulkan_symbol_wrapper_vkGetDisplayModePropertiesKHR +extern PFN_vkCreateDisplayModeKHR vulkan_symbol_wrapper_vkCreateDisplayModeKHR; +#define vkCreateDisplayModeKHR vulkan_symbol_wrapper_vkCreateDisplayModeKHR +extern PFN_vkGetDisplayPlaneCapabilitiesKHR vulkan_symbol_wrapper_vkGetDisplayPlaneCapabilitiesKHR; +#define vkGetDisplayPlaneCapabilitiesKHR vulkan_symbol_wrapper_vkGetDisplayPlaneCapabilitiesKHR +extern PFN_vkCreateDisplayPlaneSurfaceKHR vulkan_symbol_wrapper_vkCreateDisplayPlaneSurfaceKHR; +#define vkCreateDisplayPlaneSurfaceKHR vulkan_symbol_wrapper_vkCreateDisplayPlaneSurfaceKHR +extern PFN_vkCreateSharedSwapchainsKHR vulkan_symbol_wrapper_vkCreateSharedSwapchainsKHR; +#define vkCreateSharedSwapchainsKHR vulkan_symbol_wrapper_vkCreateSharedSwapchainsKHR +extern PFN_vkCreateDebugReportCallbackEXT vulkan_symbol_wrapper_vkCreateDebugReportCallbackEXT; +#define vkCreateDebugReportCallbackEXT vulkan_symbol_wrapper_vkCreateDebugReportCallbackEXT +extern PFN_vkDestroyDebugReportCallbackEXT vulkan_symbol_wrapper_vkDestroyDebugReportCallbackEXT; +#define vkDestroyDebugReportCallbackEXT vulkan_symbol_wrapper_vkDestroyDebugReportCallbackEXT +extern PFN_vkDebugReportMessageEXT vulkan_symbol_wrapper_vkDebugReportMessageEXT; +#define vkDebugReportMessageEXT vulkan_symbol_wrapper_vkDebugReportMessageEXT +extern PFN_vkDebugMarkerSetObjectTagEXT vulkan_symbol_wrapper_vkDebugMarkerSetObjectTagEXT; +#define vkDebugMarkerSetObjectTagEXT vulkan_symbol_wrapper_vkDebugMarkerSetObjectTagEXT +extern PFN_vkDebugMarkerSetObjectNameEXT vulkan_symbol_wrapper_vkDebugMarkerSetObjectNameEXT; +#define vkDebugMarkerSetObjectNameEXT vulkan_symbol_wrapper_vkDebugMarkerSetObjectNameEXT +extern PFN_vkCmdDebugMarkerBeginEXT vulkan_symbol_wrapper_vkCmdDebugMarkerBeginEXT; +#define vkCmdDebugMarkerBeginEXT vulkan_symbol_wrapper_vkCmdDebugMarkerBeginEXT +extern PFN_vkCmdDebugMarkerEndEXT vulkan_symbol_wrapper_vkCmdDebugMarkerEndEXT; +#define vkCmdDebugMarkerEndEXT vulkan_symbol_wrapper_vkCmdDebugMarkerEndEXT +extern PFN_vkCmdDebugMarkerInsertEXT vulkan_symbol_wrapper_vkCmdDebugMarkerInsertEXT; +#define vkCmdDebugMarkerInsertEXT vulkan_symbol_wrapper_vkCmdDebugMarkerInsertEXT + +void vulkan_symbol_wrapper_init(PFN_vkGetInstanceProcAddr get_instance_proc_addr); +PFN_vkGetInstanceProcAddr vulkan_symbol_wrapper_instance_proc_addr(void); +VkBool32 vulkan_symbol_wrapper_load_global_symbols(void); +VkBool32 vulkan_symbol_wrapper_load_core_instance_symbols(VkInstance instance); +VkBool32 vulkan_symbol_wrapper_load_core_symbols(VkInstance instance); +VkBool32 vulkan_symbol_wrapper_load_core_device_symbols(VkDevice device); +VkBool32 vulkan_symbol_wrapper_load_instance_symbol(VkInstance instance, const char *name, PFN_vkVoidFunction *ppSymbol); +VkBool32 vulkan_symbol_wrapper_load_device_symbol(VkDevice device, const char *name, PFN_vkVoidFunction *ppSymbol); + +#define VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, name, pfn) vulkan_symbol_wrapper_load_instance_symbol(instance, name, (PFN_vkVoidFunction*) &(pfn)) +#define VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_EXTENSION_SYMBOL(instance, name) vulkan_symbol_wrapper_load_instance_symbol(instance, #name, (PFN_vkVoidFunction*) & name) +#define VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, name, pfn) vulkan_symbol_wrapper_load_device_symbol(device, name, (PFN_vkVoidFunction*) &(pfn)) +#define VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_EXTENSION_SYMBOL(device, name) vulkan_symbol_wrapper_load_device_symbol(device, #name, (PFN_vkVoidFunction*) & name) + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/desmume/src/libretro-common/libco/libco.c b/desmume/src/libretro-common/libco/libco.c index 63126d3c2..456e9ed37 100644 --- a/desmume/src/libretro-common/libco/libco.c +++ b/desmume/src/libretro-common/libco/libco.c @@ -10,6 +10,8 @@ #include "amd64.c" #elif defined(__GNUC__) && defined(_ARCH_PPC) #include "ppc.c" +#elif defined(__GNUC__) && defined(VITA) + #include "psp2.c" #elif defined(__GNUC__) && (defined(__ARM_EABI__) || defined(__arm__)) #include "armeabi.c" #elif defined(__GNUC__) diff --git a/desmume/src/libretro-common/libco/psp2.c b/desmume/src/libretro-common/libco/psp2.c new file mode 100644 index 000000000..eaf9b7a58 --- /dev/null +++ b/desmume/src/libretro-common/libco/psp2.c @@ -0,0 +1,113 @@ +/* +libco.arm (2015-06-18) +license: public domain +*/ + +#define LIBCO_C +#include "libco.h" + +#include +#include +#include +#include +#include +#include + +#define FOUR_KB_ALIGN(x) align(x, 12) +#define MB_ALIGN(x) align(x, 20) + +#ifdef __cplusplus +extern "C" { +#endif + + static inline int align(int x, int n) + { + return (((x >> n) + 1) << n); + } + + static thread_local unsigned long co_active_buffer[64]; + static thread_local cothread_t co_active_handle = 0; + static void(*co_swap)(cothread_t, cothread_t) = 0; + static int block; + static uint32_t co_swap_function[] = { + 0xe8a16ff0, /* stmia r1!, {r4-r11,sp,lr} */ + 0xe8b0aff0, /* ldmia r0!, {r4-r11,sp,pc} */ + 0xe12fff1e, /* bx lr */ + }; + + void co_init() + { + int ret; + void *base; + + block = sceKernelAllocMemBlockForVM("libco", + MB_ALIGN(FOUR_KB_ALIGN(sizeof co_swap_function))); + if (block < 0) + return; + + /* get base address */ + ret = sceKernelGetMemBlockBase(block, &base); + if (ret < 0) + return; + + /* set domain to be writable by user */ + ret = sceKernelOpenVMDomain(); + if (ret < 0) + return; + + memcpy(base, co_swap_function, sizeof co_swap_function); + + /* set domain back to read-only */ + ret = sceKernelCloseVMDomain(); + if (ret < 0) + return; + + /* flush icache */ + ret = sceKernelSyncVMDomain(block, base, + MB_ALIGN(FOUR_KB_ALIGN(sizeof co_swap_function))); + if (ret < 0) + return; + + co_swap = (void(*)(cothread_t, cothread_t))base; + } + + cothread_t co_active(void) + { + if (!co_active_handle) co_active_handle = &co_active_buffer; + return co_active_handle; + } + + cothread_t co_create(unsigned int size, void(*entrypoint)(void)) + { + unsigned long* handle = 0; + if (!co_swap) + co_init(); + if (!co_active_handle) co_active_handle = &co_active_buffer; + size += 256; + size &= ~15; + + if ((handle = (unsigned long*)malloc(size))) + { + unsigned long* p = (unsigned long*)((unsigned char*)handle + size); + handle[8] = (unsigned long)p; + handle[9] = (unsigned long)entrypoint; + } + + return handle; + } + + void co_delete(cothread_t handle) + { + free(handle); + sceKernelFreeMemBlock(block); + } + + void co_switch(cothread_t handle) + { + cothread_t co_previous_handle = co_active_handle; + co_swap(co_active_handle = handle, co_previous_handle); + } + +#ifdef __cplusplus +} +#endif diff --git a/desmume/src/libretro-common/lists/dir_list.c b/desmume/src/libretro-common/lists/dir_list.c index 5fb2b373e..80fa09b3c 100644 --- a/desmume/src/libretro-common/lists/dir_list.c +++ b/desmume/src/libretro-common/lists/dir_list.c @@ -181,14 +181,14 @@ struct string_list *dir_list_new(const char *dir, while (retro_readdir(entry)) { - char file_path[PATH_MAX_LENGTH]; - bool is_dir; + bool is_dir = false; + char file_path[PATH_MAX_LENGTH] = {0}; int ret = 0; const char *name = retro_dirent_get_name(entry); 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); + 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/lists/file_list.c b/desmume/src/libretro-common/lists/file_list.c index 2dc9770f5..cc59978fa 100644 --- a/desmume/src/libretro-common/lists/file_list.c +++ b/desmume/src/libretro-common/lists/file_list.c @@ -38,7 +38,7 @@ * * Returns: true (1) if successful, otherwise false (0). **/ -static bool file_list_capacity(file_list_t *list, size_t cap) +static struct item_file *realloc_file_list_capacity(file_list_t *list, size_t cap) { struct item_file *new_data = NULL; retro_assert(cap > list->size); @@ -47,15 +47,47 @@ static bool file_list_capacity(file_list_t *list, size_t cap) cap * sizeof(struct item_file)); if (!new_data) - return false; + return NULL; if (cap > list->capacity) memset(&new_data[list->capacity], 0, sizeof(*new_data) * (cap - list->capacity)); - list->list = new_data; - list->capacity = cap; + return new_data; +} +static void file_list_add(file_list_t *list, unsigned idx, + const char *path, const char *label, + unsigned type, size_t directory_ptr, + size_t entry_idx) +{ + memset(&list->list[idx], 0, sizeof(*list->list)); + + list->list[idx].type = type; + list->list[idx].directory_ptr = directory_ptr; + list->list[idx].entry_idx = entry_idx; + + if (label) + list->list[idx].label = strdup(label); + if (path) + list->list[idx].path = strdup(path); + + list->size++; +} + +static bool file_list_expand_if_needed(file_list_t *list) +{ + if (list->size >= list->capacity) + { + size_t new_capacity = list->capacity * 2 + 1; + struct item_file *items = realloc_file_list_capacity( + list, new_capacity); + + if (!items) + return false; + list->list = items; + list->capacity = new_capacity; + } return true; } @@ -65,15 +97,14 @@ bool file_list_prepend(file_list_t *list, size_t entry_idx) { unsigned i; - if (list->size >= list->capacity && - !file_list_capacity(list, list->capacity * 2 + 1)) - return false; + + if (!file_list_expand_if_needed(list)) + return false; - list->size++; - - for (i = list->size -1; i > 0; i--) + for (i = list->size; i > 0; i--) { - struct item_file *copy = calloc(1, sizeof(struct item_file)); + struct item_file *copy = (struct item_file*) + calloc(1, sizeof(struct item_file)); memcpy(copy, &list->list[i-1], sizeof(struct item_file)); @@ -83,21 +114,8 @@ bool file_list_prepend(file_list_t *list, free(copy); } - memset(&list->list[0], 0, sizeof(file_list_t)); - - list->list[0].label = NULL; - list->list[0].path = NULL; - list->list[0].alt = NULL; - list->list[0].userdata = NULL; - list->list[0].actiondata = NULL; - list->list[0].type = type; - list->list[0].directory_ptr = directory_ptr; - list->list[0].entry_idx = entry_idx; - - if (label) - list->list[0].label = strdup(label); - if (path) - list->list[0].path = strdup(path); + file_list_add(list, 0, path, label, type, + directory_ptr, entry_idx); return true; } @@ -107,25 +125,11 @@ bool file_list_append(file_list_t *list, unsigned type, size_t directory_ptr, size_t entry_idx) { - if (list->size >= list->capacity && - !file_list_capacity(list, list->capacity * 2 + 1)) - return false; + if (!file_list_expand_if_needed(list)) + return false; - list->list[list->size].label = NULL; - list->list[list->size].path = NULL; - list->list[list->size].alt = NULL; - list->list[list->size].userdata = NULL; - list->list[list->size].actiondata = NULL; - list->list[list->size].type = type; - list->list[list->size].directory_ptr = directory_ptr; - list->list[list->size].entry_idx = entry_idx; - - if (label) - list->list[list->size].label = strdup(label); - if (path) - list->list[list->size].path = strdup(path); - - list->size++; + file_list_add(list, list->size, path, label, type, + directory_ptr, entry_idx); return true; } diff --git a/desmume/src/libretro-common/memmap/memalign.c b/desmume/src/libretro-common/memmap/memalign.c index 60f4ba415..a89a87830 100644 --- a/desmume/src/libretro-common/memmap/memalign.c +++ b/desmume/src/libretro-common/memmap/memalign.c @@ -25,11 +25,12 @@ #include + void *memalign_alloc(size_t boundary, size_t size) { - void **place; + void **place = NULL; uintptr_t addr = 0; - void *ptr = malloc(boundary + size + sizeof(uintptr_t)); + void *ptr = (void*)malloc(boundary + size + sizeof(uintptr_t)); if (!ptr) return NULL; @@ -43,6 +44,21 @@ void *memalign_alloc(size_t boundary, size_t size) void memalign_free(void *ptr) { - void **p = (void**)ptr; + void **p = NULL; + if (!ptr) + return; + + p = (void**)ptr; free(p[-1]); } + +void *memalign_alloc_aligned(size_t size) +{ +#if defined(__x86_64__) || defined(__LP64) || defined(__IA64__) || defined(_M_X64) || defined(_WIN64) + return memalign_alloc(64, size); +#elif defined(__i386__) || defined(__i486__) || defined(__i686__) || defined(GEKKO) + return memalign_alloc(32, size); +#else + return memalign_alloc(32, size); +#endif +} diff --git a/desmume/src/libretro-common/net/net_compat.c b/desmume/src/libretro-common/net/net_compat.c index db6c64488..bf52d3435 100644 --- a/desmume/src/libretro-common/net/net_compat.c +++ b/desmume/src/libretro-common/net/net_compat.c @@ -21,14 +21,61 @@ */ #include +#include #include #include +#include #include #include +#include #include -#if defined(VITA) +#if defined(_XBOX) +/* TODO - implement h_length and h_addrtype */ +struct hostent +{ + int h_addrtype; /* host address type */ + int h_length; /* length of addresses */ + char **h_addr_list; /* list of addresses */ +}; + +struct hostent *gethostbyname(const char *name) +{ + WSAEVENT event; + static struct hostent he; + static struct in_addr addr; + static char *addr_ptr; + XNDNS *dns = NULL; + + he.h_addr_list = &addr_ptr; + addr_ptr = (char*)&addr; + + if (!name) + return NULL; + + event = WSACreateEvent(); + XNetDnsLookup(name, event, &dns); + if (!dns) + goto error; + + WaitForSingleObject((HANDLE)event, INFINITE); + if (dns->iStatus) + goto error; + + memcpy(&addr, dns->aina, sizeof(addr)); + + WSACloseEvent(event); + XNetDnsRelease(dns); + + return &he; + +error: + if (event) + WSACloseEvent(event); + return NULL; +} +#elif defined(VITA) static void *_net_compat_net_memory = NULL; #define COMPAT_NET_INIT_SIZE 512*1024 #define INET_ADDRSTRLEN sizeof(struct sockaddr_in) @@ -55,7 +102,7 @@ struct SceNetInAddr inet_aton(const char *ip_addr) { SceNetInAddr inaddr; - sceNetInetPton(AF_INET, ip_addr, &inaddr); + inet_ptrton(AF_INET, ip_addr, &inaddr); return inaddr; } @@ -93,30 +140,53 @@ struct hostent *gethostbyname(const char *name) } int retro_epoll_fd; +#elif defined(_WIN32) +int inet_aton(const char *cp, struct in_addr *inp) +{ + uint32_t addr = 0; + if (cp == 0 || inp == 0) + return -1; + addr = inet_addr(cp); + if (addr == INADDR_NONE || addr == INADDR_ANY) + return -1; + + inp->s_addr = addr; + return 1; +} #endif int getaddrinfo_retro(const char *node, const char *service, - const struct addrinfo *hints, - struct addrinfo **res) + struct addrinfo *hints, struct addrinfo **res) { -#ifdef HAVE_SOCKET_LEGACY struct sockaddr_in *in_addr = NULL; - struct addrinfo *info = (struct addrinfo*)calloc(1, sizeof(*info)); + struct addrinfo *info = NULL; + + (void)in_addr; + (void)info; + +#if defined(_WIN32) || defined(HAVE_SOCKET_LEGACY) + hints->ai_family = AF_INET; +#else + hints->ai_family = AF_UNSPEC; +#endif + +#ifdef HAVE_SOCKET_LEGACY + info = (struct addrinfo*)calloc(1, sizeof(*info)); if (!info) goto error; - info->ai_family = AF_INET; - info->ai_socktype = hints->ai_socktype; - - in_addr = (struct sockaddr_in*)calloc(1, sizeof(*in_addr)); + info->ai_family = AF_INET; + info->ai_socktype = hints->ai_socktype; + in_addr = (struct sockaddr_in*) + calloc(1, sizeof(*in_addr)); if (!in_addr) goto error; info->ai_addrlen = sizeof(*in_addr); in_addr->sin_family = AF_INET; - in_addr->sin_port = htons(strtoul(service, NULL, 0)); + in_addr->sin_port = inet_htons(strtoul(service, NULL, 0)); if (!node && (hints->ai_flags & AI_PASSIVE)) in_addr->sin_addr.s_addr = INADDR_ANY; @@ -135,7 +205,7 @@ int getaddrinfo_retro(const char *node, const char *service, goto error; info->ai_addr = (struct sockaddr*)in_addr; - *res = info; + *res = info; return 0; @@ -160,91 +230,6 @@ void freeaddrinfo_retro(struct addrinfo *res) #endif } -bool socket_nonblock(int fd) -{ -#if defined(__CELLOS_LV2__) || defined(VITA) - int i = 1; - setsockopt(fd, SOL_SOCKET, SO_NBIO, &i, sizeof(int)); - return true; -#elif defined(_WIN32) - u_long mode = 1; - return ioctlsocket(fd, FIONBIO, &mode) == 0; -#else - return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) == 0; -#endif -} - -int socket_close(int fd) -{ -#if defined(_WIN32) && !defined(_XBOX360) - /* WinSock has headers from the stone age. */ - return closesocket(fd); -#elif defined(__CELLOS_LV2__) - return socketclose(fd); -#elif defined(VITA) - return sceNetSocketClose(fd); -#else - return close(fd); -#endif -} - -int socket_select(int nfds, fd_set *readfs, fd_set *writefds, - fd_set *errorfds, struct timeval *timeout) -{ -#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 -} - -int socket_send_all_blocking(int fd, const void *data_, size_t size) -{ - const uint8_t *data = (const uint8_t*)data_; - - while (size) - { - ssize_t ret = send(fd, (const char*)data, size, 0); - if (ret <= 0) - return false; - - data += ret; - size -= ret; - } - - return true; -} - -int socket_receive_all_blocking(int fd, void *data_, size_t size) -{ - const uint8_t *data = (const uint8_t*)data_; - - while (size) - { - ssize_t ret = recv(fd, (char*)data, size, 0); - if (ret <= 0) - return false; - - data += ret; - size -= ret; - } - - return true; -} - /** * network_init: * @@ -268,32 +253,49 @@ bool network_init(void) return false; } #elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__) + int timeout_count = 10; + cellSysmoduleLoadModule(CELL_SYSMODULE_NET); sys_net_initialize_network(); + + if (cellNetCtlInit() < 0) + return false; + + for (;;) + { + int state; + if (cellNetCtlGetState(&state) < 0) + return false; + + if (state == CELL_NET_CTL_STATE_IPObtained) + break; + + retro_sleep(500); + timeout_count--; + if (timeout_count < 0) + return 0; + } #elif defined(VITA) SceNetInitParam initparam; - /* Init Net */ - if (sceNetShowNetstat() == PSP2_NET_ERROR_ENOTINIT) + + if (sceNetShowNetstat() == SCE_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; + 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); +#elif defined(GEKKO) + char t[16]; + if (if_config(t, NULL, NULL, TRUE) < 0) + return false; #else signal(SIGPIPE, SIG_IGN); /* Do not like SIGPIPE killing our app. */ #endif @@ -312,6 +314,7 @@ void network_deinit(void) #if defined(_WIN32) WSACleanup(); #elif defined(__CELLOS_LV2__) && !defined(__PSL1GHT__) + cellNetCtlTerm(); sys_net_finalize_network(); cellSysmoduleUnloadModule(CELL_SYSMODULE_NET); #elif defined(VITA) @@ -323,5 +326,28 @@ void network_deinit(void) free(_net_compat_net_memory); _net_compat_net_memory = NULL; } +#elif defined(GEKKO) && !defined(HW_DOL) + net_deinit(); +#endif +} + +uint16_t inet_htons(uint16_t hostshort) +{ +#ifdef VITA + return sceNetHtons(hostshort); +#else + return htons(hostshort); +#endif +} + +int inet_ptrton(int af, const char *src, void *dst) +{ +#if defined(VITA) + return sceNetInetPton(af, src, dst); +#elif defined(GEKKO) || defined(_WIN32) + /* TODO/FIXME - should use InetPton on Vista and later */ + return inet_aton(src, (struct in_addr*)dst); +#else + return inet_pton(af, src, dst); #endif } diff --git a/desmume/src/libretro-common/net/net_http.c b/desmume/src/libretro-common/net/net_http.c index ecdeccf88..ff7f85120 100644 --- a/desmume/src/libretro-common/net/net_http.c +++ b/desmume/src/libretro-common/net/net_http.c @@ -26,6 +26,7 @@ #include #include +#include #include enum @@ -47,17 +48,17 @@ enum struct http_t { - int fd; - int status; - - char part; - char bodytype; - bool error; - - size_t pos; - size_t len; - size_t buflen; - char * data; + int fd; + int status; + + char part; + char bodytype; + bool error; + + size_t pos; + size_t len; + size_t buflen; + char * data; }; struct http_connection_t @@ -72,111 +73,74 @@ struct http_connection_t 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()) + int ret; + struct addrinfo *addr = NULL; + int fd = socket_init((void**)&addr, port, domain, SOCKET_TYPE_STREAM); + if (fd < 0) return -1; - snprintf(portstr, sizeof(portstr), "%i", port); - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = 0; - - if (getaddrinfo_retro(domain, portstr, &hints, &addr) < 0) - return -1; - if (!addr) - return -1; - - 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_retro(addr); - socket_close(fd); - return -1; - } + ret = socket_connect(fd, (void*)addr, true); freeaddrinfo_retro(addr); + if (ret < 0) + goto error; + if (!socket_nonblock(fd)) - { - socket_close(fd); - return -1; - } + goto error; return fd; -} -static void net_http_send(int fd, bool * error, - const char * data, size_t len) -{ - if (*error) - return; - - while (len) - { - ssize_t thislen = send(fd, data, len, MSG_NOSIGNAL); - - if (thislen <= 0) - { - if (!isagain(thislen)) - continue; - - *error=true; - return; - } - - data += thislen; - len -= thislen; - } +error: + socket_close(fd); + return -1; } static void net_http_send_str(int fd, bool *error, const char *text) { - net_http_send(fd, error, text, strlen(text)); + if (*error) + return; + + if (!socket_send_all_blocking(fd, text, strlen(text), true)) + *error = true; } -static ssize_t net_http_recv(int fd, bool *error, - uint8_t *data, size_t maxlen) +static char* urlencode(const char* url) { - ssize_t bytes; + unsigned i; + unsigned outpos = 0; + unsigned outlen = 0; + char *ret = NULL; - if (*error) - return -1; - - bytes = recv(fd, (char*)data, maxlen, 0); - - if (bytes > 0) - return bytes; - else if (bytes == 0) - return -1; - else if (isagain(bytes)) - return 0; - - *error=true; - return -1; + for (i = 0; url[i] != '\0'; i++) + { + outlen++; + if (url[i] == ' ') + outlen += 2; + } + + ret = (char*)malloc(outlen + 1); + if (!ret) + return NULL; + + for (i = 0; url[i]; i++) + { + if (url[i] == ' ') + { + ret[outpos++] = '%'; + ret[outpos++] = '2'; + ret[outpos++] = '0'; + } + else + ret[outpos++] = url[i]; + } + ret[outpos] = '\0'; + + return ret; } struct http_connection_t *net_http_connection_new(const char *url) { - size_t length; char **domain = NULL; struct http_connection_t *conn = (struct http_connection_t*)calloc(1, sizeof(struct http_connection_t)); @@ -184,22 +148,17 @@ struct http_connection_t *net_http_connection_new(const char *url) if (!conn) return NULL; - length = strlen(url) + 1; - conn->urlcopy = (char*)malloc(length); + conn->urlcopy = urlencode(url); if (!conn->urlcopy) goto error; - strlcpy(conn->urlcopy, url, length); - if (strncmp(url, "http://", strlen("http://")) != 0) goto error; conn->scan = conn->urlcopy + strlen("http://"); - domain = &conn->domain; - - *domain = conn->scan; + *domain = conn->scan; return conn; @@ -215,11 +174,10 @@ bool net_http_connection_iterate(struct http_connection_t *conn) { if (!conn) return false; - if (*conn->scan != '/' && *conn->scan != ':' && *conn->scan != '\0') - { + + while (*conn->scan != '/' && *conn->scan != ':' && *conn->scan != '\0') conn->scan++; - return false; - } + return true; } @@ -230,17 +188,16 @@ bool net_http_connection_done(struct http_connection_t *conn) if (!conn) return false; - location = &conn->location; + location = &conn->location; if (*conn->scan == '\0') return false; - *conn->scan = '\0'; + *conn->scan = '\0'; conn->port = 80; if (*conn->scan == ':') { - if (!isdigit((int)conn->scan[1])) return false; @@ -273,18 +230,18 @@ const char *net_http_connection_url(struct http_connection_t *conn) struct http_t *net_http_new(struct http_connection_t *conn) { - bool error; - int fd = -1; - struct http_t *state = NULL; + bool error = false; + int fd = -1; + struct http_t *state = NULL; if (!conn) goto error; fd = net_http_new_socket(conn->domain, conn->port); - if (fd == -1) + if (fd < 0) goto error; - error=false; + error = false; /* This is a bit lazy, but it works. */ net_http_send_str(fd, &error, "GET /"); @@ -327,15 +284,17 @@ struct http_t *net_http_new(struct http_connection_t *conn) return state; error: - if (fd != -1) + if (fd >= 0) socket_close(fd); + if (state) + free(state); return NULL; } int net_http_fd(struct http_t *state) { if (!state) - return 0; + return -1; return state->fd; } @@ -348,8 +307,11 @@ bool net_http_update(struct http_t *state, size_t* progress, size_t* total) if (state->part < P_BODY) { - newlen = net_http_recv(state->fd, &state->error, - (uint8_t*)state->data + state->pos, state->buflen - state->pos); + if (state->error) + newlen = -1; + else + newlen = socket_receive_all_nonblocking(state->fd, &state->error, + (uint8_t*)state->data + state->pos, state->buflen - state->pos); if (newlen < 0) goto fail; @@ -414,9 +376,14 @@ bool net_http_update(struct http_t *state, size_t* progress, size_t* total) { if (!newlen) { - newlen = net_http_recv(state->fd, &state->error, - (uint8_t*)state->data + state->pos, - state->buflen - state->pos); + if (state->error) + newlen = -1; + else + newlen = socket_receive_all_nonblocking( + state->fd, + &state->error, + (uint8_t*)state->data + state->pos, + state->buflen - state->pos); if (newlen < 0) { @@ -451,8 +418,8 @@ parse_again: */ char *fullend = state->data + state->pos; - char *end = (char*)memchr(state->data + state->len + 2, - '\n', state->pos - state->len - 2); + char *end = (char*)memchr(state->data + state->len + 2, '\n', + state->pos - state->len - 2); if (end) { @@ -539,9 +506,9 @@ fail: int net_http_status(struct http_t *state) { - if (state) - return state->status; - return -1; + if (!state) + return -1; + return state->status; } uint8_t* net_http_data(struct http_t *state, size_t* len, bool accept_error) @@ -567,7 +534,7 @@ void net_http_delete(struct http_t *state) if (!state) return; - if (state->fd != -1) + if (state->fd >= 0) socket_close(state->fd); free(state); } diff --git a/desmume/src/libretro-common/net/net_ifinfo.c b/desmume/src/libretro-common/net/net_ifinfo.c index 806032978..7559387f4 100644 --- a/desmume/src/libretro-common/net/net_ifinfo.c +++ b/desmume/src/libretro-common/net/net_ifinfo.c @@ -28,8 +28,8 @@ #if defined(_WIN32) && !defined(_XBOX) #include -#include -#include +#include +#include #else #include #include @@ -56,9 +56,6 @@ void net_ifinfo_free(net_ifinfo_t *list) struct net_ifinfo_entry *ptr = (struct net_ifinfo_entry*)&list->entries[k]; - if (!ptr) - continue; - if (*ptr->name) free(ptr->name); if (*ptr->host) diff --git a/desmume/src/libretro-common/net/net_socket.c b/desmume/src/libretro-common/net/net_socket.c new file mode 100644 index 000000000..735717ce5 --- /dev/null +++ b/desmume/src/libretro-common/net/net_socket.c @@ -0,0 +1,313 @@ +/* Copyright (C) 2010-2016 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (net_socket.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 + +int socket_init(void **address, uint16_t port, const char *server, enum socket_type type) +{ + char port_buf[16] = {0}; + struct addrinfo hints = {0}; + struct addrinfo **addrinfo = (struct addrinfo**)address; + struct addrinfo *addr = NULL; + + if (!network_init()) + goto error; + + switch (type) + { + case SOCKET_TYPE_DATAGRAM: + hints.ai_socktype = SOCK_DGRAM; + break; + case SOCKET_TYPE_STREAM: + hints.ai_socktype = SOCK_STREAM; + break; + case SOCKET_TYPE_SEQPACKET: + /* TODO/FIXME - implement? */ + break; + } + + if (!server) + hints.ai_flags = AI_PASSIVE; + + snprintf(port_buf, sizeof(port_buf), "%hu", (unsigned short)port); + + if (getaddrinfo_retro(server, port_buf, &hints, addrinfo) < 0) + goto error; + + addr = (struct addrinfo*)*addrinfo; + + if (!addr) + goto error; + + return socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + +error: + return -1; +} + +ssize_t socket_receive_all_nonblocking(int fd, bool *error, + void *data_, size_t size) +{ + const uint8_t *data = (const uint8_t*)data_; + ssize_t ret = recv(fd, (char*)data, size, 0); + + if (ret > 0) + return ret; + + if (ret == 0) + return -1; + + if (isagain(ret)) + return 0; + + *error = true; + return -1; +} + +int socket_receive_all_blocking(int fd, void *data_, size_t size) +{ + const uint8_t *data = (const uint8_t*)data_; + + while (size) + { + ssize_t ret = recv(fd, (char*)data, size, 0); + if (ret <= 0) + return false; + + data += ret; + size -= ret; + } + + return true; +} + +bool socket_nonblock(int fd) +{ +#if defined(__CELLOS_LV2__) || defined(VITA) + int i = 1; + setsockopt(fd, SOL_SOCKET, SO_NBIO, &i, sizeof(int)); + return true; +#elif defined(_WIN32) + u_long mode = 1; + return ioctlsocket(fd, FIONBIO, &mode) == 0; +#else + return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) == 0; +#endif +} + +int socket_close(int fd) +{ +#if defined(_WIN32) && !defined(_XBOX360) + /* WinSock has headers from the stone age. */ + return closesocket(fd); +#elif defined(__CELLOS_LV2__) + return socketclose(fd); +#elif defined(VITA) + return sceNetSocketClose(fd); +#else + return close(fd); +#endif +} + +int socket_select(int nfds, fd_set *readfs, fd_set *writefds, + fd_set *errorfds, struct timeval *timeout) +{ +#if defined(__CELLOS_LV2__) + return socketselect(nfds, readfs, writefds, errorfds, timeout); +#elif defined(VITA) + SceNetEpollEvent ev = {0}; + + ev.events = SCE_NET_EPOLLIN | SCE_NET_EPOLLHUP; + ev.data.fd = nfds; + + if((sceNetEpollControl(retro_epoll_fd, SCE_NET_EPOLL_CTL_ADD, nfds, &ev))) + { + int ret = sceNetEpollWait(retro_epoll_fd, &ev, 1, 0); + sceNetEpollControl(retro_epoll_fd, SCE_NET_EPOLL_CTL_DEL, nfds, NULL); + return ret; + } + return 0; +#else + return select(nfds, readfs, writefds, errorfds, timeout); +#endif +} + +int socket_send_all_blocking(int fd, const void *data_, size_t size, + bool no_signal) +{ + const uint8_t *data = (const uint8_t*)data_; + + while (size) + { + ssize_t ret = send(fd, (const char*)data, size, + no_signal ? MSG_NOSIGNAL : 0); + if (ret <= 0) + { + if (!isagain(ret)) + continue; + + return false; + } + + data += ret; + size -= ret; + } + + return true; +} + +bool socket_bind(int fd, void *data) +{ + int yes = 1; + struct addrinfo *res = (struct addrinfo*)data; + setsockopt(fd, SOL_SOCKET, + SO_REUSEADDR, (const char*)&yes, sizeof(int)); + if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) + return false; + return true; +} + +int socket_connect(int fd, void *data, bool timeout_enable) +{ + struct addrinfo *addr = (struct addrinfo*)data; + +#ifndef _WIN32 +#ifndef VITA + if (timeout_enable) + { + struct timeval timeout; + timeout.tv_sec = 4; + timeout.tv_usec = 0; + + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof timeout); + } +#endif +#endif + + return connect(fd, addr->ai_addr, addr->ai_addrlen); +} + +static int domain_get(enum socket_domain type) +{ + switch (type) + { + case SOCKET_DOMAIN_INET: +#ifdef VITA + return SCE_NET_AF_INET; +#else + return AF_INET; +#endif + default: + break; + } + + return 0; +} + +int socket_create( + const char *name, + enum socket_domain domain_type, + enum socket_type socket_type, + enum socket_protocol protocol_type) +{ + int type = 0; + int protocol = 0; + int domain = domain_get(domain_type); +#ifdef VITA + + switch (socket_type) + { + case SOCKET_TYPE_DATAGRAM: + type = SCE_NET_SOCK_DGRAM; + break; + case SOCKET_TYPE_STREAM: + type = SCE_NET_SOCK_STREAM; + break; + case SOCKET_TYPE_SEQPACKET: + /* TODO/FIXME - implement */ + break; + } + + switch (protocol_type) + { + case SOCKET_PROTOCOL_NONE: + protocol = 0; + break; + case SOCKET_PROTOCOL_TCP: + protocol = SCE_NET_IPPROTO_TCP; + break; + case SOCKET_PROTOCOL_UDP: + protocol = SCE_NET_IPPROTO_UDP; + break; + } + + return sceNetSocket(name, domain, type, protocol); +#else + switch (socket_type) + { + case SOCKET_TYPE_DATAGRAM: + type = SOCK_DGRAM; + break; + case SOCKET_TYPE_STREAM: + type = SOCK_STREAM; + break; + case SOCKET_TYPE_SEQPACKET: + /* TODO/FIXME - implement */ + break; + } + + switch (protocol_type) + { + case SOCKET_PROTOCOL_NONE: + protocol = 0; + break; + case SOCKET_PROTOCOL_TCP: + protocol = IPPROTO_TCP; + break; + case SOCKET_PROTOCOL_UDP: + protocol = IPPROTO_UDP; + break; + } + + return socket(domain, type, protocol); +#endif +} + +void socket_set_target(void *data, socket_target_t *in_addr) +{ + struct sockaddr_in *out_target = (struct sockaddr_in*)data; + + out_target->sin_port = inet_htons(in_addr->port); + out_target->sin_family = domain_get(in_addr->domain); +#ifdef VITA + out_target->sin_addr = inet_aton(in_addr->server); +#else +#ifdef GEKKO + out_target->sin_len = 8; +#endif + + inet_ptrton(AF_INET, in_addr->server, &out_target->sin_addr); + +#endif +} diff --git a/desmume/src/libretro-common/net/test/http_test b/desmume/src/libretro-common/net/test/http_test new file mode 100755 index 000000000..81a1556fd Binary files /dev/null and b/desmume/src/libretro-common/net/test/http_test differ diff --git a/desmume/src/libretro-common/net/test/net_ifinfo b/desmume/src/libretro-common/net/test/net_ifinfo new file mode 100755 index 000000000..e0d0b234d Binary files /dev/null and b/desmume/src/libretro-common/net/test/net_ifinfo differ diff --git a/desmume/src/libretro-common/queues/task_queue.c b/desmume/src/libretro-common/queues/task_queue.c index 35b4aae98..56e9a9c46 100644 --- a/desmume/src/libretro-common/queues/task_queue.c +++ b/desmume/src/libretro-common/queues/task_queue.c @@ -39,10 +39,12 @@ typedef struct struct retro_task_impl { void (*push_running)(retro_task_t *); + void (*cancel)(void *); void (*reset)(void); void (*wait)(void); void (*gather)(void); bool (*find)(retro_task_finder_t, void*); + void (*retrieve)(task_retriever_data_t *data); void (*init)(void); void (*deinit)(void); }; @@ -50,10 +52,13 @@ struct retro_task_impl 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, ...) { +#ifdef RARCH_INTERNAL + extern void runloop_msg_queue_push(const char *msg, unsigned prio, + unsigned duration, bool flush); +#endif char buf[1024]; va_list ap; @@ -62,11 +67,16 @@ static void task_queue_msg_push(unsigned prio, unsigned duration, va_end(ap); /* print something here */ + +#ifdef RARCH_INTERNAL + /* TODO/FIXME - ugly */ + runloop_msg_queue_push(buf, prio, duration, flush); +#endif } -void task_queue_push_progress(retro_task_t *task) +static void task_queue_push_progress(retro_task_t *task) { - if (task->title) + if (task->title && !task->mute) { if (task->finished) { @@ -86,7 +96,6 @@ void task_queue_push_progress(retro_task_t *task) } } } -#endif static void task_queue_put(task_queue_t *queue, retro_task_t *task) { @@ -123,6 +132,9 @@ static void retro_task_internal_gather(void) if (task->callback) task->callback(task->task_data, task->user_data, task->error); + if (task->cleanup) + task->cleanup(task); + if (task->error) free(task->error); @@ -138,6 +150,12 @@ static void retro_task_regular_push_running(retro_task_t *task) task_queue_put(&tasks_running, task); } +static void retro_task_regular_cancel(void *task) +{ + retro_task_t *t = (retro_task_t*)task; + t->cancelled = true; +} + static void retro_task_regular_gather(void) { retro_task_t *task = NULL; @@ -201,12 +219,57 @@ static bool retro_task_regular_find(retro_task_finder_t func, void *user_data) return false; } +static void retro_task_regular_retrieve(task_retriever_data_t *data) +{ + retro_task_t *task = NULL; + task_retriever_info_t *tail = NULL; + + /* Parse all running tasks and handle matching handlers */ + for (task = tasks_running.front; task != NULL; task = task->next) + { + task_retriever_info_t *info = NULL; + if (task->handler != data->handler) + continue; + + /* Create new link */ + info = (task_retriever_info_t*)malloc(sizeof(task_retriever_info_t)); + info->data = malloc(data->element_size); + info->next = NULL; + + /* Call retriever function and fill info-specific data */ + if (!data->func(task, info->data)) + { + free(info->data); + free(info); + continue; + } + + /* Add link to list */ + if (data->list) + { + if (tail) + { + tail->next = info; + tail = tail->next; + } + else tail = info; + } + else + { + data->list = info; + tail = data->list; + } + } +} + static struct retro_task_impl impl_regular = { retro_task_regular_push_running, + retro_task_regular_cancel, retro_task_regular_reset, retro_task_regular_wait, retro_task_regular_gather, retro_task_regular_find, + retro_task_regular_retrieve, retro_task_regular_init, retro_task_regular_deinit }; @@ -218,6 +281,35 @@ 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 task_queue_remove(task_queue_t *queue, retro_task_t *task) +{ + retro_task_t *t = NULL; + + /* Remove first element if needed */ + if (task == queue->front) + { + queue->front = task->next; + task->next = NULL; + return; + } + + /* Parse queue */ + t = queue->front; + while (t && t->next) + { + /* Remove task and update queue */ + if (t->next == task) + { + t->next = task->next; + task->next = NULL; + break; + } + + /* Update iterator */ + t = t->next; + } +} + static void retro_task_threaded_push_running(retro_task_t *task) { slock_lock(running_lock); @@ -226,6 +318,24 @@ static void retro_task_threaded_push_running(retro_task_t *task) slock_unlock(running_lock); } +static void retro_task_threaded_cancel(void *task) +{ + retro_task_t *t; + + slock_lock(running_lock); + + for (t = tasks_running.front; t; t = t->next) + { + if (t == task) + { + t->cancelled = true; + break; + } + } + + slock_unlock(running_lock); +} + static void retro_task_threaded_gather(void) { retro_task_t *task = NULL; @@ -270,16 +380,32 @@ static bool retro_task_threaded_find( retro_task_finder_t func, void *user_data) { retro_task_t *task = NULL; + bool result = false; slock_lock(running_lock); for (task = tasks_running.front; task; task = task->next) { if (func(task, user_data)) - return true; + { + result = true; + break; + } } slock_unlock(running_lock); - return false; + return result; +} + +static void retro_task_threaded_retrieve(task_retriever_data_t *data) +{ + /* Protect access to running tasks */ + slock_lock(running_lock); + + /* Call regular retrieve function */ + retro_task_regular_retrieve(data); + + /* Release access to running tasks */ + slock_unlock(running_lock); } static void threaded_worker(void *userdata) @@ -288,24 +414,16 @@ static void threaded_worker(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; - } + slock_lock(running_lock); - if (queue == NULL) /* no tasks running, lets wait a bit */ + /* Get first task to run */ + task = tasks_running.front; + if (task == NULL) { scond_wait(worker_cond, running_lock); slock_unlock(running_lock); @@ -314,23 +432,30 @@ static void threaded_worker(void *userdata) slock_unlock(running_lock); - for (task = queue; task; task = next) + task->handler(task); + + slock_lock(running_lock); + task_queue_remove(&tasks_running, task); + slock_unlock(running_lock); + + /* Update queue */ + if (!task->finished) { - 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); + /* Re-add task to running queue */ + retro_task_threaded_push_running(task); + } + else + { + /* Add task to finished queue */ + slock_lock(finished_lock); + task_queue_put(&tasks_finished, task); + slock_unlock(finished_lock); } - } - slock_unlock(running_lock); +#if 0 + retro_sleep(10); +#endif + } } static void retro_task_threaded_init(void) @@ -367,10 +492,12 @@ static void retro_task_threaded_deinit(void) static struct retro_task_impl impl_threaded = { retro_task_threaded_push_running, + retro_task_threaded_cancel, retro_task_threaded_reset, retro_task_threaded_wait, retro_task_threaded_gather, retro_task_threaded_find, + retro_task_threaded_retrieve, retro_task_threaded_init, retro_task_threaded_deinit }; @@ -421,6 +548,9 @@ bool task_queue_ctl(enum task_queue_ctl_state state, void *data) return false; } break; + case TASK_QUEUE_CTL_RETRIEVE: + impl_current->retrieve((task_retriever_data_t*)data); + break; case TASK_QUEUE_CTL_CHECK: { #ifdef HAVE_THREADS @@ -452,6 +582,9 @@ bool task_queue_ctl(enum task_queue_ctl_state state, void *data) case TASK_QUEUE_CTL_WAIT: impl_current->wait(); break; + case TASK_QUEUE_CTL_CANCEL: + impl_current->cancel(data); + break; case TASK_QUEUE_CTL_NONE: default: break; @@ -459,3 +592,37 @@ bool task_queue_ctl(enum task_queue_ctl_state state, void *data) return true; } + +void task_queue_cancel_task(void *task) +{ + task_queue_ctl(TASK_QUEUE_CTL_CANCEL, task); +} + +void *task_queue_retriever_info_next(task_retriever_info_t **link) +{ + void *data = NULL; + + /* Grab data and move to next link */ + if (*link) + { + data = (*link)->data; + *link = (*link)->next; + } + + return data; +} + +void task_queue_retriever_info_free(task_retriever_info_t *list) +{ + task_retriever_info_t *info; + + /* Free links including retriever-specific data */ + while (list) + { + info = list->next; + free(list->data); + free(list); + list = info; + } +} + diff --git a/desmume/src/libretro-common/rthreads/gx_pthread.h b/desmume/src/libretro-common/rthreads/gx_pthread.h index 4ca4b09c5..b8f9d8694 100644 --- a/desmume/src/libretro-common/rthreads/gx_pthread.h +++ b/desmume/src/libretro-common/rthreads/gx_pthread.h @@ -60,12 +60,6 @@ #define OSInitCond(cond) LWP_CondInit(cond) #endif -#if 0 -#ifndef OSSignalCond -#define OSSignalCond(cond) LWP_ThreadSignal(cond) -#endif -#endif - #ifndef OSWaitCond #define OSWaitCond(cond, mutex) LWP_CondWait(cond, mutex) #endif @@ -82,10 +76,6 @@ #define OSJoinThread(thread, val) LWP_JoinThread(thread, val) #endif -#ifndef OSSignalCond -#define OSSignalCond(thread) LWP_CondSignal(thread) -#endif - #ifndef OSCreateThread #define OSCreateThread(thread, func, intarg, ptrarg, stackbase, stacksize, priority, attrs) LWP_CreateThread(thread, func, ptrarg, stackbase, stacksize, priority) #endif @@ -177,8 +167,7 @@ static INLINE int pthread_cond_init(pthread_cond_t *cond, static INLINE int pthread_cond_signal(pthread_cond_t *cond) { - OSSignalCond(*cond); - return 0; + return LWP_CondSignal(*cond); } static INLINE int pthread_cond_broadcast(pthread_cond_t *cond) @@ -191,4 +180,6 @@ static INLINE int pthread_cond_destroy(pthread_cond_t *cond) return LWP_CondDestroy(*cond); } +extern int pthread_equal(pthread_t t1, pthread_t t2); + #endif diff --git a/desmume/src/libretro-common/rthreads/rsemaphore.c b/desmume/src/libretro-common/rthreads/rsemaphore.c index 1e7cc852b..9627769a5 100644 --- a/desmume/src/libretro-common/rthreads/rsemaphore.c +++ b/desmume/src/libretro-common/rthreads/rsemaphore.c @@ -59,11 +59,13 @@ ssem_t *ssem_new(int value) return semaphore; error: - if (semaphore->mutex) - slock_free(semaphore->mutex); - semaphore->mutex = NULL; if (semaphore) + { + if (semaphore->mutex) + slock_free(semaphore->mutex); + semaphore->mutex = NULL; free((void*)semaphore); + } return NULL; } diff --git a/desmume/src/libretro-common/rthreads/rthreads.c b/desmume/src/libretro-common/rthreads/rthreads.c index 7d6767cd0..deef2f8d2 100644 --- a/desmume/src/libretro-common/rthreads/rthreads.c +++ b/desmume/src/libretro-common/rthreads/rthreads.c @@ -43,11 +43,15 @@ #include "gx_pthread.h" #elif defined(PSP) #include "psp_pthread.h" +#elif defined(__CELLOS_LV2__) +#include +#include #else #include #include #endif + #ifdef __MACH__ #include #include @@ -219,25 +223,23 @@ bool sthread_isself(sthread_t *thread) **/ slock_t *slock_new(void) { - bool mutex_created = false; slock_t *lock = (slock_t*)calloc(1, sizeof(*lock)); if (!lock) return NULL; #ifdef USE_WIN32_THREADS lock->lock = CreateMutex(NULL, FALSE, NULL); - mutex_created = !!lock->lock; -#else - mutex_created = (pthread_mutex_init(&lock->lock, NULL) == 0); -#endif - - if (!mutex_created) + if (!lock->lock) goto error; +#else + if ((pthread_mutex_init(&lock->lock, NULL) < 0)) + goto error; +#endif return lock; error: - free(lock); + slock_free(lock); return NULL; } diff --git a/desmume/src/libretro-common/streams/file_stream.c b/desmume/src/libretro-common/streams/file_stream.c index d6ee69691..6d74a9a10 100644 --- a/desmume/src/libretro-common/streams/file_stream.c +++ b/desmume/src/libretro-common/streams/file_stream.c @@ -38,27 +38,25 @@ # include # include # endif -#elif defined(VITA) -# include -# include - -#define PSP_O_RDONLY PSP2_O_RDONLY -#define PSP_O_RDWR PSP2_O_RDWR -#define PSP_O_CREAT PSP2_O_CREAT -#define PSP_O_WRONLY PSP2_O_WRONLY -#define PSP_O_TRUNC PSP2_O_TRUNC #else # if defined(PSP) # include # endif # include # include +# if !defined(VITA) # include +# endif # include #endif #ifdef __CELLOS_LV2__ #include +#define O_RDONLY CELL_FS_O_RDONLY +#define O_WRONLY CELL_FS_O_WRONLY +#define O_CREAT CELL_FS_O_CREAT +#define O_TRUNC CELL_FS_O_TRUNC +#define O_RDWR CELL_FS_O_RDWR #else #include #endif @@ -69,10 +67,8 @@ struct RFILE { unsigned hints; -#if defined(PSP) || defined(VITA) +#if defined(PSP) SceUID fd; -#elif defined(__CELLOS_LV2__) - int fd; #else #define HAVE_BUFFERED_IO 1 @@ -126,13 +122,23 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len) switch (mode & 0xff) { - case RFILE_MODE_READ: -#if defined(VITA) || defined(PSP) - mode_int = 0777; + case RFILE_MODE_READ_TEXT: +#if defined(PSP) + mode_int = 0666; + flags = PSP_O_RDONLY; +#else +#if defined(HAVE_BUFFERED_IO) + if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) + mode_str = "r"; +#endif + /* No "else" here */ + flags = O_RDONLY; +#endif + break; + case RFILE_MODE_READ: +#if defined(PSP) + mode_int = 0666; flags = PSP_O_RDONLY; -#elif defined(__CELLOS_LV2__) - mode_int = 0777; - flags = CELL_FS_O_RDONLY; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) @@ -143,12 +149,9 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len) #endif break; case RFILE_MODE_WRITE: -#if defined(VITA) || defined(PSP) - mode_int = 0777; +#if defined(PSP) + mode_int = 0666; flags = PSP_O_CREAT | PSP_O_WRONLY | PSP_O_TRUNC; -#elif defined(__CELLOS_LV2__) - mode_int = 0777; - flags = CELL_FS_O_CREAT | CELL_FS_O_WRONLY | CELL_FS_O_TRUNC; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) @@ -164,12 +167,9 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len) #endif break; case RFILE_MODE_READ_WRITE: -#if defined(VITA) || defined(PSP) - mode_int = 0777; +#if defined(PSP) + mode_int = 0666; flags = PSP_O_RDWR; -#elif defined(__CELLOS_LV2__) - mode_int = 0777; - flags = CELL_FS_O_RDWR; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) @@ -186,10 +186,8 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len) break; } -#if defined(VITA) || defined(PSP) +#if defined(PSP) stream->fd = sceIoOpen(path, flags, mode_int); -#elif defined(__CELLOS_LV2__) - cellFsOpen(path, flags, &stream->fd, NULL, 0); #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) @@ -226,7 +224,7 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len) } #endif -#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) +#if defined(PSP) if (stream->fd == -1) goto error; #endif @@ -238,20 +236,81 @@ error: return NULL; } +char *filestream_getline(RFILE *stream) +{ + char* newline = (char*)malloc(9); + char* newline_tmp = NULL; + size_t cur_size = 8; + size_t idx = 0; + int in = filestream_getc(stream); + + if (!newline) + return NULL; + + while (in != EOF && in != '\n') + { + if (idx == cur_size) + { + cur_size *= 2; + newline_tmp = (char*)realloc(newline, cur_size + 1); + + if (!newline_tmp) + { + free(newline); + return NULL; + } + + newline = newline_tmp; + } + + newline[idx++] = in; + in = filestream_getc(stream); + } + + newline[idx] = '\0'; + return newline; +} + +char *filestream_gets(RFILE *stream, char *s, size_t len) +{ + if (!stream) + return NULL; +#if defined(HAVE_BUFFERED_IO) + return fgets(s, len, stream->fp); +#elif defined(PSP) + if(filestream_read(stream,s,len)==len) + return s; + return NULL; +#else + return gets(s); +#endif +} + +int filestream_getc(RFILE *stream) +{ + char c = 0; + (void)c; + if (!stream) + return 0; +#if defined(HAVE_BUFFERED_IO) + return fgetc(stream->fp); +#elif defined(PSP) + if(filestream_read(stream, &c, 1) == 1) + return (int)c; + return EOF; +#else + return getc(stream->fd); +#endif +} + ssize_t filestream_seek(RFILE *stream, ssize_t offset, int whence) { -#if defined(__CELLOS_LV2__) - uint64_t pos = 0; -#endif if (!stream) goto error; -#if defined(VITA) || defined(PSP) +#if defined(PSP) if (sceIoLseek(stream->fd, (SceOff)offset, whence) == -1) goto error; -#elif defined(__CELLOS_LV2__) - if (cellFsLseek(stream->fd, offset, whence, &pos) != CELL_FS_SUCCEEDED) - goto error; #else #if defined(HAVE_BUFFERED_IO) @@ -305,19 +364,25 @@ error: return -1; } +int filestream_eof(RFILE *stream) +{ + size_t current_position = filestream_tell(stream); + size_t end_position = filestream_seek(stream, 0, SEEK_END); + + filestream_seek(stream, current_position, SEEK_SET); + + if (current_position >= end_position) + return 1; + return 0; +} + ssize_t filestream_tell(RFILE *stream) { -#if defined(__CELLOS_LV2__) - uint64_t pos = 0; -#endif if (!stream) goto error; -#if defined(VITA) || defined(PSP) +#if defined(PSP) if (sceIoLseek(stream->fd, 0, SEEK_CUR) < 0) goto error; -#elif defined(__CELLOS_LV2__) - if (cellFsLseek(stream->fd, 0, CELL_FS_SEEK_CUR, &pos) != CELL_FS_SUCCEEDED) - goto error; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) @@ -348,13 +413,8 @@ ssize_t filestream_read(RFILE *stream, void *s, size_t len) { if (!stream || !s) goto error; -#if defined(VITA) || defined(PSP) +#if defined(PSP) return sceIoRead(stream->fd, s, len); -#elif defined(__CELLOS_LV2__) - uint64_t bytes_written; - if (cellFsRead(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED) - goto error; - return bytes_written; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) @@ -386,13 +446,8 @@ ssize_t filestream_write(RFILE *stream, const void *s, size_t len) { if (!stream) goto error; -#if defined(VITA) || defined(PSP) +#if defined(PSP) return sceIoWrite(stream->fd, s, len); -#elif defined(__CELLOS_LV2__) - uint64_t bytes_written; - if (cellFsWrite(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED) - goto error; - return bytes_written; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) @@ -427,12 +482,9 @@ int filestream_close(RFILE *stream) if (!stream) goto error; -#if defined(VITA) || defined(PSP) +#if defined(PSP) if (stream->fd > 0) sceIoClose(stream->fd); -#elif defined(__CELLOS_LV2__) - if (stream->fd > 0) - cellFsClose(stream->fd); #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) @@ -477,11 +529,7 @@ int filestream_read_file(const char *path, void **buf, ssize_t *len) 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; } @@ -502,11 +550,7 @@ int filestream_read_file(const char *path, void **buf, ssize_t *len) ret = filestream_read(file, content_buf, content_buf_size); if (ret < 0) { -#if __STDC_VERSION__ >= 199901L - fprintf(stderr, "%s: Failed to read %s: %s\n", __FUNCTION__, path, strerror(errno)); -#else fprintf(stderr, "Failed to read %s: %s\n", path, strerror(errno)); -#endif goto error; } diff --git a/desmume/src/libretro-common/streams/interface_stream.c b/desmume/src/libretro-common/streams/interface_stream.c index 995ac218a..a1f4b159e 100644 --- a/desmume/src/libretro-common/streams/interface_stream.c +++ b/desmume/src/libretro-common/streams/interface_stream.c @@ -198,8 +198,7 @@ char *intfstream_gets(intfstream_internal_t *intf, switch (intf->type) { case INTFSTREAM_FILE: - /* unimplemented */ - break; + return filestream_gets(intf->file.fp, buffer, len); case INTFSTREAM_MEMORY: return memstream_gets(intf->memory.fp, buffer, len); } @@ -215,8 +214,7 @@ int intfstream_getc(intfstream_internal_t *intf) switch (intf->type) { case INTFSTREAM_FILE: - /* unimplemented */ - break; + return filestream_getc(intf->file.fp); case INTFSTREAM_MEMORY: return memstream_getc(intf->memory.fp); } diff --git a/desmume/src/libretro-common/string/stdstring.c b/desmume/src/libretro-common/string/stdstring.c index dbdcbc3a6..c114f1ed1 100644 --- a/desmume/src/libretro-common/string/stdstring.c +++ b/desmume/src/libretro-common/string/stdstring.c @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include #include #include @@ -59,6 +60,21 @@ char *string_to_lower(char *s) return s; } +char *string_ucwords(char *s) +{ + char *cs = (char *)s; + for ( ; *cs != '\0'; cs++) + { + if (*cs == ' ') + { + *(cs+1) = toupper(*(cs+1)); + } + } + + s[0] = toupper(s[0]); + return s; +} + char *string_replace_substring(const char *in, const char *pattern, const char *replacement) { @@ -102,3 +118,52 @@ char *string_replace_substring(const char *in, return out; } + +/* Non-GPL licensed versions of whitespace trimming: + * http://stackoverflow.com/questions/656542/trim-a-string-in-c + */ + +/* Remove leading whitespaces */ +char *string_trim_whitespace_left(char *const s) +{ + if(s && *s) + { + size_t len = strlen(s); + char *cur = s; + + while(*cur && isspace(*cur)) + ++cur, --len; + + if(s != cur) + memmove(s, cur, len + 1); + + } + + return s; +} + +/* Remove trailing whitespaces */ +char *string_trim_whitespace_right(char *const s) +{ + if(s && *s) + { + size_t len = strlen(s); + char *cur = s + len - 1; + + while(cur != s && isspace(*cur)) + --cur, --len; + + cur[isspace(*cur) ? 0 : 1] = '\0'; + } + + return s; +} + +/* Remove leading and trailing whitespaces */ +char *string_trim_whitespace(char *const s) +{ + string_trim_whitespace_right(s); /* order matters */ + string_trim_whitespace_left(s); + + return s; +} diff --git a/desmume/src/libretro-common/vulkan/vulkan_symbol_wrapper.c b/desmume/src/libretro-common/vulkan/vulkan_symbol_wrapper.c new file mode 100644 index 000000000..abf02dca3 --- /dev/null +++ b/desmume/src/libretro-common/vulkan/vulkan_symbol_wrapper.c @@ -0,0 +1,485 @@ + +/* This header is autogenerated by vulkan_loader_generator.py */ +#include + +PFN_vkCreateInstance vulkan_symbol_wrapper_vkCreateInstance; +PFN_vkEnumerateInstanceExtensionProperties vulkan_symbol_wrapper_vkEnumerateInstanceExtensionProperties; +PFN_vkEnumerateInstanceLayerProperties vulkan_symbol_wrapper_vkEnumerateInstanceLayerProperties; +PFN_vkDestroyInstance vulkan_symbol_wrapper_vkDestroyInstance; +PFN_vkEnumeratePhysicalDevices vulkan_symbol_wrapper_vkEnumeratePhysicalDevices; +PFN_vkGetPhysicalDeviceFeatures vulkan_symbol_wrapper_vkGetPhysicalDeviceFeatures; +PFN_vkGetPhysicalDeviceFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceFormatProperties; +PFN_vkGetPhysicalDeviceImageFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceImageFormatProperties; +PFN_vkGetPhysicalDeviceProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceProperties; +PFN_vkGetPhysicalDeviceQueueFamilyProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceQueueFamilyProperties; +PFN_vkGetPhysicalDeviceMemoryProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceMemoryProperties; +PFN_vkGetDeviceProcAddr vulkan_symbol_wrapper_vkGetDeviceProcAddr; +PFN_vkCreateDevice vulkan_symbol_wrapper_vkCreateDevice; +PFN_vkDestroyDevice vulkan_symbol_wrapper_vkDestroyDevice; +PFN_vkEnumerateDeviceExtensionProperties vulkan_symbol_wrapper_vkEnumerateDeviceExtensionProperties; +PFN_vkEnumerateDeviceLayerProperties vulkan_symbol_wrapper_vkEnumerateDeviceLayerProperties; +PFN_vkGetDeviceQueue vulkan_symbol_wrapper_vkGetDeviceQueue; +PFN_vkQueueSubmit vulkan_symbol_wrapper_vkQueueSubmit; +PFN_vkQueueWaitIdle vulkan_symbol_wrapper_vkQueueWaitIdle; +PFN_vkDeviceWaitIdle vulkan_symbol_wrapper_vkDeviceWaitIdle; +PFN_vkAllocateMemory vulkan_symbol_wrapper_vkAllocateMemory; +PFN_vkFreeMemory vulkan_symbol_wrapper_vkFreeMemory; +PFN_vkMapMemory vulkan_symbol_wrapper_vkMapMemory; +PFN_vkUnmapMemory vulkan_symbol_wrapper_vkUnmapMemory; +PFN_vkFlushMappedMemoryRanges vulkan_symbol_wrapper_vkFlushMappedMemoryRanges; +PFN_vkInvalidateMappedMemoryRanges vulkan_symbol_wrapper_vkInvalidateMappedMemoryRanges; +PFN_vkGetDeviceMemoryCommitment vulkan_symbol_wrapper_vkGetDeviceMemoryCommitment; +PFN_vkBindBufferMemory vulkan_symbol_wrapper_vkBindBufferMemory; +PFN_vkBindImageMemory vulkan_symbol_wrapper_vkBindImageMemory; +PFN_vkGetBufferMemoryRequirements vulkan_symbol_wrapper_vkGetBufferMemoryRequirements; +PFN_vkGetImageMemoryRequirements vulkan_symbol_wrapper_vkGetImageMemoryRequirements; +PFN_vkGetImageSparseMemoryRequirements vulkan_symbol_wrapper_vkGetImageSparseMemoryRequirements; +PFN_vkGetPhysicalDeviceSparseImageFormatProperties vulkan_symbol_wrapper_vkGetPhysicalDeviceSparseImageFormatProperties; +PFN_vkQueueBindSparse vulkan_symbol_wrapper_vkQueueBindSparse; +PFN_vkCreateFence vulkan_symbol_wrapper_vkCreateFence; +PFN_vkDestroyFence vulkan_symbol_wrapper_vkDestroyFence; +PFN_vkResetFences vulkan_symbol_wrapper_vkResetFences; +PFN_vkGetFenceStatus vulkan_symbol_wrapper_vkGetFenceStatus; +PFN_vkWaitForFences vulkan_symbol_wrapper_vkWaitForFences; +PFN_vkCreateSemaphore vulkan_symbol_wrapper_vkCreateSemaphore; +PFN_vkDestroySemaphore vulkan_symbol_wrapper_vkDestroySemaphore; +PFN_vkCreateEvent vulkan_symbol_wrapper_vkCreateEvent; +PFN_vkDestroyEvent vulkan_symbol_wrapper_vkDestroyEvent; +PFN_vkGetEventStatus vulkan_symbol_wrapper_vkGetEventStatus; +PFN_vkSetEvent vulkan_symbol_wrapper_vkSetEvent; +PFN_vkResetEvent vulkan_symbol_wrapper_vkResetEvent; +PFN_vkCreateQueryPool vulkan_symbol_wrapper_vkCreateQueryPool; +PFN_vkDestroyQueryPool vulkan_symbol_wrapper_vkDestroyQueryPool; +PFN_vkGetQueryPoolResults vulkan_symbol_wrapper_vkGetQueryPoolResults; +PFN_vkCreateBuffer vulkan_symbol_wrapper_vkCreateBuffer; +PFN_vkDestroyBuffer vulkan_symbol_wrapper_vkDestroyBuffer; +PFN_vkCreateBufferView vulkan_symbol_wrapper_vkCreateBufferView; +PFN_vkDestroyBufferView vulkan_symbol_wrapper_vkDestroyBufferView; +PFN_vkCreateImage vulkan_symbol_wrapper_vkCreateImage; +PFN_vkDestroyImage vulkan_symbol_wrapper_vkDestroyImage; +PFN_vkGetImageSubresourceLayout vulkan_symbol_wrapper_vkGetImageSubresourceLayout; +PFN_vkCreateImageView vulkan_symbol_wrapper_vkCreateImageView; +PFN_vkDestroyImageView vulkan_symbol_wrapper_vkDestroyImageView; +PFN_vkCreateShaderModule vulkan_symbol_wrapper_vkCreateShaderModule; +PFN_vkDestroyShaderModule vulkan_symbol_wrapper_vkDestroyShaderModule; +PFN_vkCreatePipelineCache vulkan_symbol_wrapper_vkCreatePipelineCache; +PFN_vkDestroyPipelineCache vulkan_symbol_wrapper_vkDestroyPipelineCache; +PFN_vkGetPipelineCacheData vulkan_symbol_wrapper_vkGetPipelineCacheData; +PFN_vkMergePipelineCaches vulkan_symbol_wrapper_vkMergePipelineCaches; +PFN_vkCreateGraphicsPipelines vulkan_symbol_wrapper_vkCreateGraphicsPipelines; +PFN_vkCreateComputePipelines vulkan_symbol_wrapper_vkCreateComputePipelines; +PFN_vkDestroyPipeline vulkan_symbol_wrapper_vkDestroyPipeline; +PFN_vkCreatePipelineLayout vulkan_symbol_wrapper_vkCreatePipelineLayout; +PFN_vkDestroyPipelineLayout vulkan_symbol_wrapper_vkDestroyPipelineLayout; +PFN_vkCreateSampler vulkan_symbol_wrapper_vkCreateSampler; +PFN_vkDestroySampler vulkan_symbol_wrapper_vkDestroySampler; +PFN_vkCreateDescriptorSetLayout vulkan_symbol_wrapper_vkCreateDescriptorSetLayout; +PFN_vkDestroyDescriptorSetLayout vulkan_symbol_wrapper_vkDestroyDescriptorSetLayout; +PFN_vkCreateDescriptorPool vulkan_symbol_wrapper_vkCreateDescriptorPool; +PFN_vkDestroyDescriptorPool vulkan_symbol_wrapper_vkDestroyDescriptorPool; +PFN_vkResetDescriptorPool vulkan_symbol_wrapper_vkResetDescriptorPool; +PFN_vkAllocateDescriptorSets vulkan_symbol_wrapper_vkAllocateDescriptorSets; +PFN_vkFreeDescriptorSets vulkan_symbol_wrapper_vkFreeDescriptorSets; +PFN_vkUpdateDescriptorSets vulkan_symbol_wrapper_vkUpdateDescriptorSets; +PFN_vkCreateFramebuffer vulkan_symbol_wrapper_vkCreateFramebuffer; +PFN_vkDestroyFramebuffer vulkan_symbol_wrapper_vkDestroyFramebuffer; +PFN_vkCreateRenderPass vulkan_symbol_wrapper_vkCreateRenderPass; +PFN_vkDestroyRenderPass vulkan_symbol_wrapper_vkDestroyRenderPass; +PFN_vkGetRenderAreaGranularity vulkan_symbol_wrapper_vkGetRenderAreaGranularity; +PFN_vkCreateCommandPool vulkan_symbol_wrapper_vkCreateCommandPool; +PFN_vkDestroyCommandPool vulkan_symbol_wrapper_vkDestroyCommandPool; +PFN_vkResetCommandPool vulkan_symbol_wrapper_vkResetCommandPool; +PFN_vkAllocateCommandBuffers vulkan_symbol_wrapper_vkAllocateCommandBuffers; +PFN_vkFreeCommandBuffers vulkan_symbol_wrapper_vkFreeCommandBuffers; +PFN_vkBeginCommandBuffer vulkan_symbol_wrapper_vkBeginCommandBuffer; +PFN_vkEndCommandBuffer vulkan_symbol_wrapper_vkEndCommandBuffer; +PFN_vkResetCommandBuffer vulkan_symbol_wrapper_vkResetCommandBuffer; +PFN_vkCmdBindPipeline vulkan_symbol_wrapper_vkCmdBindPipeline; +PFN_vkCmdSetViewport vulkan_symbol_wrapper_vkCmdSetViewport; +PFN_vkCmdSetScissor vulkan_symbol_wrapper_vkCmdSetScissor; +PFN_vkCmdSetLineWidth vulkan_symbol_wrapper_vkCmdSetLineWidth; +PFN_vkCmdSetDepthBias vulkan_symbol_wrapper_vkCmdSetDepthBias; +PFN_vkCmdSetBlendConstants vulkan_symbol_wrapper_vkCmdSetBlendConstants; +PFN_vkCmdSetDepthBounds vulkan_symbol_wrapper_vkCmdSetDepthBounds; +PFN_vkCmdSetStencilCompareMask vulkan_symbol_wrapper_vkCmdSetStencilCompareMask; +PFN_vkCmdSetStencilWriteMask vulkan_symbol_wrapper_vkCmdSetStencilWriteMask; +PFN_vkCmdSetStencilReference vulkan_symbol_wrapper_vkCmdSetStencilReference; +PFN_vkCmdBindDescriptorSets vulkan_symbol_wrapper_vkCmdBindDescriptorSets; +PFN_vkCmdBindIndexBuffer vulkan_symbol_wrapper_vkCmdBindIndexBuffer; +PFN_vkCmdBindVertexBuffers vulkan_symbol_wrapper_vkCmdBindVertexBuffers; +PFN_vkCmdDraw vulkan_symbol_wrapper_vkCmdDraw; +PFN_vkCmdDrawIndexed vulkan_symbol_wrapper_vkCmdDrawIndexed; +PFN_vkCmdDrawIndirect vulkan_symbol_wrapper_vkCmdDrawIndirect; +PFN_vkCmdDrawIndexedIndirect vulkan_symbol_wrapper_vkCmdDrawIndexedIndirect; +PFN_vkCmdDispatch vulkan_symbol_wrapper_vkCmdDispatch; +PFN_vkCmdDispatchIndirect vulkan_symbol_wrapper_vkCmdDispatchIndirect; +PFN_vkCmdCopyBuffer vulkan_symbol_wrapper_vkCmdCopyBuffer; +PFN_vkCmdCopyImage vulkan_symbol_wrapper_vkCmdCopyImage; +PFN_vkCmdBlitImage vulkan_symbol_wrapper_vkCmdBlitImage; +PFN_vkCmdCopyBufferToImage vulkan_symbol_wrapper_vkCmdCopyBufferToImage; +PFN_vkCmdCopyImageToBuffer vulkan_symbol_wrapper_vkCmdCopyImageToBuffer; +PFN_vkCmdUpdateBuffer vulkan_symbol_wrapper_vkCmdUpdateBuffer; +PFN_vkCmdFillBuffer vulkan_symbol_wrapper_vkCmdFillBuffer; +PFN_vkCmdClearColorImage vulkan_symbol_wrapper_vkCmdClearColorImage; +PFN_vkCmdClearDepthStencilImage vulkan_symbol_wrapper_vkCmdClearDepthStencilImage; +PFN_vkCmdClearAttachments vulkan_symbol_wrapper_vkCmdClearAttachments; +PFN_vkCmdResolveImage vulkan_symbol_wrapper_vkCmdResolveImage; +PFN_vkCmdSetEvent vulkan_symbol_wrapper_vkCmdSetEvent; +PFN_vkCmdResetEvent vulkan_symbol_wrapper_vkCmdResetEvent; +PFN_vkCmdWaitEvents vulkan_symbol_wrapper_vkCmdWaitEvents; +PFN_vkCmdPipelineBarrier vulkan_symbol_wrapper_vkCmdPipelineBarrier; +PFN_vkCmdBeginQuery vulkan_symbol_wrapper_vkCmdBeginQuery; +PFN_vkCmdEndQuery vulkan_symbol_wrapper_vkCmdEndQuery; +PFN_vkCmdResetQueryPool vulkan_symbol_wrapper_vkCmdResetQueryPool; +PFN_vkCmdWriteTimestamp vulkan_symbol_wrapper_vkCmdWriteTimestamp; +PFN_vkCmdCopyQueryPoolResults vulkan_symbol_wrapper_vkCmdCopyQueryPoolResults; +PFN_vkCmdPushConstants vulkan_symbol_wrapper_vkCmdPushConstants; +PFN_vkCmdBeginRenderPass vulkan_symbol_wrapper_vkCmdBeginRenderPass; +PFN_vkCmdNextSubpass vulkan_symbol_wrapper_vkCmdNextSubpass; +PFN_vkCmdEndRenderPass vulkan_symbol_wrapper_vkCmdEndRenderPass; +PFN_vkCmdExecuteCommands vulkan_symbol_wrapper_vkCmdExecuteCommands; +PFN_vkDestroySurfaceKHR vulkan_symbol_wrapper_vkDestroySurfaceKHR; +PFN_vkGetPhysicalDeviceSurfaceSupportKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceSupportKHR; +PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceCapabilitiesKHR; +PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfaceFormatsKHR; +PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceSurfacePresentModesKHR; +PFN_vkCreateSwapchainKHR vulkan_symbol_wrapper_vkCreateSwapchainKHR; +PFN_vkDestroySwapchainKHR vulkan_symbol_wrapper_vkDestroySwapchainKHR; +PFN_vkGetSwapchainImagesKHR vulkan_symbol_wrapper_vkGetSwapchainImagesKHR; +PFN_vkAcquireNextImageKHR vulkan_symbol_wrapper_vkAcquireNextImageKHR; +PFN_vkQueuePresentKHR vulkan_symbol_wrapper_vkQueuePresentKHR; +PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceDisplayPropertiesKHR; +PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vulkan_symbol_wrapper_vkGetPhysicalDeviceDisplayPlanePropertiesKHR; +PFN_vkGetDisplayPlaneSupportedDisplaysKHR vulkan_symbol_wrapper_vkGetDisplayPlaneSupportedDisplaysKHR; +PFN_vkGetDisplayModePropertiesKHR vulkan_symbol_wrapper_vkGetDisplayModePropertiesKHR; +PFN_vkCreateDisplayModeKHR vulkan_symbol_wrapper_vkCreateDisplayModeKHR; +PFN_vkGetDisplayPlaneCapabilitiesKHR vulkan_symbol_wrapper_vkGetDisplayPlaneCapabilitiesKHR; +PFN_vkCreateDisplayPlaneSurfaceKHR vulkan_symbol_wrapper_vkCreateDisplayPlaneSurfaceKHR; +PFN_vkCreateSharedSwapchainsKHR vulkan_symbol_wrapper_vkCreateSharedSwapchainsKHR; +PFN_vkCreateDebugReportCallbackEXT vulkan_symbol_wrapper_vkCreateDebugReportCallbackEXT; +PFN_vkDestroyDebugReportCallbackEXT vulkan_symbol_wrapper_vkDestroyDebugReportCallbackEXT; +PFN_vkDebugReportMessageEXT vulkan_symbol_wrapper_vkDebugReportMessageEXT; +PFN_vkDebugMarkerSetObjectTagEXT vulkan_symbol_wrapper_vkDebugMarkerSetObjectTagEXT; +PFN_vkDebugMarkerSetObjectNameEXT vulkan_symbol_wrapper_vkDebugMarkerSetObjectNameEXT; +PFN_vkCmdDebugMarkerBeginEXT vulkan_symbol_wrapper_vkCmdDebugMarkerBeginEXT; +PFN_vkCmdDebugMarkerEndEXT vulkan_symbol_wrapper_vkCmdDebugMarkerEndEXT; +PFN_vkCmdDebugMarkerInsertEXT vulkan_symbol_wrapper_vkCmdDebugMarkerInsertEXT; + +static PFN_vkGetInstanceProcAddr GetInstanceProcAddr; +void vulkan_symbol_wrapper_init(PFN_vkGetInstanceProcAddr get_instance_proc_addr) +{ + GetInstanceProcAddr = get_instance_proc_addr; +} + +PFN_vkGetInstanceProcAddr vulkan_symbol_wrapper_instance_proc_addr(void) +{ + return GetInstanceProcAddr; +} + + +VkBool32 vulkan_symbol_wrapper_load_instance_symbol(VkInstance instance, const char *name, PFN_vkVoidFunction *ppSymbol) +{ + *ppSymbol = GetInstanceProcAddr(instance, name); + return *ppSymbol != NULL; +} + +VkBool32 vulkan_symbol_wrapper_load_device_symbol(VkDevice device, const char *name, PFN_vkVoidFunction *ppSymbol) +{ + *ppSymbol = vkGetDeviceProcAddr(device, name); + return *ppSymbol != NULL; +} + +VkBool32 vulkan_symbol_wrapper_load_global_symbols(void) +{ + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(NULL, "vkCreateInstance", vkCreateInstance)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(NULL, "vkEnumerateInstanceExtensionProperties", vkEnumerateInstanceExtensionProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(NULL, "vkEnumerateInstanceLayerProperties", vkEnumerateInstanceLayerProperties)) return VK_FALSE; + return VK_TRUE; +} + +VkBool32 vulkan_symbol_wrapper_load_core_symbols(VkInstance instance) +{ + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyInstance", vkDestroyInstance)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkEnumeratePhysicalDevices", vkEnumeratePhysicalDevices)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPhysicalDeviceFeatures", vkGetPhysicalDeviceFeatures)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPhysicalDeviceFormatProperties", vkGetPhysicalDeviceFormatProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPhysicalDeviceImageFormatProperties", vkGetPhysicalDeviceImageFormatProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPhysicalDeviceProperties", vkGetPhysicalDeviceProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPhysicalDeviceQueueFamilyProperties", vkGetPhysicalDeviceQueueFamilyProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPhysicalDeviceMemoryProperties", vkGetPhysicalDeviceMemoryProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetDeviceProcAddr", vkGetDeviceProcAddr)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateDevice", vkCreateDevice)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyDevice", vkDestroyDevice)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkEnumerateDeviceExtensionProperties", vkEnumerateDeviceExtensionProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkEnumerateDeviceLayerProperties", vkEnumerateDeviceLayerProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetDeviceQueue", vkGetDeviceQueue)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkQueueSubmit", vkQueueSubmit)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkQueueWaitIdle", vkQueueWaitIdle)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDeviceWaitIdle", vkDeviceWaitIdle)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkAllocateMemory", vkAllocateMemory)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkFreeMemory", vkFreeMemory)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkMapMemory", vkMapMemory)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkUnmapMemory", vkUnmapMemory)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkFlushMappedMemoryRanges", vkFlushMappedMemoryRanges)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkInvalidateMappedMemoryRanges", vkInvalidateMappedMemoryRanges)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetDeviceMemoryCommitment", vkGetDeviceMemoryCommitment)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkBindBufferMemory", vkBindBufferMemory)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkBindImageMemory", vkBindImageMemory)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetBufferMemoryRequirements", vkGetBufferMemoryRequirements)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetImageMemoryRequirements", vkGetImageMemoryRequirements)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetImageSparseMemoryRequirements", vkGetImageSparseMemoryRequirements)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPhysicalDeviceSparseImageFormatProperties", vkGetPhysicalDeviceSparseImageFormatProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkQueueBindSparse", vkQueueBindSparse)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateFence", vkCreateFence)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyFence", vkDestroyFence)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkResetFences", vkResetFences)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetFenceStatus", vkGetFenceStatus)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkWaitForFences", vkWaitForFences)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateSemaphore", vkCreateSemaphore)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroySemaphore", vkDestroySemaphore)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateEvent", vkCreateEvent)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyEvent", vkDestroyEvent)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetEventStatus", vkGetEventStatus)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkSetEvent", vkSetEvent)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkResetEvent", vkResetEvent)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateQueryPool", vkCreateQueryPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyQueryPool", vkDestroyQueryPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetQueryPoolResults", vkGetQueryPoolResults)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateBuffer", vkCreateBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyBuffer", vkDestroyBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateBufferView", vkCreateBufferView)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyBufferView", vkDestroyBufferView)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateImage", vkCreateImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyImage", vkDestroyImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetImageSubresourceLayout", vkGetImageSubresourceLayout)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateImageView", vkCreateImageView)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyImageView", vkDestroyImageView)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateShaderModule", vkCreateShaderModule)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyShaderModule", vkDestroyShaderModule)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreatePipelineCache", vkCreatePipelineCache)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyPipelineCache", vkDestroyPipelineCache)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPipelineCacheData", vkGetPipelineCacheData)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkMergePipelineCaches", vkMergePipelineCaches)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateGraphicsPipelines", vkCreateGraphicsPipelines)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateComputePipelines", vkCreateComputePipelines)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyPipeline", vkDestroyPipeline)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreatePipelineLayout", vkCreatePipelineLayout)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyPipelineLayout", vkDestroyPipelineLayout)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateSampler", vkCreateSampler)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroySampler", vkDestroySampler)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateDescriptorSetLayout", vkCreateDescriptorSetLayout)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyDescriptorSetLayout", vkDestroyDescriptorSetLayout)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateDescriptorPool", vkCreateDescriptorPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyDescriptorPool", vkDestroyDescriptorPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkResetDescriptorPool", vkResetDescriptorPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkAllocateDescriptorSets", vkAllocateDescriptorSets)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkFreeDescriptorSets", vkFreeDescriptorSets)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkUpdateDescriptorSets", vkUpdateDescriptorSets)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateFramebuffer", vkCreateFramebuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyFramebuffer", vkDestroyFramebuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateRenderPass", vkCreateRenderPass)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyRenderPass", vkDestroyRenderPass)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetRenderAreaGranularity", vkGetRenderAreaGranularity)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateCommandPool", vkCreateCommandPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyCommandPool", vkDestroyCommandPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkResetCommandPool", vkResetCommandPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkAllocateCommandBuffers", vkAllocateCommandBuffers)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkFreeCommandBuffers", vkFreeCommandBuffers)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkBeginCommandBuffer", vkBeginCommandBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkEndCommandBuffer", vkEndCommandBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkResetCommandBuffer", vkResetCommandBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdBindPipeline", vkCmdBindPipeline)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdSetViewport", vkCmdSetViewport)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdSetScissor", vkCmdSetScissor)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdSetLineWidth", vkCmdSetLineWidth)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdSetDepthBias", vkCmdSetDepthBias)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdSetBlendConstants", vkCmdSetBlendConstants)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdSetDepthBounds", vkCmdSetDepthBounds)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdSetStencilCompareMask", vkCmdSetStencilCompareMask)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdSetStencilWriteMask", vkCmdSetStencilWriteMask)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdSetStencilReference", vkCmdSetStencilReference)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdBindDescriptorSets", vkCmdBindDescriptorSets)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdBindIndexBuffer", vkCmdBindIndexBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdBindVertexBuffers", vkCmdBindVertexBuffers)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdDraw", vkCmdDraw)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdDrawIndexed", vkCmdDrawIndexed)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdDrawIndirect", vkCmdDrawIndirect)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdDrawIndexedIndirect", vkCmdDrawIndexedIndirect)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdDispatch", vkCmdDispatch)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdDispatchIndirect", vkCmdDispatchIndirect)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdCopyBuffer", vkCmdCopyBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdCopyImage", vkCmdCopyImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdBlitImage", vkCmdBlitImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdCopyBufferToImage", vkCmdCopyBufferToImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdCopyImageToBuffer", vkCmdCopyImageToBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdUpdateBuffer", vkCmdUpdateBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdFillBuffer", vkCmdFillBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdClearColorImage", vkCmdClearColorImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdClearDepthStencilImage", vkCmdClearDepthStencilImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdClearAttachments", vkCmdClearAttachments)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdResolveImage", vkCmdResolveImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdSetEvent", vkCmdSetEvent)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdResetEvent", vkCmdResetEvent)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdWaitEvents", vkCmdWaitEvents)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdPipelineBarrier", vkCmdPipelineBarrier)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdBeginQuery", vkCmdBeginQuery)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdEndQuery", vkCmdEndQuery)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdResetQueryPool", vkCmdResetQueryPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdWriteTimestamp", vkCmdWriteTimestamp)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdCopyQueryPoolResults", vkCmdCopyQueryPoolResults)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdPushConstants", vkCmdPushConstants)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdBeginRenderPass", vkCmdBeginRenderPass)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdNextSubpass", vkCmdNextSubpass)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdEndRenderPass", vkCmdEndRenderPass)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCmdExecuteCommands", vkCmdExecuteCommands)) return VK_FALSE; + return VK_TRUE; +} + +VkBool32 vulkan_symbol_wrapper_load_core_instance_symbols(VkInstance instance) +{ + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkDestroyInstance", vkDestroyInstance)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkEnumeratePhysicalDevices", vkEnumeratePhysicalDevices)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPhysicalDeviceFeatures", vkGetPhysicalDeviceFeatures)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPhysicalDeviceFormatProperties", vkGetPhysicalDeviceFormatProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPhysicalDeviceImageFormatProperties", vkGetPhysicalDeviceImageFormatProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPhysicalDeviceProperties", vkGetPhysicalDeviceProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPhysicalDeviceQueueFamilyProperties", vkGetPhysicalDeviceQueueFamilyProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPhysicalDeviceMemoryProperties", vkGetPhysicalDeviceMemoryProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetDeviceProcAddr", vkGetDeviceProcAddr)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkCreateDevice", vkCreateDevice)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkEnumerateDeviceExtensionProperties", vkEnumerateDeviceExtensionProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkEnumerateDeviceLayerProperties", vkEnumerateDeviceLayerProperties)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "vkGetPhysicalDeviceSparseImageFormatProperties", vkGetPhysicalDeviceSparseImageFormatProperties)) return VK_FALSE; + return VK_TRUE; +} + +VkBool32 vulkan_symbol_wrapper_load_core_device_symbols(VkDevice device) +{ + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyDevice", vkDestroyDevice)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkGetDeviceQueue", vkGetDeviceQueue)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkQueueSubmit", vkQueueSubmit)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkQueueWaitIdle", vkQueueWaitIdle)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDeviceWaitIdle", vkDeviceWaitIdle)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkAllocateMemory", vkAllocateMemory)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkFreeMemory", vkFreeMemory)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkMapMemory", vkMapMemory)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkUnmapMemory", vkUnmapMemory)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkFlushMappedMemoryRanges", vkFlushMappedMemoryRanges)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkInvalidateMappedMemoryRanges", vkInvalidateMappedMemoryRanges)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkGetDeviceMemoryCommitment", vkGetDeviceMemoryCommitment)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkBindBufferMemory", vkBindBufferMemory)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkBindImageMemory", vkBindImageMemory)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkGetBufferMemoryRequirements", vkGetBufferMemoryRequirements)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkGetImageMemoryRequirements", vkGetImageMemoryRequirements)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkGetImageSparseMemoryRequirements", vkGetImageSparseMemoryRequirements)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkQueueBindSparse", vkQueueBindSparse)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateFence", vkCreateFence)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyFence", vkDestroyFence)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkResetFences", vkResetFences)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkGetFenceStatus", vkGetFenceStatus)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkWaitForFences", vkWaitForFences)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateSemaphore", vkCreateSemaphore)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroySemaphore", vkDestroySemaphore)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateEvent", vkCreateEvent)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyEvent", vkDestroyEvent)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkGetEventStatus", vkGetEventStatus)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkSetEvent", vkSetEvent)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkResetEvent", vkResetEvent)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateQueryPool", vkCreateQueryPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyQueryPool", vkDestroyQueryPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkGetQueryPoolResults", vkGetQueryPoolResults)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateBuffer", vkCreateBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyBuffer", vkDestroyBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateBufferView", vkCreateBufferView)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyBufferView", vkDestroyBufferView)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateImage", vkCreateImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyImage", vkDestroyImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkGetImageSubresourceLayout", vkGetImageSubresourceLayout)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateImageView", vkCreateImageView)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyImageView", vkDestroyImageView)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateShaderModule", vkCreateShaderModule)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyShaderModule", vkDestroyShaderModule)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreatePipelineCache", vkCreatePipelineCache)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyPipelineCache", vkDestroyPipelineCache)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkGetPipelineCacheData", vkGetPipelineCacheData)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkMergePipelineCaches", vkMergePipelineCaches)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateGraphicsPipelines", vkCreateGraphicsPipelines)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateComputePipelines", vkCreateComputePipelines)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyPipeline", vkDestroyPipeline)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreatePipelineLayout", vkCreatePipelineLayout)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyPipelineLayout", vkDestroyPipelineLayout)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateSampler", vkCreateSampler)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroySampler", vkDestroySampler)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateDescriptorSetLayout", vkCreateDescriptorSetLayout)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyDescriptorSetLayout", vkDestroyDescriptorSetLayout)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateDescriptorPool", vkCreateDescriptorPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyDescriptorPool", vkDestroyDescriptorPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkResetDescriptorPool", vkResetDescriptorPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkAllocateDescriptorSets", vkAllocateDescriptorSets)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkFreeDescriptorSets", vkFreeDescriptorSets)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkUpdateDescriptorSets", vkUpdateDescriptorSets)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateFramebuffer", vkCreateFramebuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyFramebuffer", vkDestroyFramebuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateRenderPass", vkCreateRenderPass)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyRenderPass", vkDestroyRenderPass)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkGetRenderAreaGranularity", vkGetRenderAreaGranularity)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCreateCommandPool", vkCreateCommandPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkDestroyCommandPool", vkDestroyCommandPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkResetCommandPool", vkResetCommandPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkAllocateCommandBuffers", vkAllocateCommandBuffers)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkFreeCommandBuffers", vkFreeCommandBuffers)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkBeginCommandBuffer", vkBeginCommandBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkEndCommandBuffer", vkEndCommandBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkResetCommandBuffer", vkResetCommandBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdBindPipeline", vkCmdBindPipeline)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdSetViewport", vkCmdSetViewport)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdSetScissor", vkCmdSetScissor)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdSetLineWidth", vkCmdSetLineWidth)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdSetDepthBias", vkCmdSetDepthBias)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdSetBlendConstants", vkCmdSetBlendConstants)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdSetDepthBounds", vkCmdSetDepthBounds)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdSetStencilCompareMask", vkCmdSetStencilCompareMask)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdSetStencilWriteMask", vkCmdSetStencilWriteMask)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdSetStencilReference", vkCmdSetStencilReference)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdBindDescriptorSets", vkCmdBindDescriptorSets)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdBindIndexBuffer", vkCmdBindIndexBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdBindVertexBuffers", vkCmdBindVertexBuffers)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdDraw", vkCmdDraw)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdDrawIndexed", vkCmdDrawIndexed)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdDrawIndirect", vkCmdDrawIndirect)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdDrawIndexedIndirect", vkCmdDrawIndexedIndirect)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdDispatch", vkCmdDispatch)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdDispatchIndirect", vkCmdDispatchIndirect)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdCopyBuffer", vkCmdCopyBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdCopyImage", vkCmdCopyImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdBlitImage", vkCmdBlitImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdCopyBufferToImage", vkCmdCopyBufferToImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdCopyImageToBuffer", vkCmdCopyImageToBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdUpdateBuffer", vkCmdUpdateBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdFillBuffer", vkCmdFillBuffer)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdClearColorImage", vkCmdClearColorImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdClearDepthStencilImage", vkCmdClearDepthStencilImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdClearAttachments", vkCmdClearAttachments)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdResolveImage", vkCmdResolveImage)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdSetEvent", vkCmdSetEvent)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdResetEvent", vkCmdResetEvent)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdWaitEvents", vkCmdWaitEvents)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdPipelineBarrier", vkCmdPipelineBarrier)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdBeginQuery", vkCmdBeginQuery)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdEndQuery", vkCmdEndQuery)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdResetQueryPool", vkCmdResetQueryPool)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdWriteTimestamp", vkCmdWriteTimestamp)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdCopyQueryPoolResults", vkCmdCopyQueryPoolResults)) + { +#if 0 + /* Don't return false here. Would cause MESA Intel Ivy Bridge drivers to not work at all. */ + return VK_FALSE; +#endif + } + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdPushConstants", vkCmdPushConstants)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdBeginRenderPass", vkCmdBeginRenderPass)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdNextSubpass", vkCmdNextSubpass)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdEndRenderPass", vkCmdEndRenderPass)) return VK_FALSE; + if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "vkCmdExecuteCommands", vkCmdExecuteCommands)) return VK_FALSE; + return VK_TRUE; +}